qtdemux: Always check ctts for unreasonably large offsets
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 #define gst_qtdemux_parent_class parent_class
293 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
294 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
295     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
296
297 static void gst_qtdemux_dispose (GObject * object);
298 static void gst_qtdemux_finalize (GObject * object);
299
300 static guint32
301 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
302     GstClockTime media_time);
303 static guint32
304 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
305     QtDemuxStream * str, gint64 media_offset);
306
307 #if 0
308 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
309 static GstIndex *gst_qtdemux_get_index (GstElement * element);
310 #endif
311 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
312     GstStateChange transition);
313 static void gst_qtdemux_set_context (GstElement * element,
314     GstContext * context);
315 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
316 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
317     GstObject * parent, GstPadMode mode, gboolean active);
318
319 static void gst_qtdemux_loop (GstPad * pad);
320 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
321     GstBuffer * inbuf);
322 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
323     GstEvent * event);
324 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
325     GstQuery * query);
326 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
327 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
328     QtDemuxStream * stream);
329 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
330     QtDemuxStream * stream);
331 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
332     gboolean force);
333
334 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
335
336 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
337     const guint8 * buffer, guint length);
338 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
339     const guint8 * buffer, guint length);
340 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
341
342 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
343     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
344     GstTagList * list);
345 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
346     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
347     const guint8 * stsd_entry_data, gchar ** codec_name);
348 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
350     const guint8 * data, int len, gchar ** codec_name);
351 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
352     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
353     gchar ** codec_name);
354 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * stsd_entry_data, gchar ** codec_name);
357
358 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
359     QtDemuxStream * stream, guint32 n);
360 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
361 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
363 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
364 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
365 static void qtdemux_do_allocation (QtDemuxStream * stream,
366     GstQTDemux * qtdemux);
367 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
369 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
370     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
371     GstClockTime * _start, GstClockTime * _stop);
372 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
373     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
374
375 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
376 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
377
378 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
379
380 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
381     QtDemuxStream * stream, guint sample_index);
382 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
383     const gchar * id);
384 static void qtdemux_gst_structure_free (GstStructure * gststructure);
385 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
386
387 static void
388 gst_qtdemux_class_init (GstQTDemuxClass * klass)
389 {
390   GObjectClass *gobject_class;
391   GstElementClass *gstelement_class;
392
393   gobject_class = (GObjectClass *) klass;
394   gstelement_class = (GstElementClass *) klass;
395
396   parent_class = g_type_class_peek_parent (klass);
397
398   gobject_class->dispose = gst_qtdemux_dispose;
399   gobject_class->finalize = gst_qtdemux_finalize;
400
401   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
402 #if 0
403   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
404   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
405 #endif
406   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
407
408   gst_tag_register_musicbrainz_tags ();
409
410   gst_element_class_add_static_pad_template (gstelement_class,
411       &gst_qtdemux_sink_template);
412   gst_element_class_add_static_pad_template (gstelement_class,
413       &gst_qtdemux_videosrc_template);
414   gst_element_class_add_static_pad_template (gstelement_class,
415       &gst_qtdemux_audiosrc_template);
416   gst_element_class_add_static_pad_template (gstelement_class,
417       &gst_qtdemux_subsrc_template);
418   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
419       "Codec/Demuxer",
420       "Demultiplex a QuickTime file into audio and video streams",
421       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
422
423   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
424   gst_riff_init ();
425 }
426
427 static void
428 gst_qtdemux_init (GstQTDemux * qtdemux)
429 {
430   qtdemux->sinkpad =
431       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
432   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
433   gst_pad_set_activatemode_function (qtdemux->sinkpad,
434       qtdemux_sink_activate_mode);
435   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
436   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
437   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
438   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
439
440   qtdemux->adapter = gst_adapter_new ();
441   g_queue_init (&qtdemux->protection_event_queue);
442   qtdemux->flowcombiner = gst_flow_combiner_new ();
443   g_mutex_init (&qtdemux->expose_lock);
444
445   qtdemux->active_streams = g_ptr_array_new_with_free_func
446       ((GDestroyNotify) gst_qtdemux_stream_unref);
447   qtdemux->old_streams = g_ptr_array_new_with_free_func
448       ((GDestroyNotify) gst_qtdemux_stream_unref);
449
450   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
451
452   gst_qtdemux_reset (qtdemux, TRUE);
453 }
454
455 static void
456 gst_qtdemux_finalize (GObject * object)
457 {
458   GstQTDemux *qtdemux = GST_QTDEMUX (object);
459
460   g_free (qtdemux->redirect_location);
461
462   G_OBJECT_CLASS (parent_class)->finalize (object);
463 }
464
465 static void
466 gst_qtdemux_dispose (GObject * object)
467 {
468   GstQTDemux *qtdemux = GST_QTDEMUX (object);
469
470   if (qtdemux->adapter) {
471     g_object_unref (G_OBJECT (qtdemux->adapter));
472     qtdemux->adapter = NULL;
473   }
474   gst_tag_list_unref (qtdemux->tag_list);
475   gst_flow_combiner_free (qtdemux->flowcombiner);
476   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
477       NULL);
478   g_queue_clear (&qtdemux->protection_event_queue);
479
480   g_free (qtdemux->cenc_aux_info_sizes);
481   qtdemux->cenc_aux_info_sizes = NULL;
482   g_mutex_clear (&qtdemux->expose_lock);
483
484   g_ptr_array_free (qtdemux->active_streams, TRUE);
485   g_ptr_array_free (qtdemux->old_streams, TRUE);
486
487   G_OBJECT_CLASS (parent_class)->dispose (object);
488 }
489
490 static void
491 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
492 {
493   if (qtdemux->redirect_location) {
494     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
495         (_("This file contains no playable streams.")),
496         ("no known streams found, a redirect message has been posted"),
497         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
498   } else {
499     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
500         (_("This file contains no playable streams.")),
501         ("no known streams found"));
502   }
503 }
504
505 static GstBuffer *
506 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
507 {
508   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
509       mem, size, 0, size, mem, free_func);
510 }
511
512 static GstFlowReturn
513 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
514     GstBuffer ** buf)
515 {
516   GstFlowReturn flow;
517   GstMapInfo map;
518   gsize bsize;
519
520   if (G_UNLIKELY (size == 0)) {
521     GstFlowReturn ret;
522     GstBuffer *tmp = NULL;
523
524     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
525     if (ret != GST_FLOW_OK)
526       return ret;
527
528     gst_buffer_map (tmp, &map, GST_MAP_READ);
529     size = QT_UINT32 (map.data);
530     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
531
532     gst_buffer_unmap (tmp, &map);
533     gst_buffer_unref (tmp);
534   }
535
536   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
537   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
538     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
539       /* we're pulling header but already got most interesting bits,
540        * so never mind the rest (e.g. tags) (that much) */
541       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
542           size);
543       return GST_FLOW_EOS;
544     } else {
545       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
546           (_("This file is invalid and cannot be played.")),
547           ("atom has bogus size %" G_GUINT64_FORMAT, size));
548       return GST_FLOW_ERROR;
549     }
550   }
551
552   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
553
554   if (G_UNLIKELY (flow != GST_FLOW_OK))
555     return flow;
556
557   bsize = gst_buffer_get_size (*buf);
558   /* Catch short reads - we don't want any partial atoms */
559   if (G_UNLIKELY (bsize < size)) {
560     GST_WARNING_OBJECT (qtdemux,
561         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
562     gst_buffer_unref (*buf);
563     *buf = NULL;
564     return GST_FLOW_EOS;
565   }
566
567   return flow;
568 }
569
570 #if 1
571 static gboolean
572 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
573     GstFormat src_format, gint64 src_value, GstFormat dest_format,
574     gint64 * dest_value)
575 {
576   gboolean res = TRUE;
577   QtDemuxStream *stream = gst_pad_get_element_private (pad);
578   gint32 index;
579
580   if (stream->subtype != FOURCC_vide) {
581     res = FALSE;
582     goto done;
583   }
584
585   switch (src_format) {
586     case GST_FORMAT_TIME:
587       switch (dest_format) {
588         case GST_FORMAT_BYTES:{
589           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
590           if (-1 == index) {
591             res = FALSE;
592             goto done;
593           }
594
595           *dest_value = stream->samples[index].offset;
596
597           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
598               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
599               GST_TIME_ARGS (src_value), *dest_value);
600           break;
601         }
602         default:
603           res = FALSE;
604           break;
605       }
606       break;
607     case GST_FORMAT_BYTES:
608       switch (dest_format) {
609         case GST_FORMAT_TIME:{
610           index =
611               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
612               stream, src_value);
613
614           if (-1 == index) {
615             res = FALSE;
616             goto done;
617           }
618
619           *dest_value =
620               QTSTREAMTIME_TO_GSTTIME (stream,
621               stream->samples[index].timestamp);
622           GST_DEBUG_OBJECT (qtdemux,
623               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
624               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
625           break;
626         }
627         default:
628           res = FALSE;
629           break;
630       }
631       break;
632     default:
633       res = FALSE;
634       break;
635   }
636
637 done:
638   return res;
639 }
640 #endif
641
642 static gboolean
643 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
644 {
645   gboolean res = FALSE;
646
647   *duration = GST_CLOCK_TIME_NONE;
648
649   if (qtdemux->duration != 0 &&
650       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
651     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
652     res = TRUE;
653   } else {
654     *duration = GST_CLOCK_TIME_NONE;
655   }
656
657   return res;
658 }
659
660 static gboolean
661 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
662     GstQuery * query)
663 {
664   gboolean res = FALSE;
665   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
666
667   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
668
669   switch (GST_QUERY_TYPE (query)) {
670     case GST_QUERY_POSITION:{
671       GstFormat fmt;
672
673       gst_query_parse_position (query, &fmt, NULL);
674       if (fmt == GST_FORMAT_TIME
675           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
676         gst_query_set_position (query, GST_FORMAT_TIME,
677             qtdemux->segment.position);
678         res = TRUE;
679       }
680     }
681       break;
682     case GST_QUERY_DURATION:{
683       GstFormat fmt;
684
685       gst_query_parse_duration (query, &fmt, NULL);
686       if (fmt == GST_FORMAT_TIME) {
687         /* First try to query upstream */
688         res = gst_pad_query_default (pad, parent, query);
689         if (!res) {
690           GstClockTime duration;
691           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
692             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
693             res = TRUE;
694           }
695         }
696       }
697       break;
698     }
699     case GST_QUERY_CONVERT:{
700       GstFormat src_fmt, dest_fmt;
701       gint64 src_value, dest_value = 0;
702
703       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
704
705       res = gst_qtdemux_src_convert (qtdemux, pad,
706           src_fmt, src_value, dest_fmt, &dest_value);
707       if (res)
708         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
709
710       break;
711     }
712     case GST_QUERY_FORMATS:
713       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
714       res = TRUE;
715       break;
716     case GST_QUERY_SEEKING:{
717       GstFormat fmt;
718       gboolean seekable;
719
720       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
721
722       if (fmt == GST_FORMAT_BYTES) {
723         /* We always refuse BYTES seeks from downstream */
724         break;
725       }
726
727       /* try upstream first */
728       res = gst_pad_query_default (pad, parent, query);
729
730       if (!res) {
731         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
732         if (fmt == GST_FORMAT_TIME) {
733           GstClockTime duration;
734
735           gst_qtdemux_get_duration (qtdemux, &duration);
736           seekable = TRUE;
737           if (!qtdemux->pullbased) {
738             GstQuery *q;
739
740             /* we might be able with help from upstream */
741             seekable = FALSE;
742             q = gst_query_new_seeking (GST_FORMAT_BYTES);
743             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
744               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
745               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
746             }
747             gst_query_unref (q);
748           }
749           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
750           res = TRUE;
751         }
752       }
753       break;
754     }
755     case GST_QUERY_SEGMENT:
756     {
757       GstFormat format;
758       gint64 start, stop;
759
760       format = qtdemux->segment.format;
761
762       start =
763           gst_segment_to_stream_time (&qtdemux->segment, format,
764           qtdemux->segment.start);
765       if ((stop = qtdemux->segment.stop) == -1)
766         stop = qtdemux->segment.duration;
767       else
768         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
769
770       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
771       res = TRUE;
772       break;
773     }
774     default:
775       res = gst_pad_query_default (pad, parent, query);
776       break;
777   }
778
779   return res;
780 }
781
782 static void
783 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
784 {
785   if (G_LIKELY (stream->pad)) {
786     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
787         GST_DEBUG_PAD_NAME (stream->pad));
788
789     if (!gst_tag_list_is_empty (stream->stream_tags)) {
790       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
791           stream->stream_tags);
792       gst_pad_push_event (stream->pad,
793           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
794     }
795
796     if (G_UNLIKELY (stream->send_global_tags)) {
797       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
798           qtdemux->tag_list);
799       gst_pad_push_event (stream->pad,
800           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
801       stream->send_global_tags = FALSE;
802     }
803   }
804 }
805
806 /* push event on all source pads; takes ownership of the event */
807 static void
808 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
809 {
810   gboolean has_valid_stream = FALSE;
811   GstEventType etype = GST_EVENT_TYPE (event);
812   guint i;
813
814   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
815       GST_EVENT_TYPE_NAME (event));
816
817   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
818     GstPad *pad;
819     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
820     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
821
822     if ((pad = stream->pad)) {
823       has_valid_stream = TRUE;
824
825       if (etype == GST_EVENT_EOS) {
826         /* let's not send twice */
827         if (stream->sent_eos)
828           continue;
829         stream->sent_eos = TRUE;
830       }
831
832       gst_pad_push_event (pad, gst_event_ref (event));
833     }
834   }
835
836   gst_event_unref (event);
837
838   /* if it is EOS and there are no pads, post an error */
839   if (!has_valid_stream && etype == GST_EVENT_EOS) {
840     gst_qtdemux_post_no_playable_stream_error (qtdemux);
841   }
842 }
843
844 typedef struct
845 {
846   guint64 media_time;
847 } FindData;
848
849 static gint
850 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
851 {
852   if ((gint64) s1->timestamp > *media_time)
853     return 1;
854   if ((gint64) s1->timestamp == *media_time)
855     return 0;
856
857   return -1;
858 }
859
860 /* find the index of the sample that includes the data for @media_time using a
861  * binary search.  Only to be called in optimized cases of linear search below.
862  *
863  * Returns the index of the sample with the corresponding *DTS*.
864  */
865 static guint32
866 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
867     guint64 media_time)
868 {
869   QtDemuxSample *result;
870   guint32 index;
871
872   /* convert media_time to mov format */
873   media_time =
874       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
875
876   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
877       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
878       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
879
880   if (G_LIKELY (result))
881     index = result - str->samples;
882   else
883     index = 0;
884
885   return index;
886 }
887
888
889
890 /* find the index of the sample that includes the data for @media_offset using a
891  * linear search
892  *
893  * Returns the index of the sample.
894  */
895 static guint32
896 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
897     QtDemuxStream * str, gint64 media_offset)
898 {
899   QtDemuxSample *result = str->samples;
900   guint32 index = 0;
901
902   if (result == NULL || str->n_samples == 0)
903     return -1;
904
905   if (media_offset == result->offset)
906     return index;
907
908   result++;
909   while (index < str->n_samples - 1) {
910     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
911       goto parse_failed;
912
913     if (media_offset < result->offset)
914       break;
915
916     index++;
917     result++;
918   }
919   return index;
920
921   /* ERRORS */
922 parse_failed:
923   {
924     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
925     return -1;
926   }
927 }
928
929 /* find the index of the sample that includes the data for @media_time using a
930  * linear search, and keeping in mind that not all samples may have been parsed
931  * yet.  If possible, it will delegate to binary search.
932  *
933  * Returns the index of the sample.
934  */
935 static guint32
936 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
937     GstClockTime media_time)
938 {
939   guint32 index = 0;
940   guint64 mov_time;
941   QtDemuxSample *sample;
942
943   /* convert media_time to mov format */
944   mov_time =
945       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
946
947   sample = str->samples;
948   if (mov_time == sample->timestamp + sample->pts_offset)
949     return index;
950
951   /* use faster search if requested time in already parsed range */
952   sample = str->samples + str->stbl_index;
953   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
954     index = gst_qtdemux_find_index (qtdemux, str, media_time);
955     sample = str->samples + index;
956   } else {
957     while (index < str->n_samples - 1) {
958       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
959         goto parse_failed;
960
961       sample = str->samples + index + 1;
962       if (mov_time < sample->timestamp) {
963         sample = str->samples + index;
964         break;
965       }
966
967       index++;
968     }
969   }
970
971   /* sample->timestamp is now <= media_time, need to find the corresponding
972    * PTS now by looking backwards */
973   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
974     index--;
975     sample = str->samples + index;
976   }
977
978   return index;
979
980   /* ERRORS */
981 parse_failed:
982   {
983     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
984     return -1;
985   }
986 }
987
988 /* find the index of the keyframe needed to decode the sample at @index
989  * of stream @str, or of a subsequent keyframe (depending on @next)
990  *
991  * Returns the index of the keyframe.
992  */
993 static guint32
994 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
995     guint32 index, gboolean next)
996 {
997   guint32 new_index = index;
998
999   if (index >= str->n_samples) {
1000     new_index = str->n_samples;
1001     goto beach;
1002   }
1003
1004   /* all keyframes, return index */
1005   if (str->all_keyframe) {
1006     new_index = index;
1007     goto beach;
1008   }
1009
1010   /* else search until we have a keyframe */
1011   while (new_index < str->n_samples) {
1012     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1013       goto parse_failed;
1014
1015     if (str->samples[new_index].keyframe)
1016       break;
1017
1018     if (new_index == 0)
1019       break;
1020
1021     if (next)
1022       new_index++;
1023     else
1024       new_index--;
1025   }
1026
1027   if (new_index == str->n_samples) {
1028     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1029     new_index = -1;
1030   }
1031
1032 beach:
1033   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1034       "gave %u", next ? "after" : "before", index, new_index);
1035
1036   return new_index;
1037
1038   /* ERRORS */
1039 parse_failed:
1040   {
1041     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1042     return -1;
1043   }
1044 }
1045
1046 /* find the segment for @time_position for @stream
1047  *
1048  * Returns the index of the segment containing @time_position.
1049  * Returns the last segment and sets the @eos variable to TRUE
1050  * if the time is beyond the end. @eos may be NULL
1051  */
1052 static guint32
1053 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1054     GstClockTime time_position)
1055 {
1056   gint i;
1057   guint32 seg_idx;
1058
1059   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1060       GST_TIME_ARGS (time_position));
1061
1062   seg_idx = -1;
1063   for (i = 0; i < stream->n_segments; i++) {
1064     QtDemuxSegment *segment = &stream->segments[i];
1065
1066     GST_LOG_OBJECT (stream->pad,
1067         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1068         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1069
1070     /* For the last segment we include stop_time in the last segment */
1071     if (i < stream->n_segments - 1) {
1072       if (segment->time <= time_position && time_position < segment->stop_time) {
1073         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1074         seg_idx = i;
1075         break;
1076       }
1077     } else {
1078       /* Last segment always matches */
1079       seg_idx = i;
1080       break;
1081     }
1082   }
1083   return seg_idx;
1084 }
1085
1086 /* move the stream @str to the sample position @index.
1087  *
1088  * Updates @str->sample_index and marks discontinuity if needed.
1089  */
1090 static void
1091 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1092     guint32 index)
1093 {
1094   /* no change needed */
1095   if (index == str->sample_index)
1096     return;
1097
1098   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1099       str->n_samples);
1100
1101   /* position changed, we have a discont */
1102   str->sample_index = index;
1103   str->offset_in_sample = 0;
1104   /* Each time we move in the stream we store the position where we are
1105    * starting from */
1106   str->from_sample = index;
1107   str->discont = TRUE;
1108 }
1109
1110 static void
1111 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1112     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1113 {
1114   guint64 min_offset;
1115   gint64 min_byte_offset = -1;
1116   guint i;
1117
1118   min_offset = desired_time;
1119
1120   /* for each stream, find the index of the sample in the segment
1121    * and move back to the previous keyframe. */
1122   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1123     QtDemuxStream *str;
1124     guint32 index, kindex;
1125     guint32 seg_idx;
1126     GstClockTime media_start;
1127     GstClockTime media_time;
1128     GstClockTime seg_time;
1129     QtDemuxSegment *seg;
1130     gboolean empty_segment = FALSE;
1131
1132     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1133
1134     if (CUR_STREAM (str)->sparse && !use_sparse)
1135       continue;
1136
1137     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1138     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1139
1140     /* get segment and time in the segment */
1141     seg = &str->segments[seg_idx];
1142     seg_time = (desired_time - seg->time) * seg->rate;
1143
1144     while (QTSEGMENT_IS_EMPTY (seg)) {
1145       seg_time = 0;
1146       empty_segment = TRUE;
1147       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1148           seg_idx);
1149       seg_idx++;
1150       if (seg_idx == str->n_segments)
1151         break;
1152       seg = &str->segments[seg_idx];
1153     }
1154
1155     if (seg_idx == str->n_segments) {
1156       /* FIXME track shouldn't have the last segment as empty, but if it
1157        * happens we better handle it */
1158       continue;
1159     }
1160
1161     /* get the media time in the segment */
1162     media_start = seg->media_start + seg_time;
1163
1164     /* get the index of the sample with media time */
1165     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1166     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1167         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1168         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1169         empty_segment);
1170
1171     /* shift to next frame if we are looking for next keyframe */
1172     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1173         && index < str->stbl_index)
1174       index++;
1175
1176     if (!empty_segment) {
1177       /* find previous keyframe */
1178       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1179
1180       /* we will settle for one before if none found after */
1181       if (next && kindex == -1)
1182         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1183
1184       /* Update the requested time whenever a keyframe was found, to make it
1185        * accurate and avoid having the first buffer fall outside of the segment
1186        */
1187       if (kindex != -1) {
1188         index = kindex;
1189
1190         /* get timestamp of keyframe */
1191         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1192         GST_DEBUG_OBJECT (qtdemux,
1193             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1194             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1195             str->samples[kindex].offset);
1196
1197         /* keyframes in the segment get a chance to change the
1198          * desired_offset. keyframes out of the segment are
1199          * ignored. */
1200         if (media_time >= seg->media_start) {
1201           GstClockTime seg_time;
1202
1203           /* this keyframe is inside the segment, convert back to
1204            * segment time */
1205           seg_time = (media_time - seg->media_start) + seg->time;
1206           if ((!next && (seg_time < min_offset)) ||
1207               (next && (seg_time > min_offset)))
1208             min_offset = seg_time;
1209         }
1210       }
1211     }
1212
1213     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1214       min_byte_offset = str->samples[index].offset;
1215   }
1216
1217   if (key_time)
1218     *key_time = min_offset;
1219   if (key_offset)
1220     *key_offset = min_byte_offset;
1221 }
1222
1223 static gboolean
1224 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1225     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1226 {
1227   gboolean res;
1228
1229   g_return_val_if_fail (format != NULL, FALSE);
1230   g_return_val_if_fail (cur != NULL, FALSE);
1231   g_return_val_if_fail (stop != NULL, FALSE);
1232
1233   if (*format == GST_FORMAT_TIME)
1234     return TRUE;
1235
1236   res = TRUE;
1237   if (cur_type != GST_SEEK_TYPE_NONE)
1238     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1239   if (res && stop_type != GST_SEEK_TYPE_NONE)
1240     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1241
1242   if (res)
1243     *format = GST_FORMAT_TIME;
1244
1245   return res;
1246 }
1247
1248 /* perform seek in push based mode:
1249    find BYTE position to move to based on time and delegate to upstream
1250 */
1251 static gboolean
1252 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1253 {
1254   gdouble rate;
1255   GstFormat format;
1256   GstSeekFlags flags;
1257   GstSeekType cur_type, stop_type;
1258   gint64 cur, stop, key_cur;
1259   gboolean res;
1260   gint64 byte_cur;
1261   gint64 original_stop;
1262   guint32 seqnum;
1263
1264   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1265
1266   gst_event_parse_seek (event, &rate, &format, &flags,
1267       &cur_type, &cur, &stop_type, &stop);
1268   seqnum = gst_event_get_seqnum (event);
1269
1270   /* Directly send the instant-rate-change event here before taking the
1271    * stream-lock so that it can be applied as soon as possible */
1272   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1273     GstEvent *ev;
1274
1275     /* instant rate change only supported if direction does not change. All
1276      * other requirements are already checked before creating the seek event
1277      * but let's double-check here to be sure */
1278     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1279         (qtdemux->segment.rate < 0 && rate > 0) ||
1280         cur_type != GST_SEEK_TYPE_NONE ||
1281         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1282       GST_ERROR_OBJECT (qtdemux,
1283           "Instant rate change seeks only supported in the "
1284           "same direction, without flushing and position change");
1285       return FALSE;
1286     }
1287
1288     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1289         (GstSegmentFlags) flags);
1290     gst_event_set_seqnum (ev, seqnum);
1291     gst_qtdemux_push_event (qtdemux, ev);
1292     return TRUE;
1293   }
1294
1295   /* only forward streaming and seeking is possible */
1296   if (rate <= 0)
1297     goto unsupported_seek;
1298
1299   /* convert to TIME if needed and possible */
1300   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1301           stop_type, &stop))
1302     goto no_format;
1303
1304   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1305    * the original stop position to use when upstream pushes the new segment
1306    * for this seek */
1307   original_stop = stop;
1308   stop = -1;
1309
1310   /* find reasonable corresponding BYTE position,
1311    * also try to mind about keyframes, since we can not go back a bit for them
1312    * later on */
1313   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1314    * mostly just work, but let's not yet boldly go there  ... */
1315   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1316
1317   if (byte_cur == -1)
1318     goto abort_seek;
1319
1320   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1321       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1322       stop);
1323
1324   GST_OBJECT_LOCK (qtdemux);
1325   qtdemux->seek_offset = byte_cur;
1326   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1327     qtdemux->push_seek_start = cur;
1328   } else {
1329     qtdemux->push_seek_start = key_cur;
1330   }
1331
1332   if (stop_type == GST_SEEK_TYPE_NONE) {
1333     qtdemux->push_seek_stop = qtdemux->segment.stop;
1334   } else {
1335     qtdemux->push_seek_stop = original_stop;
1336   }
1337   GST_OBJECT_UNLOCK (qtdemux);
1338
1339   qtdemux->segment_seqnum = seqnum;
1340   /* BYTE seek event */
1341   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1342       stop_type, stop);
1343   gst_event_set_seqnum (event, seqnum);
1344   res = gst_pad_push_event (qtdemux->sinkpad, event);
1345
1346   return res;
1347
1348   /* ERRORS */
1349 abort_seek:
1350   {
1351     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1352         "seek aborted.");
1353     return FALSE;
1354   }
1355 unsupported_seek:
1356   {
1357     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1358     return FALSE;
1359   }
1360 no_format:
1361   {
1362     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1363     return FALSE;
1364   }
1365 }
1366
1367 /* perform the seek.
1368  *
1369  * We set all segment_indexes in the streams to unknown and
1370  * adjust the time_position to the desired position. this is enough
1371  * to trigger a segment switch in the streaming thread to start
1372  * streaming from the desired position.
1373  *
1374  * Keyframe seeking is a little more complicated when dealing with
1375  * segments. Ideally we want to move to the previous keyframe in
1376  * the segment but there might not be a keyframe in the segment. In
1377  * fact, none of the segments could contain a keyframe. We take a
1378  * practical approach: seek to the previous keyframe in the segment,
1379  * if there is none, seek to the beginning of the segment.
1380  *
1381  * Called with STREAM_LOCK
1382  */
1383 static gboolean
1384 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1385     guint32 seqnum, GstSeekFlags flags)
1386 {
1387   gint64 desired_offset;
1388   guint i;
1389
1390   desired_offset = segment->position;
1391
1392   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1393       GST_TIME_ARGS (desired_offset));
1394
1395   /* may not have enough fragmented info to do this adjustment,
1396    * and we can't scan (and probably should not) at this time with
1397    * possibly flushing upstream */
1398   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1399     gint64 min_offset;
1400     gboolean next, before, after;
1401
1402     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1403     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1404     next = after && !before;
1405     if (segment->rate < 0)
1406       next = !next;
1407
1408     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1409         NULL);
1410     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1411         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1412     desired_offset = min_offset;
1413   }
1414
1415   /* and set all streams to the final position */
1416   GST_OBJECT_LOCK (qtdemux);
1417   gst_flow_combiner_reset (qtdemux->flowcombiner);
1418   GST_OBJECT_UNLOCK (qtdemux);
1419   qtdemux->segment_seqnum = seqnum;
1420   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1421     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1422
1423     stream->time_position = desired_offset;
1424     stream->accumulated_base = 0;
1425     stream->sample_index = -1;
1426     stream->offset_in_sample = 0;
1427     stream->segment_index = -1;
1428     stream->sent_eos = FALSE;
1429     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1430
1431     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1432       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1433   }
1434   segment->position = desired_offset;
1435   if (segment->rate >= 0) {
1436     segment->start = desired_offset;
1437     /* We need to update time as we update start in that direction */
1438     segment->time = desired_offset;
1439
1440     /* we stop at the end */
1441     if (segment->stop == -1)
1442       segment->stop = segment->duration;
1443   } else {
1444     segment->stop = desired_offset;
1445   }
1446
1447   if (qtdemux->fragmented)
1448     qtdemux->fragmented_seek_pending = TRUE;
1449
1450   return TRUE;
1451 }
1452
1453 /* do a seek in pull based mode */
1454 static gboolean
1455 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1456 {
1457   gdouble rate = 1.0;
1458   GstFormat format;
1459   GstSeekFlags flags;
1460   GstSeekType cur_type, stop_type;
1461   gint64 cur, stop;
1462   gboolean flush, instant_rate_change;
1463   gboolean update;
1464   GstSegment seeksegment;
1465   guint32 seqnum = GST_SEQNUM_INVALID;
1466   GstEvent *flush_event;
1467   gboolean ret;
1468
1469   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1470
1471   gst_event_parse_seek (event, &rate, &format, &flags,
1472       &cur_type, &cur, &stop_type, &stop);
1473   seqnum = gst_event_get_seqnum (event);
1474
1475   /* we have to have a format as the segment format. Try to convert
1476    * if not. */
1477   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1478           stop_type, &stop))
1479     goto no_format;
1480
1481   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1482
1483   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1484   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1485
1486   /* Directly send the instant-rate-change event here before taking the
1487    * stream-lock so that it can be applied as soon as possible */
1488   if (instant_rate_change) {
1489     GstEvent *ev;
1490
1491     /* instant rate change only supported if direction does not change. All
1492      * other requirements are already checked before creating the seek event
1493      * but let's double-check here to be sure */
1494     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1495         (qtdemux->segment.rate < 0 && rate > 0) ||
1496         cur_type != GST_SEEK_TYPE_NONE ||
1497         stop_type != GST_SEEK_TYPE_NONE || flush) {
1498       GST_ERROR_OBJECT (qtdemux,
1499           "Instant rate change seeks only supported in the "
1500           "same direction, without flushing and position change");
1501       return FALSE;
1502     }
1503
1504     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1505         (GstSegmentFlags) flags);
1506     gst_event_set_seqnum (ev, seqnum);
1507     gst_qtdemux_push_event (qtdemux, ev);
1508     return TRUE;
1509   }
1510
1511   /* stop streaming, either by flushing or by pausing the task */
1512   if (flush) {
1513     flush_event = gst_event_new_flush_start ();
1514     if (seqnum != GST_SEQNUM_INVALID)
1515       gst_event_set_seqnum (flush_event, seqnum);
1516     /* unlock upstream pull_range */
1517     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1518     /* make sure out loop function exits */
1519     gst_qtdemux_push_event (qtdemux, flush_event);
1520   } else {
1521     /* non flushing seek, pause the task */
1522     gst_pad_pause_task (qtdemux->sinkpad);
1523   }
1524
1525   /* wait for streaming to finish */
1526   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1527
1528   /* copy segment, we need this because we still need the old
1529    * segment when we close the current segment. */
1530   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1531
1532   /* configure the segment with the seek variables */
1533   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1534   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1535           cur_type, cur, stop_type, stop, &update)) {
1536     ret = FALSE;
1537     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1538   } else {
1539     /* now do the seek */
1540     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1541   }
1542
1543   /* prepare for streaming again */
1544   if (flush) {
1545     flush_event = gst_event_new_flush_stop (TRUE);
1546     if (seqnum != GST_SEQNUM_INVALID)
1547       gst_event_set_seqnum (flush_event, seqnum);
1548
1549     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1550     gst_qtdemux_push_event (qtdemux, flush_event);
1551   }
1552
1553   /* commit the new segment */
1554   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1555
1556   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1557     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1558         qtdemux->segment.format, qtdemux->segment.position);
1559     if (seqnum != GST_SEQNUM_INVALID)
1560       gst_message_set_seqnum (msg, seqnum);
1561     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1562   }
1563
1564   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1565   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1566       qtdemux->sinkpad, NULL);
1567
1568   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1569
1570   return ret;
1571
1572   /* ERRORS */
1573 no_format:
1574   {
1575     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1576     return FALSE;
1577   }
1578 }
1579
1580 static gboolean
1581 qtdemux_ensure_index (GstQTDemux * qtdemux)
1582 {
1583   guint i;
1584
1585   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1586
1587   /* Build complete index */
1588   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1589     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1590
1591     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1592       GST_LOG_OBJECT (qtdemux,
1593           "Building complete index of track-id %u for seeking failed!",
1594           stream->track_id);
1595       return FALSE;
1596     }
1597   }
1598
1599   return TRUE;
1600 }
1601
1602 static gboolean
1603 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1604     GstEvent * event)
1605 {
1606   gboolean res = TRUE;
1607   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1608
1609   switch (GST_EVENT_TYPE (event)) {
1610     case GST_EVENT_RECONFIGURE:
1611       GST_OBJECT_LOCK (qtdemux);
1612       gst_flow_combiner_reset (qtdemux->flowcombiner);
1613       GST_OBJECT_UNLOCK (qtdemux);
1614       res = gst_pad_event_default (pad, parent, event);
1615       break;
1616     case GST_EVENT_SEEK:
1617     {
1618       GstSeekFlags flags = 0;
1619       GstFormat seek_format;
1620       gboolean instant_rate_change;
1621
1622 #ifndef GST_DISABLE_GST_DEBUG
1623       GstClockTime ts = gst_util_get_timestamp ();
1624 #endif
1625       guint32 seqnum = gst_event_get_seqnum (event);
1626
1627       qtdemux->received_seek = TRUE;
1628
1629       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1630           NULL);
1631       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1632
1633       if (seqnum == qtdemux->segment_seqnum) {
1634         GST_LOG_OBJECT (pad,
1635             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1636         gst_event_unref (event);
1637         return TRUE;
1638       }
1639
1640       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1641         /* seek should be handled by upstream, we might need to re-download fragments */
1642         GST_DEBUG_OBJECT (qtdemux,
1643             "let upstream handle seek for fragmented playback");
1644         goto upstream;
1645       }
1646
1647       if (seek_format == GST_FORMAT_BYTES) {
1648         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1649         gst_event_unref (event);
1650         return FALSE;
1651       }
1652
1653       gst_event_parse_seek_trickmode_interval (event,
1654           &qtdemux->trickmode_interval);
1655
1656       /* Build complete index for seeking;
1657        * if not a fragmented file at least and we're really doing a seek,
1658        * not just an instant-rate-change */
1659       if (!qtdemux->fragmented && !instant_rate_change) {
1660         if (!qtdemux_ensure_index (qtdemux))
1661           goto index_failed;
1662       }
1663 #ifndef GST_DISABLE_GST_DEBUG
1664       ts = gst_util_get_timestamp () - ts;
1665       GST_INFO_OBJECT (qtdemux,
1666           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1667 #endif
1668       if (qtdemux->pullbased) {
1669         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1670       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1671         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1672         res = TRUE;
1673       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1674           && QTDEMUX_N_STREAMS (qtdemux)
1675           && !qtdemux->fragmented) {
1676         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1677       } else {
1678         GST_DEBUG_OBJECT (qtdemux,
1679             "ignoring seek in push mode in current state");
1680         res = FALSE;
1681       }
1682       gst_event_unref (event);
1683     }
1684       break;
1685     default:
1686     upstream:
1687       res = gst_pad_event_default (pad, parent, event);
1688       break;
1689   }
1690
1691 done:
1692   return res;
1693
1694   /* ERRORS */
1695 index_failed:
1696   {
1697     GST_ERROR_OBJECT (qtdemux, "Index failed");
1698     gst_event_unref (event);
1699     res = FALSE;
1700     goto done;
1701   }
1702 }
1703
1704 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1705  *
1706  * If @fw is false, the coding order is explored backwards.
1707  *
1708  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1709  * sample is found for that track.
1710  *
1711  * The stream and sample index of the sample with the minimum offset in the direction explored
1712  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1713  *
1714  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1715  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1716  * @_stream and @_index. */
1717 static void
1718 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1719     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1720 {
1721   gint i, index;
1722   gint64 time, min_time;
1723   QtDemuxStream *stream;
1724   gint iter;
1725
1726   min_time = -1;
1727   stream = NULL;
1728   index = -1;
1729
1730   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1731     QtDemuxStream *str;
1732     gint inc;
1733     gboolean set_sample;
1734
1735     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1736     set_sample = !set;
1737
1738     if (fw) {
1739       i = 0;
1740       inc = 1;
1741     } else {
1742       i = str->n_samples - 1;
1743       inc = -1;
1744     }
1745
1746     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1747       if (str->samples[i].size == 0)
1748         continue;
1749
1750       if (fw && (str->samples[i].offset < byte_pos))
1751         continue;
1752
1753       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1754         continue;
1755
1756       /* move stream to first available sample */
1757       if (set) {
1758         gst_qtdemux_move_stream (qtdemux, str, i);
1759         set_sample = TRUE;
1760       }
1761
1762       /* avoid index from sparse streams since they might be far away */
1763       if (!CUR_STREAM (str)->sparse) {
1764         /* determine min/max time */
1765         time = QTSAMPLE_PTS (str, &str->samples[i]);
1766         if (min_time == -1 || (!fw && time > min_time) ||
1767             (fw && time < min_time)) {
1768           min_time = time;
1769         }
1770
1771         /* determine stream with leading sample, to get its position */
1772         if (!stream ||
1773             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1774             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1775           stream = str;
1776           index = i;
1777         }
1778       }
1779       break;
1780     }
1781
1782     /* no sample for this stream, mark eos */
1783     if (!set_sample)
1784       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1785   }
1786
1787   if (_time)
1788     *_time = min_time;
1789   if (_stream)
1790     *_stream = stream;
1791   if (_index)
1792     *_index = index;
1793 }
1794
1795 /* Copied from mpegtsbase code */
1796 /* FIXME: replace this function when we add new util function for stream-id creation */
1797 static gchar *
1798 _get_upstream_id (GstQTDemux * demux)
1799 {
1800   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1801
1802   if (!upstream_id) {
1803     /* Try to create one from the upstream URI, else use a randome number */
1804     GstQuery *query;
1805     gchar *uri = NULL;
1806
1807     /* Try to generate one from the URI query and
1808      * if it fails take a random number instead */
1809     query = gst_query_new_uri ();
1810     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1811       gst_query_parse_uri (query, &uri);
1812     }
1813
1814     if (uri) {
1815       GChecksum *cs;
1816
1817       /* And then generate an SHA256 sum of the URI */
1818       cs = g_checksum_new (G_CHECKSUM_SHA256);
1819       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1820       g_free (uri);
1821       upstream_id = g_strdup (g_checksum_get_string (cs));
1822       g_checksum_free (cs);
1823     } else {
1824       /* Just get some random number if the URI query fails */
1825       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1826           "implementing a deterministic way of creating a stream-id");
1827       upstream_id =
1828           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1829           g_random_int (), g_random_int ());
1830     }
1831
1832     gst_query_unref (query);
1833   }
1834   return upstream_id;
1835 }
1836
1837 static QtDemuxStream *
1838 _create_stream (GstQTDemux * demux, guint32 track_id)
1839 {
1840   QtDemuxStream *stream;
1841   gchar *upstream_id;
1842
1843   stream = g_new0 (QtDemuxStream, 1);
1844   stream->demux = demux;
1845   stream->track_id = track_id;
1846   upstream_id = _get_upstream_id (demux);
1847   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1848   g_free (upstream_id);
1849   /* new streams always need a discont */
1850   stream->discont = TRUE;
1851   /* we enable clipping for raw audio/video streams */
1852   stream->need_clip = FALSE;
1853   stream->process_func = NULL;
1854   stream->segment_index = -1;
1855   stream->time_position = 0;
1856   stream->sample_index = -1;
1857   stream->offset_in_sample = 0;
1858   stream->new_stream = TRUE;
1859   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1860   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1861   stream->protected = FALSE;
1862   stream->protection_scheme_type = 0;
1863   stream->protection_scheme_version = 0;
1864   stream->protection_scheme_info = NULL;
1865   stream->n_samples_moof = 0;
1866   stream->duration_moof = 0;
1867   stream->duration_last_moof = 0;
1868   stream->alignment = 1;
1869   stream->stream_tags = gst_tag_list_new_empty ();
1870   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1871   g_queue_init (&stream->protection_scheme_event_queue);
1872   stream->ref_count = 1;
1873   /* consistent default for push based mode */
1874   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1875   return stream;
1876 }
1877
1878 static gboolean
1879 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1880 {
1881   GstStructure *structure;
1882   const gchar *variant;
1883   const GstCaps *mediacaps = NULL;
1884
1885   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1886
1887   structure = gst_caps_get_structure (caps, 0);
1888   variant = gst_structure_get_string (structure, "variant");
1889
1890   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1891     QtDemuxStream *stream;
1892     const GValue *value;
1893
1894     demux->fragmented = TRUE;
1895     demux->mss_mode = TRUE;
1896
1897     if (QTDEMUX_N_STREAMS (demux) > 1) {
1898       /* can't do this, we can only renegotiate for another mss format */
1899       return FALSE;
1900     }
1901
1902     value = gst_structure_get_value (structure, "media-caps");
1903     /* create stream */
1904     if (value) {
1905       const GValue *timescale_v;
1906
1907       /* TODO update when stream changes during playback */
1908
1909       if (QTDEMUX_N_STREAMS (demux) == 0) {
1910         stream = _create_stream (demux, 1);
1911         g_ptr_array_add (demux->active_streams, stream);
1912         /* mss has no stsd/stsd entry, use id 0 as default */
1913         stream->stsd_entries_length = 1;
1914         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1915         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1916       } else {
1917         stream = QTDEMUX_NTH_STREAM (demux, 0);
1918       }
1919
1920       timescale_v = gst_structure_get_value (structure, "timescale");
1921       if (timescale_v) {
1922         stream->timescale = g_value_get_uint64 (timescale_v);
1923       } else {
1924         /* default mss timescale */
1925         stream->timescale = 10000000;
1926       }
1927       demux->timescale = stream->timescale;
1928
1929       mediacaps = gst_value_get_caps (value);
1930       if (!CUR_STREAM (stream)->caps
1931           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1932         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1933             mediacaps);
1934         stream->new_caps = TRUE;
1935       }
1936       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1937       structure = gst_caps_get_structure (mediacaps, 0);
1938       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1939         stream->subtype = FOURCC_vide;
1940
1941         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1942         gst_structure_get_int (structure, "height",
1943             &CUR_STREAM (stream)->height);
1944         gst_structure_get_fraction (structure, "framerate",
1945             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1946       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1947         gint rate = 0;
1948         stream->subtype = FOURCC_soun;
1949         gst_structure_get_int (structure, "channels",
1950             &CUR_STREAM (stream)->n_channels);
1951         gst_structure_get_int (structure, "rate", &rate);
1952         CUR_STREAM (stream)->rate = rate;
1953       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1954         if (gst_structure_has_field (structure, "original-media-type")) {
1955           const gchar *media_type =
1956               gst_structure_get_string (structure, "original-media-type");
1957           if (g_str_has_prefix (media_type, "video")) {
1958             stream->subtype = FOURCC_vide;
1959           } else if (g_str_has_prefix (media_type, "audio")) {
1960             stream->subtype = FOURCC_soun;
1961           }
1962         }
1963       }
1964     }
1965     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1966   } else {
1967     demux->mss_mode = FALSE;
1968   }
1969
1970   return TRUE;
1971 }
1972
1973 static void
1974 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1975 {
1976   gint i;
1977
1978   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1979   gst_pad_stop_task (qtdemux->sinkpad);
1980
1981   if (hard || qtdemux->upstream_format_is_time) {
1982     qtdemux->state = QTDEMUX_STATE_INITIAL;
1983     qtdemux->neededbytes = 16;
1984     qtdemux->todrop = 0;
1985     qtdemux->pullbased = FALSE;
1986     g_clear_pointer (&qtdemux->redirect_location, g_free);
1987     qtdemux->first_mdat = -1;
1988     qtdemux->header_size = 0;
1989     qtdemux->mdatoffset = -1;
1990     qtdemux->restoredata_offset = -1;
1991     if (qtdemux->mdatbuffer)
1992       gst_buffer_unref (qtdemux->mdatbuffer);
1993     if (qtdemux->restoredata_buffer)
1994       gst_buffer_unref (qtdemux->restoredata_buffer);
1995     qtdemux->mdatbuffer = NULL;
1996     qtdemux->restoredata_buffer = NULL;
1997     qtdemux->mdatleft = 0;
1998     qtdemux->mdatsize = 0;
1999     if (qtdemux->comp_brands)
2000       gst_buffer_unref (qtdemux->comp_brands);
2001     qtdemux->comp_brands = NULL;
2002     qtdemux->last_moov_offset = -1;
2003     if (qtdemux->moov_node_compressed) {
2004       g_node_destroy (qtdemux->moov_node_compressed);
2005       if (qtdemux->moov_node)
2006         g_free (qtdemux->moov_node->data);
2007     }
2008     qtdemux->moov_node_compressed = NULL;
2009     if (qtdemux->moov_node)
2010       g_node_destroy (qtdemux->moov_node);
2011     qtdemux->moov_node = NULL;
2012     if (qtdemux->tag_list)
2013       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2014     qtdemux->tag_list = gst_tag_list_new_empty ();
2015     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2016 #if 0
2017     if (qtdemux->element_index)
2018       gst_object_unref (qtdemux->element_index);
2019     qtdemux->element_index = NULL;
2020 #endif
2021     qtdemux->major_brand = 0;
2022     qtdemux->upstream_format_is_time = FALSE;
2023     qtdemux->upstream_seekable = FALSE;
2024     qtdemux->upstream_size = 0;
2025
2026     qtdemux->fragment_start = -1;
2027     qtdemux->fragment_start_offset = -1;
2028     qtdemux->duration = 0;
2029     qtdemux->moof_offset = 0;
2030     qtdemux->chapters_track_id = 0;
2031     qtdemux->have_group_id = FALSE;
2032     qtdemux->group_id = G_MAXUINT;
2033
2034     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2035         NULL);
2036     g_queue_clear (&qtdemux->protection_event_queue);
2037
2038     qtdemux->received_seek = FALSE;
2039     qtdemux->first_moof_already_parsed = FALSE;
2040   }
2041   qtdemux->offset = 0;
2042   gst_adapter_clear (qtdemux->adapter);
2043   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2044   qtdemux->need_segment = TRUE;
2045
2046   if (hard) {
2047     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2048     qtdemux->trickmode_interval = 0;
2049     g_ptr_array_set_size (qtdemux->active_streams, 0);
2050     g_ptr_array_set_size (qtdemux->old_streams, 0);
2051     qtdemux->n_video_streams = 0;
2052     qtdemux->n_audio_streams = 0;
2053     qtdemux->n_sub_streams = 0;
2054     qtdemux->exposed = FALSE;
2055     qtdemux->fragmented = FALSE;
2056     qtdemux->mss_mode = FALSE;
2057     gst_caps_replace (&qtdemux->media_caps, NULL);
2058     qtdemux->timescale = 0;
2059     qtdemux->got_moov = FALSE;
2060     qtdemux->cenc_aux_info_offset = 0;
2061     qtdemux->cenc_aux_info_sizes = NULL;
2062     qtdemux->cenc_aux_sample_count = 0;
2063     if (qtdemux->protection_system_ids) {
2064       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2065       qtdemux->protection_system_ids = NULL;
2066     }
2067     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2068         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2069         GST_BIN_FLAG_STREAMS_AWARE);
2070
2071     if (qtdemux->preferred_protection_system_id) {
2072       g_free (qtdemux->preferred_protection_system_id);
2073       qtdemux->preferred_protection_system_id = NULL;
2074     }
2075   } else if (qtdemux->mss_mode) {
2076     gst_flow_combiner_reset (qtdemux->flowcombiner);
2077     g_ptr_array_foreach (qtdemux->active_streams,
2078         (GFunc) gst_qtdemux_stream_clear, NULL);
2079   } else {
2080     gst_flow_combiner_reset (qtdemux->flowcombiner);
2081     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2082       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2083       stream->sent_eos = FALSE;
2084       stream->time_position = 0;
2085       stream->accumulated_base = 0;
2086       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2087     }
2088   }
2089 }
2090
2091
2092 /* Maps the @segment to the qt edts internal segments and pushes
2093  * the corresponding segment event.
2094  *
2095  * If it ends up being at a empty segment, a gap will be pushed and the next
2096  * edts segment will be activated in sequence.
2097  *
2098  * To be used in push-mode only */
2099 static void
2100 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2101 {
2102   gint i, iter;
2103
2104   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2105     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2106
2107     stream->time_position = segment->start;
2108
2109     /* in push mode we should be guaranteed that we will have empty segments
2110      * at the beginning and then one segment after, other scenarios are not
2111      * supported and are discarded when parsing the edts */
2112     for (i = 0; i < stream->n_segments; i++) {
2113       if (stream->segments[i].stop_time > segment->start) {
2114         /* push the empty segment and move to the next one */
2115         gst_qtdemux_activate_segment (qtdemux, stream, i,
2116             stream->time_position);
2117         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2118           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2119               stream->time_position);
2120
2121           /* accumulate previous segments */
2122           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2123             stream->accumulated_base +=
2124                 (stream->segment.stop -
2125                 stream->segment.start) / ABS (stream->segment.rate);
2126           continue;
2127         }
2128
2129         g_assert (i == stream->n_segments - 1);
2130       }
2131     }
2132   }
2133 }
2134
2135 static void
2136 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2137     GPtrArray * src)
2138 {
2139   guint i;
2140   guint len;
2141
2142   len = src->len;
2143
2144   if (len == 0)
2145     return;
2146
2147   for (i = 0; i < len; i++) {
2148     QtDemuxStream *stream = g_ptr_array_index (src, i);
2149
2150 #ifndef GST_DISABLE_GST_DEBUG
2151     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2152         stream, GST_STR_NULL (stream->stream_id), dest);
2153 #endif
2154     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2155   }
2156
2157   g_ptr_array_set_size (src, 0);
2158 }
2159
2160 static gboolean
2161 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2162     GstEvent * event)
2163 {
2164   GstQTDemux *demux = GST_QTDEMUX (parent);
2165   gboolean res = TRUE;
2166
2167   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2168
2169   switch (GST_EVENT_TYPE (event)) {
2170     case GST_EVENT_SEGMENT:
2171     {
2172       gint64 offset = 0;
2173       QtDemuxStream *stream;
2174       gint idx;
2175       GstSegment segment;
2176
2177       /* some debug output */
2178       gst_event_copy_segment (event, &segment);
2179       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2180           &segment);
2181
2182       if (segment.format == GST_FORMAT_TIME) {
2183         demux->upstream_format_is_time = TRUE;
2184         demux->segment_seqnum = gst_event_get_seqnum (event);
2185       } else {
2186         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2187             "not in time format");
2188
2189         /* chain will send initial newsegment after pads have been added */
2190         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2191           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2192           goto exit;
2193         }
2194       }
2195
2196       /* check if this matches a time seek we received previously
2197        * FIXME for backwards compatibility reasons we use the
2198        * seek_offset here to compare. In the future we might want to
2199        * change this to use the seqnum as it uniquely should identify
2200        * the segment that corresponds to the seek. */
2201       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2202           ", received segment offset %" G_GINT64_FORMAT,
2203           demux->seek_offset, segment.start);
2204       if (segment.format == GST_FORMAT_BYTES
2205           && demux->seek_offset == segment.start) {
2206         GST_OBJECT_LOCK (demux);
2207         offset = segment.start;
2208
2209         segment.format = GST_FORMAT_TIME;
2210         segment.start = demux->push_seek_start;
2211         segment.stop = demux->push_seek_stop;
2212         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2213             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2214             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2215         GST_OBJECT_UNLOCK (demux);
2216       }
2217
2218       /* we only expect a BYTE segment, e.g. following a seek */
2219       if (segment.format == GST_FORMAT_BYTES) {
2220         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2221           offset = segment.start;
2222
2223           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2224               NULL, (gint64 *) & segment.start);
2225           if ((gint64) segment.start < 0)
2226             segment.start = 0;
2227         }
2228         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2229           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2230               NULL, (gint64 *) & segment.stop);
2231           /* keyframe seeking should already arrange for start >= stop,
2232            * but make sure in other rare cases */
2233           segment.stop = MAX (segment.stop, segment.start);
2234         }
2235       } else if (segment.format == GST_FORMAT_TIME) {
2236         /* push all data on the adapter before starting this
2237          * new segment */
2238         gst_qtdemux_process_adapter (demux, TRUE);
2239       } else {
2240         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2241         goto exit;
2242       }
2243
2244       /* We shouldn't modify upstream driven TIME FORMAT segment */
2245       if (!demux->upstream_format_is_time) {
2246         /* accept upstream's notion of segment and distribute along */
2247         segment.format = GST_FORMAT_TIME;
2248         segment.position = segment.time = segment.start;
2249         segment.duration = demux->segment.duration;
2250         segment.base = gst_segment_to_running_time (&demux->segment,
2251             GST_FORMAT_TIME, demux->segment.position);
2252       }
2253
2254       gst_segment_copy_into (&segment, &demux->segment);
2255       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2256
2257       /* map segment to internal qt segments and push on each stream */
2258       if (QTDEMUX_N_STREAMS (demux)) {
2259         demux->need_segment = TRUE;
2260         gst_qtdemux_check_send_pending_segment (demux);
2261       }
2262
2263       /* clear leftover in current segment, if any */
2264       gst_adapter_clear (demux->adapter);
2265
2266       /* set up streaming thread */
2267       demux->offset = offset;
2268       if (demux->upstream_format_is_time) {
2269         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2270             "set values to restart reading from a new atom");
2271         demux->neededbytes = 16;
2272         demux->todrop = 0;
2273       } else {
2274         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2275             NULL);
2276         if (stream) {
2277           demux->todrop = stream->samples[idx].offset - offset;
2278           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2279         } else {
2280           /* set up for EOS */
2281           demux->neededbytes = -1;
2282           demux->todrop = 0;
2283         }
2284       }
2285     exit:
2286       gst_event_unref (event);
2287       res = TRUE;
2288       goto drop;
2289     }
2290     case GST_EVENT_FLUSH_START:
2291     {
2292       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2293         gst_event_unref (event);
2294         goto drop;
2295       }
2296       QTDEMUX_EXPOSE_LOCK (demux);
2297       res = gst_pad_event_default (demux->sinkpad, parent, event);
2298       QTDEMUX_EXPOSE_UNLOCK (demux);
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_STOP:
2302     {
2303       guint64 dur;
2304
2305       dur = demux->segment.duration;
2306       gst_qtdemux_reset (demux, FALSE);
2307       demux->segment.duration = dur;
2308
2309       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2310         gst_event_unref (event);
2311         goto drop;
2312       }
2313       break;
2314     }
2315     case GST_EVENT_EOS:
2316       /* If we are in push mode, and get an EOS before we've seen any streams,
2317        * then error out - we have nowhere to send the EOS */
2318       if (!demux->pullbased) {
2319         gint i;
2320         gboolean has_valid_stream = FALSE;
2321         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2322           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2323             has_valid_stream = TRUE;
2324             break;
2325           }
2326         }
2327         if (!has_valid_stream)
2328           gst_qtdemux_post_no_playable_stream_error (demux);
2329         else {
2330           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2331               (guint) gst_adapter_available (demux->adapter));
2332           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2333             res = FALSE;
2334           }
2335         }
2336       }
2337       break;
2338     case GST_EVENT_CAPS:{
2339       GstCaps *caps = NULL;
2340
2341       gst_event_parse_caps (event, &caps);
2342       gst_qtdemux_setcaps (demux, caps);
2343       res = TRUE;
2344       gst_event_unref (event);
2345       goto drop;
2346     }
2347     case GST_EVENT_PROTECTION:
2348     {
2349       const gchar *system_id = NULL;
2350
2351       gst_event_parse_protection (event, &system_id, NULL, NULL);
2352       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2353           system_id);
2354       gst_qtdemux_append_protection_system_id (demux, system_id);
2355       /* save the event for later, for source pads that have not been created */
2356       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2357       /* send it to all pads that already exist */
2358       gst_qtdemux_push_event (demux, event);
2359       res = TRUE;
2360       goto drop;
2361     }
2362     case GST_EVENT_STREAM_START:
2363     {
2364       res = TRUE;
2365       gst_event_unref (event);
2366
2367       /* Drain all the buffers */
2368       gst_qtdemux_process_adapter (demux, TRUE);
2369       gst_qtdemux_reset (demux, FALSE);
2370       /* We expect new moov box after new stream-start event */
2371       if (demux->exposed) {
2372         gst_qtdemux_stream_concat (demux,
2373             demux->old_streams, demux->active_streams);
2374       }
2375
2376       goto drop;
2377     }
2378     default:
2379       break;
2380   }
2381
2382   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2383
2384 drop:
2385   return res;
2386 }
2387
2388 static gboolean
2389 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2390     GstQuery * query)
2391 {
2392   GstQTDemux *demux = GST_QTDEMUX (parent);
2393   gboolean res = FALSE;
2394
2395   switch (GST_QUERY_TYPE (query)) {
2396     case GST_QUERY_BITRATE:
2397     {
2398       GstClockTime duration;
2399
2400       /* populate demux->upstream_size if not done yet */
2401       gst_qtdemux_check_seekability (demux);
2402
2403       if (demux->upstream_size != -1
2404           && gst_qtdemux_get_duration (demux, &duration)) {
2405         guint bitrate =
2406             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2407             duration);
2408
2409         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2410             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2411             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2412
2413         /* TODO: better results based on ranges/index tables */
2414         gst_query_set_bitrate (query, bitrate);
2415         res = TRUE;
2416       }
2417       break;
2418     }
2419     default:
2420       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2421       break;
2422   }
2423
2424   return res;
2425 }
2426
2427
2428 #if 0
2429 static void
2430 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2431 {
2432   GstQTDemux *demux = GST_QTDEMUX (element);
2433
2434   GST_OBJECT_LOCK (demux);
2435   if (demux->element_index)
2436     gst_object_unref (demux->element_index);
2437   if (index) {
2438     demux->element_index = gst_object_ref (index);
2439   } else {
2440     demux->element_index = NULL;
2441   }
2442   GST_OBJECT_UNLOCK (demux);
2443   /* object lock might be taken again */
2444   if (index)
2445     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2446   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2447       demux->element_index, demux->index_id);
2448 }
2449
2450 static GstIndex *
2451 gst_qtdemux_get_index (GstElement * element)
2452 {
2453   GstIndex *result = NULL;
2454   GstQTDemux *demux = GST_QTDEMUX (element);
2455
2456   GST_OBJECT_LOCK (demux);
2457   if (demux->element_index)
2458     result = gst_object_ref (demux->element_index);
2459   GST_OBJECT_UNLOCK (demux);
2460
2461   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2462
2463   return result;
2464 }
2465 #endif
2466
2467 static void
2468 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2469 {
2470   g_free ((gpointer) stream->stco.data);
2471   stream->stco.data = NULL;
2472   g_free ((gpointer) stream->stsz.data);
2473   stream->stsz.data = NULL;
2474   g_free ((gpointer) stream->stsc.data);
2475   stream->stsc.data = NULL;
2476   g_free ((gpointer) stream->stts.data);
2477   stream->stts.data = NULL;
2478   g_free ((gpointer) stream->stss.data);
2479   stream->stss.data = NULL;
2480   g_free ((gpointer) stream->stps.data);
2481   stream->stps.data = NULL;
2482   g_free ((gpointer) stream->ctts.data);
2483   stream->ctts.data = NULL;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2488 {
2489   g_free (stream->segments);
2490   stream->segments = NULL;
2491   stream->segment_index = -1;
2492   stream->accumulated_base = 0;
2493 }
2494
2495 static void
2496 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2497 {
2498   g_free (stream->samples);
2499   stream->samples = NULL;
2500   gst_qtdemux_stbl_free (stream);
2501
2502   /* fragments */
2503   g_free (stream->ra_entries);
2504   stream->ra_entries = NULL;
2505   stream->n_ra_entries = 0;
2506
2507   stream->sample_index = -1;
2508   stream->stbl_index = -1;
2509   stream->n_samples = 0;
2510   stream->time_position = 0;
2511
2512   stream->n_samples_moof = 0;
2513   stream->duration_moof = 0;
2514   stream->duration_last_moof = 0;
2515 }
2516
2517 static void
2518 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2519 {
2520   gint i;
2521   if (stream->allocator)
2522     gst_object_unref (stream->allocator);
2523   while (stream->buffers) {
2524     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2525     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2526   }
2527   for (i = 0; i < stream->stsd_entries_length; i++) {
2528     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2529     if (entry->rgb8_palette) {
2530       gst_memory_unref (entry->rgb8_palette);
2531       entry->rgb8_palette = NULL;
2532     }
2533     entry->sparse = FALSE;
2534   }
2535
2536   if (stream->stream_tags)
2537     gst_tag_list_unref (stream->stream_tags);
2538
2539   stream->stream_tags = gst_tag_list_new_empty ();
2540   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2541   g_free (stream->redirect_uri);
2542   stream->redirect_uri = NULL;
2543   stream->sent_eos = FALSE;
2544   stream->protected = FALSE;
2545   if (stream->protection_scheme_info) {
2546     if (stream->protection_scheme_type == FOURCC_cenc
2547         || stream->protection_scheme_type == FOURCC_cbcs) {
2548       QtDemuxCencSampleSetInfo *info =
2549           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2550       if (info->default_properties)
2551         gst_structure_free (info->default_properties);
2552       if (info->crypto_info)
2553         g_ptr_array_free (info->crypto_info, TRUE);
2554     }
2555     if (stream->protection_scheme_type == FOURCC_aavd) {
2556       QtDemuxAavdEncryptionInfo *info =
2557           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2558       if (info->default_properties)
2559         gst_structure_free (info->default_properties);
2560     }
2561     g_free (stream->protection_scheme_info);
2562     stream->protection_scheme_info = NULL;
2563   }
2564   stream->protection_scheme_type = 0;
2565   stream->protection_scheme_version = 0;
2566   g_queue_foreach (&stream->protection_scheme_event_queue,
2567       (GFunc) gst_event_unref, NULL);
2568   g_queue_clear (&stream->protection_scheme_event_queue);
2569   gst_qtdemux_stream_flush_segments_data (stream);
2570   gst_qtdemux_stream_flush_samples_data (stream);
2571 }
2572
2573 static void
2574 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2575 {
2576   gint i;
2577   gst_qtdemux_stream_clear (stream);
2578   for (i = 0; i < stream->stsd_entries_length; i++) {
2579     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2580     if (entry->caps) {
2581       gst_caps_unref (entry->caps);
2582       entry->caps = NULL;
2583     }
2584   }
2585   g_free (stream->stsd_entries);
2586   stream->stsd_entries = NULL;
2587   stream->stsd_entries_length = 0;
2588 }
2589
2590 static QtDemuxStream *
2591 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2592 {
2593   g_atomic_int_add (&stream->ref_count, 1);
2594
2595   return stream;
2596 }
2597
2598 static void
2599 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2600 {
2601   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2602     gst_qtdemux_stream_reset (stream);
2603     gst_tag_list_unref (stream->stream_tags);
2604     if (stream->pad) {
2605       GstQTDemux *demux = stream->demux;
2606       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2607       GST_OBJECT_LOCK (demux);
2608       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2609       GST_OBJECT_UNLOCK (demux);
2610     }
2611     g_free (stream->stream_id);
2612     g_free (stream);
2613   }
2614 }
2615
2616 static GstStateChangeReturn
2617 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2618 {
2619   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2620   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2621
2622   switch (transition) {
2623     case GST_STATE_CHANGE_READY_TO_PAUSED:
2624       gst_qtdemux_reset (qtdemux, TRUE);
2625       break;
2626     default:
2627       break;
2628   }
2629
2630   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2631
2632   switch (transition) {
2633     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2634       gst_qtdemux_reset (qtdemux, TRUE);
2635       break;
2636     }
2637     default:
2638       break;
2639   }
2640
2641   return result;
2642 }
2643
2644 static void
2645 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2646 {
2647   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2648
2649   g_return_if_fail (GST_IS_CONTEXT (context));
2650
2651   if (gst_context_has_context_type (context,
2652           "drm-preferred-decryption-system-id")) {
2653     const GstStructure *s;
2654
2655     s = gst_context_get_structure (context);
2656     g_free (qtdemux->preferred_protection_system_id);
2657     qtdemux->preferred_protection_system_id =
2658         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2659     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2660         qtdemux->preferred_protection_system_id);
2661   }
2662
2663   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2664 }
2665
2666 static void
2667 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2668 {
2669   /* counts as header data */
2670   qtdemux->header_size += length;
2671
2672   /* only consider at least a sufficiently complete ftyp atom */
2673   if (length >= 20) {
2674     GstBuffer *buf;
2675
2676     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2677     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2678         GST_FOURCC_ARGS (qtdemux->major_brand));
2679     if (qtdemux->comp_brands)
2680       gst_buffer_unref (qtdemux->comp_brands);
2681     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2682     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2683   }
2684 }
2685
2686 static void
2687 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2688     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2689     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2690     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2691     const guint8 * constant_iv)
2692 {
2693   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2694   gst_buffer_fill (kid_buf, 0, kid, 16);
2695   if (info->default_properties)
2696     gst_structure_free (info->default_properties);
2697   info->default_properties =
2698       gst_structure_new ("application/x-cenc",
2699       "iv_size", G_TYPE_UINT, iv_size,
2700       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2701       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2702   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2703       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2704   gst_buffer_unref (kid_buf);
2705   if (protection_scheme_type == FOURCC_cbcs) {
2706     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2707       gst_structure_set (info->default_properties, "crypt_byte_block",
2708           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2709           skip_byte_block, NULL);
2710     }
2711     if (constant_iv != NULL) {
2712       GstBuffer *constant_iv_buf =
2713           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2714       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2715       gst_structure_set (info->default_properties, "constant_iv_size",
2716           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2717           NULL);
2718       gst_buffer_unref (constant_iv_buf);
2719     }
2720     gst_structure_set (info->default_properties, "cipher-mode",
2721         G_TYPE_STRING, "cbcs", NULL);
2722   } else {
2723     gst_structure_set (info->default_properties, "cipher-mode",
2724         G_TYPE_STRING, "cenc", NULL);
2725   }
2726 }
2727
2728 static gboolean
2729 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2730     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2731 {
2732   guint32 algorithm_id = 0;
2733   const guint8 *kid;
2734   gboolean is_encrypted = TRUE;
2735   guint8 iv_size = 8;
2736
2737   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2738     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2739     return FALSE;
2740   }
2741
2742   algorithm_id >>= 8;
2743   if (algorithm_id == 0) {
2744     is_encrypted = FALSE;
2745   } else if (algorithm_id == 1) {
2746     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2747   } else if (algorithm_id == 2) {
2748     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2749   }
2750
2751   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2752     return FALSE;
2753
2754   if (!gst_byte_reader_get_data (br, 16, &kid))
2755     return FALSE;
2756
2757   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2758       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2759   gst_structure_set (info->default_properties, "piff_algorithm_id",
2760       G_TYPE_UINT, algorithm_id, NULL);
2761   return TRUE;
2762 }
2763
2764
2765 static void
2766 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2767     guint offset)
2768 {
2769   GstByteReader br;
2770   guint8 version;
2771   guint32 flags = 0;
2772   guint i;
2773   guint iv_size = 8;
2774   QtDemuxStream *stream;
2775   GstStructure *structure;
2776   QtDemuxCencSampleSetInfo *ss_info = NULL;
2777   const gchar *system_id;
2778   gboolean uses_sub_sample_encryption = FALSE;
2779   guint32 sample_count;
2780
2781   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2782     return;
2783
2784   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2785
2786   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2787   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2788     GST_WARNING_OBJECT (qtdemux,
2789         "Attempting PIFF box parsing on an unencrypted stream.");
2790     return;
2791   }
2792
2793   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2794       G_TYPE_STRING, &system_id, NULL);
2795   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2796
2797   stream->protected = TRUE;
2798   stream->protection_scheme_type = FOURCC_cenc;
2799
2800   if (!stream->protection_scheme_info)
2801     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2802
2803   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2804   if (!ss_info->default_properties) {
2805     ss_info->default_properties =
2806         gst_structure_new ("application/x-cenc",
2807         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2808         NULL);
2809
2810   }
2811
2812   if (ss_info->crypto_info) {
2813     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2814     g_ptr_array_free (ss_info->crypto_info, TRUE);
2815     ss_info->crypto_info = NULL;
2816   }
2817
2818   /* skip UUID */
2819   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2820
2821   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2822     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2823     return;
2824   }
2825
2826   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2827     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2828     return;
2829   }
2830
2831   if ((flags & 0x000001)) {
2832     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2833             &br))
2834       return;
2835   } else if ((flags & 0x000002)) {
2836     uses_sub_sample_encryption = TRUE;
2837   }
2838
2839   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2840           &iv_size)) {
2841     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2842     return;
2843   }
2844
2845   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2846     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2847     return;
2848   }
2849
2850   ss_info->crypto_info =
2851       g_ptr_array_new_full (sample_count,
2852       (GDestroyNotify) qtdemux_gst_structure_free);
2853
2854   for (i = 0; i < sample_count; ++i) {
2855     GstStructure *properties;
2856     guint8 *data;
2857     GstBuffer *buf;
2858
2859     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2860     if (properties == NULL) {
2861       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2862       qtdemux->cenc_aux_sample_count = i;
2863       return;
2864     }
2865
2866     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2867       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2868       gst_structure_free (properties);
2869       qtdemux->cenc_aux_sample_count = i;
2870       return;
2871     }
2872     buf = gst_buffer_new_wrapped (data, iv_size);
2873     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2874     gst_buffer_unref (buf);
2875
2876     if (uses_sub_sample_encryption) {
2877       guint16 n_subsamples;
2878       const GValue *kid_buf_value;
2879
2880       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2881           || n_subsamples == 0) {
2882         GST_ERROR_OBJECT (qtdemux,
2883             "failed to get subsample count for sample %u", i);
2884         gst_structure_free (properties);
2885         qtdemux->cenc_aux_sample_count = i;
2886         return;
2887       }
2888       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2889       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2890         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2891             i);
2892         gst_structure_free (properties);
2893         qtdemux->cenc_aux_sample_count = i;
2894         return;
2895       }
2896       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2897
2898       kid_buf_value =
2899           gst_structure_get_value (ss_info->default_properties, "kid");
2900
2901       gst_structure_set (properties,
2902           "subsample_count", G_TYPE_UINT, n_subsamples,
2903           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2904       gst_structure_set_value (properties, "kid", kid_buf_value);
2905       gst_buffer_unref (buf);
2906     } else {
2907       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2908     }
2909
2910     g_ptr_array_add (ss_info->crypto_info, properties);
2911   }
2912
2913   qtdemux->cenc_aux_sample_count = sample_count;
2914 }
2915
2916 static void
2917 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2918 {
2919   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2920     0x97, 0xA9, 0x42, 0xE8,
2921     0x9C, 0x71, 0x99, 0x94,
2922     0x91, 0xE3, 0xAF, 0xAC
2923   };
2924   static const guint8 playready_uuid[] = {
2925     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2926     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2927   };
2928
2929   static const guint8 piff_sample_encryption_uuid[] = {
2930     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2931     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2932   };
2933
2934   guint offset;
2935
2936   /* counts as header data */
2937   qtdemux->header_size += length;
2938
2939   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2940
2941   if (length <= offset + 16) {
2942     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2943     return;
2944   }
2945
2946   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2947     GstBuffer *buf;
2948     GstTagList *taglist;
2949
2950     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2951         length - offset - 16, NULL);
2952     taglist = gst_tag_list_from_xmp_buffer (buf);
2953     gst_buffer_unref (buf);
2954
2955     /* make sure we have a usable taglist */
2956     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2957
2958     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2959
2960   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2961     int len;
2962     const gunichar2 *s_utf16;
2963     char *contents;
2964
2965     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2966     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2967     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2968     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2969
2970     g_free (contents);
2971
2972     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2973         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2974         (NULL));
2975   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2976     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2977   } else {
2978     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2979         GST_READ_UINT32_LE (buffer + offset),
2980         GST_READ_UINT32_LE (buffer + offset + 4),
2981         GST_READ_UINT32_LE (buffer + offset + 8),
2982         GST_READ_UINT32_LE (buffer + offset + 12));
2983   }
2984 }
2985
2986 static void
2987 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2988 {
2989   GstSidxParser sidx_parser;
2990   GstIsoffParserResult res;
2991   guint consumed;
2992
2993   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2994
2995   res =
2996       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2997       &consumed);
2998   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2999   if (res == GST_ISOFF_QT_PARSER_DONE) {
3000     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3001   }
3002   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3003 }
3004
3005 /* caller verifies at least 8 bytes in buf */
3006 static void
3007 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3008     guint64 * plength, guint32 * pfourcc)
3009 {
3010   guint64 length;
3011   guint32 fourcc;
3012
3013   length = QT_UINT32 (data);
3014   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3015   fourcc = QT_FOURCC (data + 4);
3016   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3017
3018   if (length == 0) {
3019     length = G_MAXUINT64;
3020   } else if (length == 1 && size >= 16) {
3021     /* this means we have an extended size, which is the 64 bit value of
3022      * the next 8 bytes */
3023     length = QT_UINT64 (data + 8);
3024     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3025   }
3026
3027   if (plength)
3028     *plength = length;
3029   if (pfourcc)
3030     *pfourcc = fourcc;
3031 }
3032
3033 static gboolean
3034 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3035 {
3036   guint32 version = 0;
3037   GstClockTime duration = 0;
3038
3039   if (!gst_byte_reader_get_uint32_be (br, &version))
3040     goto failed;
3041
3042   version >>= 24;
3043   if (version == 1) {
3044     if (!gst_byte_reader_get_uint64_be (br, &duration))
3045       goto failed;
3046   } else {
3047     guint32 dur = 0;
3048
3049     if (!gst_byte_reader_get_uint32_be (br, &dur))
3050       goto failed;
3051     duration = dur;
3052   }
3053
3054   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3055   qtdemux->duration = duration;
3056
3057   return TRUE;
3058
3059 failed:
3060   {
3061     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3062     return FALSE;
3063   }
3064 }
3065
3066 static gboolean
3067 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3068     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3069 {
3070   if (!stream->parsed_trex && qtdemux->moov_node) {
3071     GNode *mvex, *trex;
3072     GstByteReader trex_data;
3073
3074     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3075     if (mvex) {
3076       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3077           &trex_data);
3078       while (trex) {
3079         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3080
3081         /* skip version/flags */
3082         if (!gst_byte_reader_skip (&trex_data, 4))
3083           goto next;
3084         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3085           goto next;
3086         if (id != stream->track_id)
3087           goto next;
3088         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3089           goto next;
3090         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3091           goto next;
3092         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3093           goto next;
3094         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3095           goto next;
3096
3097         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3098             "duration %d,  size %d, flags 0x%x", stream->track_id,
3099             dur, size, flags);
3100
3101         stream->parsed_trex = TRUE;
3102         stream->def_sample_description_index = sdi;
3103         stream->def_sample_duration = dur;
3104         stream->def_sample_size = size;
3105         stream->def_sample_flags = flags;
3106
3107       next:
3108         /* iterate all siblings */
3109         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3110             &trex_data);
3111       }
3112     }
3113   }
3114
3115   *ds_duration = stream->def_sample_duration;
3116   *ds_size = stream->def_sample_size;
3117   *ds_flags = stream->def_sample_flags;
3118
3119   /* even then, above values are better than random ... */
3120   if (G_UNLIKELY (!stream->parsed_trex)) {
3121     GST_WARNING_OBJECT (qtdemux,
3122         "failed to find fragment defaults for stream %d", stream->track_id);
3123     return FALSE;
3124   }
3125
3126   return TRUE;
3127 }
3128
3129 /* This method should be called whenever a more accurate duration might
3130  * have been found. It will update all relevant variables if/where needed
3131  */
3132 static void
3133 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3134 {
3135   guint i;
3136   guint64 movdur;
3137   GstClockTime prevdur;
3138
3139   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3140
3141   if (movdur > qtdemux->duration) {
3142     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3143     GST_DEBUG_OBJECT (qtdemux,
3144         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3145         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3146     qtdemux->duration = movdur;
3147     GST_DEBUG_OBJECT (qtdemux,
3148         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3149         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3150         GST_TIME_ARGS (qtdemux->segment.stop));
3151     if (qtdemux->segment.duration == prevdur) {
3152       /* If the current segment has duration/stop identical to previous duration
3153        * update them also (because they were set at that point in time with
3154        * the wrong duration */
3155       /* We convert the value *from* the timescale version to avoid rounding errors */
3156       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3157       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3158       qtdemux->segment.duration = fixeddur;
3159       qtdemux->segment.stop = fixeddur;
3160     }
3161   }
3162
3163   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3164     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3165
3166     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3167     if (movdur > stream->duration) {
3168       GST_DEBUG_OBJECT (qtdemux,
3169           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3170           GST_TIME_ARGS (duration));
3171       stream->duration = movdur;
3172       /* internal duration tracking state has been updated above, so */
3173       /* preserve an open-ended dummy segment rather than repeatedly updating
3174        * it and spamming downstream accordingly with segment events */
3175       /* also mangle the edit list end time when fragmented with a single edit
3176        * list that may only cover any non-fragmented data */
3177       if ((stream->dummy_segment ||
3178               (qtdemux->fragmented && stream->n_segments == 1)) &&
3179           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3180         /* Update all dummy values to new duration */
3181         stream->segments[0].stop_time = duration;
3182         stream->segments[0].duration = duration;
3183         stream->segments[0].media_stop = duration;
3184
3185         /* let downstream know we possibly have a new stop time */
3186         if (stream->segment_index != -1) {
3187           GstClockTime pos;
3188
3189           if (qtdemux->segment.rate >= 0) {
3190             pos = stream->segment.start;
3191           } else {
3192             pos = stream->segment.stop;
3193           }
3194
3195           gst_qtdemux_stream_update_segment (qtdemux, stream,
3196               stream->segment_index, pos, NULL, NULL);
3197         }
3198       }
3199     }
3200   }
3201 }
3202
3203 static gboolean
3204 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3205     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3206     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3207     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3208     gboolean has_tfdt)
3209 {
3210   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3211   guint64 timestamp;
3212   gint32 data_offset = 0;
3213   guint8 version;
3214   guint32 flags = 0, first_flags = 0, samples_count = 0;
3215   gint i;
3216   guint8 *data;
3217   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3218   QtDemuxSample *sample;
3219   gboolean ismv = FALSE;
3220   gint64 initial_offset;
3221   gint32 min_ct = 0;
3222
3223   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3224       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3225       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3226       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3227
3228   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3229     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3230     return TRUE;
3231   }
3232
3233   /* presence of stss or not can't really tell us much,
3234    * and flags and so on tend to be marginally reliable in these files */
3235   if (stream->subtype == FOURCC_soun) {
3236     GST_DEBUG_OBJECT (qtdemux,
3237         "sound track in fragmented file; marking all keyframes");
3238     stream->all_keyframe = TRUE;
3239   }
3240
3241   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3242       !gst_byte_reader_get_uint24_be (trun, &flags))
3243     goto fail;
3244
3245   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3246     goto fail;
3247
3248   if (flags & TR_DATA_OFFSET) {
3249     /* note this is really signed */
3250     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3251       goto fail;
3252     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3253     /* default base offset = first byte of moof */
3254     if (*base_offset == -1) {
3255       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3256       *base_offset = moof_offset;
3257     }
3258     *running_offset = *base_offset + data_offset;
3259   } else {
3260     /* if no offset at all, that would mean data starts at moof start,
3261      * which is a bit wrong and is ismv crappy way, so compensate
3262      * assuming data is in mdat following moof */
3263     if (*base_offset == -1) {
3264       *base_offset = moof_offset + moof_length + 8;
3265       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3266       ismv = TRUE;
3267     }
3268     if (*running_offset == -1)
3269       *running_offset = *base_offset;
3270   }
3271
3272   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3273       *running_offset);
3274   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3275       data_offset, flags, samples_count);
3276
3277   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3278     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3279       GST_DEBUG_OBJECT (qtdemux,
3280           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3281       flags ^= TR_FIRST_SAMPLE_FLAGS;
3282     } else {
3283       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3284         goto fail;
3285       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3286     }
3287   }
3288
3289   /* FIXME ? spec says other bits should also be checked to determine
3290    * entry size (and prefix size for that matter) */
3291   entry_size = 0;
3292   dur_offset = size_offset = 0;
3293   if (flags & TR_SAMPLE_DURATION) {
3294     GST_LOG_OBJECT (qtdemux, "entry duration present");
3295     dur_offset = entry_size;
3296     entry_size += 4;
3297   }
3298   if (flags & TR_SAMPLE_SIZE) {
3299     GST_LOG_OBJECT (qtdemux, "entry size present");
3300     size_offset = entry_size;
3301     entry_size += 4;
3302   }
3303   if (flags & TR_SAMPLE_FLAGS) {
3304     GST_LOG_OBJECT (qtdemux, "entry flags present");
3305     flags_offset = entry_size;
3306     entry_size += 4;
3307   }
3308   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3309     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3310     ct_offset = entry_size;
3311     entry_size += 4;
3312   }
3313
3314   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3315     goto fail;
3316   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3317
3318   if (stream->n_samples + samples_count >=
3319       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3320     goto index_too_big;
3321
3322   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3323       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3324       (stream->n_samples + samples_count) *
3325       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3326
3327   /* create a new array of samples if it's the first sample parsed */
3328   if (stream->n_samples == 0) {
3329     g_assert (stream->samples == NULL);
3330     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3331     /* or try to reallocate it with space enough to insert the new samples */
3332   } else
3333     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3334         stream->n_samples + samples_count);
3335   if (stream->samples == NULL)
3336     goto out_of_memory;
3337
3338   if (qtdemux->fragment_start != -1) {
3339     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3340     qtdemux->fragment_start = -1;
3341   } else {
3342     if (stream->n_samples == 0) {
3343       if (decode_ts > 0) {
3344         timestamp = decode_ts;
3345       } else if (stream->pending_seek != NULL) {
3346         /* if we don't have a timestamp from a tfdt box, we'll use the one
3347          * from the mfra seek table */
3348         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3349             GST_TIME_ARGS (stream->pending_seek->ts));
3350
3351         /* FIXME: this is not fully correct, the timestamp refers to the random
3352          * access sample refered to in the tfra entry, which may not necessarily
3353          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3354         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3355       } else {
3356         timestamp = 0;
3357       }
3358
3359       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3360       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3361           GST_TIME_ARGS (gst_ts));
3362     } else {
3363       /* subsequent fragments extend stream */
3364       timestamp =
3365           stream->samples[stream->n_samples - 1].timestamp +
3366           stream->samples[stream->n_samples - 1].duration;
3367
3368       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3369        * difference (1 sec.) between decode_ts and timestamp, prefer the
3370        * former */
3371       if (has_tfdt && !qtdemux->upstream_format_is_time
3372           && ABSDIFF (decode_ts, timestamp) >
3373           MAX (stream->duration_last_moof / 2,
3374               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3375         GST_INFO_OBJECT (qtdemux,
3376             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3377             ") are significantly different (more than %" GST_TIME_FORMAT
3378             "), using decode_ts",
3379             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3380             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3381             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3382                     MAX (stream->duration_last_moof / 2,
3383                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3384         timestamp = decode_ts;
3385       }
3386
3387       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3388       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3389           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3390     }
3391   }
3392
3393   initial_offset = *running_offset;
3394
3395   sample = stream->samples + stream->n_samples;
3396   for (i = 0; i < samples_count; i++) {
3397     guint32 dur, size, sflags;
3398     gint32 ct;
3399
3400     /* first read sample data */
3401     if (flags & TR_SAMPLE_DURATION) {
3402       dur = QT_UINT32 (data + dur_offset);
3403     } else {
3404       dur = d_sample_duration;
3405     }
3406     if (flags & TR_SAMPLE_SIZE) {
3407       size = QT_UINT32 (data + size_offset);
3408     } else {
3409       size = d_sample_size;
3410     }
3411     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3412       if (i == 0) {
3413         sflags = first_flags;
3414       } else {
3415         sflags = d_sample_flags;
3416       }
3417     } else if (flags & TR_SAMPLE_FLAGS) {
3418       sflags = QT_UINT32 (data + flags_offset);
3419     } else {
3420       sflags = d_sample_flags;
3421     }
3422
3423     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3424       /* Read offsets as signed numbers regardless of trun version as very
3425        * high offsets are unlikely and there are files out there that use
3426        * version=0 truns with negative offsets */
3427       ct = QT_UINT32 (data + ct_offset);
3428     } else {
3429       ct = 0;
3430     }
3431     data += entry_size;
3432
3433     /* fill the sample information */
3434     sample->offset = *running_offset;
3435     sample->pts_offset = ct;
3436     sample->size = size;
3437     sample->timestamp = timestamp;
3438     sample->duration = dur;
3439     /* sample-is-difference-sample */
3440     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3441      * now idea how it relates to bitfield other than massive LE/BE confusion */
3442     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3443     *running_offset += size;
3444     timestamp += dur;
3445     stream->duration_moof += dur;
3446     sample++;
3447
3448     if (ct < min_ct)
3449       min_ct = ct;
3450   }
3451
3452   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3453    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3454    * non-fragmented case.
3455    */
3456   if (min_ct < 0)
3457     stream->cslg_shift = -min_ct;
3458   else
3459     stream->cslg_shift = 0;
3460
3461   /* Update total duration if needed */
3462   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3463
3464   /* Pre-emptively figure out size of mdat based on trun information.
3465    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3466    * size, else we will still be able to use this when dealing with gap'ed
3467    * input */
3468   qtdemux->mdatleft = *running_offset - initial_offset;
3469   qtdemux->mdatoffset = initial_offset;
3470   qtdemux->mdatsize = qtdemux->mdatleft;
3471
3472   stream->n_samples += samples_count;
3473   stream->n_samples_moof += samples_count;
3474
3475   if (stream->pending_seek != NULL)
3476     stream->pending_seek = NULL;
3477
3478   return TRUE;
3479
3480 fail:
3481   {
3482     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3483     return FALSE;
3484   }
3485 out_of_memory:
3486   {
3487     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3488         stream->n_samples);
3489     return FALSE;
3490   }
3491 index_too_big:
3492   {
3493     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3494         "be larger than %uMB (broken file?)", stream->n_samples,
3495         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3496     return FALSE;
3497   }
3498 }
3499
3500 /* find stream with @id */
3501 static inline QtDemuxStream *
3502 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3503 {
3504   QtDemuxStream *stream;
3505   gint i;
3506
3507   /* check */
3508   if (G_UNLIKELY (!id)) {
3509     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3510     return NULL;
3511   }
3512
3513   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3514     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3515     if (stream->track_id == id)
3516       return stream;
3517   }
3518   if (qtdemux->mss_mode) {
3519     /* mss should have only 1 stream anyway */
3520     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3521   }
3522
3523   return NULL;
3524 }
3525
3526 static gboolean
3527 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3528     guint32 * fragment_number)
3529 {
3530   if (!gst_byte_reader_skip (mfhd, 4))
3531     goto fail;
3532   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3533     goto fail;
3534   return TRUE;
3535 fail:
3536   {
3537     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3538     return FALSE;
3539   }
3540 }
3541
3542 static gboolean
3543 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3544     QtDemuxStream ** stream, guint32 * default_sample_duration,
3545     guint32 * default_sample_size, guint32 * default_sample_flags,
3546     gint64 * base_offset)
3547 {
3548   guint32 flags = 0;
3549   guint32 track_id = 0;
3550
3551   if (!gst_byte_reader_skip (tfhd, 1) ||
3552       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3553     goto invalid_track;
3554
3555   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3556     goto invalid_track;
3557
3558   *stream = qtdemux_find_stream (qtdemux, track_id);
3559   if (G_UNLIKELY (!*stream))
3560     goto unknown_stream;
3561
3562   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3563     *base_offset = qtdemux->moof_offset;
3564
3565   if (flags & TF_BASE_DATA_OFFSET)
3566     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3567       goto invalid_track;
3568
3569   /* obtain stream defaults */
3570   qtdemux_parse_trex (qtdemux, *stream,
3571       default_sample_duration, default_sample_size, default_sample_flags);
3572
3573   (*stream)->stsd_sample_description_id =
3574       (*stream)->def_sample_description_index - 1;
3575
3576   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3577     guint32 sample_description_index;
3578     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3579       goto invalid_track;
3580     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3581   }
3582
3583   if (qtdemux->mss_mode) {
3584     /* mss has no stsd entry */
3585     (*stream)->stsd_sample_description_id = 0;
3586   }
3587
3588   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3589     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3590       goto invalid_track;
3591
3592   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3593     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3594       goto invalid_track;
3595
3596   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3597     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3598       goto invalid_track;
3599
3600   return TRUE;
3601
3602 invalid_track:
3603   {
3604     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3605     return FALSE;
3606   }
3607 unknown_stream:
3608   {
3609     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3610     return TRUE;
3611   }
3612 }
3613
3614 static gboolean
3615 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3616     guint64 * decode_time)
3617 {
3618   guint32 version = 0;
3619
3620   if (!gst_byte_reader_get_uint32_be (br, &version))
3621     return FALSE;
3622
3623   version >>= 24;
3624   if (version == 1) {
3625     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3626       goto failed;
3627   } else {
3628     guint32 dec_time = 0;
3629     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3630       goto failed;
3631     *decode_time = dec_time;
3632   }
3633
3634   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3635       *decode_time);
3636
3637   return TRUE;
3638
3639 failed:
3640   {
3641     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3642     return FALSE;
3643   }
3644 }
3645
3646 /* Returns a pointer to a GstStructure containing the properties of
3647  * the stream sample identified by @sample_index. The caller must unref
3648  * the returned object after use. Returns NULL if unsuccessful. */
3649 static GstStructure *
3650 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3651     QtDemuxStream * stream, guint sample_index)
3652 {
3653   QtDemuxCencSampleSetInfo *info = NULL;
3654
3655   g_return_val_if_fail (stream != NULL, NULL);
3656   g_return_val_if_fail (stream->protected, NULL);
3657   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3658
3659   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3660
3661   /* Currently, cenc properties for groups of samples are not supported, so
3662    * simply return a copy of the default sample properties */
3663   return gst_structure_copy (info->default_properties);
3664 }
3665
3666 /* Parses the sizes of sample auxiliary information contained within a stream,
3667  * as given in a saiz box. Returns array of sample_count guint8 size values,
3668  * or NULL on failure */
3669 static guint8 *
3670 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3671     GstByteReader * br, guint32 * sample_count)
3672 {
3673   guint32 flags = 0;
3674   guint8 *info_sizes;
3675   guint8 default_info_size;
3676
3677   g_return_val_if_fail (qtdemux != NULL, NULL);
3678   g_return_val_if_fail (stream != NULL, NULL);
3679   g_return_val_if_fail (br != NULL, NULL);
3680   g_return_val_if_fail (sample_count != NULL, NULL);
3681
3682   if (!gst_byte_reader_get_uint32_be (br, &flags))
3683     return NULL;
3684
3685   if (flags & 0x1) {
3686     /* aux_info_type and aux_info_type_parameter are ignored */
3687     if (!gst_byte_reader_skip (br, 8))
3688       return NULL;
3689   }
3690
3691   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3692     return NULL;
3693   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3694
3695   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3696     return NULL;
3697   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3698
3699
3700   if (default_info_size == 0) {
3701     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3702       return NULL;
3703     }
3704   } else {
3705     info_sizes = g_new (guint8, *sample_count);
3706     memset (info_sizes, default_info_size, *sample_count);
3707   }
3708
3709   return info_sizes;
3710 }
3711
3712 /* Parses the offset of sample auxiliary information contained within a stream,
3713  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3714 static gboolean
3715 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3716     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3717     guint64 * offset)
3718 {
3719   guint8 version = 0;
3720   guint32 flags = 0;
3721   guint32 aux_info_type = 0;
3722   guint32 aux_info_type_parameter = 0;
3723   guint32 entry_count;
3724   guint32 off_32;
3725   guint64 off_64;
3726   const guint8 *aux_info_type_data = NULL;
3727
3728   g_return_val_if_fail (qtdemux != NULL, FALSE);
3729   g_return_val_if_fail (stream != NULL, FALSE);
3730   g_return_val_if_fail (br != NULL, FALSE);
3731   g_return_val_if_fail (offset != NULL, FALSE);
3732
3733   if (!gst_byte_reader_get_uint8 (br, &version))
3734     return FALSE;
3735
3736   if (!gst_byte_reader_get_uint24_be (br, &flags))
3737     return FALSE;
3738
3739   if (flags & 0x1) {
3740
3741     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3742       return FALSE;
3743     aux_info_type = QT_FOURCC (aux_info_type_data);
3744
3745     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3746       return FALSE;
3747   } else if (stream->protected) {
3748     aux_info_type = stream->protection_scheme_type;
3749   } else {
3750     aux_info_type = CUR_STREAM (stream)->fourcc;
3751   }
3752
3753   if (info_type)
3754     *info_type = aux_info_type;
3755   if (info_type_parameter)
3756     *info_type_parameter = aux_info_type_parameter;
3757
3758   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3759       "aux_info_type_parameter:  %#06x",
3760       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3761
3762   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3763     return FALSE;
3764
3765   if (entry_count != 1) {
3766     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3767     return FALSE;
3768   }
3769
3770   if (version == 0) {
3771     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3772       return FALSE;
3773     *offset = (guint64) off_32;
3774   } else {
3775     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3776       return FALSE;
3777     *offset = off_64;
3778   }
3779
3780   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3781   return TRUE;
3782 }
3783
3784 static void
3785 qtdemux_gst_structure_free (GstStructure * gststructure)
3786 {
3787   if (gststructure) {
3788     gst_structure_free (gststructure);
3789   }
3790 }
3791
3792 /* Parses auxiliary information relating to samples protected using
3793  * Common Encryption (cenc); the format of this information
3794  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3795  * otherwise. */
3796 static gboolean
3797 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3798     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3799 {
3800   QtDemuxCencSampleSetInfo *ss_info = NULL;
3801   guint8 size;
3802   gint i;
3803   GPtrArray *old_crypto_info = NULL;
3804   guint old_entries = 0;
3805
3806   g_return_val_if_fail (qtdemux != NULL, FALSE);
3807   g_return_val_if_fail (stream != NULL, FALSE);
3808   g_return_val_if_fail (br != NULL, FALSE);
3809   g_return_val_if_fail (stream->protected, FALSE);
3810   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3811
3812   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3813
3814   if (ss_info->crypto_info) {
3815     old_crypto_info = ss_info->crypto_info;
3816     /* Count number of non-null entries remaining at the tail end */
3817     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3818       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3819         break;
3820       old_entries++;
3821     }
3822   }
3823
3824   ss_info->crypto_info =
3825       g_ptr_array_new_full (sample_count + old_entries,
3826       (GDestroyNotify) qtdemux_gst_structure_free);
3827
3828   /* We preserve old entries because we parse the next moof in advance
3829    * of consuming all samples from the previous moof, and otherwise
3830    * we'd discard the corresponding crypto info for the samples
3831    * from the previous fragment. */
3832   if (old_entries) {
3833     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3834         old_entries);
3835     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3836       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3837               i));
3838       g_ptr_array_index (old_crypto_info, i) = NULL;
3839     }
3840   }
3841
3842   if (old_crypto_info) {
3843     /* Everything now belongs to the new array */
3844     g_ptr_array_free (old_crypto_info, TRUE);
3845   }
3846
3847   for (i = 0; i < sample_count; ++i) {
3848     GstStructure *properties;
3849     guint16 n_subsamples = 0;
3850     guint8 *data;
3851     guint iv_size;
3852     GstBuffer *buf;
3853     gboolean could_read_iv;
3854
3855     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3856     if (properties == NULL) {
3857       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3858       return FALSE;
3859     }
3860     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3861       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3862       gst_structure_free (properties);
3863       return FALSE;
3864     }
3865     could_read_iv =
3866         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3867     if (could_read_iv) {
3868       buf = gst_buffer_new_wrapped (data, iv_size);
3869       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3870       gst_buffer_unref (buf);
3871     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3872       const GValue *constant_iv_size_value =
3873           gst_structure_get_value (properties, "constant_iv_size");
3874       const GValue *constant_iv_value =
3875           gst_structure_get_value (properties, "iv");
3876       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3877         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3878         gst_structure_free (properties);
3879         return FALSE;
3880       }
3881       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3882       gst_structure_remove_field (properties, "constant_iv_size");
3883     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3884       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3885       gst_structure_free (properties);
3886       return FALSE;
3887     }
3888     size = info_sizes[i];
3889     if (size > iv_size) {
3890       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3891           || !(n_subsamples > 0)) {
3892         gst_structure_free (properties);
3893         GST_ERROR_OBJECT (qtdemux,
3894             "failed to get subsample count for sample %u", i);
3895         return FALSE;
3896       }
3897       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3898       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3899         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3900             i);
3901         gst_structure_free (properties);
3902         return FALSE;
3903       }
3904       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3905       if (!buf) {
3906         gst_structure_free (properties);
3907         return FALSE;
3908       }
3909       gst_structure_set (properties,
3910           "subsample_count", G_TYPE_UINT, n_subsamples,
3911           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3912       gst_buffer_unref (buf);
3913     } else {
3914       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3915     }
3916     g_ptr_array_add (ss_info->crypto_info, properties);
3917   }
3918   return TRUE;
3919 }
3920
3921 /* Converts a UUID in raw byte form to a string representation, as defined in
3922  * RFC 4122. The caller takes ownership of the returned string and is
3923  * responsible for freeing it after use. */
3924 static gchar *
3925 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3926 {
3927   const guint8 *uuid = (const guint8 *) uuid_bytes;
3928
3929   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3930       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3931       uuid[0], uuid[1], uuid[2], uuid[3],
3932       uuid[4], uuid[5], uuid[6], uuid[7],
3933       uuid[8], uuid[9], uuid[10], uuid[11],
3934       uuid[12], uuid[13], uuid[14], uuid[15]);
3935 }
3936
3937 /* Parses a Protection System Specific Header box (pssh), as defined in the
3938  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3939  * information needed by a specific content protection system in order to
3940  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3941  * otherwise. */
3942 static gboolean
3943 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3944 {
3945   gchar *sysid_string;
3946   guint32 pssh_size = QT_UINT32 (node->data);
3947   GstBuffer *pssh = NULL;
3948   GstEvent *event = NULL;
3949   guint32 parent_box_type;
3950   gint i;
3951
3952   if (G_UNLIKELY (pssh_size < 32U)) {
3953     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3954     return FALSE;
3955   }
3956
3957   sysid_string =
3958       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3959
3960   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3961
3962   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3963   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3964       gst_buffer_get_size (pssh));
3965
3966   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3967
3968   /* Push an event containing the pssh box onto the queues of all streams. */
3969   event = gst_event_new_protection (sysid_string, pssh,
3970       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3971   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3972     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3973     GST_TRACE_OBJECT (qtdemux,
3974         "adding protection event for stream %s and system %s",
3975         stream->stream_id, sysid_string);
3976     g_queue_push_tail (&stream->protection_scheme_event_queue,
3977         gst_event_ref (event));
3978   }
3979   g_free (sysid_string);
3980   gst_event_unref (event);
3981   gst_buffer_unref (pssh);
3982   return TRUE;
3983 }
3984
3985 static gboolean
3986 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3987     guint64 moof_offset, QtDemuxStream * stream)
3988 {
3989   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3990   GNode *uuid_node;
3991   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3992   GNode *saiz_node, *saio_node, *pssh_node;
3993   GstByteReader saiz_data, saio_data;
3994   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3995   gint64 base_offset, running_offset;
3996   guint32 frag_num;
3997   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3998
3999   /* NOTE @stream ignored */
4000
4001   moof_node = g_node_new ((guint8 *) buffer);
4002   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4003   qtdemux_node_dump (qtdemux, moof_node);
4004
4005   /* Get fragment number from mfhd and check it's valid */
4006   mfhd_node =
4007       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4008   if (mfhd_node == NULL)
4009     goto missing_mfhd;
4010   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4011     goto fail;
4012   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4013
4014   /* unknown base_offset to start with */
4015   base_offset = running_offset = -1;
4016   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4017   while (traf_node) {
4018     guint64 decode_time = 0;
4019
4020     /* Fragment Header node */
4021     tfhd_node =
4022         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4023         &tfhd_data);
4024     if (!tfhd_node)
4025       goto missing_tfhd;
4026     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4027             &ds_size, &ds_flags, &base_offset))
4028       goto missing_tfhd;
4029
4030     /* The following code assumes at most a single set of sample auxiliary
4031      * data in the fragment (consisting of a saiz box and a corresponding saio
4032      * box); in theory, however, there could be multiple sets of sample
4033      * auxiliary data in a fragment. */
4034     saiz_node =
4035         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4036         &saiz_data);
4037     if (saiz_node) {
4038       guint32 info_type = 0;
4039       guint64 offset = 0;
4040       guint32 info_type_parameter = 0;
4041
4042       g_free (qtdemux->cenc_aux_info_sizes);
4043
4044       qtdemux->cenc_aux_info_sizes =
4045           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4046           &qtdemux->cenc_aux_sample_count);
4047       if (qtdemux->cenc_aux_info_sizes == NULL) {
4048         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4049         goto fail;
4050       }
4051       saio_node =
4052           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4053           &saio_data);
4054       if (!saio_node) {
4055         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4056         g_free (qtdemux->cenc_aux_info_sizes);
4057         qtdemux->cenc_aux_info_sizes = NULL;
4058         goto fail;
4059       }
4060
4061       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4062                   &info_type, &info_type_parameter, &offset))) {
4063         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4064         g_free (qtdemux->cenc_aux_info_sizes);
4065         qtdemux->cenc_aux_info_sizes = NULL;
4066         goto fail;
4067       }
4068       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4069         offset += (guint64) (base_offset - qtdemux->moof_offset);
4070       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4071           && info_type_parameter == 0U) {
4072         GstByteReader br;
4073         if (offset > length) {
4074           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4075           qtdemux->cenc_aux_info_offset = offset;
4076         } else {
4077           gst_byte_reader_init (&br, buffer + offset, length - offset);
4078           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4079                   qtdemux->cenc_aux_info_sizes,
4080                   qtdemux->cenc_aux_sample_count)) {
4081             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4082             g_free (qtdemux->cenc_aux_info_sizes);
4083             qtdemux->cenc_aux_info_sizes = NULL;
4084             goto fail;
4085           }
4086         }
4087       }
4088     }
4089
4090     tfdt_node =
4091         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4092         &tfdt_data);
4093     if (tfdt_node) {
4094       /* We'll use decode_time to interpolate timestamps
4095        * in case the input timestamps are missing */
4096       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4097
4098       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4099           " (%" GST_TIME_FORMAT ")", decode_time,
4100           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4101                   decode_time) : GST_CLOCK_TIME_NONE));
4102
4103       /* Discard the fragment buffer timestamp info to avoid using it.
4104        * Rely on tfdt instead as it is more accurate than the timestamp
4105        * that is fetched from a manifest/playlist and is usually
4106        * less accurate. */
4107       qtdemux->fragment_start = -1;
4108     }
4109
4110     if (G_UNLIKELY (!stream)) {
4111       /* we lost track of offset, we'll need to regain it,
4112        * but can delay complaining until later or avoid doing so altogether */
4113       base_offset = -2;
4114       goto next;
4115     }
4116     if (G_UNLIKELY (base_offset < -1))
4117       goto lost_offset;
4118
4119     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4120
4121     if (!qtdemux->pullbased) {
4122       /* Sample tables can grow enough to be problematic if the system memory
4123        * is very low (e.g. embedded devices) and the videos very long
4124        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4125        * Fortunately, we can easily discard them for each new fragment when
4126        * we know qtdemux will not receive seeks outside of the current fragment.
4127        * adaptivedemux honors this assumption.
4128        * This optimization is also useful for applications that use qtdemux as
4129        * a push-based simple demuxer, like Media Source Extensions. */
4130       gst_qtdemux_stream_flush_samples_data (stream);
4131     }
4132
4133     /* initialise moof sample data */
4134     stream->n_samples_moof = 0;
4135     stream->duration_last_moof = stream->duration_moof;
4136     stream->duration_moof = 0;
4137
4138     /* Track Run node */
4139     trun_node =
4140         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4141         &trun_data);
4142     while (trun_node) {
4143       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4144           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4145           &running_offset, decode_time, (tfdt_node != NULL));
4146       /* iterate all siblings */
4147       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4148           &trun_data);
4149     }
4150
4151     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4152     if (uuid_node) {
4153       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4154       guint32 box_length = QT_UINT32 (uuid_buffer);
4155
4156       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4157     }
4158
4159     /* if no new base_offset provided for next traf,
4160      * base is end of current traf */
4161     base_offset = running_offset;
4162     running_offset = -1;
4163
4164     if (stream->n_samples_moof && stream->duration_moof)
4165       stream->new_caps = TRUE;
4166
4167   next:
4168     /* iterate all siblings */
4169     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4170   }
4171
4172   /* parse any protection system info */
4173   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4174   while (pssh_node) {
4175     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4176     qtdemux_parse_pssh (qtdemux, pssh_node);
4177     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4178   }
4179
4180   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4181       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4182       && min_dts != 0) {
4183     /* Unless the user has explicitly requested another seek, perform an
4184      * internal seek to the time specified in the tfdt.
4185      *
4186      * This way if the user opens a file where the first tfdt is 1 hour
4187      * into the presentation, they will not have to wait 1 hour for run
4188      * time to catch up and actual playback to start. */
4189     gint i;
4190
4191     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4192         "performing an internal seek to %" GST_TIME_FORMAT,
4193         GST_TIME_ARGS (min_dts));
4194
4195     qtdemux->segment.start = min_dts;
4196     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4197
4198     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4199       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4200       stream->time_position = min_dts;
4201     }
4202
4203     /* Before this code was run a segment was already sent when the moov was
4204      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4205      * be emitted after a moov, and we can emit a second segment anyway for
4206      * special cases like this. */
4207     qtdemux->need_segment = TRUE;
4208   }
4209
4210   qtdemux->first_moof_already_parsed = TRUE;
4211
4212   g_node_destroy (moof_node);
4213   return TRUE;
4214
4215 missing_tfhd:
4216   {
4217     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4218     goto fail;
4219   }
4220 missing_mfhd:
4221   {
4222     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4223     goto fail;
4224   }
4225 lost_offset:
4226   {
4227     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4228     goto fail;
4229   }
4230 fail:
4231   {
4232     g_node_destroy (moof_node);
4233     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4234         (_("This file is corrupt and cannot be played.")), (NULL));
4235     return FALSE;
4236   }
4237 }
4238
4239 #if 0
4240 /* might be used if some day we actually use mfra & co
4241  * for random access to fragments,
4242  * but that will require quite some modifications and much less relying
4243  * on a sample array */
4244 #endif
4245
4246 static gboolean
4247 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4248 {
4249   QtDemuxStream *stream;
4250   guint32 ver_flags, track_id, len, num_entries, i;
4251   guint value_size, traf_size, trun_size, sample_size;
4252   guint64 time = 0, moof_offset = 0;
4253 #if 0
4254   GstBuffer *buf = NULL;
4255   GstFlowReturn ret;
4256 #endif
4257   GstByteReader tfra;
4258
4259   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4260
4261   if (!gst_byte_reader_skip (&tfra, 8))
4262     return FALSE;
4263
4264   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4265     return FALSE;
4266
4267   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4268       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4269       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4270     return FALSE;
4271
4272   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4273
4274   stream = qtdemux_find_stream (qtdemux, track_id);
4275   if (stream == NULL)
4276     goto unknown_trackid;
4277
4278   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4279   sample_size = (len & 3) + 1;
4280   trun_size = ((len & 12) >> 2) + 1;
4281   traf_size = ((len & 48) >> 4) + 1;
4282
4283   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4284       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4285
4286   if (num_entries == 0)
4287     goto no_samples;
4288
4289   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4290           value_size + value_size + traf_size + trun_size + sample_size))
4291     goto corrupt_file;
4292
4293   g_free (stream->ra_entries);
4294   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4295   stream->n_ra_entries = num_entries;
4296
4297   for (i = 0; i < num_entries; i++) {
4298     qt_atom_parser_get_offset (&tfra, value_size, &time);
4299     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4300     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4301     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4302     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4303
4304     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4305
4306     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4307         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4308
4309     stream->ra_entries[i].ts = time;
4310     stream->ra_entries[i].moof_offset = moof_offset;
4311
4312     /* don't want to go through the entire file and read all moofs at startup */
4313 #if 0
4314     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4315     if (ret != GST_FLOW_OK)
4316       goto corrupt_file;
4317     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4318         moof_offset, stream);
4319     gst_buffer_unref (buf);
4320 #endif
4321   }
4322
4323   check_update_duration (qtdemux, time);
4324
4325   return TRUE;
4326
4327 /* ERRORS */
4328 unknown_trackid:
4329   {
4330     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4331     return FALSE;
4332   }
4333 corrupt_file:
4334   {
4335     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4336     return FALSE;
4337   }
4338 no_samples:
4339   {
4340     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4341     return FALSE;
4342   }
4343 }
4344
4345 static gboolean
4346 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4347 {
4348   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4349   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4350   GstBuffer *mfro = NULL, *mfra = NULL;
4351   GstFlowReturn flow;
4352   gboolean ret = FALSE;
4353   GNode *mfra_node, *tfra_node;
4354   guint64 mfra_offset = 0;
4355   guint32 fourcc, mfra_size;
4356   gint64 len;
4357
4358   /* query upstream size in bytes */
4359   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4360     goto size_query_failed;
4361
4362   /* mfro box should be at the very end of the file */
4363   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4364   if (flow != GST_FLOW_OK)
4365     goto exit;
4366
4367   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4368
4369   fourcc = QT_FOURCC (mfro_map.data + 4);
4370   if (fourcc != FOURCC_mfro)
4371     goto exit;
4372
4373   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4374   if (mfro_map.size < 16)
4375     goto invalid_mfro_size;
4376
4377   mfra_size = QT_UINT32 (mfro_map.data + 12);
4378   if (mfra_size >= len)
4379     goto invalid_mfra_size;
4380
4381   mfra_offset = len - mfra_size;
4382
4383   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4384       mfra_offset, mfra_size);
4385
4386   /* now get and parse mfra box */
4387   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4388   if (flow != GST_FLOW_OK)
4389     goto broken_file;
4390
4391   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4392
4393   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4394   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4395
4396   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4397
4398   while (tfra_node) {
4399     qtdemux_parse_tfra (qtdemux, tfra_node);
4400     /* iterate all siblings */
4401     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4402   }
4403   g_node_destroy (mfra_node);
4404
4405   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4406   ret = TRUE;
4407
4408 exit:
4409
4410   if (mfro) {
4411     if (mfro_map.memory != NULL)
4412       gst_buffer_unmap (mfro, &mfro_map);
4413     gst_buffer_unref (mfro);
4414   }
4415   if (mfra) {
4416     if (mfra_map.memory != NULL)
4417       gst_buffer_unmap (mfra, &mfra_map);
4418     gst_buffer_unref (mfra);
4419   }
4420   return ret;
4421
4422 /* ERRORS */
4423 size_query_failed:
4424   {
4425     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4426     goto exit;
4427   }
4428 invalid_mfro_size:
4429   {
4430     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4431     goto exit;
4432   }
4433 invalid_mfra_size:
4434   {
4435     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4436     goto exit;
4437   }
4438 broken_file:
4439   {
4440     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4441     goto exit;
4442   }
4443 }
4444
4445 static guint64
4446 add_offset (guint64 offset, guint64 advance)
4447 {
4448   /* Avoid 64-bit overflow by clamping */
4449   if (offset > G_MAXUINT64 - advance)
4450     return G_MAXUINT64;
4451   return offset + advance;
4452 }
4453
4454 static GstFlowReturn
4455 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4456 {
4457   guint64 length = 0;
4458   guint32 fourcc = 0;
4459   GstBuffer *buf = NULL;
4460   GstFlowReturn ret = GST_FLOW_OK;
4461   guint64 cur_offset = qtdemux->offset;
4462   GstMapInfo map;
4463
4464   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4465   if (G_UNLIKELY (ret != GST_FLOW_OK))
4466     goto beach;
4467   gst_buffer_map (buf, &map, GST_MAP_READ);
4468   if (G_LIKELY (map.size >= 8))
4469     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4470   gst_buffer_unmap (buf, &map);
4471   gst_buffer_unref (buf);
4472
4473   /* maybe we already got most we needed, so only consider this eof */
4474   if (G_UNLIKELY (length == 0)) {
4475     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4476         (_("Invalid atom size.")),
4477         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4478             GST_FOURCC_ARGS (fourcc)));
4479     ret = GST_FLOW_EOS;
4480     goto beach;
4481   }
4482
4483   switch (fourcc) {
4484     case FOURCC_moof:
4485       /* record for later parsing when needed */
4486       if (!qtdemux->moof_offset) {
4487         qtdemux->moof_offset = qtdemux->offset;
4488       }
4489       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4490         /* FIXME */
4491       } else {
4492         qtdemux->offset += length;      /* skip moof and keep going */
4493       }
4494       if (qtdemux->got_moov) {
4495         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4496         ret = GST_FLOW_EOS;
4497         goto beach;
4498       }
4499       break;
4500     case FOURCC_mdat:
4501     case FOURCC_free:
4502     case FOURCC_skip:
4503     case FOURCC_wide:
4504     case FOURCC_PICT:
4505     case FOURCC_pnot:
4506     {
4507       GST_LOG_OBJECT (qtdemux,
4508           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4509           GST_FOURCC_ARGS (fourcc), cur_offset);
4510       qtdemux->offset = add_offset (qtdemux->offset, length);
4511       break;
4512     }
4513     case FOURCC_moov:
4514     {
4515       GstBuffer *moov = NULL;
4516
4517       if (qtdemux->got_moov) {
4518         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4519         qtdemux->offset = add_offset (qtdemux->offset, length);
4520         goto beach;
4521       }
4522
4523       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4524       if (ret != GST_FLOW_OK)
4525         goto beach;
4526       gst_buffer_map (moov, &map, GST_MAP_READ);
4527
4528       if (length != map.size) {
4529         /* Some files have a 'moov' atom at the end of the file which contains
4530          * a terminal 'free' atom where the body of the atom is missing.
4531          * Check for, and permit, this special case.
4532          */
4533         if (map.size >= 8) {
4534           guint8 *final_data = map.data + (map.size - 8);
4535           guint32 final_length = QT_UINT32 (final_data);
4536           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4537
4538           if (final_fourcc == FOURCC_free
4539               && map.size + final_length - 8 == length) {
4540             /* Ok, we've found that special case. Allocate a new buffer with
4541              * that free atom actually present. */
4542             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4543             gst_buffer_fill (newmoov, 0, map.data, map.size);
4544             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4545             gst_buffer_unmap (moov, &map);
4546             gst_buffer_unref (moov);
4547             moov = newmoov;
4548             gst_buffer_map (moov, &map, GST_MAP_READ);
4549           }
4550         }
4551       }
4552
4553       if (length != map.size) {
4554         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4555             (_("This file is incomplete and cannot be played.")),
4556             ("We got less than expected (received %" G_GSIZE_FORMAT
4557                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4558                 (guint) length, cur_offset));
4559         gst_buffer_unmap (moov, &map);
4560         gst_buffer_unref (moov);
4561         ret = GST_FLOW_ERROR;
4562         goto beach;
4563       }
4564       qtdemux->offset += length;
4565
4566       qtdemux_parse_moov (qtdemux, map.data, length);
4567       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4568
4569       qtdemux_parse_tree (qtdemux);
4570       if (qtdemux->moov_node_compressed) {
4571         g_node_destroy (qtdemux->moov_node_compressed);
4572         g_free (qtdemux->moov_node->data);
4573       }
4574       qtdemux->moov_node_compressed = NULL;
4575       g_node_destroy (qtdemux->moov_node);
4576       qtdemux->moov_node = NULL;
4577       gst_buffer_unmap (moov, &map);
4578       gst_buffer_unref (moov);
4579       qtdemux->got_moov = TRUE;
4580
4581       break;
4582     }
4583     case FOURCC_ftyp:
4584     {
4585       GstBuffer *ftyp = NULL;
4586
4587       /* extract major brand; might come in handy for ISO vs QT issues */
4588       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4589       if (ret != GST_FLOW_OK)
4590         goto beach;
4591       qtdemux->offset += length;
4592       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4593       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4594       gst_buffer_unmap (ftyp, &map);
4595       gst_buffer_unref (ftyp);
4596       break;
4597     }
4598     case FOURCC_uuid:
4599     {
4600       GstBuffer *uuid = NULL;
4601
4602       /* uuid are extension atoms */
4603       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4604       if (ret != GST_FLOW_OK)
4605         goto beach;
4606       qtdemux->offset += length;
4607       gst_buffer_map (uuid, &map, GST_MAP_READ);
4608       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4609       gst_buffer_unmap (uuid, &map);
4610       gst_buffer_unref (uuid);
4611       break;
4612     }
4613     case FOURCC_sidx:
4614     {
4615       GstBuffer *sidx = NULL;
4616       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4617       if (ret != GST_FLOW_OK)
4618         goto beach;
4619       qtdemux->offset += length;
4620       gst_buffer_map (sidx, &map, GST_MAP_READ);
4621       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4622       gst_buffer_unmap (sidx, &map);
4623       gst_buffer_unref (sidx);
4624       break;
4625     }
4626     default:
4627     {
4628       GstBuffer *unknown = NULL;
4629
4630       GST_LOG_OBJECT (qtdemux,
4631           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4632           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4633           cur_offset);
4634       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4635       if (ret != GST_FLOW_OK)
4636         goto beach;
4637       gst_buffer_map (unknown, &map, GST_MAP_READ);
4638       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4639       gst_buffer_unmap (unknown, &map);
4640       gst_buffer_unref (unknown);
4641       qtdemux->offset += length;
4642       break;
4643     }
4644   }
4645
4646 beach:
4647   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4648     /* digested all data, show what we have */
4649     qtdemux_prepare_streams (qtdemux);
4650     QTDEMUX_EXPOSE_LOCK (qtdemux);
4651     ret = qtdemux_expose_streams (qtdemux);
4652     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4653
4654     qtdemux->state = QTDEMUX_STATE_MOVIE;
4655     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4656         qtdemux->state);
4657     return ret;
4658   }
4659   return ret;
4660 }
4661
4662 /* Seeks to the previous keyframe of the indexed stream and
4663  * aligns other streams with respect to the keyframe timestamp
4664  * of indexed stream. Only called in case of Reverse Playback
4665  */
4666 static GstFlowReturn
4667 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4668 {
4669   guint32 seg_idx = 0, k_index = 0;
4670   guint32 ref_seg_idx, ref_k_index;
4671   GstClockTime k_pos = 0, last_stop = 0;
4672   QtDemuxSegment *seg = NULL;
4673   QtDemuxStream *ref_str = NULL;
4674   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4675   guint64 target_ts;
4676   gint i;
4677
4678   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4679    * and finally align all the other streams on that timestamp with their
4680    * respective keyframes */
4681   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4682     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4683
4684     /* No candidate yet, take the first stream */
4685     if (!ref_str) {
4686       ref_str = str;
4687       continue;
4688     }
4689
4690     /* So that stream has a segment, we prefer video streams */
4691     if (str->subtype == FOURCC_vide) {
4692       ref_str = str;
4693       break;
4694     }
4695   }
4696
4697   if (G_UNLIKELY (!ref_str)) {
4698     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4699     goto eos;
4700   }
4701
4702   if (G_UNLIKELY (!ref_str->from_sample)) {
4703     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4704     goto eos;
4705   }
4706
4707   /* So that stream has been playing from from_sample to to_sample. We will
4708    * get the timestamp of the previous sample and search for a keyframe before
4709    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4710   if (ref_str->subtype == FOURCC_vide) {
4711     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4712         ref_str->from_sample - 1, FALSE);
4713   } else {
4714     if (ref_str->from_sample >= 10)
4715       k_index = ref_str->from_sample - 10;
4716     else
4717       k_index = 0;
4718   }
4719
4720   target_ts =
4721       ref_str->samples[k_index].timestamp +
4722       ref_str->samples[k_index].pts_offset;
4723
4724   /* get current segment for that stream */
4725   seg = &ref_str->segments[ref_str->segment_index];
4726   /* Use segment start in original timescale for comparisons */
4727   seg_media_start_mov = seg->trak_media_start;
4728
4729   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4730       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4731       k_index, target_ts, seg_media_start_mov,
4732       GST_TIME_ARGS (seg->media_start));
4733
4734   /* Crawl back through segments to find the one containing this I frame */
4735   while (target_ts < seg_media_start_mov) {
4736     GST_DEBUG_OBJECT (qtdemux,
4737         "keyframe position (sample %u) is out of segment %u " " target %"
4738         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4739         ref_str->segment_index, target_ts, seg_media_start_mov);
4740
4741     if (G_UNLIKELY (!ref_str->segment_index)) {
4742       /* Reached first segment, let's consider it's EOS */
4743       goto eos;
4744     }
4745     ref_str->segment_index--;
4746     seg = &ref_str->segments[ref_str->segment_index];
4747     /* Use segment start in original timescale for comparisons */
4748     seg_media_start_mov = seg->trak_media_start;
4749   }
4750   /* Calculate time position of the keyframe and where we should stop */
4751   k_pos =
4752       QTSTREAMTIME_TO_GSTTIME (ref_str,
4753       target_ts - seg->trak_media_start) + seg->time;
4754   last_stop =
4755       QTSTREAMTIME_TO_GSTTIME (ref_str,
4756       ref_str->samples[ref_str->from_sample].timestamp -
4757       seg->trak_media_start) + seg->time;
4758
4759   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4760       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4761       k_index, GST_TIME_ARGS (k_pos));
4762
4763   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4764   qtdemux->segment.position = last_stop;
4765   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4766       GST_TIME_ARGS (last_stop));
4767
4768   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4769     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4770     goto eos;
4771   }
4772
4773   ref_seg_idx = ref_str->segment_index;
4774   ref_k_index = k_index;
4775
4776   /* Align them all on this */
4777   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4778     guint32 index = 0;
4779     GstClockTime seg_time = 0;
4780     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4781
4782     /* aligning reference stream again might lead to backing up to yet another
4783      * keyframe (due to timestamp rounding issues),
4784      * potentially putting more load on downstream; so let's try to avoid */
4785     if (str == ref_str) {
4786       seg_idx = ref_seg_idx;
4787       seg = &str->segments[seg_idx];
4788       k_index = ref_k_index;
4789       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4790           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4791     } else {
4792       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4793       GST_DEBUG_OBJECT (qtdemux,
4794           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4795           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4796
4797       /* get segment and time in the segment */
4798       seg = &str->segments[seg_idx];
4799       seg_time = k_pos - seg->time;
4800
4801       /* get the media time in the segment.
4802        * No adjustment for empty "filler" segments */
4803       if (seg->media_start != GST_CLOCK_TIME_NONE)
4804         seg_time += seg->media_start;
4805
4806       /* get the index of the sample with media time */
4807       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4808       GST_DEBUG_OBJECT (qtdemux,
4809           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4810           GST_TIME_ARGS (seg_time), index);
4811
4812       /* find previous keyframe */
4813       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4814     }
4815
4816     /* Remember until where we want to go */
4817     str->to_sample = str->from_sample - 1;
4818     /* Define our time position */
4819     target_ts =
4820         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4821     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4822     if (seg->media_start != GST_CLOCK_TIME_NONE)
4823       str->time_position -= seg->media_start;
4824
4825     /* Now seek back in time */
4826     gst_qtdemux_move_stream (qtdemux, str, k_index);
4827     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4828         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4829         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4830   }
4831
4832   return GST_FLOW_OK;
4833
4834 eos:
4835   return GST_FLOW_EOS;
4836 }
4837
4838 /*
4839  * Gets the current qt segment start, stop and position for the
4840  * given time offset. This is used in update_segment()
4841  */
4842 static void
4843 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4844     QtDemuxStream * stream, GstClockTime offset,
4845     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4846 {
4847   GstClockTime seg_time;
4848   GstClockTime start, stop, time;
4849   QtDemuxSegment *segment;
4850
4851   segment = &stream->segments[stream->segment_index];
4852
4853   /* get time in this segment */
4854   seg_time = (offset - segment->time) * segment->rate;
4855
4856   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4857       GST_TIME_ARGS (seg_time));
4858
4859   if (G_UNLIKELY (seg_time > segment->duration)) {
4860     GST_LOG_OBJECT (stream->pad,
4861         "seg_time > segment->duration %" GST_TIME_FORMAT,
4862         GST_TIME_ARGS (segment->duration));
4863     seg_time = segment->duration;
4864   }
4865
4866   /* qtdemux->segment.stop is in outside-time-realm, whereas
4867    * segment->media_stop is in track-time-realm.
4868    *
4869    * In order to compare the two, we need to bring segment.stop
4870    * into the track-time-realm
4871    *
4872    * FIXME - does this comment still hold? Don't see any conversion here */
4873
4874   stop = qtdemux->segment.stop;
4875   if (stop == GST_CLOCK_TIME_NONE)
4876     stop = qtdemux->segment.duration;
4877   if (stop == GST_CLOCK_TIME_NONE)
4878     stop = segment->media_stop;
4879   else
4880     stop =
4881         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4882
4883   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4884     start = segment->time + seg_time;
4885     time = offset;
4886     stop = start - seg_time + segment->duration;
4887   } else if (qtdemux->segment.rate >= 0) {
4888     start = MIN (segment->media_start + seg_time, stop);
4889     time = offset;
4890   } else {
4891     if (segment->media_start >= qtdemux->segment.start) {
4892       time = segment->time;
4893     } else {
4894       time = segment->time + (qtdemux->segment.start - segment->media_start);
4895     }
4896
4897     start = MAX (segment->media_start, qtdemux->segment.start);
4898     stop = MIN (segment->media_start + seg_time, stop);
4899   }
4900
4901   *_start = start;
4902   *_stop = stop;
4903   *_time = time;
4904 }
4905
4906 /*
4907  * Updates the qt segment used for the stream and pushes a new segment event
4908  * downstream on this stream's pad.
4909  */
4910 static gboolean
4911 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4912     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4913     GstClockTime * _stop)
4914 {
4915   QtDemuxSegment *segment;
4916   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4917   gdouble rate;
4918   GstEvent *event;
4919
4920   /* update the current segment */
4921   stream->segment_index = seg_idx;
4922
4923   /* get the segment */
4924   segment = &stream->segments[seg_idx];
4925
4926   if (G_UNLIKELY (offset < segment->time)) {
4927     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4928         GST_TIME_ARGS (segment->time));
4929     return FALSE;
4930   }
4931
4932   /* segment lies beyond total indicated duration */
4933   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4934           segment->time > qtdemux->segment.duration)) {
4935     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4936         " < segment->time %" GST_TIME_FORMAT,
4937         GST_TIME_ARGS (qtdemux->segment.duration),
4938         GST_TIME_ARGS (segment->time));
4939     return FALSE;
4940   }
4941
4942   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4943       &start, &stop, &time);
4944
4945   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4946       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4947       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4948
4949   /* combine global rate with that of the segment */
4950   rate = segment->rate * qtdemux->segment.rate;
4951
4952   /* Copy flags from main segment */
4953   stream->segment.flags = qtdemux->segment.flags;
4954
4955   /* update the segment values used for clipping */
4956   stream->segment.offset = qtdemux->segment.offset;
4957   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4958   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4959   stream->segment.rate = rate;
4960   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4961       stream->cslg_shift);
4962   if (stop != -1)
4963     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4964         stream->cslg_shift);
4965   else
4966     stream->segment.stop = stop;
4967   stream->segment.time = time;
4968   stream->segment.position = stream->segment.start;
4969
4970   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4971       &stream->segment);
4972
4973   /* now prepare and send the segment */
4974   if (stream->pad) {
4975     event = gst_event_new_segment (&stream->segment);
4976     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4977       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4978     }
4979     gst_pad_push_event (stream->pad, event);
4980     /* assume we can send more data now */
4981     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4982     /* clear to send tags on this pad now */
4983     gst_qtdemux_push_tags (qtdemux, stream);
4984   }
4985
4986   if (_start)
4987     *_start = start;
4988   if (_stop)
4989     *_stop = stop;
4990
4991   return TRUE;
4992 }
4993
4994 /* activate the given segment number @seg_idx of @stream at time @offset.
4995  * @offset is an absolute global position over all the segments.
4996  *
4997  * This will push out a NEWSEGMENT event with the right values and
4998  * position the stream index to the first decodable sample before
4999  * @offset.
5000  */
5001 static gboolean
5002 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5003     guint32 seg_idx, GstClockTime offset)
5004 {
5005   QtDemuxSegment *segment;
5006   guint32 index, kf_index;
5007   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5008
5009   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5010       seg_idx, GST_TIME_ARGS (offset));
5011
5012   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5013           &start, &stop))
5014     return FALSE;
5015
5016   segment = &stream->segments[stream->segment_index];
5017
5018   /* in the fragmented case, we pick a fragment that starts before our
5019    * desired position and rely on downstream to wait for a keyframe
5020    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5021    * tfra entries tells us which trun/sample the key unit is in, but we don't
5022    * make use of this additional information at the moment) */
5023   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5024     stream->to_sample = G_MAXUINT32;
5025     return TRUE;
5026   } else {
5027     /* well, it will be taken care of below */
5028     qtdemux->fragmented_seek_pending = FALSE;
5029     /* FIXME ideally the do_fragmented_seek can be done right here,
5030      * rather than at loop level
5031      * (which might even allow handling edit lists in a fragmented file) */
5032   }
5033
5034   /* We don't need to look for a sample in push-based */
5035   if (!qtdemux->pullbased)
5036     return TRUE;
5037
5038   /* and move to the keyframe before the indicated media time of the
5039    * segment */
5040   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5041     if (qtdemux->segment.rate >= 0) {
5042       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5043       stream->to_sample = G_MAXUINT32;
5044       GST_DEBUG_OBJECT (stream->pad,
5045           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5046           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5047           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5048     } else {
5049       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5050       stream->to_sample = index;
5051       GST_DEBUG_OBJECT (stream->pad,
5052           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5053           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5054           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5055     }
5056   } else {
5057     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5058         "this is an empty segment");
5059     return TRUE;
5060   }
5061
5062   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5063    * encountered an error and printed a message so we return appropriately */
5064   if (index == -1)
5065     return FALSE;
5066
5067   /* we're at the right spot */
5068   if (index == stream->sample_index) {
5069     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5070     return TRUE;
5071   }
5072
5073   /* find keyframe of the target index */
5074   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5075
5076   /* go back two frames to provide lead-in for non-raw audio decoders */
5077   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5078     guint32 lead_in = 2;
5079     guint32 old_index = kf_index;
5080     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5081
5082     if (gst_structure_has_name (s, "audio/mpeg")) {
5083       gint mpegversion;
5084       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5085           && mpegversion == 1) {
5086         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5087         lead_in = 30;
5088       }
5089     }
5090
5091     kf_index = MAX (kf_index, lead_in) - lead_in;
5092     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5093       GST_DEBUG_OBJECT (stream->pad,
5094           "Moving backwards %u frames to ensure sufficient sound lead-in",
5095           old_index - kf_index);
5096     } else {
5097       kf_index = old_index;
5098     }
5099   }
5100
5101   /* if we move forwards, we don't have to go back to the previous
5102    * keyframe since we already sent that. We can also just jump to
5103    * the keyframe right before the target index if there is one. */
5104   if (index > stream->sample_index) {
5105     /* moving forwards check if we move past a keyframe */
5106     if (kf_index > stream->sample_index) {
5107       GST_DEBUG_OBJECT (stream->pad,
5108           "moving forwards to keyframe at %u "
5109           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5110           kf_index,
5111           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5112           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5113       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5114     } else {
5115       GST_DEBUG_OBJECT (stream->pad,
5116           "moving forwards, keyframe at %u "
5117           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5118           kf_index,
5119           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5120           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5121     }
5122   } else {
5123     GST_DEBUG_OBJECT (stream->pad,
5124         "moving backwards to %sframe at %u "
5125         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5126         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5127         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5128         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5129     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5130   }
5131
5132   return TRUE;
5133 }
5134
5135 /* prepare to get the current sample of @stream, getting essential values.
5136  *
5137  * This function will also prepare and send the segment when needed.
5138  *
5139  * Return FALSE if the stream is EOS.
5140  *
5141  * PULL-BASED
5142  */
5143 static gboolean
5144 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5145     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5146     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5147     gboolean * keyframe)
5148 {
5149   QtDemuxSample *sample;
5150   GstClockTime time_position;
5151   guint32 seg_idx;
5152
5153   g_return_val_if_fail (stream != NULL, FALSE);
5154
5155   time_position = stream->time_position;
5156   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5157     goto eos;
5158
5159   seg_idx = stream->segment_index;
5160   if (G_UNLIKELY (seg_idx == -1)) {
5161     /* find segment corresponding to time_position if we are looking
5162      * for a segment. */
5163     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5164   }
5165
5166   /* different segment, activate it, sample_index will be set. */
5167   if (G_UNLIKELY (stream->segment_index != seg_idx))
5168     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5169
5170   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5171               segments[stream->segment_index]))) {
5172     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5173
5174     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5175         " prepare empty sample");
5176
5177     *empty = TRUE;
5178     *pts = *dts = time_position;
5179     *duration = seg->duration - (time_position - seg->time);
5180
5181     return TRUE;
5182   }
5183
5184   *empty = FALSE;
5185
5186   if (stream->sample_index == -1)
5187     stream->sample_index = 0;
5188
5189   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5190       stream->sample_index, stream->n_samples);
5191
5192   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5193     if (!qtdemux->fragmented)
5194       goto eos;
5195
5196     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5197     do {
5198       GstFlowReturn flow;
5199
5200       GST_OBJECT_LOCK (qtdemux);
5201       flow = qtdemux_add_fragmented_samples (qtdemux);
5202       GST_OBJECT_UNLOCK (qtdemux);
5203
5204       if (flow != GST_FLOW_OK)
5205         goto eos;
5206     }
5207     while (stream->sample_index >= stream->n_samples);
5208   }
5209
5210   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5211     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5212         stream->sample_index);
5213     return FALSE;
5214   }
5215
5216   /* now get the info for the sample we're at */
5217   sample = &stream->samples[stream->sample_index];
5218
5219   *dts = QTSAMPLE_DTS (stream, sample);
5220   *pts = QTSAMPLE_PTS (stream, sample);
5221   *offset = sample->offset;
5222   *size = sample->size;
5223   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5224   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5225
5226   return TRUE;
5227
5228   /* special cases */
5229 eos:
5230   {
5231     stream->time_position = GST_CLOCK_TIME_NONE;
5232     return FALSE;
5233   }
5234 }
5235
5236 /* move to the next sample in @stream.
5237  *
5238  * Moves to the next segment when needed.
5239  */
5240 static void
5241 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5242 {
5243   QtDemuxSample *sample;
5244   QtDemuxSegment *segment;
5245
5246   /* get current segment */
5247   segment = &stream->segments[stream->segment_index];
5248
5249   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5250     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5251     goto next_segment;
5252   }
5253
5254   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5255     /* Mark the stream as EOS */
5256     GST_DEBUG_OBJECT (qtdemux,
5257         "reached max allowed sample %u, mark EOS", stream->to_sample);
5258     stream->time_position = GST_CLOCK_TIME_NONE;
5259     return;
5260   }
5261
5262   /* move to next sample */
5263   stream->sample_index++;
5264   stream->offset_in_sample = 0;
5265
5266   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5267       stream->n_samples);
5268
5269   /* reached the last sample, we need the next segment */
5270   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5271     goto next_segment;
5272
5273   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5274     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5275         stream->sample_index);
5276     return;
5277   }
5278
5279   /* get next sample */
5280   sample = &stream->samples[stream->sample_index];
5281
5282   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5283       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5284       GST_TIME_ARGS (segment->media_stop));
5285
5286   /* see if we are past the segment */
5287   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5288     goto next_segment;
5289
5290   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5291     /* inside the segment, update time_position, looks very familiar to
5292      * GStreamer segments, doesn't it? */
5293     stream->time_position =
5294         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5295   } else {
5296     /* not yet in segment, time does not yet increment. This means
5297      * that we are still prerolling keyframes to the decoder so it can
5298      * decode the first sample of the segment. */
5299     stream->time_position = segment->time;
5300   }
5301   return;
5302
5303   /* move to the next segment */
5304 next_segment:
5305   {
5306     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5307
5308     if (stream->segment_index == stream->n_segments - 1) {
5309       /* are we at the end of the last segment, we're EOS */
5310       stream->time_position = GST_CLOCK_TIME_NONE;
5311     } else {
5312       /* else we're only at the end of the current segment */
5313       stream->time_position = segment->stop_time;
5314     }
5315     /* make sure we select a new segment */
5316
5317     /* accumulate previous segments */
5318     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5319       stream->accumulated_base +=
5320           (stream->segment.stop -
5321           stream->segment.start) / ABS (stream->segment.rate);
5322
5323     stream->segment_index = -1;
5324   }
5325 }
5326
5327 static void
5328 gst_qtdemux_sync_streams (GstQTDemux * demux)
5329 {
5330   gint i;
5331
5332   if (QTDEMUX_N_STREAMS (demux) <= 1)
5333     return;
5334
5335   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5336     QtDemuxStream *stream;
5337     GstClockTime end_time;
5338
5339     stream = QTDEMUX_NTH_STREAM (demux, i);
5340
5341     if (!stream->pad)
5342       continue;
5343
5344     /* TODO advance time on subtitle streams here, if any some day */
5345
5346     /* some clips/trailers may have unbalanced streams at the end,
5347      * so send EOS on shorter stream to prevent stalling others */
5348
5349     /* do not mess with EOS if SEGMENT seeking */
5350     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5351       continue;
5352
5353     if (demux->pullbased) {
5354       /* loop mode is sample time based */
5355       if (!STREAM_IS_EOS (stream))
5356         continue;
5357     } else {
5358       /* push mode is byte position based */
5359       if (stream->n_samples &&
5360           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5361         continue;
5362     }
5363
5364     if (stream->sent_eos)
5365       continue;
5366
5367     /* only act if some gap */
5368     end_time = stream->segments[stream->n_segments - 1].stop_time;
5369     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5370         ", stream end: %" GST_TIME_FORMAT,
5371         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5372     if (GST_CLOCK_TIME_IS_VALID (end_time)
5373         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5374       GstEvent *event;
5375
5376       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5377           GST_PAD_NAME (stream->pad));
5378       stream->sent_eos = TRUE;
5379       event = gst_event_new_eos ();
5380       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5381         gst_event_set_seqnum (event, demux->segment_seqnum);
5382       gst_pad_push_event (stream->pad, event);
5383     }
5384   }
5385 }
5386
5387 /* EOS and NOT_LINKED need to be combined. This means that we return:
5388  *
5389  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5390  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5391  */
5392 static GstFlowReturn
5393 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5394     GstFlowReturn ret)
5395 {
5396   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5397
5398   if (stream->pad)
5399     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5400         ret);
5401   else
5402     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5403
5404   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5405   return ret;
5406 }
5407
5408 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5409  * completely clipped
5410  *
5411  * Should be used only with raw buffers */
5412 static GstBuffer *
5413 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5414     GstBuffer * buf)
5415 {
5416   guint64 start, stop, cstart, cstop, diff;
5417   GstClockTime pts, duration;
5418   gsize size, osize;
5419   gint num_rate, denom_rate;
5420   gint frame_size;
5421   gboolean clip_data;
5422   guint offset;
5423
5424   osize = size = gst_buffer_get_size (buf);
5425   offset = 0;
5426
5427   /* depending on the type, setup the clip parameters */
5428   if (stream->subtype == FOURCC_soun) {
5429     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5430     num_rate = GST_SECOND;
5431     denom_rate = (gint) CUR_STREAM (stream)->rate;
5432     clip_data = TRUE;
5433   } else if (stream->subtype == FOURCC_vide) {
5434     frame_size = size;
5435     num_rate = CUR_STREAM (stream)->fps_n;
5436     denom_rate = CUR_STREAM (stream)->fps_d;
5437     clip_data = FALSE;
5438   } else
5439     goto wrong_type;
5440
5441   if (frame_size <= 0)
5442     goto bad_frame_size;
5443
5444   /* we can only clip if we have a valid pts */
5445   pts = GST_BUFFER_PTS (buf);
5446   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5447     goto no_pts;
5448
5449   duration = GST_BUFFER_DURATION (buf);
5450
5451   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5452     duration =
5453         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5454   }
5455
5456   start = pts;
5457   stop = start + duration;
5458
5459   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5460               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5461     goto clipped;
5462
5463   /* see if some clipping happened */
5464   diff = cstart - start;
5465   if (diff > 0) {
5466     pts += diff;
5467     duration -= diff;
5468
5469     if (clip_data) {
5470       /* bring clipped time to samples and to bytes */
5471       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5472       diff *= frame_size;
5473
5474       GST_DEBUG_OBJECT (qtdemux,
5475           "clipping start to %" GST_TIME_FORMAT " %"
5476           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5477
5478       offset = diff;
5479       size -= diff;
5480     }
5481   }
5482   diff = stop - cstop;
5483   if (diff > 0) {
5484     duration -= diff;
5485
5486     if (clip_data) {
5487       /* bring clipped time to samples and then to bytes */
5488       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5489       diff *= frame_size;
5490       GST_DEBUG_OBJECT (qtdemux,
5491           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5492           " bytes", GST_TIME_ARGS (cstop), diff);
5493       size -= diff;
5494     }
5495   }
5496
5497   if (offset != 0 || size != osize)
5498     gst_buffer_resize (buf, offset, size);
5499
5500   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5501   GST_BUFFER_PTS (buf) = pts;
5502   GST_BUFFER_DURATION (buf) = duration;
5503
5504   return buf;
5505
5506   /* dropped buffer */
5507 wrong_type:
5508   {
5509     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5510     return buf;
5511   }
5512 bad_frame_size:
5513   {
5514     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5515     return buf;
5516   }
5517 no_pts:
5518   {
5519     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5520     return buf;
5521   }
5522 clipped:
5523   {
5524     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5525     gst_buffer_unref (buf);
5526     return NULL;
5527   }
5528 }
5529
5530 static GstBuffer *
5531 gst_qtdemux_align_buffer (GstQTDemux * demux,
5532     GstBuffer * buffer, gsize alignment)
5533 {
5534   GstMapInfo map;
5535
5536   gst_buffer_map (buffer, &map, GST_MAP_READ);
5537
5538   if (map.size < sizeof (guintptr)) {
5539     gst_buffer_unmap (buffer, &map);
5540     return buffer;
5541   }
5542
5543   if (((guintptr) map.data) & (alignment - 1)) {
5544     GstBuffer *new_buffer;
5545     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5546
5547     new_buffer = gst_buffer_new_allocate (NULL,
5548         gst_buffer_get_size (buffer), &params);
5549
5550     /* Copy data "by hand", so ensure alignment is kept: */
5551     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5552
5553     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5554     GST_DEBUG_OBJECT (demux,
5555         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5556         alignment);
5557
5558     gst_buffer_unmap (buffer, &map);
5559     gst_buffer_unref (buffer);
5560
5561     return new_buffer;
5562   }
5563
5564   gst_buffer_unmap (buffer, &map);
5565   return buffer;
5566 }
5567
5568 static guint8 *
5569 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5570     gsize * res)
5571 {
5572   guint8 *storage;
5573   gsize i;
5574
5575   /* We are converting from pairs to triplets */
5576   *res = ccpair_size / 2 * 3;
5577   storage = g_malloc (*res);
5578   for (i = 0; i * 2 < ccpair_size; i += 1) {
5579     /* FIXME: Use line offset 0 as we simply can't know here */
5580     if (field == 1)
5581       storage[i * 3] = 0x80 | 0x00;
5582     else
5583       storage[i * 3] = 0x00 | 0x00;
5584     storage[i * 3 + 1] = ccpair[i * 2];
5585     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5586   }
5587
5588   return storage;
5589 }
5590
5591 static guint8 *
5592 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5593     gsize * cclen)
5594 {
5595   guint8 *res = NULL;
5596   guint32 atom_length, fourcc;
5597   QtDemuxStreamStsdEntry *stsd_entry;
5598
5599   GST_MEMDUMP ("caption atom", data, size);
5600
5601   /* There might be multiple atoms */
5602
5603   *cclen = 0;
5604   if (size < 8)
5605     goto invalid_cdat;
5606   atom_length = QT_UINT32 (data);
5607   fourcc = QT_FOURCC (data + 4);
5608   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5609     goto invalid_cdat;
5610
5611   GST_DEBUG_OBJECT (stream->pad, "here");
5612
5613   /* Check if we have something compatible */
5614   stsd_entry = CUR_STREAM (stream);
5615   switch (stsd_entry->fourcc) {
5616     case FOURCC_c608:{
5617       guint8 *cdat = NULL, *cdt2 = NULL;
5618       gsize cdat_size = 0, cdt2_size = 0;
5619       /* Should be cdat or cdt2 */
5620       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5621         GST_WARNING_OBJECT (stream->pad,
5622             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5623             GST_FOURCC_ARGS (fourcc));
5624         goto invalid_cdat;
5625       }
5626
5627       /* Convert to S334-1 Annex A byte triplet */
5628       if (fourcc == FOURCC_cdat)
5629         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5630       else
5631         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5632       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5633           size, atom_length);
5634
5635       /* Check for another atom ? */
5636       if (size > atom_length + 8) {
5637         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5638         if (size >= atom_length + new_atom_length) {
5639           fourcc = QT_FOURCC (data + atom_length + 4);
5640           if (fourcc == FOURCC_cdat) {
5641             if (cdat == NULL)
5642               cdat =
5643                   convert_to_s334_1a (data + atom_length + 8,
5644                   new_atom_length - 8, 1, &cdat_size);
5645             else
5646               GST_WARNING_OBJECT (stream->pad,
5647                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5648           } else {
5649             if (cdt2 == NULL)
5650               cdt2 =
5651                   convert_to_s334_1a (data + atom_length + 8,
5652                   new_atom_length - 8, 2, &cdt2_size);
5653             else
5654               GST_WARNING_OBJECT (stream->pad,
5655                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5656           }
5657         }
5658       }
5659
5660       *cclen = cdat_size + cdt2_size;
5661       res = g_malloc (*cclen);
5662       if (cdat_size)
5663         memcpy (res, cdat, cdat_size);
5664       if (cdt2_size)
5665         memcpy (res + cdat_size, cdt2, cdt2_size);
5666       g_free (cdat);
5667       g_free (cdt2);
5668     }
5669       break;
5670     case FOURCC_c708:
5671       if (fourcc != FOURCC_ccdp) {
5672         GST_WARNING_OBJECT (stream->pad,
5673             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5674             GST_FOURCC_ARGS (fourcc));
5675         goto invalid_cdat;
5676       }
5677       *cclen = atom_length - 8;
5678       res = g_memdup2 (data + 8, *cclen);
5679       break;
5680     default:
5681       /* Keep this here in case other closed caption formats are added */
5682       g_assert_not_reached ();
5683       break;
5684   }
5685
5686   GST_MEMDUMP ("Output", res, *cclen);
5687   return res;
5688
5689   /* Errors */
5690 invalid_cdat:
5691   GST_WARNING ("[cdat] atom is too small or invalid");
5692   return NULL;
5693 }
5694
5695 /* Handle Closed Caption sample buffers.
5696  * The input buffer metadata must be writable,
5697  * but time/duration etc not yet set and need not be preserved */
5698 static GstBuffer *
5699 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5700     GstBuffer * buf)
5701 {
5702   GstBuffer *outbuf = NULL;
5703   GstMapInfo map;
5704   guint8 *cc;
5705   gsize cclen = 0;
5706
5707   gst_buffer_map (buf, &map, GST_MAP_READ);
5708
5709   /* empty buffer is sent to terminate previous subtitle */
5710   if (map.size <= 2) {
5711     gst_buffer_unmap (buf, &map);
5712     gst_buffer_unref (buf);
5713     return NULL;
5714   }
5715
5716   /* For closed caption, we need to extract the information from the
5717    * [cdat],[cdt2] or [ccdp] atom */
5718   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5719   gst_buffer_unmap (buf, &map);
5720   if (cc) {
5721     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5722     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5723   } else {
5724     /* Conversion failed or there's nothing */
5725   }
5726   gst_buffer_unref (buf);
5727
5728   return outbuf;
5729 }
5730
5731 /* DVD subpicture specific sample handling.
5732  * the input buffer metadata must be writable,
5733  * but time/duration etc not yet set and need not be preserved */
5734 static GstBuffer *
5735 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5736     GstBuffer * buf)
5737 {
5738   /* send a one time dvd clut event */
5739   if (stream->pending_event && stream->pad)
5740     gst_pad_push_event (stream->pad, stream->pending_event);
5741   stream->pending_event = NULL;
5742
5743   /* empty buffer is sent to terminate previous subtitle */
5744   if (gst_buffer_get_size (buf) <= 2) {
5745     gst_buffer_unref (buf);
5746     return NULL;
5747   }
5748
5749   /* That's all the processing needed for subpictures */
5750   return buf;
5751 }
5752
5753 /* Timed text formats
5754  * the input buffer metadata must be writable,
5755  * but time/duration etc not yet set and need not be preserved */
5756 static GstBuffer *
5757 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5758     GstBuffer * buf)
5759 {
5760   GstBuffer *outbuf = NULL;
5761   GstMapInfo map;
5762   guint nsize = 0;
5763   gchar *str;
5764
5765   /* not many cases for now */
5766   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5767           stream->subtype != FOURCC_sbtl)) {
5768     return buf;
5769   }
5770
5771   gst_buffer_map (buf, &map, GST_MAP_READ);
5772
5773   /* empty buffer is sent to terminate previous subtitle */
5774   if (map.size <= 2) {
5775     gst_buffer_unmap (buf, &map);
5776     gst_buffer_unref (buf);
5777     return NULL;
5778   }
5779
5780   nsize = GST_READ_UINT16_BE (map.data);
5781   nsize = MIN (nsize, map.size - 2);
5782
5783   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5784       nsize, map.size);
5785
5786   /* takes care of UTF-8 validation or UTF-16 recognition,
5787    * no other encoding expected */
5788   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5789   gst_buffer_unmap (buf, &map);
5790
5791   if (str) {
5792     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5793     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5794   } else {
5795     /* this should not really happen unless the subtitle is corrupted */
5796   }
5797   gst_buffer_unref (buf);
5798
5799   /* FIXME ? convert optional subsequent style info to markup */
5800
5801   return outbuf;
5802 }
5803
5804 /* WebVTT sample handling according to 14496-30 */
5805 static GstBuffer *
5806 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5807     GstBuffer * buf)
5808 {
5809   GstBuffer *outbuf = NULL;
5810   GstMapInfo map;
5811
5812   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5813     g_assert_not_reached ();    /* The buffer must be mappable */
5814   }
5815
5816   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5817     GstEvent *gap = NULL;
5818     /* Push a gap event */
5819     stream->segment.position = GST_BUFFER_PTS (buf);
5820     gap =
5821         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5822     gst_pad_push_event (stream->pad, gap);
5823
5824     if (GST_BUFFER_DURATION_IS_VALID (buf))
5825       stream->segment.position += GST_BUFFER_DURATION (buf);
5826   } else {
5827     outbuf =
5828         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5829         GST_BUFFER_DURATION (buf), map.data, map.size);
5830     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5831   }
5832
5833   gst_buffer_unmap (buf, &map);
5834   gst_buffer_unref (buf);
5835
5836   return outbuf;
5837 }
5838
5839 static GstFlowReturn
5840 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5841     GstBuffer * buf)
5842 {
5843   GstFlowReturn ret = GST_FLOW_OK;
5844   GstClockTime pts, duration;
5845
5846   if (stream->need_clip)
5847     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5848
5849   if (G_UNLIKELY (buf == NULL))
5850     goto exit;
5851
5852   if (G_UNLIKELY (stream->discont)) {
5853     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5854     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5855     stream->discont = FALSE;
5856   } else {
5857     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5858   }
5859
5860   GST_LOG_OBJECT (qtdemux,
5861       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5862       ", duration %" GST_TIME_FORMAT " on pad %s",
5863       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5864       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5865       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5866
5867   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5868     GstStructure *crypto_info;
5869     QtDemuxAavdEncryptionInfo *info =
5870         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5871
5872     crypto_info = gst_structure_copy (info->default_properties);
5873     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5874       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5875   }
5876
5877   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5878           || stream->protection_scheme_type == FOURCC_cbcs)) {
5879     GstStructure *crypto_info;
5880     QtDemuxCencSampleSetInfo *info =
5881         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5882     gint index;
5883     GstEvent *event;
5884
5885     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5886       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5887           GST_PTR_FORMAT, event);
5888       gst_pad_push_event (stream->pad, event);
5889     }
5890
5891     if (info->crypto_info == NULL) {
5892       if (stream->protection_scheme_type == FOURCC_cbcs) {
5893         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5894         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5895           GST_ERROR_OBJECT (qtdemux,
5896               "failed to attach cbcs metadata to buffer");
5897           qtdemux_gst_structure_free (crypto_info);
5898         } else {
5899           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5900         }
5901       } else {
5902         GST_DEBUG_OBJECT (qtdemux,
5903             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5904       }
5905     } else {
5906       /* The end of the crypto_info array matches our n_samples position,
5907        * so count backward from there */
5908       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5909       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5910         /* steal structure from array */
5911         crypto_info = g_ptr_array_index (info->crypto_info, index);
5912         g_ptr_array_index (info->crypto_info, index) = NULL;
5913         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5914             info->crypto_info->len);
5915         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5916           GST_ERROR_OBJECT (qtdemux,
5917               "failed to attach cenc metadata to buffer");
5918       } else {
5919         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5920             index, stream->sample_index);
5921       }
5922     }
5923   }
5924
5925   if (stream->alignment > 1)
5926     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5927
5928   pts = GST_BUFFER_PTS (buf);
5929   duration = GST_BUFFER_DURATION (buf);
5930
5931   ret = gst_pad_push (stream->pad, buf);
5932
5933   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5934     /* mark position in stream, we'll need this to know when to send GAP event */
5935     stream->segment.position = pts + duration;
5936   }
5937
5938 exit:
5939
5940   return ret;
5941 }
5942
5943 static GstFlowReturn
5944 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5945     GstBuffer * buf)
5946 {
5947   GstFlowReturn ret = GST_FLOW_OK;
5948
5949   if (stream->subtype == FOURCC_clcp
5950       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5951     GstMapInfo map;
5952     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5953     guint n_triplets, i;
5954     guint field1_off = 0, field2_off = 0;
5955
5956     /* We have to split CEA608 buffers so that each outgoing buffer contains
5957      * one byte pair per field according to the framerate of the video track.
5958      *
5959      * If there is only a single byte pair per field we don't have to do
5960      * anything
5961      */
5962
5963     gst_buffer_map (buf, &map, GST_MAP_READ);
5964
5965     n_triplets = map.size / 3;
5966     for (i = 0; i < n_triplets; i++) {
5967       if (map.data[3 * i] & 0x80)
5968         n_field1++;
5969       else
5970         n_field2++;
5971     }
5972
5973     g_assert (n_field1 || n_field2);
5974
5975     /* If there's more than 1 frame we have to split, otherwise we can just
5976      * pass through */
5977     if (n_field1 > 1 || n_field2 > 1) {
5978       n_output_buffers =
5979           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5980           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5981
5982       for (i = 0; i < n_output_buffers; i++) {
5983         GstBuffer *outbuf =
5984             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5985         GstMapInfo outmap;
5986         guint8 *outptr;
5987
5988         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5989         outptr = outmap.data;
5990
5991         if (n_field1) {
5992           gboolean found = FALSE;
5993
5994           while (map.data + field1_off < map.data + map.size) {
5995             if (map.data[field1_off] & 0x80) {
5996               memcpy (outptr, &map.data[field1_off], 3);
5997               field1_off += 3;
5998               found = TRUE;
5999               break;
6000             }
6001             field1_off += 3;
6002           }
6003
6004           if (!found) {
6005             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6006
6007             memcpy (outptr, empty, 3);
6008           }
6009
6010           outptr += 3;
6011         }
6012
6013         if (n_field2) {
6014           gboolean found = FALSE;
6015
6016           while (map.data + field2_off < map.data + map.size) {
6017             if ((map.data[field2_off] & 0x80) == 0) {
6018               memcpy (outptr, &map.data[field2_off], 3);
6019               field2_off += 3;
6020               found = TRUE;
6021               break;
6022             }
6023             field2_off += 3;
6024           }
6025
6026           if (!found) {
6027             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6028
6029             memcpy (outptr, empty, 3);
6030           }
6031
6032           outptr += 3;
6033         }
6034
6035         gst_buffer_unmap (outbuf, &outmap);
6036
6037         GST_BUFFER_PTS (outbuf) =
6038             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6039             GST_SECOND * CUR_STREAM (stream)->fps_d,
6040             CUR_STREAM (stream)->fps_n);
6041         GST_BUFFER_DURATION (outbuf) =
6042             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6043             CUR_STREAM (stream)->fps_n);
6044         GST_BUFFER_OFFSET (outbuf) = -1;
6045         GST_BUFFER_OFFSET_END (outbuf) = -1;
6046
6047         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6048
6049         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6050           break;
6051       }
6052       gst_buffer_unmap (buf, &map);
6053       gst_buffer_unref (buf);
6054     } else {
6055       gst_buffer_unmap (buf, &map);
6056       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6057     }
6058   } else {
6059     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6060   }
6061
6062   return ret;
6063 }
6064
6065 /* Sets a buffer's attributes properly and pushes it downstream.
6066  * Also checks for additional actions and custom processing that may
6067  * need to be done first.
6068  */
6069 static GstFlowReturn
6070 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6071     QtDemuxStream * stream, GstBuffer * buf,
6072     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6073     gboolean keyframe, GstClockTime position, guint64 byte_position)
6074 {
6075   GstFlowReturn ret = GST_FLOW_OK;
6076
6077   /* offset the timestamps according to the edit list */
6078
6079   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6080     gchar *url;
6081     GstMapInfo map;
6082
6083     gst_buffer_map (buf, &map, GST_MAP_READ);
6084     url = g_strndup ((gchar *) map.data, map.size);
6085     gst_buffer_unmap (buf, &map);
6086     if (url != NULL && strlen (url) != 0) {
6087       /* we have RTSP redirect now */
6088       g_free (qtdemux->redirect_location);
6089       qtdemux->redirect_location = g_strdup (url);
6090       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6091           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6092               gst_structure_new ("redirect",
6093                   "new-location", G_TYPE_STRING, url, NULL)));
6094     } else {
6095       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6096           "posting");
6097     }
6098     g_free (url);
6099   }
6100
6101   /* position reporting */
6102   if (qtdemux->segment.rate >= 0) {
6103     qtdemux->segment.position = position;
6104     gst_qtdemux_sync_streams (qtdemux);
6105   }
6106
6107   if (G_UNLIKELY (!stream->pad)) {
6108     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6109     gst_buffer_unref (buf);
6110     goto exit;
6111   }
6112
6113   /* send out pending buffers */
6114   while (stream->buffers) {
6115     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6116
6117     if (G_UNLIKELY (stream->discont)) {
6118       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6119       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6120       stream->discont = FALSE;
6121     } else {
6122       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6123     }
6124
6125     if (stream->alignment > 1)
6126       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6127     gst_pad_push (stream->pad, buffer);
6128
6129     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6130   }
6131
6132   /* we're going to modify the metadata */
6133   buf = gst_buffer_make_writable (buf);
6134
6135   GST_BUFFER_DTS (buf) = dts;
6136   GST_BUFFER_PTS (buf) = pts;
6137   GST_BUFFER_DURATION (buf) = duration;
6138   GST_BUFFER_OFFSET (buf) = -1;
6139   GST_BUFFER_OFFSET_END (buf) = -1;
6140
6141   if (G_UNLIKELY (stream->process_func))
6142     buf = stream->process_func (qtdemux, stream, buf);
6143
6144   if (!buf) {
6145     goto exit;
6146   }
6147
6148   if (!keyframe) {
6149     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6150     stream->on_keyframe = FALSE;
6151   } else {
6152     stream->on_keyframe = TRUE;
6153   }
6154
6155   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6156     gst_buffer_append_memory (buf,
6157         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6158
6159   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6160     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6161   }
6162 #if 0
6163   if (G_UNLIKELY (qtdemux->element_index)) {
6164     GstClockTime stream_time;
6165
6166     stream_time =
6167         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6168         timestamp);
6169     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6170       GST_LOG_OBJECT (qtdemux,
6171           "adding association %" GST_TIME_FORMAT "-> %"
6172           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6173       gst_index_add_association (qtdemux->element_index,
6174           qtdemux->index_id,
6175           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6176           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6177           GST_FORMAT_BYTES, byte_position, NULL);
6178     }
6179   }
6180 #endif
6181
6182   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6183
6184 exit:
6185   return ret;
6186 }
6187
6188 static const QtDemuxRandomAccessEntry *
6189 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6190     GstClockTime pos, gboolean after)
6191 {
6192   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6193   guint n_entries = stream->n_ra_entries;
6194   guint i;
6195
6196   /* we assume the table is sorted */
6197   for (i = 0; i < n_entries; ++i) {
6198     if (entries[i].ts > pos)
6199       break;
6200   }
6201
6202   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6203    * probably okay to assume that the index lists the very first fragment */
6204   if (i == 0)
6205     return &entries[0];
6206
6207   if (after)
6208     return &entries[i];
6209   else
6210     return &entries[i - 1];
6211 }
6212
6213 static gboolean
6214 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6215 {
6216   const QtDemuxRandomAccessEntry *best_entry = NULL;
6217   gint i;
6218
6219   GST_OBJECT_LOCK (qtdemux);
6220
6221   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6222
6223   /* first see if we can determine where to go to using mfra,
6224    * before we start clearing things */
6225   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6226     const QtDemuxRandomAccessEntry *entry;
6227     QtDemuxStream *stream;
6228     gboolean is_audio_or_video;
6229
6230     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6231
6232     if (stream->ra_entries == NULL)
6233       continue;
6234
6235     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6236       is_audio_or_video = TRUE;
6237     else
6238       is_audio_or_video = FALSE;
6239
6240     entry =
6241         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6242         stream->time_position, !is_audio_or_video);
6243
6244     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6245         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6246
6247     stream->pending_seek = entry;
6248
6249     /* decide position to jump to just based on audio/video tracks, not subs */
6250     if (!is_audio_or_video)
6251       continue;
6252
6253     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6254       best_entry = entry;
6255   }
6256
6257   /* no luck, will handle seek otherwise */
6258   if (best_entry == NULL) {
6259     GST_OBJECT_UNLOCK (qtdemux);
6260     return FALSE;
6261   }
6262
6263   /* ok, now we can prepare for processing as of located moof */
6264   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6265     QtDemuxStream *stream;
6266
6267     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6268
6269     g_free (stream->samples);
6270     stream->samples = NULL;
6271     stream->n_samples = 0;
6272     stream->stbl_index = -1;    /* no samples have yet been parsed */
6273     stream->sample_index = -1;
6274
6275     if (stream->protection_scheme_info) {
6276       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6277       if (stream->protection_scheme_type == FOURCC_cenc
6278           || stream->protection_scheme_type == FOURCC_cbcs) {
6279         QtDemuxCencSampleSetInfo *info =
6280             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6281         if (info->crypto_info) {
6282           g_ptr_array_free (info->crypto_info, TRUE);
6283           info->crypto_info = NULL;
6284         }
6285       }
6286     }
6287   }
6288
6289   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6290       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6291       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6292       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6293
6294   qtdemux->moof_offset = best_entry->moof_offset;
6295
6296   qtdemux_add_fragmented_samples (qtdemux);
6297
6298   GST_OBJECT_UNLOCK (qtdemux);
6299   return TRUE;
6300 }
6301
6302 static GstFlowReturn
6303 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6304 {
6305   GstFlowReturn ret = GST_FLOW_OK;
6306   GstBuffer *buf = NULL;
6307   QtDemuxStream *stream, *target_stream = NULL;
6308   GstClockTime min_time;
6309   guint64 offset = 0;
6310   GstClockTime dts = GST_CLOCK_TIME_NONE;
6311   GstClockTime pts = GST_CLOCK_TIME_NONE;
6312   GstClockTime duration = 0;
6313   gboolean keyframe = FALSE;
6314   guint sample_size = 0;
6315   guint num_samples = 1;
6316   gboolean empty = 0;
6317   guint size;
6318   gint i;
6319
6320   if (qtdemux->fragmented_seek_pending) {
6321     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6322     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6323       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6324       qtdemux->fragmented_seek_pending = FALSE;
6325     } else {
6326       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6327     }
6328   }
6329
6330   /* Figure out the next stream sample to output, min_time is expressed in
6331    * global time and runs over the edit list segments. */
6332   min_time = G_MAXUINT64;
6333   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6334     GstClockTime position;
6335
6336     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6337     position = stream->time_position;
6338
6339     if (!GST_CLOCK_TIME_IS_VALID (position))
6340       continue;
6341
6342     if (stream->segment_index != -1) {
6343       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6344       position += segment->media_start;
6345     }
6346
6347     /* position of -1 is EOS */
6348     if (position < min_time) {
6349       min_time = position;
6350       target_stream = stream;
6351     }
6352   }
6353   /* all are EOS */
6354   if (G_UNLIKELY (target_stream == NULL)) {
6355     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6356     goto eos;
6357   }
6358
6359   /* check for segment end */
6360   if (G_UNLIKELY (qtdemux->segment.stop != -1
6361           && qtdemux->segment.rate >= 0
6362           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6363     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6364     target_stream->time_position = GST_CLOCK_TIME_NONE;
6365     goto eos_stream;
6366   }
6367
6368   /* gap events for subtitle streams */
6369   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6370     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6371     if (stream->pad) {
6372       GstClockTime gap_threshold;
6373
6374       /* Only send gap events on non-subtitle streams if lagging way behind. */
6375       if (stream->subtype == FOURCC_subp
6376           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6377           stream->subtype == FOURCC_wvtt)
6378         gap_threshold = 1 * GST_SECOND;
6379       else
6380         gap_threshold = 3 * GST_SECOND;
6381
6382       /* send gap events until the stream catches up */
6383       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6384       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6385           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6386           stream->segment.position + gap_threshold < min_time) {
6387         GstEvent *gap =
6388             gst_event_new_gap (stream->segment.position, gap_threshold);
6389         gst_pad_push_event (stream->pad, gap);
6390         stream->segment.position += gap_threshold;
6391       }
6392     }
6393   }
6394
6395   stream = target_stream;
6396   /* fetch info for the current sample of this stream */
6397   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6398               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6399     goto eos_stream;
6400
6401   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6402   if (stream->new_caps) {
6403     gst_qtdemux_configure_stream (qtdemux, stream);
6404     qtdemux_do_allocation (stream, qtdemux);
6405   }
6406
6407   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6408   if (G_UNLIKELY (qtdemux->segment.
6409           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6410     if (stream->subtype == FOURCC_vide) {
6411       if (!keyframe) {
6412         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6413             stream->track_id);
6414         goto next;
6415       } else if (qtdemux->trickmode_interval > 0) {
6416         GstClockTimeDiff interval;
6417
6418         if (qtdemux->segment.rate > 0)
6419           interval = stream->time_position - stream->last_keyframe_dts;
6420         else
6421           interval = stream->last_keyframe_dts - stream->time_position;
6422
6423         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6424             && interval < qtdemux->trickmode_interval) {
6425           GST_LOG_OBJECT (qtdemux,
6426               "Skipping keyframe within interval on track-id %u",
6427               stream->track_id);
6428           goto next;
6429         } else {
6430           stream->last_keyframe_dts = stream->time_position;
6431         }
6432       }
6433     }
6434   }
6435
6436   GST_DEBUG_OBJECT (qtdemux,
6437       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6438       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6439       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6440       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6441       GST_TIME_ARGS (duration));
6442
6443   if (G_UNLIKELY (empty)) {
6444     /* empty segment, push a gap if there's a second or more
6445      * difference and move to the next one */
6446     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6447       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6448     stream->segment.position = pts + duration;
6449     goto next;
6450   }
6451
6452   /* hmm, empty sample, skip and move to next sample */
6453   if (G_UNLIKELY (sample_size <= 0))
6454     goto next;
6455
6456   /* last pushed sample was out of boundary, goto next sample */
6457   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6458     goto next;
6459
6460   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6461     GST_DEBUG_OBJECT (qtdemux,
6462         "size %d larger than stream max_buffer_size %d, trimming",
6463         sample_size, stream->max_buffer_size);
6464     size =
6465         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6466   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6467       && sample_size < stream->min_buffer_size) {
6468     guint start_sample_index = stream->sample_index;
6469     guint accumulated_size = sample_size;
6470     guint64 expected_next_offset = offset + sample_size;
6471
6472     GST_DEBUG_OBJECT (qtdemux,
6473         "size %d smaller than stream min_buffer_size %d, combining with the next",
6474         sample_size, stream->min_buffer_size);
6475
6476     while (stream->sample_index < stream->to_sample
6477         && stream->sample_index + 1 < stream->n_samples) {
6478       const QtDemuxSample *next_sample;
6479
6480       /* Increment temporarily */
6481       stream->sample_index++;
6482
6483       /* Failed to parse sample so let's go back to the previous one that was
6484        * still successful */
6485       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6486         stream->sample_index--;
6487         break;
6488       }
6489
6490       next_sample = &stream->samples[stream->sample_index];
6491
6492       /* Not contiguous with the previous sample so let's go back to the
6493        * previous one that was still successful */
6494       if (next_sample->offset != expected_next_offset) {
6495         stream->sample_index--;
6496         break;
6497       }
6498
6499       accumulated_size += next_sample->size;
6500       expected_next_offset += next_sample->size;
6501       if (accumulated_size >= stream->min_buffer_size)
6502         break;
6503     }
6504
6505     num_samples = stream->sample_index + 1 - start_sample_index;
6506     stream->sample_index = start_sample_index;
6507     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6508         num_samples, accumulated_size);
6509     size = accumulated_size;
6510   } else {
6511     size = sample_size;
6512   }
6513
6514   if (qtdemux->cenc_aux_info_offset > 0) {
6515     GstMapInfo map;
6516     GstByteReader br;
6517     GstBuffer *aux_info = NULL;
6518
6519     /* pull the data stored before the sample */
6520     ret =
6521         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6522         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6523     if (G_UNLIKELY (ret != GST_FLOW_OK))
6524       goto beach;
6525     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6526     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6527     gst_byte_reader_init (&br, map.data + 8, map.size);
6528     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6529             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6530       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6531       gst_buffer_unmap (aux_info, &map);
6532       gst_buffer_unref (aux_info);
6533       ret = GST_FLOW_ERROR;
6534       goto beach;
6535     }
6536     gst_buffer_unmap (aux_info, &map);
6537     gst_buffer_unref (aux_info);
6538   }
6539
6540   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6541       offset);
6542
6543   if (stream->use_allocator) {
6544     /* if we have a per-stream allocator, use it */
6545     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6546   }
6547
6548   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6549       size, &buf);
6550   if (G_UNLIKELY (ret != GST_FLOW_OK))
6551     goto beach;
6552
6553   /* Update for both splitting and combining of samples */
6554   if (size != sample_size) {
6555     pts += gst_util_uint64_scale_int (GST_SECOND,
6556         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6557         stream->timescale);
6558     dts +=
6559         gst_util_uint64_scale_int (GST_SECOND,
6560         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6561         stream->timescale);
6562     duration =
6563         gst_util_uint64_scale_int (GST_SECOND,
6564         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6565   }
6566
6567   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6568       dts, pts, duration, keyframe, min_time, offset);
6569
6570   if (size < sample_size) {
6571     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6572     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6573
6574     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6575         sample->timestamp +
6576         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6577     if (time_position >= segment->media_start) {
6578       /* inside the segment, update time_position, looks very familiar to
6579        * GStreamer segments, doesn't it? */
6580       stream->time_position = (time_position - segment->media_start) +
6581           segment->time;
6582     } else {
6583       /* not yet in segment, time does not yet increment. This means
6584        * that we are still prerolling keyframes to the decoder so it can
6585        * decode the first sample of the segment. */
6586       stream->time_position = segment->time;
6587     }
6588   } else if (size > sample_size) {
6589     /* Increase to the last sample we already pulled so that advancing
6590      * below brings us to the next sample we need to pull */
6591     stream->sample_index += num_samples - 1;
6592   }
6593
6594   /* combine flows */
6595   GST_OBJECT_LOCK (qtdemux);
6596   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6597   GST_OBJECT_UNLOCK (qtdemux);
6598   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6599    * we have no more data for the pad to push */
6600   if (ret == GST_FLOW_EOS)
6601     ret = GST_FLOW_OK;
6602
6603   stream->offset_in_sample += size;
6604   if (stream->offset_in_sample >= sample_size) {
6605     gst_qtdemux_advance_sample (qtdemux, stream);
6606   }
6607   goto beach;
6608
6609 next:
6610   gst_qtdemux_advance_sample (qtdemux, stream);
6611
6612 beach:
6613   return ret;
6614
6615   /* special cases */
6616 eos:
6617   {
6618     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6619     ret = GST_FLOW_EOS;
6620     goto beach;
6621   }
6622 eos_stream:
6623   {
6624     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6625     /* EOS will be raised if all are EOS */
6626     ret = GST_FLOW_OK;
6627     goto beach;
6628   }
6629 }
6630
6631 static void
6632 gst_qtdemux_loop (GstPad * pad)
6633 {
6634   GstQTDemux *qtdemux;
6635   guint64 cur_offset;
6636   GstFlowReturn ret;
6637
6638   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6639
6640   cur_offset = qtdemux->offset;
6641   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6642       cur_offset, qt_demux_state_string (qtdemux->state));
6643
6644   switch (qtdemux->state) {
6645     case QTDEMUX_STATE_INITIAL:
6646     case QTDEMUX_STATE_HEADER:
6647       ret = gst_qtdemux_loop_state_header (qtdemux);
6648       break;
6649     case QTDEMUX_STATE_MOVIE:
6650       ret = gst_qtdemux_loop_state_movie (qtdemux);
6651       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6652         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6653       }
6654       break;
6655     default:
6656       /* ouch */
6657       goto invalid_state;
6658   }
6659
6660   /* if something went wrong, pause */
6661   if (ret != GST_FLOW_OK)
6662     goto pause;
6663
6664 done:
6665   gst_object_unref (qtdemux);
6666   return;
6667
6668   /* ERRORS */
6669 invalid_state:
6670   {
6671     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6672         (NULL), ("streaming stopped, invalid state"));
6673     gst_pad_pause_task (pad);
6674     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6675     goto done;
6676   }
6677 pause:
6678   {
6679     const gchar *reason = gst_flow_get_name (ret);
6680
6681     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6682
6683     gst_pad_pause_task (pad);
6684
6685     /* fatal errors need special actions */
6686     /* check EOS */
6687     if (ret == GST_FLOW_EOS) {
6688       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6689         /* we have no streams, post an error */
6690         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6691       }
6692       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6693         gint64 stop;
6694
6695         if ((stop = qtdemux->segment.stop) == -1)
6696           stop = qtdemux->segment.duration;
6697
6698         if (qtdemux->segment.rate >= 0) {
6699           GstMessage *message;
6700           GstEvent *event;
6701
6702           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6703           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6704               GST_FORMAT_TIME, stop);
6705           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6706           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6707             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6708             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6709           }
6710           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6711           gst_qtdemux_push_event (qtdemux, event);
6712         } else {
6713           GstMessage *message;
6714           GstEvent *event;
6715
6716           /*  For Reverse Playback */
6717           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6718           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6719               GST_FORMAT_TIME, qtdemux->segment.start);
6720           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6721               qtdemux->segment.start);
6722           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6723             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6724             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6725           }
6726           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6727           gst_qtdemux_push_event (qtdemux, event);
6728         }
6729       } else {
6730         GstEvent *event;
6731
6732         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6733         event = gst_event_new_eos ();
6734         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6735           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6736         gst_qtdemux_push_event (qtdemux, event);
6737       }
6738     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6739       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6740       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6741     }
6742     goto done;
6743   }
6744 }
6745
6746 /*
6747  * has_next_entry
6748  *
6749  * Returns if there are samples to be played.
6750  */
6751 static gboolean
6752 has_next_entry (GstQTDemux * demux)
6753 {
6754   QtDemuxStream *stream;
6755   gint i;
6756
6757   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6758
6759   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6760     stream = QTDEMUX_NTH_STREAM (demux, i);
6761
6762     if (stream->sample_index == -1) {
6763       stream->sample_index = 0;
6764       stream->offset_in_sample = 0;
6765     }
6766
6767     if (stream->sample_index >= stream->n_samples) {
6768       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6769       continue;
6770     }
6771     GST_DEBUG_OBJECT (demux, "Found a sample");
6772     return TRUE;
6773   }
6774
6775   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6776   return FALSE;
6777 }
6778
6779 /*
6780  * next_entry_size
6781  *
6782  * Returns the size of the first entry at the current offset.
6783  * If -1, there are none (which means EOS or empty file).
6784  */
6785 static guint64
6786 next_entry_size (GstQTDemux * demux)
6787 {
6788   QtDemuxStream *stream, *target_stream = NULL;
6789   guint64 smalloffs = (guint64) - 1;
6790   QtDemuxSample *sample;
6791   gint i;
6792
6793   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6794       demux->offset);
6795
6796   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6797     stream = QTDEMUX_NTH_STREAM (demux, i);
6798
6799     if (stream->sample_index == -1) {
6800       stream->sample_index = 0;
6801       stream->offset_in_sample = 0;
6802     }
6803
6804     if (stream->sample_index >= stream->n_samples) {
6805       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6806       continue;
6807     }
6808
6809     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6810       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6811           stream->sample_index);
6812       return -1;
6813     }
6814
6815     sample = &stream->samples[stream->sample_index];
6816
6817     GST_LOG_OBJECT (demux,
6818         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6819         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6820         stream->sample_index, sample->offset, sample->size);
6821
6822     if (((smalloffs == -1)
6823             || (sample->offset < smalloffs)) && (sample->size)) {
6824       smalloffs = sample->offset;
6825       target_stream = stream;
6826     }
6827   }
6828
6829   if (!target_stream)
6830     return -1;
6831
6832   GST_LOG_OBJECT (demux,
6833       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6834       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6835
6836   stream = target_stream;
6837   sample = &stream->samples[stream->sample_index];
6838
6839   if (sample->offset >= demux->offset) {
6840     demux->todrop = sample->offset - demux->offset;
6841     return sample->size + demux->todrop;
6842   }
6843
6844   GST_DEBUG_OBJECT (demux,
6845       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6846   return -1;
6847 }
6848
6849 static void
6850 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6851 {
6852   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6853
6854   gst_element_post_message (GST_ELEMENT_CAST (demux),
6855       gst_message_new_element (GST_OBJECT_CAST (demux),
6856           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6857 }
6858
6859 static gboolean
6860 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6861 {
6862   GstEvent *event;
6863   gboolean res = 0;
6864
6865   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6866
6867   event =
6868       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6869       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6870       GST_SEEK_TYPE_NONE, -1);
6871
6872   /* store seqnum to drop flush events, they don't need to reach downstream */
6873   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6874   res = gst_pad_push_event (demux->sinkpad, event);
6875   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6876
6877   return res;
6878 }
6879
6880 /* check for seekable upstream, above and beyond a mere query */
6881 static void
6882 gst_qtdemux_check_seekability (GstQTDemux * demux)
6883 {
6884   GstQuery *query;
6885   gboolean seekable = FALSE;
6886   gint64 start = -1, stop = -1;
6887
6888   if (demux->upstream_size)
6889     return;
6890
6891   if (demux->upstream_format_is_time)
6892     return;
6893
6894   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6895   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6896     GST_DEBUG_OBJECT (demux, "seeking query failed");
6897     goto done;
6898   }
6899
6900   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6901
6902   /* try harder to query upstream size if we didn't get it the first time */
6903   if (seekable && stop == -1) {
6904     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6905     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6906   }
6907
6908   /* if upstream doesn't know the size, it's likely that it's not seekable in
6909    * practice even if it technically may be seekable */
6910   if (seekable && (start != 0 || stop <= start)) {
6911     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6912     seekable = FALSE;
6913   }
6914
6915 done:
6916   gst_query_unref (query);
6917
6918   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6919       G_GUINT64_FORMAT ")", seekable, start, stop);
6920   demux->upstream_seekable = seekable;
6921   demux->upstream_size = seekable ? stop : -1;
6922 }
6923
6924 static void
6925 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6926 {
6927   g_return_if_fail (bytes <= demux->todrop);
6928
6929   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6930   gst_adapter_flush (demux->adapter, bytes);
6931   demux->neededbytes -= bytes;
6932   demux->offset += bytes;
6933   demux->todrop -= bytes;
6934 }
6935
6936 /* PUSH-MODE only: Send a segment, if not done already. */
6937 static void
6938 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6939 {
6940   if (G_UNLIKELY (demux->need_segment)) {
6941     gint i;
6942
6943     if (!demux->upstream_format_is_time) {
6944       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6945     } else {
6946       GstEvent *segment_event;
6947       segment_event = gst_event_new_segment (&demux->segment);
6948       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6949         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6950       gst_qtdemux_push_event (demux, segment_event);
6951     }
6952
6953     demux->need_segment = FALSE;
6954
6955     /* clear to send tags on all streams */
6956     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6957       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6958       gst_qtdemux_push_tags (demux, stream);
6959       if (CUR_STREAM (stream)->sparse) {
6960         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6961         gst_pad_push_event (stream->pad,
6962             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6963       }
6964     }
6965   }
6966 }
6967
6968 /* Used for push mode only. */
6969 static void
6970 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6971     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6972 {
6973   GstClockTime ts, dur;
6974
6975   ts = pos;
6976   dur =
6977       stream->segments[segment_index].duration - (pos -
6978       stream->segments[segment_index].time);
6979   stream->time_position += dur;
6980
6981   /* Only gaps with a duration of at least one second are propagated.
6982    * Same workaround as in pull mode.
6983    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6984   if (dur >= GST_SECOND) {
6985     GstEvent *gap;
6986     gap = gst_event_new_gap (ts, dur);
6987
6988     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6989         "segment: %" GST_PTR_FORMAT, gap);
6990     gst_pad_push_event (stream->pad, gap);
6991   }
6992 }
6993
6994 static GstFlowReturn
6995 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6996 {
6997   GstQTDemux *demux;
6998
6999   demux = GST_QTDEMUX (parent);
7000
7001   GST_DEBUG_OBJECT (demux,
7002       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7003       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7004       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7005       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7006       gst_buffer_get_size (inbuf), demux->offset);
7007
7008   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7009     gboolean is_gap_input = FALSE;
7010     gint i;
7011
7012     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7013
7014     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7015       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7016     }
7017
7018     /* Check if we can land back on our feet in the case where upstream is
7019      * handling the seeking/pushing of samples with gaps in between (like
7020      * in the case of trick-mode DASH for example) */
7021     if (demux->upstream_format_is_time
7022         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7023       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7024         guint32 res;
7025         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7026         GST_LOG_OBJECT (demux,
7027             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7028             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7029         res =
7030             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7031             stream, GST_BUFFER_OFFSET (inbuf));
7032         if (res != -1) {
7033           QtDemuxSample *sample = &stream->samples[res];
7034           GST_LOG_OBJECT (demux,
7035               "Checking if sample %d from track-id %u is valid (offset:%"
7036               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7037               stream->track_id, sample->offset, sample->size);
7038           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7039             GST_LOG_OBJECT (demux,
7040                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7041                 res);
7042             is_gap_input = TRUE;
7043             /* We can go back to standard playback mode */
7044             demux->state = QTDEMUX_STATE_MOVIE;
7045             /* Remember which sample this stream is at */
7046             stream->sample_index = res;
7047             /* Finally update all push-based values to the expected values */
7048             demux->neededbytes = stream->samples[res].size;
7049             demux->offset = GST_BUFFER_OFFSET (inbuf);
7050             demux->mdatleft =
7051                 demux->mdatsize - demux->offset + demux->mdatoffset;
7052             demux->todrop = 0;
7053           }
7054         }
7055       }
7056       if (!is_gap_input) {
7057         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7058         /* Reset state if it's a real discont */
7059         demux->neededbytes = 16;
7060         demux->state = QTDEMUX_STATE_INITIAL;
7061         demux->offset = GST_BUFFER_OFFSET (inbuf);
7062         gst_adapter_clear (demux->adapter);
7063       }
7064     }
7065     /* Reverse fragmented playback, need to flush all we have before
7066      * consuming a new fragment.
7067      * The samples array have the timestamps calculated by accumulating the
7068      * durations but this won't work for reverse playback of fragments as
7069      * the timestamps of a subsequent fragment should be smaller than the
7070      * previously received one. */
7071     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7072       gst_qtdemux_process_adapter (demux, TRUE);
7073       g_ptr_array_foreach (demux->active_streams,
7074           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7075     }
7076   }
7077
7078   gst_adapter_push (demux->adapter, inbuf);
7079
7080   GST_DEBUG_OBJECT (demux,
7081       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7082       demux->neededbytes, gst_adapter_available (demux->adapter));
7083
7084   return gst_qtdemux_process_adapter (demux, FALSE);
7085 }
7086
7087 static GstFlowReturn
7088 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7089 {
7090   GstFlowReturn ret = GST_FLOW_OK;
7091
7092   /* we never really mean to buffer that much */
7093   if (demux->neededbytes == -1) {
7094     goto eos;
7095   }
7096
7097   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7098       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7099
7100 #ifndef GST_DISABLE_GST_DEBUG
7101     {
7102       guint64 discont_offset, distance_from_discont;
7103
7104       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7105       distance_from_discont =
7106           gst_adapter_distance_from_discont (demux->adapter);
7107
7108       GST_DEBUG_OBJECT (demux,
7109           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7110           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7111           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7112           demux->offset, discont_offset, distance_from_discont);
7113     }
7114 #endif
7115
7116     switch (demux->state) {
7117       case QTDEMUX_STATE_INITIAL:{
7118         const guint8 *data;
7119         guint32 fourcc;
7120         guint64 size;
7121
7122         gst_qtdemux_check_seekability (demux);
7123
7124         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7125
7126         /* get fourcc/length, set neededbytes */
7127         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7128             &size, &fourcc);
7129         gst_adapter_unmap (demux->adapter);
7130         data = NULL;
7131         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7132             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7133         if (size == 0) {
7134           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7135               (_("This file is invalid and cannot be played.")),
7136               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7137                   GST_FOURCC_ARGS (fourcc)));
7138           ret = GST_FLOW_ERROR;
7139           break;
7140         }
7141         if (fourcc == FOURCC_mdat) {
7142           gint next_entry = next_entry_size (demux);
7143           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7144                   || !demux->fragmented)) {
7145             /* we have the headers, start playback */
7146             demux->state = QTDEMUX_STATE_MOVIE;
7147             demux->neededbytes = next_entry;
7148             demux->mdatleft = size;
7149             demux->mdatsize = demux->mdatleft;
7150           } else {
7151             /* no headers yet, try to get them */
7152             guint bs;
7153             gboolean res;
7154             guint64 old, target;
7155
7156           buffer_data:
7157             old = demux->offset;
7158             target = old + size;
7159
7160             /* try to jump over the atom with a seek */
7161             /* only bother if it seems worth doing so,
7162              * and avoids possible upstream/server problems */
7163             if (demux->upstream_seekable &&
7164                 demux->upstream_size > 4 * (1 << 20)) {
7165               res = qtdemux_seek_offset (demux, target);
7166             } else {
7167               GST_DEBUG_OBJECT (demux, "skipping seek");
7168               res = FALSE;
7169             }
7170
7171             if (res) {
7172               GST_DEBUG_OBJECT (demux, "seek success");
7173               /* remember the offset fo the first mdat so we can seek back to it
7174                * after we have the headers */
7175               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7176                 demux->first_mdat = old;
7177                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7178                     demux->first_mdat);
7179               }
7180               /* seek worked, continue reading */
7181               demux->offset = target;
7182               demux->neededbytes = 16;
7183               demux->state = QTDEMUX_STATE_INITIAL;
7184             } else {
7185               /* seek failed, need to buffer */
7186               demux->offset = old;
7187               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7188               /* there may be multiple mdat (or alike) buffers */
7189               /* sanity check */
7190               if (demux->mdatbuffer)
7191                 bs = gst_buffer_get_size (demux->mdatbuffer);
7192               else
7193                 bs = 0;
7194               if (size + bs > 10 * (1 << 20))
7195                 goto no_moov;
7196               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7197               demux->neededbytes = size;
7198               if (!demux->mdatbuffer)
7199                 demux->mdatoffset = demux->offset;
7200             }
7201           }
7202         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7203           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7204               (_("This file is invalid and cannot be played.")),
7205               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7206                   GST_FOURCC_ARGS (fourcc), size));
7207           ret = GST_FLOW_ERROR;
7208           break;
7209         } else {
7210           /* this means we already started buffering and still no moov header,
7211            * let's continue buffering everything till we get moov */
7212           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7213                   || fourcc == FOURCC_moof))
7214             goto buffer_data;
7215           demux->neededbytes = size;
7216           demux->state = QTDEMUX_STATE_HEADER;
7217         }
7218         break;
7219       }
7220       case QTDEMUX_STATE_HEADER:{
7221         const guint8 *data;
7222         guint32 fourcc;
7223
7224         GST_DEBUG_OBJECT (demux, "In header");
7225
7226         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7227
7228         /* parse the header */
7229         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7230             &fourcc);
7231         if (fourcc == FOURCC_moov) {
7232           /* in usual fragmented setup we could try to scan for more
7233            * and end up at the the moov (after mdat) again */
7234           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7235               (!demux->fragmented
7236                   || demux->last_moov_offset == demux->offset)) {
7237             GST_DEBUG_OBJECT (demux,
7238                 "Skipping moov atom as we have (this) one already");
7239           } else {
7240             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7241
7242             if (demux->got_moov && demux->fragmented) {
7243               GST_DEBUG_OBJECT (demux,
7244                   "Got a second moov, clean up data from old one");
7245               if (demux->moov_node_compressed) {
7246                 g_node_destroy (demux->moov_node_compressed);
7247                 if (demux->moov_node)
7248                   g_free (demux->moov_node->data);
7249               }
7250               demux->moov_node_compressed = NULL;
7251               if (demux->moov_node)
7252                 g_node_destroy (demux->moov_node);
7253               demux->moov_node = NULL;
7254             }
7255
7256             demux->last_moov_offset = demux->offset;
7257
7258             /* Update streams with new moov */
7259             gst_qtdemux_stream_concat (demux,
7260                 demux->old_streams, demux->active_streams);
7261
7262             qtdemux_parse_moov (demux, data, demux->neededbytes);
7263             qtdemux_node_dump (demux, demux->moov_node);
7264             qtdemux_parse_tree (demux);
7265             qtdemux_prepare_streams (demux);
7266             QTDEMUX_EXPOSE_LOCK (demux);
7267             qtdemux_expose_streams (demux);
7268             QTDEMUX_EXPOSE_UNLOCK (demux);
7269
7270             demux->got_moov = TRUE;
7271
7272             gst_qtdemux_check_send_pending_segment (demux);
7273
7274             if (demux->moov_node_compressed) {
7275               g_node_destroy (demux->moov_node_compressed);
7276               g_free (demux->moov_node->data);
7277             }
7278             demux->moov_node_compressed = NULL;
7279             g_node_destroy (demux->moov_node);
7280             demux->moov_node = NULL;
7281             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7282           }
7283         } else if (fourcc == FOURCC_moof) {
7284           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7285             guint64 dist = 0;
7286             GstClockTime prev_pts;
7287             guint64 prev_offset;
7288             guint64 adapter_discont_offset, adapter_discont_dist;
7289
7290             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7291
7292             /*
7293              * The timestamp of the moof buffer is relevant as some scenarios
7294              * won't have the initial timestamp in the atoms. Whenever a new
7295              * buffer has started, we get that buffer's PTS and use it as a base
7296              * timestamp for the trun entries.
7297              *
7298              * To keep track of the current buffer timestamp and starting point
7299              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7300              * from the beginning of the buffer, with the distance and demux->offset
7301              * we know if it is still the same buffer or not.
7302              */
7303             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7304             prev_offset = demux->offset - dist;
7305             if (demux->fragment_start_offset == -1
7306                 || prev_offset > demux->fragment_start_offset) {
7307               demux->fragment_start_offset = prev_offset;
7308               demux->fragment_start = prev_pts;
7309               GST_DEBUG_OBJECT (demux,
7310                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7311                   GST_TIME_FORMAT, demux->fragment_start_offset,
7312                   GST_TIME_ARGS (demux->fragment_start));
7313             }
7314
7315             /* We can't use prev_offset() here because this would require
7316              * upstream to set consistent and correct offsets on all buffers
7317              * since the discont. Nothing ever did that in the past and we
7318              * would break backwards compatibility here then.
7319              * Instead take the offset we had at the last discont and count
7320              * the bytes from there. This works with old code as there would
7321              * be no discont between moov and moof, and also works with
7322              * adaptivedemux which correctly sets offset and will set the
7323              * DISCONT flag accordingly when needed.
7324              *
7325              * We also only do this for upstream TIME segments as otherwise
7326              * there are potential backwards compatibility problems with
7327              * seeking in PUSH mode and upstream providing inconsistent
7328              * timestamps. */
7329             adapter_discont_offset =
7330                 gst_adapter_offset_at_discont (demux->adapter);
7331             adapter_discont_dist =
7332                 gst_adapter_distance_from_discont (demux->adapter);
7333
7334             GST_DEBUG_OBJECT (demux,
7335                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7336                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7337                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7338
7339             if (demux->upstream_format_is_time) {
7340               demux->moof_offset = adapter_discont_offset;
7341               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7342                 demux->moof_offset += adapter_discont_dist;
7343               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7344                 demux->moof_offset = demux->offset;
7345             } else {
7346               demux->moof_offset = demux->offset;
7347             }
7348
7349             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7350                     demux->moof_offset, NULL)) {
7351               gst_adapter_unmap (demux->adapter);
7352               ret = GST_FLOW_ERROR;
7353               goto done;
7354             }
7355
7356             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7357             if (demux->mss_mode && !demux->exposed) {
7358               QTDEMUX_EXPOSE_LOCK (demux);
7359               qtdemux_expose_streams (demux);
7360               QTDEMUX_EXPOSE_UNLOCK (demux);
7361             }
7362
7363             gst_qtdemux_check_send_pending_segment (demux);
7364           } else {
7365             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7366           }
7367         } else if (fourcc == FOURCC_ftyp) {
7368           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7369           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7370         } else if (fourcc == FOURCC_uuid) {
7371           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7372           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7373         } else if (fourcc == FOURCC_sidx) {
7374           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7375           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7376         } else {
7377           switch (fourcc) {
7378             case FOURCC_styp:
7379               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7380                * FALLTHROUGH */
7381             case FOURCC_skip:
7382             case FOURCC_free:
7383               /* [free] and [skip] are padding atoms */
7384               GST_DEBUG_OBJECT (demux,
7385                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7386                   GST_FOURCC_ARGS (fourcc));
7387               break;
7388             default:
7389               GST_WARNING_OBJECT (demux,
7390                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7391                   GST_FOURCC_ARGS (fourcc));
7392               /* Let's jump that one and go back to initial state */
7393               break;
7394           }
7395         }
7396         gst_adapter_unmap (demux->adapter);
7397         data = NULL;
7398
7399         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7400           gsize remaining_data_size = 0;
7401
7402           /* the mdat was before the header */
7403           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7404               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7405           /* restore our adapter/offset view of things with upstream;
7406            * put preceding buffered data ahead of current moov data.
7407            * This should also handle evil mdat, moov, mdat cases and alike */
7408           gst_adapter_flush (demux->adapter, demux->neededbytes);
7409
7410           /* Store any remaining data after the mdat for later usage */
7411           remaining_data_size = gst_adapter_available (demux->adapter);
7412           if (remaining_data_size > 0) {
7413             g_assert (demux->restoredata_buffer == NULL);
7414             demux->restoredata_buffer =
7415                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7416             demux->restoredata_offset = demux->offset + demux->neededbytes;
7417             GST_DEBUG_OBJECT (demux,
7418                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7419                 G_GUINT64_FORMAT, remaining_data_size,
7420                 demux->restoredata_offset);
7421           }
7422
7423           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7424           demux->mdatbuffer = NULL;
7425           demux->offset = demux->mdatoffset;
7426           demux->neededbytes = next_entry_size (demux);
7427           demux->state = QTDEMUX_STATE_MOVIE;
7428           demux->mdatleft = gst_adapter_available (demux->adapter);
7429           demux->mdatsize = demux->mdatleft;
7430         } else {
7431           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7432           gst_adapter_flush (demux->adapter, demux->neededbytes);
7433
7434           /* only go back to the mdat if there are samples to play */
7435           if (demux->got_moov && demux->first_mdat != -1
7436               && has_next_entry (demux)) {
7437             gboolean res;
7438
7439             /* we need to seek back */
7440             res = qtdemux_seek_offset (demux, demux->first_mdat);
7441             if (res) {
7442               demux->offset = demux->first_mdat;
7443             } else {
7444               GST_DEBUG_OBJECT (demux, "Seek back failed");
7445             }
7446           } else {
7447             demux->offset += demux->neededbytes;
7448           }
7449           demux->neededbytes = 16;
7450           demux->state = QTDEMUX_STATE_INITIAL;
7451         }
7452
7453         break;
7454       }
7455       case QTDEMUX_STATE_BUFFER_MDAT:{
7456         GstBuffer *buf;
7457         guint8 fourcc[4];
7458
7459         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7460             demux->offset);
7461         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7462         gst_buffer_extract (buf, 0, fourcc, 4);
7463         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7464             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7465         if (demux->mdatbuffer)
7466           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7467         else
7468           demux->mdatbuffer = buf;
7469         demux->offset += demux->neededbytes;
7470         demux->neededbytes = 16;
7471         demux->state = QTDEMUX_STATE_INITIAL;
7472         gst_qtdemux_post_progress (demux, 1, 1);
7473
7474         break;
7475       }
7476       case QTDEMUX_STATE_MOVIE:{
7477         QtDemuxStream *stream = NULL;
7478         QtDemuxSample *sample;
7479         GstClockTime dts, pts, duration;
7480         gboolean keyframe;
7481         gint i;
7482
7483         GST_DEBUG_OBJECT (demux,
7484             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7485
7486         if (demux->fragmented) {
7487           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7488               demux->mdatleft);
7489           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7490             /* if needed data starts within this atom,
7491              * then it should not exceed this atom */
7492             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7493               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7494                   (_("This file is invalid and cannot be played.")),
7495                   ("sample data crosses atom boundary"));
7496               ret = GST_FLOW_ERROR;
7497               break;
7498             }
7499             demux->mdatleft -= demux->neededbytes;
7500           } else {
7501             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7502             /* so we are dropping more than left in this atom */
7503             gst_qtdemux_drop_data (demux, demux->mdatleft);
7504             demux->mdatleft = 0;
7505
7506             /* need to resume atom parsing so we do not miss any other pieces */
7507             demux->state = QTDEMUX_STATE_INITIAL;
7508             demux->neededbytes = 16;
7509
7510             /* check if there was any stored post mdat data from previous buffers */
7511             if (demux->restoredata_buffer) {
7512               g_assert (gst_adapter_available (demux->adapter) == 0);
7513
7514               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7515               demux->restoredata_buffer = NULL;
7516               demux->offset = demux->restoredata_offset;
7517             }
7518
7519             break;
7520           }
7521         }
7522
7523         if (demux->todrop) {
7524           if (demux->cenc_aux_info_offset > 0) {
7525             GstByteReader br;
7526             const guint8 *data;
7527
7528             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7529             data = gst_adapter_map (demux->adapter, demux->todrop);
7530             gst_byte_reader_init (&br, data + 8, demux->todrop);
7531             if (!qtdemux_parse_cenc_aux_info (demux,
7532                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7533                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7534               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7535               ret = GST_FLOW_ERROR;
7536               gst_adapter_unmap (demux->adapter);
7537               g_free (demux->cenc_aux_info_sizes);
7538               demux->cenc_aux_info_sizes = NULL;
7539               goto done;
7540             }
7541             demux->cenc_aux_info_offset = 0;
7542             g_free (demux->cenc_aux_info_sizes);
7543             demux->cenc_aux_info_sizes = NULL;
7544             gst_adapter_unmap (demux->adapter);
7545           }
7546           gst_qtdemux_drop_data (demux, demux->todrop);
7547         }
7548
7549         /* first buffer? */
7550         /* initial newsegment sent here after having added pads,
7551          * possible others in sink_event */
7552         gst_qtdemux_check_send_pending_segment (demux);
7553
7554         /* Figure out which stream this packet belongs to */
7555         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7556           stream = QTDEMUX_NTH_STREAM (demux, i);
7557           if (stream->sample_index >= stream->n_samples) {
7558             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7559             stream = NULL;
7560             continue;
7561           }
7562           GST_LOG_OBJECT (demux,
7563               "Checking track-id %u (sample_index:%d / offset:%"
7564               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7565               stream->sample_index,
7566               stream->samples[stream->sample_index].offset,
7567               stream->samples[stream->sample_index].size);
7568
7569           if (stream->samples[stream->sample_index].offset == demux->offset)
7570             break;
7571         }
7572
7573         if (G_UNLIKELY (stream == NULL))
7574           goto unknown_stream;
7575
7576         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7577
7578         if (stream->new_caps) {
7579           gst_qtdemux_configure_stream (demux, stream);
7580         }
7581
7582         /* Put data in a buffer, set timestamps, caps, ... */
7583         sample = &stream->samples[stream->sample_index];
7584
7585         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7586           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7587               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7588
7589           dts = QTSAMPLE_DTS (stream, sample);
7590           pts = QTSAMPLE_PTS (stream, sample);
7591           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7592           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7593
7594           /* check for segment end */
7595           if (G_UNLIKELY (demux->segment.stop != -1
7596                   && demux->segment.stop <= pts && stream->on_keyframe)
7597               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7598             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7599             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7600
7601             /* skip this data, stream is EOS */
7602             gst_adapter_flush (demux->adapter, demux->neededbytes);
7603             demux->offset += demux->neededbytes;
7604
7605             /* check if all streams are eos */
7606             ret = GST_FLOW_EOS;
7607             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7608               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7609                 ret = GST_FLOW_OK;
7610                 break;
7611               }
7612             }
7613           } else {
7614             GstBuffer *outbuf;
7615
7616             outbuf =
7617                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7618
7619             /* FIXME: should either be an assert or a plain check */
7620             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7621
7622             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7623                 dts, pts, duration, keyframe, dts, demux->offset);
7624           }
7625
7626           /* combine flows */
7627           GST_OBJECT_LOCK (demux);
7628           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7629           GST_OBJECT_UNLOCK (demux);
7630         } else {
7631           /* skip this data, stream is EOS */
7632           gst_adapter_flush (demux->adapter, demux->neededbytes);
7633         }
7634
7635         stream->sample_index++;
7636         stream->offset_in_sample = 0;
7637
7638         /* update current offset and figure out size of next buffer */
7639         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7640             demux->offset, demux->neededbytes);
7641         demux->offset += demux->neededbytes;
7642         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7643             demux->offset);
7644
7645
7646         if (ret == GST_FLOW_EOS) {
7647           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7648           demux->neededbytes = -1;
7649           goto eos;
7650         }
7651
7652         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7653           if (demux->fragmented) {
7654             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7655             /* there may be more to follow, only finish this atom */
7656             demux->todrop = demux->mdatleft;
7657             demux->neededbytes = demux->todrop;
7658             break;
7659           }
7660           goto eos;
7661         }
7662         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7663           goto non_ok_unlinked_flow;
7664         }
7665         break;
7666       }
7667       default:
7668         goto invalid_state;
7669     }
7670   }
7671
7672   /* when buffering movie data, at least show user something is happening */
7673   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7674       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7675     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7676         demux->neededbytes);
7677   }
7678 done:
7679
7680   return ret;
7681
7682   /* ERRORS */
7683 non_ok_unlinked_flow:
7684   {
7685     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7686         gst_flow_get_name (ret));
7687     return ret;
7688   }
7689 unknown_stream:
7690   {
7691     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7692     ret = GST_FLOW_ERROR;
7693     goto done;
7694   }
7695 eos:
7696   {
7697     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7698     ret = GST_FLOW_EOS;
7699     goto done;
7700   }
7701 invalid_state:
7702   {
7703     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7704         (NULL), ("qtdemuxer invalid state %d", demux->state));
7705     ret = GST_FLOW_ERROR;
7706     goto done;
7707   }
7708 no_moov:
7709   {
7710     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7711         (NULL), ("no 'moov' atom within the first 10 MB"));
7712     ret = GST_FLOW_ERROR;
7713     goto done;
7714   }
7715 }
7716
7717 static gboolean
7718 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7719 {
7720   GstQuery *query;
7721   gboolean pull_mode;
7722
7723   query = gst_query_new_scheduling ();
7724
7725   if (!gst_pad_peer_query (sinkpad, query)) {
7726     gst_query_unref (query);
7727     goto activate_push;
7728   }
7729
7730   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7731       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7732   gst_query_unref (query);
7733
7734   if (!pull_mode)
7735     goto activate_push;
7736
7737   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7738   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7739
7740 activate_push:
7741   {
7742     GST_DEBUG_OBJECT (sinkpad, "activating push");
7743     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7744   }
7745 }
7746
7747 static gboolean
7748 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7749     GstPadMode mode, gboolean active)
7750 {
7751   gboolean res;
7752   GstQTDemux *demux = GST_QTDEMUX (parent);
7753
7754   switch (mode) {
7755     case GST_PAD_MODE_PUSH:
7756       demux->pullbased = FALSE;
7757       res = TRUE;
7758       break;
7759     case GST_PAD_MODE_PULL:
7760       if (active) {
7761         demux->pullbased = TRUE;
7762         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7763             sinkpad, NULL);
7764       } else {
7765         res = gst_pad_stop_task (sinkpad);
7766       }
7767       break;
7768     default:
7769       res = FALSE;
7770       break;
7771   }
7772   return res;
7773 }
7774
7775 #ifdef HAVE_ZLIB
7776 static void *
7777 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7778 {
7779   guint8 *buffer;
7780   z_stream z;
7781   int ret;
7782
7783   memset (&z, 0, sizeof (z));
7784   z.zalloc = NULL;
7785   z.zfree = NULL;
7786   z.opaque = NULL;
7787
7788   if ((ret = inflateInit (&z)) != Z_OK) {
7789     GST_ERROR ("inflateInit() returned %d", ret);
7790     return NULL;
7791   }
7792
7793   z.next_in = z_buffer;
7794   z.avail_in = z_length;
7795
7796   buffer = (guint8 *) g_malloc (*length);
7797   z.avail_out = *length;
7798   z.next_out = (Bytef *) buffer;
7799   do {
7800     ret = inflate (&z, Z_NO_FLUSH);
7801     if (ret == Z_STREAM_END) {
7802       break;
7803     } else if (ret != Z_OK) {
7804       GST_WARNING ("inflate() returned %d", ret);
7805       break;
7806     }
7807
7808     *length += 4096;
7809     buffer = (guint8 *) g_realloc (buffer, *length);
7810     z.next_out = (Bytef *) (buffer + z.total_out);
7811     z.avail_out += 4096;
7812   } while (z.avail_in > 0);
7813
7814   if (ret != Z_STREAM_END) {
7815     g_free (buffer);
7816     buffer = NULL;
7817     *length = 0;
7818   } else {
7819     *length = z.total_out;
7820   }
7821
7822   inflateEnd (&z);
7823
7824   return buffer;
7825 }
7826 #endif /* HAVE_ZLIB */
7827
7828 static gboolean
7829 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7830 {
7831   GNode *cmov;
7832
7833   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7834
7835   /* counts as header data */
7836   qtdemux->header_size += length;
7837
7838   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7839   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7840
7841   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7842   if (cmov) {
7843     guint32 method;
7844     GNode *dcom;
7845     GNode *cmvd;
7846     guint32 dcom_len;
7847
7848     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7849     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7850     if (dcom == NULL || cmvd == NULL)
7851       goto invalid_compression;
7852
7853     dcom_len = QT_UINT32 (dcom->data);
7854     if (dcom_len < 12)
7855       goto invalid_compression;
7856
7857     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7858     switch (method) {
7859 #ifdef HAVE_ZLIB
7860       case FOURCC_zlib:{
7861         guint uncompressed_length;
7862         guint compressed_length;
7863         guint8 *buf;
7864         guint32 cmvd_len;
7865
7866         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7867         if (cmvd_len < 12)
7868           goto invalid_compression;
7869
7870         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7871         compressed_length = cmvd_len - 12;
7872         GST_LOG ("length = %u", uncompressed_length);
7873
7874         buf =
7875             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7876             compressed_length, &uncompressed_length);
7877
7878         if (buf) {
7879           qtdemux->moov_node_compressed = qtdemux->moov_node;
7880           qtdemux->moov_node = g_node_new (buf);
7881
7882           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7883               uncompressed_length);
7884         }
7885         break;
7886       }
7887 #endif /* HAVE_ZLIB */
7888       default:
7889         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7890             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7891         break;
7892     }
7893   }
7894   return TRUE;
7895
7896   /* ERRORS */
7897 invalid_compression:
7898   {
7899     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7900     return FALSE;
7901   }
7902 }
7903
7904 static gboolean
7905 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7906     const guint8 * end)
7907 {
7908   while (G_UNLIKELY (buf < end)) {
7909     GNode *child;
7910     guint32 len;
7911
7912     if (G_UNLIKELY (buf + 4 > end)) {
7913       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7914       break;
7915     }
7916     len = QT_UINT32 (buf);
7917     if (G_UNLIKELY (len == 0)) {
7918       GST_LOG_OBJECT (qtdemux, "empty container");
7919       break;
7920     }
7921     if (G_UNLIKELY (len < 8)) {
7922       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7923       break;
7924     }
7925     if (G_UNLIKELY (len > (end - buf))) {
7926       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7927           (gint) (end - buf));
7928       break;
7929     }
7930
7931     child = g_node_new ((guint8 *) buf);
7932     g_node_append (node, child);
7933     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7934     qtdemux_parse_node (qtdemux, child, buf, len);
7935
7936     buf += len;
7937   }
7938   return TRUE;
7939 }
7940
7941 static gboolean
7942 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7943     GNode * xdxt)
7944 {
7945   int len = QT_UINT32 (xdxt->data);
7946   guint8 *buf = xdxt->data;
7947   guint8 *end = buf + len;
7948   GstBuffer *buffer;
7949
7950   /* skip size and type */
7951   buf += 8;
7952   end -= 8;
7953
7954   while (buf < end) {
7955     gint size;
7956     guint32 type;
7957
7958     size = QT_UINT32 (buf);
7959     type = QT_FOURCC (buf + 4);
7960
7961     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7962
7963     if (buf + size > end || size <= 0)
7964       break;
7965
7966     buf += 8;
7967     size -= 8;
7968
7969     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7970         GST_FOURCC_ARGS (type));
7971
7972     switch (type) {
7973       case FOURCC_tCtH:
7974         buffer = gst_buffer_new_and_alloc (size);
7975         gst_buffer_fill (buffer, 0, buf, size);
7976         stream->buffers = g_slist_append (stream->buffers, buffer);
7977         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7978         break;
7979       case FOURCC_tCt_:
7980         buffer = gst_buffer_new_and_alloc (size);
7981         gst_buffer_fill (buffer, 0, buf, size);
7982         stream->buffers = g_slist_append (stream->buffers, buffer);
7983         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7984         break;
7985       case FOURCC_tCtC:
7986         buffer = gst_buffer_new_and_alloc (size);
7987         gst_buffer_fill (buffer, 0, buf, size);
7988         stream->buffers = g_slist_append (stream->buffers, buffer);
7989         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7990         break;
7991       default:
7992         GST_WARNING_OBJECT (qtdemux,
7993             "unknown theora cookie %" GST_FOURCC_FORMAT,
7994             GST_FOURCC_ARGS (type));
7995         break;
7996     }
7997     buf += size;
7998   }
7999   return TRUE;
8000 }
8001
8002 static gboolean
8003 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8004     guint length)
8005 {
8006   guint32 fourcc = 0;
8007   guint32 node_length = 0;
8008   const QtNodeType *type;
8009   const guint8 *end;
8010
8011   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8012
8013   if (G_UNLIKELY (length < 8))
8014     goto not_enough_data;
8015
8016   node_length = QT_UINT32 (buffer);
8017   fourcc = QT_FOURCC (buffer + 4);
8018
8019   /* ignore empty nodes */
8020   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8021     return TRUE;
8022
8023   type = qtdemux_type_get (fourcc);
8024
8025   end = buffer + length;
8026
8027   GST_LOG_OBJECT (qtdemux,
8028       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8029       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8030
8031   if (node_length > length)
8032     goto broken_atom_size;
8033
8034   if (type->flags & QT_FLAG_CONTAINER) {
8035     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8036   } else {
8037     switch (fourcc) {
8038       case FOURCC_stsd:
8039       {
8040         if (node_length < 20) {
8041           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8042           break;
8043         }
8044         GST_DEBUG_OBJECT (qtdemux,
8045             "parsing stsd (sample table, sample description) atom");
8046         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8047         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8048         break;
8049       }
8050       case FOURCC_mp4a:
8051       case FOURCC_alac:
8052       case FOURCC_fLaC:
8053       case FOURCC_aavd:
8054       {
8055         guint32 version;
8056         guint32 offset;
8057         guint min_size;
8058
8059         /* also read alac (or whatever) in stead of mp4a in the following,
8060          * since a similar layout is used in other cases as well */
8061         if (fourcc == FOURCC_mp4a)
8062           min_size = 20;
8063         else if (fourcc == FOURCC_fLaC)
8064           min_size = 86;
8065         else
8066           min_size = 40;
8067
8068         /* There are two things we might encounter here: a true mp4a atom, and
8069            an mp4a entry in an stsd atom. The latter is what we're interested
8070            in, and it looks like an atom, but isn't really one. The true mp4a
8071            atom is short, so we detect it based on length here. */
8072         if (length < min_size) {
8073           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8074               GST_FOURCC_ARGS (fourcc));
8075           break;
8076         }
8077
8078         /* 'version' here is the sound sample description version. Types 0 and
8079            1 are documented in the QTFF reference, but type 2 is not: it's
8080            described in Apple header files instead (struct SoundDescriptionV2
8081            in Movies.h) */
8082         version = QT_UINT16 (buffer + 16);
8083
8084         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8085             GST_FOURCC_ARGS (fourcc), version);
8086
8087         /* parse any esds descriptors */
8088         switch (version) {
8089           case 0:
8090             offset = 0x24;
8091             break;
8092           case 1:
8093             offset = 0x34;
8094             break;
8095           case 2:
8096             offset = 0x48;
8097             break;
8098           default:
8099             GST_WARNING_OBJECT (qtdemux,
8100                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8101                 GST_FOURCC_ARGS (fourcc), version);
8102             offset = 0;
8103             break;
8104         }
8105         if (offset)
8106           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8107         break;
8108       }
8109       case FOURCC_mp4v:
8110       case FOURCC_MP4V:
8111       case FOURCC_fmp4:
8112       case FOURCC_FMP4:
8113       case FOURCC_apcs:
8114       case FOURCC_apch:
8115       case FOURCC_apcn:
8116       case FOURCC_apco:
8117       case FOURCC_ap4h:
8118       case FOURCC_xvid:
8119       case FOURCC_XVID:
8120       case FOURCC_H264:
8121       case FOURCC_avc1:
8122       case FOURCC_avc3:
8123       case FOURCC_H265:
8124       case FOURCC_hvc1:
8125       case FOURCC_hev1:
8126       case FOURCC_dvh1:
8127       case FOURCC_dvhe:
8128       case FOURCC_mjp2:
8129       case FOURCC_encv:
8130       {
8131         guint32 version;
8132         guint32 str_len;
8133
8134         /* codec_data is contained inside these atoms, which all have
8135          * the same format. */
8136         /* video sample description size is 86 bytes without extension.
8137          * node_length have to be bigger than 86 bytes because video sample
8138          * description can include extensions such as esds, fiel, glbl, etc. */
8139         if (node_length < 86) {
8140           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8141               " sample description length too short (%u < 86)",
8142               GST_FOURCC_ARGS (fourcc), node_length);
8143           break;
8144         }
8145
8146         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8147             GST_FOURCC_ARGS (fourcc));
8148
8149         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8150          *              its data format.
8151          * revision level (2 bytes) : must be set to 0. */
8152         version = QT_UINT32 (buffer + 16);
8153         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8154
8155         /* compressor name : PASCAL string and informative purposes
8156          * first byte : the number of bytes to be displayed.
8157          *              it has to be less than 32 because it is reserved
8158          *              space of 32 bytes total including itself. */
8159         str_len = QT_UINT8 (buffer + 50);
8160         if (str_len < 32)
8161           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8162               (char *) buffer + 51);
8163         else
8164           GST_WARNING_OBJECT (qtdemux,
8165               "compressorname length too big (%u > 31)", str_len);
8166
8167         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8168             end - buffer);
8169         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8170         break;
8171       }
8172       case FOURCC_meta:
8173       {
8174         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8175
8176         /* You are reading this correctly. QTFF specifies that the
8177          * metadata atom is a short atom, whereas ISO BMFF specifies
8178          * it's a full atom. But since so many people are doing things
8179          * differently, we actually peek into the atom to see which
8180          * variant it is */
8181         if (length < 16) {
8182           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8183               GST_FOURCC_ARGS (fourcc));
8184           break;
8185         }
8186         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8187           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8188            * starts with a 'hdlr' atom */
8189           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8190         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8191           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8192            * with version/flags both set to zero */
8193           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8194         } else
8195           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8196         break;
8197       }
8198       case FOURCC_mp4s:
8199       {
8200         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8201         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8202         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8203         break;
8204       }
8205       case FOURCC_XiTh:
8206       {
8207         guint32 version;
8208         guint32 offset;
8209
8210         if (length < 16) {
8211           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8212               GST_FOURCC_ARGS (fourcc));
8213           break;
8214         }
8215
8216         version = QT_UINT32 (buffer + 12);
8217         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8218
8219         switch (version) {
8220           case 0x00000001:
8221             offset = 0x62;
8222             break;
8223           default:
8224             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8225             offset = 0;
8226             break;
8227         }
8228         if (offset) {
8229           if (length < offset) {
8230             GST_WARNING_OBJECT (qtdemux,
8231                 "skipping too small %" GST_FOURCC_FORMAT " box",
8232                 GST_FOURCC_ARGS (fourcc));
8233             break;
8234           }
8235           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8236         }
8237         break;
8238       }
8239       case FOURCC_in24:
8240       {
8241         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8242         break;
8243       }
8244       case FOURCC_uuid:
8245       {
8246         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8247         break;
8248       }
8249       case FOURCC_enca:
8250       {
8251         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8252         break;
8253       }
8254       default:
8255         if (!strcmp (type->name, "unknown"))
8256           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8257         break;
8258     }
8259   }
8260   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8261       GST_FOURCC_ARGS (fourcc));
8262   return TRUE;
8263
8264 /* ERRORS */
8265 not_enough_data:
8266   {
8267     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8268         (_("This file is corrupt and cannot be played.")),
8269         ("Not enough data for an atom header, got only %u bytes", length));
8270     return FALSE;
8271   }
8272 broken_atom_size:
8273   {
8274     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8275         (_("This file is corrupt and cannot be played.")),
8276         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8277             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8278             length));
8279     return FALSE;
8280   }
8281 }
8282
8283 static void
8284 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8285 {
8286 /* FIXME: This can only reliably work if demuxers have a
8287  * separate streaming thread per srcpad. This should be
8288  * done in a demuxer base class, which integrates parts
8289  * of multiqueue
8290  *
8291  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8292  */
8293 #if 0
8294   GstQuery *query;
8295
8296   query = gst_query_new_allocation (stream->caps, FALSE);
8297
8298   if (!gst_pad_peer_query (stream->pad, query)) {
8299     /* not a problem, just debug a little */
8300     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8301   }
8302
8303   if (stream->allocator)
8304     gst_object_unref (stream->allocator);
8305
8306   if (gst_query_get_n_allocation_params (query) > 0) {
8307     /* try the allocator */
8308     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8309         &stream->params);
8310     stream->use_allocator = TRUE;
8311   } else {
8312     stream->allocator = NULL;
8313     gst_allocation_params_init (&stream->params);
8314     stream->use_allocator = FALSE;
8315   }
8316   gst_query_unref (query);
8317 #endif
8318 }
8319
8320 static gboolean
8321 pad_query (const GValue * item, GValue * value, gpointer user_data)
8322 {
8323   GstPad *pad = g_value_get_object (item);
8324   GstQuery *query = user_data;
8325   gboolean res;
8326
8327   res = gst_pad_peer_query (pad, query);
8328
8329   if (res) {
8330     g_value_set_boolean (value, TRUE);
8331     return FALSE;
8332   }
8333
8334   GST_INFO_OBJECT (pad, "pad peer query failed");
8335   return TRUE;
8336 }
8337
8338 static gboolean
8339 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8340     GstPadDirection direction)
8341 {
8342   GstIterator *it;
8343   GstIteratorFoldFunction func = pad_query;
8344   GValue res = { 0, };
8345
8346   g_value_init (&res, G_TYPE_BOOLEAN);
8347   g_value_set_boolean (&res, FALSE);
8348
8349   /* Ask neighbor */
8350   if (direction == GST_PAD_SRC)
8351     it = gst_element_iterate_src_pads (element);
8352   else
8353     it = gst_element_iterate_sink_pads (element);
8354
8355   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8356     gst_iterator_resync (it);
8357
8358   gst_iterator_free (it);
8359
8360   return g_value_get_boolean (&res);
8361 }
8362
8363 static void
8364 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8365     QtDemuxStream * stream)
8366 {
8367   GstQuery *query;
8368   GstContext *ctxt;
8369   GstElement *element = GST_ELEMENT (qtdemux);
8370   GstStructure *st;
8371   gchar **filtered_sys_ids;
8372   GValue event_list = G_VALUE_INIT;
8373   GList *walk;
8374
8375   /* 1. Check if we already have the context. */
8376   if (qtdemux->preferred_protection_system_id != NULL) {
8377     GST_LOG_OBJECT (element,
8378         "already have the protection context, no need to request it again");
8379     return;
8380   }
8381
8382   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8383   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8384       (const gchar **) qtdemux->protection_system_ids->pdata);
8385
8386   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8387       qtdemux->protection_system_ids->len - 1);
8388   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8389       "decryptors for %u of them, running context request",
8390       qtdemux->protection_system_ids->len,
8391       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8392
8393
8394   if (stream->protection_scheme_event_queue.length) {
8395     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8396         stream->protection_scheme_event_queue.length);
8397     walk = stream->protection_scheme_event_queue.tail;
8398   } else {
8399     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8400         qtdemux->protection_event_queue.length);
8401     walk = qtdemux->protection_event_queue.tail;
8402   }
8403
8404   g_value_init (&event_list, GST_TYPE_LIST);
8405   for (; walk; walk = g_list_previous (walk)) {
8406     GValue *event_value = g_new0 (GValue, 1);
8407     g_value_init (event_value, GST_TYPE_EVENT);
8408     g_value_set_boxed (event_value, walk->data);
8409     gst_value_list_append_and_take_value (&event_list, event_value);
8410   }
8411
8412   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8413    *      check if downstream already has a context of the specific type
8414    *  2b) Query upstream as above.
8415    */
8416   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8417   st = gst_query_writable_structure (query);
8418   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8419       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8420       NULL);
8421   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8422   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8423     gst_query_parse_context (query, &ctxt);
8424     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8425     gst_element_set_context (element, ctxt);
8426   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8427     gst_query_parse_context (query, &ctxt);
8428     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8429     gst_element_set_context (element, ctxt);
8430   } else {
8431     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8432      *    the required context type and afterwards check if a
8433      *    usable context was set now as in 1). The message could
8434      *    be handled by the parent bins of the element and the
8435      *    application.
8436      */
8437     GstMessage *msg;
8438
8439     GST_INFO_OBJECT (element, "posting need context message");
8440     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8441         "drm-preferred-decryption-system-id");
8442     st = (GstStructure *) gst_message_get_structure (msg);
8443     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8444         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8445         NULL);
8446
8447     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8448     gst_element_post_message (element, msg);
8449   }
8450
8451   g_strfreev (filtered_sys_ids);
8452   g_value_unset (&event_list);
8453   gst_query_unref (query);
8454 }
8455
8456 static gboolean
8457 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8458     QtDemuxStream * stream)
8459 {
8460   GstStructure *s;
8461   const gchar *selected_system = NULL;
8462
8463   g_return_val_if_fail (qtdemux != NULL, FALSE);
8464   g_return_val_if_fail (stream != NULL, FALSE);
8465   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8466       FALSE);
8467
8468   if (stream->protection_scheme_type == FOURCC_aavd) {
8469     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8470     if (!gst_structure_has_name (s, "application/x-aavd")) {
8471       gst_structure_set (s,
8472           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8473           NULL);
8474       gst_structure_set_name (s, "application/x-aavd");
8475     }
8476     return TRUE;
8477   }
8478
8479   if (stream->protection_scheme_type != FOURCC_cenc
8480       && stream->protection_scheme_type != FOURCC_cbcs) {
8481     GST_ERROR_OBJECT (qtdemux,
8482         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8483         GST_FOURCC_ARGS (stream->protection_scheme_type));
8484     return FALSE;
8485   }
8486
8487   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8488   if (!gst_structure_has_name (s, "application/x-cenc")) {
8489     gst_structure_set (s,
8490         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8491     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8492         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8493         NULL);
8494     gst_structure_set_name (s, "application/x-cenc");
8495   }
8496
8497   if (qtdemux->protection_system_ids == NULL) {
8498     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8499         "cenc protection system information has been found, not setting a "
8500         "protection system UUID");
8501     return TRUE;
8502   }
8503
8504   gst_qtdemux_request_protection_context (qtdemux, stream);
8505   if (qtdemux->preferred_protection_system_id != NULL) {
8506     const gchar *preferred_system_array[] =
8507         { qtdemux->preferred_protection_system_id, NULL };
8508
8509     selected_system = gst_protection_select_system (preferred_system_array);
8510
8511     if (selected_system) {
8512       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8513           qtdemux->preferred_protection_system_id);
8514     } else {
8515       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8516           "because there is no available decryptor",
8517           qtdemux->preferred_protection_system_id);
8518     }
8519   }
8520
8521   if (!selected_system) {
8522     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8523     selected_system = gst_protection_select_system ((const gchar **)
8524         qtdemux->protection_system_ids->pdata);
8525     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8526         qtdemux->protection_system_ids->len - 1);
8527   }
8528
8529   if (!selected_system) {
8530     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8531         "suitable decryptor element has been found");
8532     return FALSE;
8533   }
8534
8535   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8536       selected_system);
8537
8538   gst_structure_set (s,
8539       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8540       NULL);
8541
8542   return TRUE;
8543 }
8544
8545 static gboolean
8546 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8547 {
8548   /* fps is calculated base on the duration of the average framerate since
8549    * qt does not have a fixed framerate. */
8550   gboolean fps_available = TRUE;
8551   guint32 first_duration = 0;
8552
8553   if (stream->n_samples > 0)
8554     first_duration = stream->samples[0].duration;
8555
8556   if ((stream->n_samples == 1 && first_duration == 0)
8557       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8558     /* still frame */
8559     CUR_STREAM (stream)->fps_n = 0;
8560     CUR_STREAM (stream)->fps_d = 1;
8561   } else {
8562     if (stream->duration == 0 || stream->n_samples < 2) {
8563       CUR_STREAM (stream)->fps_n = stream->timescale;
8564       CUR_STREAM (stream)->fps_d = 1;
8565       fps_available = FALSE;
8566     } else {
8567       GstClockTime avg_duration;
8568       guint64 duration;
8569       guint32 n_samples;
8570
8571       /* duration and n_samples can be updated for fragmented format
8572        * so, framerate of fragmented format is calculated using data in a moof */
8573       if (qtdemux->fragmented && stream->n_samples_moof > 0
8574           && stream->duration_moof > 0) {
8575         n_samples = stream->n_samples_moof;
8576         duration = stream->duration_moof;
8577       } else {
8578         n_samples = stream->n_samples;
8579         duration = stream->duration;
8580       }
8581
8582       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8583       /* stream->duration is guint64, timescale, n_samples are guint32 */
8584       avg_duration =
8585           gst_util_uint64_scale_round (duration -
8586           first_duration, GST_SECOND,
8587           (guint64) (stream->timescale) * (n_samples - 1));
8588
8589       GST_LOG_OBJECT (qtdemux,
8590           "Calculating avg sample duration based on stream (or moof) duration %"
8591           G_GUINT64_FORMAT
8592           " minus first sample %u, leaving %d samples gives %"
8593           GST_TIME_FORMAT, duration, first_duration,
8594           n_samples - 1, GST_TIME_ARGS (avg_duration));
8595
8596       fps_available =
8597           gst_video_guess_framerate (avg_duration,
8598           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8599
8600       GST_DEBUG_OBJECT (qtdemux,
8601           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8602           stream->timescale, CUR_STREAM (stream)->fps_n,
8603           CUR_STREAM (stream)->fps_d);
8604     }
8605   }
8606
8607   return fps_available;
8608 }
8609
8610 static gboolean
8611 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8612 {
8613   if (stream->subtype == FOURCC_vide) {
8614     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8615
8616     if (CUR_STREAM (stream)->caps) {
8617       CUR_STREAM (stream)->caps =
8618           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8619
8620       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8621         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8622             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8623             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8624
8625       /* set framerate if calculated framerate is reliable */
8626       if (fps_available) {
8627         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8628             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8629             CUR_STREAM (stream)->fps_d, NULL);
8630       }
8631
8632       /* calculate pixel-aspect-ratio using display width and height */
8633       GST_DEBUG_OBJECT (qtdemux,
8634           "video size %dx%d, target display size %dx%d",
8635           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8636           stream->display_width, stream->display_height);
8637       /* qt file might have pasp atom */
8638       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8639         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8640             CUR_STREAM (stream)->par_h);
8641         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8642             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8643             CUR_STREAM (stream)->par_h, NULL);
8644       } else if (stream->display_width > 0 && stream->display_height > 0
8645           && CUR_STREAM (stream)->width > 0
8646           && CUR_STREAM (stream)->height > 0) {
8647         gint n, d;
8648
8649         /* calculate the pixel aspect ratio using the display and pixel w/h */
8650         n = stream->display_width * CUR_STREAM (stream)->height;
8651         d = stream->display_height * CUR_STREAM (stream)->width;
8652         if (n == d)
8653           n = d = 1;
8654         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8655         CUR_STREAM (stream)->par_w = n;
8656         CUR_STREAM (stream)->par_h = d;
8657         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8658             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8659             CUR_STREAM (stream)->par_h, NULL);
8660       }
8661
8662       if (CUR_STREAM (stream)->interlace_mode > 0) {
8663         if (CUR_STREAM (stream)->interlace_mode == 1) {
8664           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8665               G_TYPE_STRING, "progressive", NULL);
8666         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8667           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8668               G_TYPE_STRING, "interleaved", NULL);
8669           if (CUR_STREAM (stream)->field_order == 9) {
8670             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8671                 G_TYPE_STRING, "top-field-first", NULL);
8672           } else if (CUR_STREAM (stream)->field_order == 14) {
8673             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8674                 G_TYPE_STRING, "bottom-field-first", NULL);
8675           }
8676         }
8677       }
8678
8679       /* Create incomplete colorimetry here if needed */
8680       if (CUR_STREAM (stream)->colorimetry.range ||
8681           CUR_STREAM (stream)->colorimetry.matrix ||
8682           CUR_STREAM (stream)->colorimetry.transfer
8683           || CUR_STREAM (stream)->colorimetry.primaries) {
8684         gchar *colorimetry =
8685             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8686         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8687             G_TYPE_STRING, colorimetry, NULL);
8688         g_free (colorimetry);
8689       }
8690
8691       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8692         guint par_w = 1, par_h = 1;
8693
8694         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8695           par_w = CUR_STREAM (stream)->par_w;
8696           par_h = CUR_STREAM (stream)->par_h;
8697         }
8698
8699         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8700                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8701                 par_h)) {
8702           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8703         }
8704
8705         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8706             "multiview-mode", G_TYPE_STRING,
8707             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8708             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8709             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8710       }
8711     }
8712   }
8713
8714   else if (stream->subtype == FOURCC_soun) {
8715     if (CUR_STREAM (stream)->caps) {
8716       CUR_STREAM (stream)->caps =
8717           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8718       if (CUR_STREAM (stream)->rate > 0)
8719         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8720             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8721       if (CUR_STREAM (stream)->n_channels > 0)
8722         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8723             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8724       if (CUR_STREAM (stream)->n_channels > 2) {
8725         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8726          * correctly; this is just the minimum we can do - assume
8727          * we don't actually have any channel positions. */
8728         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8729             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8730       }
8731     }
8732   }
8733
8734   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8735     const GstStructure *s;
8736     QtDemuxStream *fps_stream = NULL;
8737     gboolean fps_available = FALSE;
8738
8739     /* CEA608 closed caption tracks are a bit special in that each sample
8740      * can contain CCs for multiple frames, and CCs can be omitted and have to
8741      * be inferred from the duration of the sample then.
8742      *
8743      * As such we take the framerate from the (first) video track here for
8744      * CEA608 as there must be one CC byte pair for every video frame
8745      * according to the spec.
8746      *
8747      * For CEA708 all is fine and there is one sample per frame.
8748      */
8749
8750     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8751     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8752       gint i;
8753
8754       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8755         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8756
8757         if (tmp->subtype == FOURCC_vide) {
8758           fps_stream = tmp;
8759           break;
8760         }
8761       }
8762
8763       if (fps_stream) {
8764         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8765         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8766         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8767       }
8768     } else {
8769       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8770       fps_stream = stream;
8771     }
8772
8773     CUR_STREAM (stream)->caps =
8774         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8775
8776     /* set framerate if calculated framerate is reliable */
8777     if (fps_available) {
8778       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8779           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8780           CUR_STREAM (stream)->fps_d, NULL);
8781     }
8782   }
8783
8784   if (stream->pad) {
8785     GstCaps *prev_caps = NULL;
8786
8787     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8788     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8789     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8790     gst_pad_set_active (stream->pad, TRUE);
8791
8792     gst_pad_use_fixed_caps (stream->pad);
8793
8794     if (stream->protected) {
8795       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8796         GST_ERROR_OBJECT (qtdemux,
8797             "Failed to configure protected stream caps.");
8798         return FALSE;
8799       }
8800     }
8801
8802     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8803         CUR_STREAM (stream)->caps);
8804     if (stream->new_stream) {
8805       GstEvent *event;
8806       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8807
8808       event =
8809           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8810           0);
8811       if (event) {
8812         gst_event_parse_stream_flags (event, &stream_flags);
8813         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8814           qtdemux->have_group_id = TRUE;
8815         else
8816           qtdemux->have_group_id = FALSE;
8817         gst_event_unref (event);
8818       } else if (!qtdemux->have_group_id) {
8819         qtdemux->have_group_id = TRUE;
8820         qtdemux->group_id = gst_util_group_id_next ();
8821       }
8822
8823       stream->new_stream = FALSE;
8824       event = gst_event_new_stream_start (stream->stream_id);
8825       if (qtdemux->have_group_id)
8826         gst_event_set_group_id (event, qtdemux->group_id);
8827       if (stream->disabled)
8828         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8829       if (CUR_STREAM (stream)->sparse) {
8830         stream_flags |= GST_STREAM_FLAG_SPARSE;
8831       } else {
8832         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8833       }
8834       gst_event_set_stream_flags (event, stream_flags);
8835       gst_pad_push_event (stream->pad, event);
8836     }
8837
8838     prev_caps = gst_pad_get_current_caps (stream->pad);
8839
8840     if (CUR_STREAM (stream)->caps) {
8841       if (!prev_caps
8842           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8843         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8844             CUR_STREAM (stream)->caps);
8845         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8846       } else {
8847         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8848       }
8849     } else {
8850       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8851     }
8852
8853     if (prev_caps)
8854       gst_caps_unref (prev_caps);
8855     stream->new_caps = FALSE;
8856   }
8857   return TRUE;
8858 }
8859
8860 static void
8861 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8862     QtDemuxStream * stream)
8863 {
8864   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8865     return;
8866
8867   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8868       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8869   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8870           stream->stsd_entries_length)) {
8871     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8872         (_("This file is invalid and cannot be played.")),
8873         ("New sample description id is out of bounds (%d >= %d)",
8874             stream->stsd_sample_description_id, stream->stsd_entries_length));
8875   } else {
8876     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8877     stream->new_caps = TRUE;
8878   }
8879 }
8880
8881 static gboolean
8882 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8883     QtDemuxStream * stream, GstTagList * list)
8884 {
8885   gboolean ret = TRUE;
8886
8887   if (stream->subtype == FOURCC_vide) {
8888     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8889
8890     stream->pad =
8891         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8892     g_free (name);
8893
8894     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8895       gst_object_unref (stream->pad);
8896       stream->pad = NULL;
8897       ret = FALSE;
8898       goto done;
8899     }
8900
8901     qtdemux->n_video_streams++;
8902   } else if (stream->subtype == FOURCC_soun) {
8903     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8904
8905     stream->pad =
8906         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8907     g_free (name);
8908     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8909       gst_object_unref (stream->pad);
8910       stream->pad = NULL;
8911       ret = FALSE;
8912       goto done;
8913     }
8914     qtdemux->n_audio_streams++;
8915   } else if (stream->subtype == FOURCC_strm) {
8916     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8917   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8918       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8919       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
8920     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8921
8922     stream->pad =
8923         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8924     g_free (name);
8925     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8926       gst_object_unref (stream->pad);
8927       stream->pad = NULL;
8928       ret = FALSE;
8929       goto done;
8930     }
8931     qtdemux->n_sub_streams++;
8932   } else if (CUR_STREAM (stream)->caps) {
8933     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8934
8935     stream->pad =
8936         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8937     g_free (name);
8938     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8939       gst_object_unref (stream->pad);
8940       stream->pad = NULL;
8941       ret = FALSE;
8942       goto done;
8943     }
8944     qtdemux->n_video_streams++;
8945   } else {
8946     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8947     goto done;
8948   }
8949
8950   if (stream->pad) {
8951     GList *l;
8952
8953     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8954         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8955     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8956     GST_OBJECT_LOCK (qtdemux);
8957     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8958     GST_OBJECT_UNLOCK (qtdemux);
8959
8960     if (stream->stream_tags)
8961       gst_tag_list_unref (stream->stream_tags);
8962     stream->stream_tags = list;
8963     list = NULL;
8964     /* global tags go on each pad anyway */
8965     stream->send_global_tags = TRUE;
8966     /* send upstream GST_EVENT_PROTECTION events that were received before
8967        this source pad was created */
8968     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8969       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8970   }
8971 done:
8972   if (list)
8973     gst_tag_list_unref (list);
8974   return ret;
8975 }
8976
8977 /* find next atom with @fourcc starting at @offset */
8978 static GstFlowReturn
8979 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8980     guint64 * length, guint32 fourcc)
8981 {
8982   GstFlowReturn ret;
8983   guint32 lfourcc;
8984   GstBuffer *buf;
8985
8986   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8987       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8988
8989   while (TRUE) {
8990     GstMapInfo map;
8991
8992     buf = NULL;
8993     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8994     if (G_UNLIKELY (ret != GST_FLOW_OK))
8995       goto locate_failed;
8996     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8997       /* likely EOF */
8998       ret = GST_FLOW_EOS;
8999       gst_buffer_unref (buf);
9000       goto locate_failed;
9001     }
9002     gst_buffer_map (buf, &map, GST_MAP_READ);
9003     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9004     gst_buffer_unmap (buf, &map);
9005     gst_buffer_unref (buf);
9006
9007     if (G_UNLIKELY (*length == 0)) {
9008       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9009       ret = GST_FLOW_ERROR;
9010       goto locate_failed;
9011     }
9012
9013     if (lfourcc == fourcc) {
9014       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9015           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9016       break;
9017     } else {
9018       GST_LOG_OBJECT (qtdemux,
9019           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9020           GST_FOURCC_ARGS (lfourcc), *offset);
9021       if (*offset == G_MAXUINT64)
9022         goto locate_failed;
9023       *offset += *length;
9024     }
9025   }
9026
9027   return GST_FLOW_OK;
9028
9029 locate_failed:
9030   {
9031     /* might simply have had last one */
9032     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9033     return ret;
9034   }
9035 }
9036
9037 /* should only do something in pull mode */
9038 /* call with OBJECT lock */
9039 static GstFlowReturn
9040 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9041 {
9042   guint64 length, offset;
9043   GstBuffer *buf = NULL;
9044   GstFlowReturn ret = GST_FLOW_OK;
9045   GstFlowReturn res = GST_FLOW_OK;
9046   GstMapInfo map;
9047
9048   offset = qtdemux->moof_offset;
9049   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9050
9051   if (!offset) {
9052     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9053     return GST_FLOW_EOS;
9054   }
9055
9056   /* best not do pull etc with lock held */
9057   GST_OBJECT_UNLOCK (qtdemux);
9058
9059   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9060   if (ret != GST_FLOW_OK)
9061     goto flow_failed;
9062
9063   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9064   if (G_UNLIKELY (ret != GST_FLOW_OK))
9065     goto flow_failed;
9066   gst_buffer_map (buf, &map, GST_MAP_READ);
9067   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9068     gst_buffer_unmap (buf, &map);
9069     gst_buffer_unref (buf);
9070     buf = NULL;
9071     goto parse_failed;
9072   }
9073
9074   gst_buffer_unmap (buf, &map);
9075   gst_buffer_unref (buf);
9076   buf = NULL;
9077
9078   offset += length;
9079   /* look for next moof */
9080   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9081   if (G_UNLIKELY (ret != GST_FLOW_OK))
9082     goto flow_failed;
9083
9084 exit:
9085   GST_OBJECT_LOCK (qtdemux);
9086
9087   qtdemux->moof_offset = offset;
9088
9089   return res;
9090
9091 parse_failed:
9092   {
9093     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9094     offset = 0;
9095     res = GST_FLOW_ERROR;
9096     goto exit;
9097   }
9098 flow_failed:
9099   {
9100     /* maybe upstream temporarily flushing */
9101     if (ret != GST_FLOW_FLUSHING) {
9102       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9103       offset = 0;
9104     } else {
9105       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9106       /* resume at current position next time */
9107     }
9108     res = ret;
9109     goto exit;
9110   }
9111 }
9112
9113 static void
9114 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9115 {
9116   guint i;
9117   guint32 num_chunks;
9118   gint32 stts_duration;
9119   GstByteWriter stsc, stts, stsz;
9120
9121   /* Each sample has a different size, which we don't support for merging */
9122   if (stream->sample_size == 0) {
9123     GST_DEBUG_OBJECT (qtdemux,
9124         "Not all samples have the same size, not merging");
9125     return;
9126   }
9127
9128   /* The stream has a ctts table, we don't support that */
9129   if (stream->ctts_present) {
9130     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9131     return;
9132   }
9133
9134   /* If there's a sync sample table also ignore this stream */
9135   if (stream->stps_present || stream->stss_present) {
9136     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9137     return;
9138   }
9139
9140   /* If chunks are considered samples already ignore this stream */
9141   if (stream->chunks_are_samples) {
9142     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9143     return;
9144   }
9145
9146   /* Require that all samples have the same duration */
9147   if (stream->n_sample_times > 1) {
9148     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9149     return;
9150   }
9151
9152   /* Parse the stts to get the sample duration and number of samples */
9153   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9154   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9155
9156   /* Parse the number of chunks from the stco manually because the
9157    * reader is already behind that */
9158   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9159
9160   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9161       num_chunks);
9162
9163   /* Now parse stsc, convert chunks into single samples and generate a
9164    * new stsc, stts and stsz from this information */
9165   gst_byte_writer_init (&stsc);
9166   gst_byte_writer_init (&stts);
9167   gst_byte_writer_init (&stsz);
9168
9169   /* Note: we skip fourccs, size, version, flags and other fields of the new
9170    * atoms as the byte readers with them are already behind that position
9171    * anyway and only update the values of those inside the stream directly.
9172    */
9173   stream->n_sample_times = 0;
9174   stream->n_samples = 0;
9175   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9176     guint j;
9177     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9178
9179     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9180     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9181     sample_description_id =
9182         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9183
9184     if (i == stream->n_samples_per_chunk - 1) {
9185       /* +1 because first_chunk is 1-based */
9186       last_chunk = num_chunks + 1;
9187     } else {
9188       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9189     }
9190
9191     GST_DEBUG_OBJECT (qtdemux,
9192         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9193         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9194
9195     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9196     /* One sample in this chunk */
9197     gst_byte_writer_put_uint32_be (&stsc, 1);
9198     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9199
9200     /* For each chunk write a stts and stsz entry now */
9201     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9202     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9203     for (j = first_chunk; j < last_chunk; j++) {
9204       gst_byte_writer_put_uint32_be (&stsz,
9205           stream->sample_size * samples_per_chunk);
9206     }
9207
9208     stream->n_sample_times += 1;
9209     stream->n_samples += last_chunk - first_chunk;
9210   }
9211
9212   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9213
9214   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9215       stream->n_samples, stream->n_sample_times);
9216
9217   /* We don't have a fixed sample size anymore */
9218   stream->sample_size = 0;
9219
9220   /* Free old data for the atoms */
9221   g_free ((gpointer) stream->stsz.data);
9222   stream->stsz.data = NULL;
9223   g_free ((gpointer) stream->stsc.data);
9224   stream->stsc.data = NULL;
9225   g_free ((gpointer) stream->stts.data);
9226   stream->stts.data = NULL;
9227
9228   /* Store new data and replace byte readers */
9229   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9230   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9231   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9232   stream->stts.size = gst_byte_writer_get_size (&stts);
9233   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9234   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9235   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9236   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9237   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9238 }
9239
9240 /* initialise bytereaders for stbl sub-atoms */
9241 static gboolean
9242 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9243 {
9244   stream->stbl_index = -1;      /* no samples have yet been parsed */
9245   stream->sample_index = -1;
9246
9247   /* time-to-sample atom */
9248   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9249     goto corrupt_file;
9250
9251   /* copy atom data into a new buffer for later use */
9252   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9253
9254   /* skip version + flags */
9255   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9256       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9257     goto corrupt_file;
9258   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9259
9260   /* make sure there's enough data */
9261   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9262     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9263     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9264         stream->n_sample_times);
9265     if (!stream->n_sample_times)
9266       goto corrupt_file;
9267   }
9268
9269   /* sync sample atom */
9270   stream->stps_present = FALSE;
9271   if ((stream->stss_present =
9272           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9273               &stream->stss) ? TRUE : FALSE) == TRUE) {
9274     /* copy atom data into a new buffer for later use */
9275     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9276
9277     /* skip version + flags */
9278     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9279         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9280       goto corrupt_file;
9281
9282     if (stream->n_sample_syncs) {
9283       /* make sure there's enough data */
9284       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9285         goto corrupt_file;
9286     }
9287
9288     /* partial sync sample atom */
9289     if ((stream->stps_present =
9290             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9291                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9292       /* copy atom data into a new buffer for later use */
9293       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9294
9295       /* skip version + flags */
9296       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9297           !gst_byte_reader_get_uint32_be (&stream->stps,
9298               &stream->n_sample_partial_syncs))
9299         goto corrupt_file;
9300
9301       /* if there are no entries, the stss table contains the real
9302        * sync samples */
9303       if (stream->n_sample_partial_syncs) {
9304         /* make sure there's enough data */
9305         if (!qt_atom_parser_has_chunks (&stream->stps,
9306                 stream->n_sample_partial_syncs, 4))
9307           goto corrupt_file;
9308       }
9309     }
9310   }
9311
9312   /* sample size */
9313   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9314     goto no_samples;
9315
9316   /* copy atom data into a new buffer for later use */
9317   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9318
9319   /* skip version + flags */
9320   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9321       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9322     goto corrupt_file;
9323
9324   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9325     goto corrupt_file;
9326
9327   if (!stream->n_samples)
9328     goto no_samples;
9329
9330   /* sample-to-chunk atom */
9331   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9332     goto corrupt_file;
9333
9334   /* copy atom data into a new buffer for later use */
9335   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9336
9337   /* skip version + flags */
9338   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9339       !gst_byte_reader_get_uint32_be (&stream->stsc,
9340           &stream->n_samples_per_chunk))
9341     goto corrupt_file;
9342
9343   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9344       stream->n_samples_per_chunk);
9345
9346   /* make sure there's enough data */
9347   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9348           12))
9349     goto corrupt_file;
9350
9351
9352   /* chunk offset */
9353   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9354     stream->co_size = sizeof (guint32);
9355   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9356           &stream->stco))
9357     stream->co_size = sizeof (guint64);
9358   else
9359     goto corrupt_file;
9360
9361   /* copy atom data into a new buffer for later use */
9362   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9363
9364   /* skip version + flags */
9365   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9366     goto corrupt_file;
9367
9368   /* chunks_are_samples == TRUE means treat chunks as samples */
9369   stream->chunks_are_samples = stream->sample_size
9370       && !CUR_STREAM (stream)->sampled;
9371   if (stream->chunks_are_samples) {
9372     /* treat chunks as samples */
9373     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9374       goto corrupt_file;
9375   } else {
9376     /* skip number of entries */
9377     if (!gst_byte_reader_skip (&stream->stco, 4))
9378       goto corrupt_file;
9379
9380     /* make sure there are enough data in the stsz atom */
9381     if (!stream->sample_size) {
9382       /* different sizes for each sample */
9383       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9384         goto corrupt_file;
9385     }
9386   }
9387
9388   /* composition time-to-sample */
9389   if ((stream->ctts_present =
9390           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9391               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9392     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9393     guint8 ctts_version;
9394     gboolean checked_ctts = FALSE;
9395
9396     /* copy atom data into a new buffer for later use */
9397     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9398
9399     /* version 1 has signed offsets */
9400     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9401       goto corrupt_file;
9402
9403     /* flags */
9404     if (!gst_byte_reader_skip (&stream->ctts, 3)
9405         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9406             &stream->n_composition_times))
9407       goto corrupt_file;
9408
9409     /* make sure there's enough data */
9410     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9411             4 + 4))
9412       goto corrupt_file;
9413
9414     /* This is optional, if missing we iterate the ctts */
9415     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9416       guint8 cslg_version;
9417
9418       /* cslg version 1 has 64 bit fields */
9419       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9420         goto corrupt_file;
9421
9422       /* skip flags */
9423       if (!gst_byte_reader_skip (&cslg, 3))
9424         goto corrupt_file;
9425
9426       if (cslg_version == 0) {
9427         gint32 composition_to_dts_shift;
9428
9429         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9430           goto corrupt_file;
9431
9432         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9433       } else {
9434         gint64 composition_to_dts_shift;
9435
9436         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9437           goto corrupt_file;
9438
9439         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9440       }
9441     } else {
9442       gint32 cslg_least = 0;
9443       guint num_entries, pos;
9444       gint i;
9445
9446       pos = gst_byte_reader_get_pos (&stream->ctts);
9447       num_entries = stream->n_composition_times;
9448
9449       checked_ctts = TRUE;
9450
9451       stream->cslg_shift = 0;
9452
9453       for (i = 0; i < num_entries; i++) {
9454         gint32 offset;
9455
9456         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9457         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9458         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9459          * slightly inaccurate PTS could be more usable than corrupted one */
9460         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9461           GST_WARNING_OBJECT (qtdemux,
9462               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9463               " larger than duration %" G_GUINT64_FORMAT,
9464               offset, stream->duration);
9465
9466           stream->cslg_shift = 0;
9467           stream->ctts_present = FALSE;
9468           goto done;
9469         }
9470
9471         if (offset < cslg_least)
9472           cslg_least = offset;
9473       }
9474
9475       if (cslg_least < 0)
9476         stream->cslg_shift = -cslg_least;
9477       else
9478         stream->cslg_shift = 0;
9479
9480       /* reset the reader so we can generate sample table */
9481       gst_byte_reader_set_pos (&stream->ctts, pos);
9482     }
9483
9484     /* Check if ctts values are looking reasonable if that didn't happen above */
9485     if (!checked_ctts) {
9486       guint num_entries, pos;
9487       gint i;
9488
9489       pos = gst_byte_reader_get_pos (&stream->ctts);
9490       num_entries = stream->n_composition_times;
9491
9492       for (i = 0; i < num_entries; i++) {
9493         gint32 offset;
9494
9495         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9496         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9497         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9498          * slightly inaccurate PTS could be more usable than corrupted one */
9499         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9500           GST_WARNING_OBJECT (qtdemux,
9501               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9502               " larger than duration %" G_GUINT64_FORMAT,
9503               offset, stream->duration);
9504
9505           stream->cslg_shift = 0;
9506           stream->ctts_present = FALSE;
9507           goto done;
9508         }
9509       }
9510
9511       /* reset the reader so we can generate sample table */
9512       gst_byte_reader_set_pos (&stream->ctts, pos);
9513     }
9514   } else {
9515     /* Ensure the cslg_shift value is consistent so we can use it
9516      * unconditionally to produce TS and Segment */
9517     stream->cslg_shift = 0;
9518   }
9519
9520   /* For raw audio streams especially we might want to merge the samples
9521    * to not output one audio sample per buffer. We're doing this here
9522    * before allocating the sample tables so that from this point onwards
9523    * the number of container samples are static */
9524   if (stream->min_buffer_size > 0) {
9525     qtdemux_merge_sample_table (qtdemux, stream);
9526   }
9527
9528 done:
9529   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9530       stream->n_samples, (guint) sizeof (QtDemuxSample),
9531       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9532
9533   if (stream->n_samples >=
9534       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9535     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9536         "be larger than %uMB (broken file?)", stream->n_samples,
9537         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9538     return FALSE;
9539   }
9540
9541   g_assert (stream->samples == NULL);
9542   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9543   if (!stream->samples) {
9544     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9545         stream->n_samples);
9546     return FALSE;
9547   }
9548
9549   return TRUE;
9550
9551 corrupt_file:
9552   {
9553     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9554         (_("This file is corrupt and cannot be played.")), (NULL));
9555     return FALSE;
9556   }
9557 no_samples:
9558   {
9559     gst_qtdemux_stbl_free (stream);
9560     if (!qtdemux->fragmented) {
9561       /* not quite good */
9562       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9563       return FALSE;
9564     } else {
9565       /* may pick up samples elsewhere */
9566       return TRUE;
9567     }
9568   }
9569 }
9570
9571 /* collect samples from the next sample to be parsed up to sample @n for @stream
9572  * by reading the info from @stbl
9573  *
9574  * This code can be executed from both the streaming thread and the seeking
9575  * thread so it takes the object lock to protect itself
9576  */
9577 static gboolean
9578 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9579 {
9580   gint i, j, k;
9581   QtDemuxSample *samples, *first, *cur, *last;
9582   guint32 n_samples_per_chunk;
9583   guint32 n_samples;
9584
9585   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9586       GST_FOURCC_FORMAT ", pad %s",
9587       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9588       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9589
9590   n_samples = stream->n_samples;
9591
9592   if (n >= n_samples)
9593     goto out_of_samples;
9594
9595   GST_OBJECT_LOCK (qtdemux);
9596   if (n <= stream->stbl_index)
9597     goto already_parsed;
9598
9599   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9600
9601   if (!stream->stsz.data) {
9602     /* so we already parsed and passed all the moov samples;
9603      * onto fragmented ones */
9604     g_assert (qtdemux->fragmented);
9605     goto done;
9606   }
9607
9608   /* pointer to the sample table */
9609   samples = stream->samples;
9610
9611   /* starts from -1, moves to the next sample index to parse */
9612   stream->stbl_index++;
9613
9614   /* keep track of the first and last sample to fill */
9615   first = &samples[stream->stbl_index];
9616   last = &samples[n];
9617
9618   if (!stream->chunks_are_samples) {
9619     /* set the sample sizes */
9620     if (stream->sample_size == 0) {
9621       /* different sizes for each sample */
9622       for (cur = first; cur <= last; cur++) {
9623         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9624         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9625             (guint) (cur - samples), cur->size);
9626       }
9627     } else {
9628       /* samples have the same size */
9629       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9630       for (cur = first; cur <= last; cur++)
9631         cur->size = stream->sample_size;
9632     }
9633   }
9634
9635   n_samples_per_chunk = stream->n_samples_per_chunk;
9636   cur = first;
9637
9638   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9639     guint32 last_chunk;
9640
9641     if (stream->stsc_chunk_index >= stream->last_chunk
9642         || stream->stsc_chunk_index < stream->first_chunk) {
9643       stream->first_chunk =
9644           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9645       stream->samples_per_chunk =
9646           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9647       /* starts from 1 */
9648       stream->stsd_sample_description_id =
9649           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9650
9651       /* chunk numbers are counted from 1 it seems */
9652       if (G_UNLIKELY (stream->first_chunk == 0))
9653         goto corrupt_file;
9654
9655       --stream->first_chunk;
9656
9657       /* the last chunk of each entry is calculated by taking the first chunk
9658        * of the next entry; except if there is no next, where we fake it with
9659        * INT_MAX */
9660       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9661         stream->last_chunk = G_MAXUINT32;
9662       } else {
9663         stream->last_chunk =
9664             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9665         if (G_UNLIKELY (stream->last_chunk == 0))
9666           goto corrupt_file;
9667
9668         --stream->last_chunk;
9669       }
9670
9671       GST_LOG_OBJECT (qtdemux,
9672           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9673           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9674           stream->samples_per_chunk, stream->stsd_sample_description_id);
9675
9676       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9677         goto corrupt_file;
9678
9679       if (stream->last_chunk != G_MAXUINT32) {
9680         if (!qt_atom_parser_peek_sub (&stream->stco,
9681                 stream->first_chunk * stream->co_size,
9682                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9683                 &stream->co_chunk))
9684           goto corrupt_file;
9685
9686       } else {
9687         stream->co_chunk = stream->stco;
9688         if (!gst_byte_reader_skip (&stream->co_chunk,
9689                 stream->first_chunk * stream->co_size))
9690           goto corrupt_file;
9691       }
9692
9693       stream->stsc_chunk_index = stream->first_chunk;
9694     }
9695
9696     last_chunk = stream->last_chunk;
9697
9698     if (stream->chunks_are_samples) {
9699       cur = &samples[stream->stsc_chunk_index];
9700
9701       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9702         if (j > n) {
9703           /* save state */
9704           stream->stsc_chunk_index = j;
9705           goto done;
9706         }
9707
9708         cur->offset =
9709             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9710             stream->co_size);
9711
9712         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9713             "%" G_GUINT64_FORMAT, j, cur->offset);
9714
9715         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9716             CUR_STREAM (stream)->bytes_per_frame > 0) {
9717           cur->size =
9718               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9719               CUR_STREAM (stream)->samples_per_frame *
9720               CUR_STREAM (stream)->bytes_per_frame;
9721         } else {
9722           cur->size = stream->samples_per_chunk;
9723         }
9724
9725         GST_DEBUG_OBJECT (qtdemux,
9726             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9727             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9728                     stream->stco_sample_index)), cur->size);
9729
9730         cur->timestamp = stream->stco_sample_index;
9731         cur->duration = stream->samples_per_chunk;
9732         cur->keyframe = TRUE;
9733         cur++;
9734
9735         stream->stco_sample_index += stream->samples_per_chunk;
9736       }
9737       stream->stsc_chunk_index = j;
9738     } else {
9739       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9740         guint32 samples_per_chunk;
9741         guint64 chunk_offset;
9742
9743         if (!stream->stsc_sample_index
9744             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9745                 &stream->chunk_offset))
9746           goto corrupt_file;
9747
9748         samples_per_chunk = stream->samples_per_chunk;
9749         chunk_offset = stream->chunk_offset;
9750
9751         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9752           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9753               G_GUINT64_FORMAT " and size %d",
9754               (guint) (cur - samples), chunk_offset, cur->size);
9755
9756           cur->offset = chunk_offset;
9757           chunk_offset += cur->size;
9758           cur++;
9759
9760           if (G_UNLIKELY (cur > last)) {
9761             /* save state */
9762             stream->stsc_sample_index = k + 1;
9763             stream->chunk_offset = chunk_offset;
9764             stream->stsc_chunk_index = j;
9765             goto done2;
9766           }
9767         }
9768         stream->stsc_sample_index = 0;
9769       }
9770       stream->stsc_chunk_index = j;
9771     }
9772     stream->stsc_index++;
9773   }
9774
9775   if (stream->chunks_are_samples)
9776     goto ctts;
9777 done2:
9778   {
9779     guint32 n_sample_times;
9780
9781     n_sample_times = stream->n_sample_times;
9782     cur = first;
9783
9784     for (i = stream->stts_index; i < n_sample_times; i++) {
9785       guint32 stts_samples;
9786       gint32 stts_duration;
9787       gint64 stts_time;
9788
9789       if (stream->stts_sample_index >= stream->stts_samples
9790           || !stream->stts_sample_index) {
9791
9792         stream->stts_samples =
9793             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9794         stream->stts_duration =
9795             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9796
9797         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9798             i, stream->stts_samples, stream->stts_duration);
9799
9800         stream->stts_sample_index = 0;
9801       }
9802
9803       stts_samples = stream->stts_samples;
9804       stts_duration = stream->stts_duration;
9805       stts_time = stream->stts_time;
9806
9807       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9808         GST_DEBUG_OBJECT (qtdemux,
9809             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9810             (guint) (cur - samples), j,
9811             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9812
9813         cur->timestamp = stts_time;
9814         cur->duration = stts_duration;
9815
9816         /* avoid 32-bit wrap-around,
9817          * but still mind possible 'negative' duration */
9818         stts_time += (gint64) stts_duration;
9819         cur++;
9820
9821         if (G_UNLIKELY (cur > last)) {
9822           /* save values */
9823           stream->stts_time = stts_time;
9824           stream->stts_sample_index = j + 1;
9825           if (stream->stts_sample_index >= stream->stts_samples)
9826             stream->stts_index++;
9827           goto done3;
9828         }
9829       }
9830       stream->stts_sample_index = 0;
9831       stream->stts_time = stts_time;
9832       stream->stts_index++;
9833     }
9834     /* fill up empty timestamps with the last timestamp, this can happen when
9835      * the last samples do not decode and so we don't have timestamps for them.
9836      * We however look at the last timestamp to estimate the track length so we
9837      * need something in here. */
9838     for (; cur < last; cur++) {
9839       GST_DEBUG_OBJECT (qtdemux,
9840           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9841           (guint) (cur - samples),
9842           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9843       cur->timestamp = stream->stts_time;
9844       cur->duration = -1;
9845     }
9846   }
9847 done3:
9848   {
9849     /* sample sync, can be NULL */
9850     if (stream->stss_present == TRUE) {
9851       guint32 n_sample_syncs;
9852
9853       n_sample_syncs = stream->n_sample_syncs;
9854
9855       if (!n_sample_syncs) {
9856         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9857         stream->all_keyframe = TRUE;
9858       } else {
9859         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9860           /* note that the first sample is index 1, not 0 */
9861           guint32 index;
9862
9863           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9864
9865           if (G_LIKELY (index > 0 && index <= n_samples)) {
9866             index -= 1;
9867             samples[index].keyframe = TRUE;
9868             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9869             /* and exit if we have enough samples */
9870             if (G_UNLIKELY (index >= n)) {
9871               i++;
9872               break;
9873             }
9874           }
9875         }
9876         /* save state */
9877         stream->stss_index = i;
9878       }
9879
9880       /* stps marks partial sync frames like open GOP I-Frames */
9881       if (stream->stps_present == TRUE) {
9882         guint32 n_sample_partial_syncs;
9883
9884         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9885
9886         /* if there are no entries, the stss table contains the real
9887          * sync samples */
9888         if (n_sample_partial_syncs) {
9889           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9890             /* note that the first sample is index 1, not 0 */
9891             guint32 index;
9892
9893             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9894
9895             if (G_LIKELY (index > 0 && index <= n_samples)) {
9896               index -= 1;
9897               samples[index].keyframe = TRUE;
9898               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9899               /* and exit if we have enough samples */
9900               if (G_UNLIKELY (index >= n)) {
9901                 i++;
9902                 break;
9903               }
9904             }
9905           }
9906           /* save state */
9907           stream->stps_index = i;
9908         }
9909       }
9910     } else {
9911       /* no stss, all samples are keyframes */
9912       stream->all_keyframe = TRUE;
9913       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9914     }
9915   }
9916
9917 ctts:
9918   /* composition time to sample */
9919   if (stream->ctts_present == TRUE) {
9920     guint32 n_composition_times;
9921     guint32 ctts_count;
9922     gint32 ctts_soffset;
9923
9924     /* Fill in the pts_offsets */
9925     cur = first;
9926     n_composition_times = stream->n_composition_times;
9927
9928     for (i = stream->ctts_index; i < n_composition_times; i++) {
9929       if (stream->ctts_sample_index >= stream->ctts_count
9930           || !stream->ctts_sample_index) {
9931         stream->ctts_count =
9932             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9933         stream->ctts_soffset =
9934             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9935         stream->ctts_sample_index = 0;
9936       }
9937
9938       ctts_count = stream->ctts_count;
9939       ctts_soffset = stream->ctts_soffset;
9940
9941       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9942         cur->pts_offset = ctts_soffset;
9943         cur++;
9944
9945         if (G_UNLIKELY (cur > last)) {
9946           /* save state */
9947           stream->ctts_sample_index = j + 1;
9948           goto done;
9949         }
9950       }
9951       stream->ctts_sample_index = 0;
9952       stream->ctts_index++;
9953     }
9954   }
9955 done:
9956   stream->stbl_index = n;
9957   /* if index has been completely parsed, free data that is no-longer needed */
9958   if (n + 1 == stream->n_samples) {
9959     gst_qtdemux_stbl_free (stream);
9960     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9961     if (qtdemux->pullbased) {
9962       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9963       while (n + 1 == stream->n_samples)
9964         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9965           break;
9966     }
9967   }
9968   GST_OBJECT_UNLOCK (qtdemux);
9969
9970   return TRUE;
9971
9972   /* SUCCESS */
9973 already_parsed:
9974   {
9975     GST_LOG_OBJECT (qtdemux,
9976         "Tried to parse up to sample %u but this sample has already been parsed",
9977         n);
9978     /* if fragmented, there may be more */
9979     if (qtdemux->fragmented && n == stream->stbl_index)
9980       goto done;
9981     GST_OBJECT_UNLOCK (qtdemux);
9982     return TRUE;
9983   }
9984   /* ERRORS */
9985 out_of_samples:
9986   {
9987     GST_LOG_OBJECT (qtdemux,
9988         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9989         stream->n_samples);
9990     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9991         (_("This file is corrupt and cannot be played.")), (NULL));
9992     return FALSE;
9993   }
9994 corrupt_file:
9995   {
9996     GST_OBJECT_UNLOCK (qtdemux);
9997     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9998         (_("This file is corrupt and cannot be played.")), (NULL));
9999     return FALSE;
10000   }
10001 }
10002
10003 /* collect all segment info for @stream.
10004  */
10005 static gboolean
10006 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10007     GNode * trak)
10008 {
10009   GNode *edts;
10010   /* accept edts if they contain gaps at start and there is only
10011    * one media segment */
10012   gboolean allow_pushbased_edts = TRUE;
10013   gint media_segments_count = 0;
10014
10015   /* parse and prepare segment info from the edit list */
10016   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10017   stream->n_segments = 0;
10018   stream->segments = NULL;
10019   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10020     GNode *elst;
10021     gint n_segments;
10022     gint segment_number, entry_size;
10023     guint64 time;
10024     GstClockTime stime;
10025     const guint8 *buffer;
10026     guint8 version;
10027     guint32 size;
10028
10029     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10030     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10031       goto done;
10032
10033     buffer = elst->data;
10034
10035     size = QT_UINT32 (buffer);
10036     /* version, flags, n_segments */
10037     if (size < 16) {
10038       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10039       goto done;
10040     }
10041     version = QT_UINT8 (buffer + 8);
10042     entry_size = (version == 1) ? 20 : 12;
10043
10044     n_segments = QT_UINT32 (buffer + 12);
10045
10046     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10047       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10048       goto done;
10049     }
10050
10051     /* we might allocate a bit too much, at least allocate 1 segment */
10052     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10053
10054     /* segments always start from 0 */
10055     time = 0;
10056     stime = 0;
10057     buffer += 16;
10058     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10059       guint64 duration;
10060       guint64 media_time;
10061       gboolean empty_edit = FALSE;
10062       QtDemuxSegment *segment;
10063       guint32 rate_int;
10064       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10065
10066       if (version == 1) {
10067         media_time = QT_UINT64 (buffer + 8);
10068         duration = QT_UINT64 (buffer);
10069         if (media_time == G_MAXUINT64)
10070           empty_edit = TRUE;
10071       } else {
10072         media_time = QT_UINT32 (buffer + 4);
10073         duration = QT_UINT32 (buffer);
10074         if (media_time == G_MAXUINT32)
10075           empty_edit = TRUE;
10076       }
10077
10078       if (!empty_edit)
10079         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10080
10081       segment = &stream->segments[segment_number];
10082
10083       /* time and duration expressed in global timescale */
10084       segment->time = stime;
10085       if (duration != 0 || empty_edit) {
10086         /* edge case: empty edits with duration=zero are treated here.
10087          * (files should not have these anyway). */
10088
10089         /* add non scaled values so we don't cause roundoff errors */
10090         time += duration;
10091         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10092         segment->duration = stime - segment->time;
10093       } else {
10094         /* zero duration does not imply media_start == media_stop
10095          * but, only specify media_start. The edit ends with the track. */
10096         stime = segment->duration = GST_CLOCK_TIME_NONE;
10097         /* Don't allow more edits after this one. */
10098         n_segments = segment_number + 1;
10099       }
10100       segment->stop_time = stime;
10101
10102       segment->trak_media_start = media_time;
10103       /* media_time expressed in stream timescale */
10104       if (!empty_edit) {
10105         segment->media_start = media_start;
10106         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10107             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10108         media_segments_count++;
10109       } else {
10110         segment->media_start = GST_CLOCK_TIME_NONE;
10111         segment->media_stop = GST_CLOCK_TIME_NONE;
10112       }
10113       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10114
10115       if (rate_int <= 1) {
10116         /* 0 is not allowed, some programs write 1 instead of the floating point
10117          * value */
10118         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10119             rate_int);
10120         segment->rate = 1;
10121       } else {
10122         segment->rate = rate_int / 65536.0;
10123       }
10124
10125       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10126           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10127           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10128           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10129           segment_number, GST_TIME_ARGS (segment->time),
10130           GST_TIME_ARGS (segment->duration),
10131           GST_TIME_ARGS (segment->media_start), media_time,
10132           GST_TIME_ARGS (segment->media_stop),
10133           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10134           stream->timescale);
10135       if (segment->stop_time > qtdemux->segment.stop &&
10136           !qtdemux->upstream_format_is_time) {
10137         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10138             " extends to %" GST_TIME_FORMAT
10139             " past the end of the declared movie duration %" GST_TIME_FORMAT
10140             " movie segment will be extended", segment_number,
10141             GST_TIME_ARGS (segment->stop_time),
10142             GST_TIME_ARGS (qtdemux->segment.stop));
10143         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10144       }
10145
10146       buffer += entry_size;
10147     }
10148     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10149     stream->n_segments = n_segments;
10150     if (media_segments_count != 1)
10151       allow_pushbased_edts = FALSE;
10152   }
10153 done:
10154
10155   /* push based does not handle segments, so act accordingly here,
10156    * and warn if applicable */
10157   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10158     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10159     /* remove and use default one below, we stream like it anyway */
10160     g_free (stream->segments);
10161     stream->segments = NULL;
10162     stream->n_segments = 0;
10163   }
10164
10165   /* no segments, create one to play the complete trak */
10166   if (stream->n_segments == 0) {
10167     GstClockTime stream_duration =
10168         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10169
10170     if (stream->segments == NULL)
10171       stream->segments = g_new (QtDemuxSegment, 1);
10172
10173     /* represent unknown our way */
10174     if (stream_duration == 0)
10175       stream_duration = GST_CLOCK_TIME_NONE;
10176
10177     stream->segments[0].time = 0;
10178     stream->segments[0].stop_time = stream_duration;
10179     stream->segments[0].duration = stream_duration;
10180     stream->segments[0].media_start = 0;
10181     stream->segments[0].media_stop = stream_duration;
10182     stream->segments[0].rate = 1.0;
10183     stream->segments[0].trak_media_start = 0;
10184
10185     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10186         GST_TIME_ARGS (stream_duration));
10187     stream->n_segments = 1;
10188     stream->dummy_segment = TRUE;
10189   }
10190   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10191
10192   return TRUE;
10193 }
10194
10195 /*
10196  * Parses the stsd atom of a svq3 trak looking for
10197  * the SMI and gama atoms.
10198  */
10199 static void
10200 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10201     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10202 {
10203   const guint8 *_gamma = NULL;
10204   GstBuffer *_seqh = NULL;
10205   const guint8 *stsd_data = stsd_entry_data;
10206   guint32 length = QT_UINT32 (stsd_data);
10207   guint16 version;
10208
10209   if (length < 32) {
10210     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10211     goto end;
10212   }
10213
10214   stsd_data += 16;
10215   length -= 16;
10216   version = QT_UINT16 (stsd_data);
10217   if (version == 3) {
10218     if (length >= 70) {
10219       length -= 70;
10220       stsd_data += 70;
10221       while (length > 8) {
10222         guint32 fourcc, size;
10223         const guint8 *data;
10224         size = QT_UINT32 (stsd_data);
10225         fourcc = QT_FOURCC (stsd_data + 4);
10226         data = stsd_data + 8;
10227
10228         if (size == 0) {
10229           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10230               "svq3 atom parsing");
10231           goto end;
10232         }
10233
10234         switch (fourcc) {
10235           case FOURCC_gama:{
10236             if (size == 12) {
10237               _gamma = data;
10238             } else {
10239               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10240                   " for gama atom, expected 12", size);
10241             }
10242             break;
10243           }
10244           case FOURCC_SMI_:{
10245             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10246               guint32 seqh_size;
10247               if (_seqh != NULL) {
10248                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10249                     " found, ignoring");
10250               } else {
10251                 seqh_size = QT_UINT32 (data + 4);
10252                 if (seqh_size > 0) {
10253                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10254                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10255                 }
10256               }
10257             }
10258             break;
10259           }
10260           default:{
10261             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10262                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10263           }
10264         }
10265
10266         if (size <= length) {
10267           length -= size;
10268           stsd_data += size;
10269         }
10270       }
10271     } else {
10272       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10273     }
10274   } else {
10275     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10276         G_GUINT16_FORMAT, version);
10277     goto end;
10278   }
10279
10280 end:
10281   if (gamma) {
10282     *gamma = _gamma;
10283   }
10284   if (seqh) {
10285     *seqh = _seqh;
10286   } else if (_seqh) {
10287     gst_buffer_unref (_seqh);
10288   }
10289 }
10290
10291 static gchar *
10292 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10293 {
10294   GNode *dinf;
10295   GstByteReader dref;
10296   gchar *uri = NULL;
10297
10298   /*
10299    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10300    * atom that might contain a 'data' atom with the rtsp uri.
10301    * This case was reported in bug #597497, some info about
10302    * the hndl atom can be found in TN1195
10303    */
10304   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10305   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10306
10307   if (dinf) {
10308     guint32 dref_num_entries = 0;
10309     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10310         gst_byte_reader_skip (&dref, 4) &&
10311         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10312       gint i;
10313
10314       /* search dref entries for hndl atom */
10315       for (i = 0; i < dref_num_entries; i++) {
10316         guint32 size = 0, type;
10317         guint8 string_len = 0;
10318         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10319             qt_atom_parser_get_fourcc (&dref, &type)) {
10320           if (type == FOURCC_hndl) {
10321             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10322
10323             /* skip data reference handle bytes and the
10324              * following pascal string and some extra 4
10325              * bytes I have no idea what are */
10326             if (!gst_byte_reader_skip (&dref, 4) ||
10327                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10328                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10329               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10330               break;
10331             }
10332
10333             /* iterate over the atoms to find the data atom */
10334             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10335               guint32 atom_size;
10336               guint32 atom_type;
10337
10338               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10339                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10340                 if (atom_type == FOURCC_data) {
10341                   const guint8 *uri_aux = NULL;
10342
10343                   /* found the data atom that might contain the rtsp uri */
10344                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10345                       "hndl atom, interpreting it as an URI");
10346                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10347                           &uri_aux)) {
10348                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10349                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10350                     else
10351                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10352                           "didn't contain a rtsp address");
10353                   } else {
10354                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10355                         "atom contents");
10356                   }
10357                   break;
10358                 }
10359                 /* skipping to the next entry */
10360                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10361                   break;
10362               } else {
10363                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10364                     "atom header");
10365                 break;
10366               }
10367             }
10368             break;
10369           }
10370           /* skip to the next entry */
10371           if (!gst_byte_reader_skip (&dref, size - 8))
10372             break;
10373         } else {
10374           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10375         }
10376       }
10377       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10378     }
10379   }
10380   return uri;
10381 }
10382
10383 #define AMR_NB_ALL_MODES        0x81ff
10384 #define AMR_WB_ALL_MODES        0x83ff
10385 static guint
10386 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10387 {
10388   /* The 'damr' atom is of the form:
10389    *
10390    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10391    *    32 b       8 b          16 b           8 b                 8 b
10392    *
10393    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10394    * represents the highest mode used in the stream (and thus the maximum
10395    * bitrate), with a couple of special cases as seen below.
10396    */
10397
10398   /* Map of frame type ID -> bitrate */
10399   static const guint nb_bitrates[] = {
10400     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10401   };
10402   static const guint wb_bitrates[] = {
10403     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10404   };
10405   GstMapInfo map;
10406   gsize max_mode;
10407   guint16 mode_set;
10408
10409   gst_buffer_map (buf, &map, GST_MAP_READ);
10410
10411   if (map.size != 0x11) {
10412     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10413     goto bad_data;
10414   }
10415
10416   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10417     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10418         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10419     goto bad_data;
10420   }
10421
10422   mode_set = QT_UINT16 (map.data + 13);
10423
10424   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10425     max_mode = 7 + (wb ? 1 : 0);
10426   else
10427     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10428     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10429
10430   if (max_mode == -1) {
10431     GST_DEBUG ("No mode indication was found (mode set) = %x",
10432         (guint) mode_set);
10433     goto bad_data;
10434   }
10435
10436   gst_buffer_unmap (buf, &map);
10437   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10438
10439 bad_data:
10440   gst_buffer_unmap (buf, &map);
10441   return 0;
10442 }
10443
10444 static gboolean
10445 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10446     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10447 {
10448   /*
10449    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10450    * [0 1 2]
10451    * [3 4 5]
10452    * [6 7 8]
10453    */
10454
10455   if (gst_byte_reader_get_remaining (reader) < 36)
10456     return FALSE;
10457
10458   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10459   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10460   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10461   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10462   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10463   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10464   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10465   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10466   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10467
10468   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10469   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10470       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10471       matrix[2] & 0xFF);
10472   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10473       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10474       matrix[5] & 0xFF);
10475   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10476       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10477       matrix[8] & 0xFF);
10478
10479   return TRUE;
10480 }
10481
10482 static void
10483 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10484     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10485 {
10486
10487 /* [a b c]
10488  * [d e f]
10489  * [g h i]
10490  *
10491  * This macro will only compare value abdegh, it expects cfi to have already
10492  * been checked
10493  */
10494 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10495                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10496
10497   /* only handle the cases where the last column has standard values */
10498   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10499     const gchar *rotation_tag = NULL;
10500
10501     /* no rotation needed */
10502     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10503       /* NOP */
10504     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10505       rotation_tag = "rotate-90";
10506     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10507       rotation_tag = "rotate-180";
10508     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10509       rotation_tag = "rotate-270";
10510     } else {
10511       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10512     }
10513
10514     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10515         GST_STR_NULL (rotation_tag));
10516     if (rotation_tag != NULL) {
10517       if (*taglist == NULL)
10518         *taglist = gst_tag_list_new_empty ();
10519       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10520           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10521     }
10522   } else {
10523     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10524   }
10525 }
10526
10527 static gboolean
10528 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10529     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10530 {
10531   GNode *adrm;
10532   guint32 adrm_size;
10533   GstBuffer *adrm_buf = NULL;
10534   QtDemuxAavdEncryptionInfo *info;
10535
10536   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10537   if (G_UNLIKELY (!adrm)) {
10538     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10539     return FALSE;
10540   }
10541   adrm_size = QT_UINT32 (adrm->data);
10542   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10543
10544   stream->protection_scheme_type = FOURCC_aavd;
10545
10546   if (!stream->protection_scheme_info)
10547     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10548
10549   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10550
10551   if (info->default_properties)
10552     gst_structure_free (info->default_properties);
10553   info->default_properties = gst_structure_new ("application/x-aavd",
10554       "encrypted", G_TYPE_BOOLEAN, TRUE,
10555       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10556   gst_buffer_unref (adrm_buf);
10557
10558   *original_fmt = FOURCC_mp4a;
10559   return TRUE;
10560 }
10561
10562 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10563  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10564  * Common Encryption (cenc), the function will also parse the tenc box (defined
10565  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10566  * (typically an enc[v|a|t|s] sample entry); the function will set
10567  * @original_fmt to the fourcc of the original unencrypted stream format.
10568  * Returns TRUE if successful; FALSE otherwise. */
10569 static gboolean
10570 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10571     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10572 {
10573   GNode *sinf;
10574   GNode *frma;
10575   GNode *schm;
10576   GNode *schi;
10577   QtDemuxCencSampleSetInfo *info;
10578   GNode *tenc;
10579   const guint8 *tenc_data;
10580
10581   g_return_val_if_fail (qtdemux != NULL, FALSE);
10582   g_return_val_if_fail (stream != NULL, FALSE);
10583   g_return_val_if_fail (container != NULL, FALSE);
10584   g_return_val_if_fail (original_fmt != NULL, FALSE);
10585
10586   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10587   if (G_UNLIKELY (!sinf)) {
10588     if (stream->protection_scheme_type == FOURCC_cenc
10589         || stream->protection_scheme_type == FOURCC_cbcs) {
10590       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10591           "mandatory for Common Encryption");
10592       return FALSE;
10593     }
10594     return TRUE;
10595   }
10596
10597   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10598   if (G_UNLIKELY (!frma)) {
10599     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10600     return FALSE;
10601   }
10602
10603   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10604   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10605       GST_FOURCC_ARGS (*original_fmt));
10606
10607   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10608   if (!schm) {
10609     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10610     return FALSE;
10611   }
10612   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10613   stream->protection_scheme_version =
10614       QT_UINT32 ((const guint8 *) schm->data + 16);
10615
10616   GST_DEBUG_OBJECT (qtdemux,
10617       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10618       "protection_scheme_version: %#010x",
10619       GST_FOURCC_ARGS (stream->protection_scheme_type),
10620       stream->protection_scheme_version);
10621
10622   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10623   if (!schi) {
10624     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10625     return FALSE;
10626   }
10627   if (stream->protection_scheme_type != FOURCC_cenc &&
10628       stream->protection_scheme_type != FOURCC_piff &&
10629       stream->protection_scheme_type != FOURCC_cbcs) {
10630     GST_ERROR_OBJECT (qtdemux,
10631         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10632         GST_FOURCC_ARGS (stream->protection_scheme_type));
10633     return FALSE;
10634   }
10635
10636   if (G_UNLIKELY (!stream->protection_scheme_info))
10637     stream->protection_scheme_info =
10638         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10639
10640   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10641
10642   if (stream->protection_scheme_type == FOURCC_cenc
10643       || stream->protection_scheme_type == FOURCC_cbcs) {
10644     guint8 is_encrypted;
10645     guint8 iv_size;
10646     guint8 constant_iv_size = 0;
10647     const guint8 *default_kid;
10648     guint8 crypt_byte_block = 0;
10649     guint8 skip_byte_block = 0;
10650     const guint8 *constant_iv = NULL;
10651
10652     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10653     if (!tenc) {
10654       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10655           "which is mandatory for Common Encryption");
10656       return FALSE;
10657     }
10658     tenc_data = (const guint8 *) tenc->data + 12;
10659     is_encrypted = QT_UINT8 (tenc_data + 2);
10660     iv_size = QT_UINT8 (tenc_data + 3);
10661     default_kid = (tenc_data + 4);
10662     if (stream->protection_scheme_type == FOURCC_cbcs) {
10663       guint8 possible_pattern_info;
10664       if (iv_size == 0) {
10665         constant_iv_size = QT_UINT8 (tenc_data + 20);
10666         if (constant_iv_size != 8 && constant_iv_size != 16) {
10667           GST_ERROR_OBJECT (qtdemux,
10668               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10669           return FALSE;
10670         }
10671         constant_iv = (tenc_data + 21);
10672       }
10673       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10674       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10675       skip_byte_block = possible_pattern_info & 0x0f;
10676     }
10677     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10678         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10679         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10680   } else if (stream->protection_scheme_type == FOURCC_piff) {
10681     GstByteReader br;
10682     static const guint8 piff_track_encryption_uuid[] = {
10683       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10684       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10685     };
10686
10687     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10688     if (!tenc) {
10689       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10690           "which is mandatory for Common Encryption");
10691       return FALSE;
10692     }
10693
10694     tenc_data = (const guint8 *) tenc->data + 8;
10695     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10696       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10697       GST_ERROR_OBJECT (qtdemux,
10698           "Unsupported track encryption box with uuid: %s", box_uuid);
10699       g_free (box_uuid);
10700       return FALSE;
10701     }
10702     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10703     gst_byte_reader_init (&br, tenc_data, 20);
10704     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10705       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10706       return FALSE;
10707     }
10708     stream->protection_scheme_type = FOURCC_cenc;
10709   }
10710
10711   return TRUE;
10712 }
10713
10714 static gint
10715 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10716     QtDemuxStream ** stream2)
10717 {
10718   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10719 }
10720
10721 static gboolean
10722 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10723     GNode * stbl)
10724 {
10725   GNode *svmi;
10726
10727   /*parse svmi header if existing */
10728   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10729   if (svmi) {
10730     guint len = QT_UINT32 ((guint8 *) svmi->data);
10731     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10732     if (!version) {
10733       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10734       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10735       guint8 frame_type, frame_layout;
10736       guint32 stereo_mono_change_count;
10737
10738       if (len < 18)
10739         return FALSE;
10740
10741       /* MPEG-A stereo video */
10742       if (qtdemux->major_brand == FOURCC_ss02)
10743         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10744
10745       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10746       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10747       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10748
10749       switch (frame_type) {
10750         case 0:
10751           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10752           break;
10753         case 1:
10754           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10755           break;
10756         case 2:
10757           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10758           break;
10759         case 3:
10760           /* mode 3 is primary/secondary view sequence, ie
10761            * left/right views in separate tracks. See section 7.2
10762            * of ISO/IEC 23000-11:2009 */
10763           /* In the future this might be supported using related
10764            * streams, like an enhancement track - if files like this
10765            * ever exist */
10766           GST_FIXME_OBJECT (qtdemux,
10767               "Implement stereo video in separate streams");
10768       }
10769
10770       if ((frame_layout & 0x1) == 0)
10771         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10772
10773       GST_LOG_OBJECT (qtdemux,
10774           "StereoVideo: composition type: %u, is_left_first: %u",
10775           frame_type, frame_layout);
10776
10777       if (stereo_mono_change_count > 1) {
10778         GST_FIXME_OBJECT (qtdemux,
10779             "Mixed-mono flags are not yet supported in qtdemux.");
10780       }
10781
10782       stream->multiview_mode = mode;
10783       stream->multiview_flags = flags;
10784     }
10785   }
10786
10787   return TRUE;
10788 }
10789
10790 /* parse the traks.
10791  * With each track we associate a new QtDemuxStream that contains all the info
10792  * about the trak.
10793  * traks that do not decode to something (like strm traks) will not have a pad.
10794  */
10795 static gboolean
10796 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10797 {
10798   GstByteReader tkhd;
10799   int offset;
10800   GNode *mdia;
10801   GNode *mdhd;
10802   GNode *hdlr;
10803   GNode *minf;
10804   GNode *stbl;
10805   GNode *stsd;
10806   GNode *mp4a;
10807   GNode *mp4v;
10808   GNode *esds;
10809   GNode *tref;
10810   GNode *udta;
10811
10812   QtDemuxStream *stream = NULL;
10813   const guint8 *stsd_data;
10814   const guint8 *stsd_entry_data;
10815   guint remaining_stsd_len;
10816   guint stsd_entry_count;
10817   guint stsd_index;
10818   guint16 lang_code;            /* quicktime lang code or packed iso code */
10819   guint32 version;
10820   guint32 tkhd_flags = 0;
10821   guint8 tkhd_version = 0;
10822   guint32 w = 0, h = 0;
10823   guint value_size, stsd_len, len;
10824   guint32 track_id;
10825   guint32 dummy;
10826
10827   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10828
10829   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10830       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10831       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10832     goto corrupt_file;
10833
10834   /* pick between 64 or 32 bits */
10835   value_size = tkhd_version == 1 ? 8 : 4;
10836   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10837       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10838     goto corrupt_file;
10839
10840   /* Check if current moov has duplicated track_id */
10841   if (qtdemux_find_stream (qtdemux, track_id))
10842     goto existing_stream;
10843
10844   stream = _create_stream (qtdemux, track_id);
10845   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10846
10847   /* need defaults for fragments */
10848   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10849
10850   if ((tkhd_flags & 1) == 0)
10851     stream->disabled = TRUE;
10852
10853   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10854       tkhd_version, tkhd_flags, stream->track_id);
10855
10856   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10857     goto corrupt_file;
10858
10859   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10860     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10861     if (qtdemux->major_brand != FOURCC_mjp2 ||
10862         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10863       goto corrupt_file;
10864   }
10865
10866   len = QT_UINT32 ((guint8 *) mdhd->data);
10867   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10868   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10869   if (version == 0x01000000) {
10870     if (len < 42)
10871       goto corrupt_file;
10872     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10873     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10874     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10875   } else {
10876     if (len < 30)
10877       goto corrupt_file;
10878     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10879     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10880     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10881   }
10882
10883   if (lang_code < 0x400) {
10884     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10885   } else if (lang_code == 0x7fff) {
10886     stream->lang_id[0] = 0;     /* unspecified */
10887   } else {
10888     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10889     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10890     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10891     stream->lang_id[3] = 0;
10892   }
10893
10894   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10895       stream->timescale);
10896   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10897       stream->duration);
10898   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10899       lang_code, stream->lang_id);
10900
10901   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10902     goto corrupt_file;
10903
10904   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10905     /* chapters track reference */
10906     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10907     if (chap) {
10908       gsize length = GST_READ_UINT32_BE (chap->data);
10909       if (qtdemux->chapters_track_id)
10910         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10911
10912       if (length >= 12) {
10913         qtdemux->chapters_track_id =
10914             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10915       }
10916     }
10917   }
10918
10919   /* fragmented files may have bogus duration in moov */
10920   if (!qtdemux->fragmented &&
10921       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10922     guint64 tdur1, tdur2;
10923
10924     /* don't overflow */
10925     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10926     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10927
10928     /* HACK:
10929      * some of those trailers, nowadays, have prologue images that are
10930      * themselves video tracks as well. I haven't really found a way to
10931      * identify those yet, except for just looking at their duration. */
10932     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10933       GST_WARNING_OBJECT (qtdemux,
10934           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10935           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10936           "found, assuming preview image or something; skipping track",
10937           stream->duration, stream->timescale, qtdemux->duration,
10938           qtdemux->timescale);
10939       gst_qtdemux_stream_unref (stream);
10940       return TRUE;
10941     }
10942   }
10943
10944   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10945     goto corrupt_file;
10946
10947   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10948       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10949
10950   len = QT_UINT32 ((guint8 *) hdlr->data);
10951   if (len >= 20)
10952     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10953   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10954       GST_FOURCC_ARGS (stream->subtype));
10955
10956   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10957     goto corrupt_file;
10958
10959   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10960     goto corrupt_file;
10961
10962   /* Parse out svmi (and later st3d/sv3d) atoms */
10963   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10964     goto corrupt_file;
10965
10966   /* parse rest of tkhd */
10967   if (stream->subtype == FOURCC_vide) {
10968     guint32 matrix[9];
10969
10970     /* version 1 uses some 64-bit ints */
10971     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10972       goto corrupt_file;
10973
10974     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10975       goto corrupt_file;
10976
10977     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10978         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10979       goto corrupt_file;
10980
10981     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10982         &stream->stream_tags);
10983   }
10984
10985   /* parse stsd */
10986   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10987     goto corrupt_file;
10988   stsd_data = (const guint8 *) stsd->data;
10989
10990   /* stsd should at least have one entry */
10991   stsd_len = QT_UINT32 (stsd_data);
10992   if (stsd_len < 24) {
10993     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10994     if (stream->subtype == FOURCC_vivo) {
10995       gst_qtdemux_stream_unref (stream);
10996       return TRUE;
10997     } else {
10998       goto corrupt_file;
10999     }
11000   }
11001
11002   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11003   /* each stsd entry must contain at least 8 bytes */
11004   if (stream->stsd_entries_length == 0
11005       || stream->stsd_entries_length > stsd_len / 8) {
11006     stream->stsd_entries_length = 0;
11007     goto corrupt_file;
11008   }
11009   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11010   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11011   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11012
11013   stsd_entry_data = stsd_data + 16;
11014   remaining_stsd_len = stsd_len - 16;
11015   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11016     guint32 fourcc;
11017     gchar *codec = NULL;
11018     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11019
11020     /* and that entry should fit within stsd */
11021     len = QT_UINT32 (stsd_entry_data);
11022     if (len > remaining_stsd_len)
11023       goto corrupt_file;
11024
11025     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11026     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11027         GST_FOURCC_ARGS (entry->fourcc));
11028     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11029
11030     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11031       goto error_encrypted;
11032
11033     if (fourcc == FOURCC_aavd) {
11034       if (stream->subtype != FOURCC_soun) {
11035         GST_ERROR_OBJECT (qtdemux,
11036             "Unexpeced stsd type 'aavd' outside 'soun' track");
11037       } else {
11038         /* encrypted audio with sound sample description v0 */
11039         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11040         stream->protected = TRUE;
11041         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11042           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11043       }
11044     }
11045
11046     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11047       /* FIXME this looks wrong, there might be multiple children
11048        * with the same type */
11049       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11050       stream->protected = TRUE;
11051       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11052         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11053     }
11054
11055     if (stream->subtype == FOURCC_vide) {
11056       GNode *colr;
11057       GNode *fiel;
11058       GNode *pasp;
11059       gboolean gray;
11060       gint depth, palette_size, palette_count;
11061       guint32 *palette_data = NULL;
11062
11063       entry->sampled = TRUE;
11064
11065       stream->display_width = w >> 16;
11066       stream->display_height = h >> 16;
11067
11068       offset = 16;
11069       if (len < 86)             /* TODO verify */
11070         goto corrupt_file;
11071
11072       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11073       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11074       entry->fps_n = 0;         /* this is filled in later */
11075       entry->fps_d = 0;         /* this is filled in later */
11076       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11077       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11078
11079       /* if color_table_id is 0, ctab atom must follow; however some files
11080        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11081        * if color table is not present we'll correct the value */
11082       if (entry->color_table_id == 0 &&
11083           (len < 90
11084               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11085         entry->color_table_id = -1;
11086       }
11087
11088       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11089           entry->width, entry->height, entry->bits_per_sample,
11090           entry->color_table_id);
11091
11092       depth = entry->bits_per_sample;
11093
11094       /* more than 32 bits means grayscale */
11095       gray = (depth > 32);
11096       /* low 32 bits specify the depth  */
11097       depth &= 0x1F;
11098
11099       /* different number of palette entries is determined by depth. */
11100       palette_count = 0;
11101       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11102         palette_count = (1 << depth);
11103       palette_size = palette_count * 4;
11104
11105       if (entry->color_table_id) {
11106         switch (palette_count) {
11107           case 0:
11108             break;
11109           case 2:
11110             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11111             break;
11112           case 4:
11113             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11114             break;
11115           case 16:
11116             if (gray)
11117               palette_data =
11118                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11119             else
11120               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11121             break;
11122           case 256:
11123             if (gray)
11124               palette_data =
11125                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11126             else
11127               palette_data =
11128                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11129             break;
11130           default:
11131             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11132                 (_("The video in this file might not play correctly.")),
11133                 ("unsupported palette depth %d", depth));
11134             break;
11135         }
11136       } else {
11137         gint i, j, start, end;
11138
11139         if (len < 94)
11140           goto corrupt_file;
11141
11142         /* read table */
11143         start = QT_UINT32 (stsd_entry_data + offset + 70);
11144         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11145         end = QT_UINT16 (stsd_entry_data + offset + 76);
11146
11147         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11148             start, end, palette_count);
11149
11150         if (end > 255)
11151           end = 255;
11152         if (start > end)
11153           start = end;
11154
11155         if (len < 94 + (end - start) * 8)
11156           goto corrupt_file;
11157
11158         /* palette is always the same size */
11159         palette_data = g_malloc0 (256 * 4);
11160         palette_size = 256 * 4;
11161
11162         for (j = 0, i = start; i <= end; j++, i++) {
11163           guint32 a, r, g, b;
11164
11165           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11166           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11167           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11168           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11169
11170           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11171               (g & 0xff00) | (b >> 8);
11172         }
11173       }
11174
11175       if (entry->caps)
11176         gst_caps_unref (entry->caps);
11177
11178       entry->caps =
11179           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11180           &codec);
11181       if (G_UNLIKELY (!entry->caps)) {
11182         g_free (palette_data);
11183         goto unknown_stream;
11184       }
11185
11186       if (codec) {
11187         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11188             GST_TAG_VIDEO_CODEC, codec, NULL);
11189         g_free (codec);
11190         codec = NULL;
11191       }
11192
11193       if (palette_data) {
11194         GstStructure *s;
11195
11196         if (entry->rgb8_palette)
11197           gst_memory_unref (entry->rgb8_palette);
11198         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11199             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11200
11201         s = gst_caps_get_structure (entry->caps, 0);
11202
11203         /* non-raw video has a palette_data property. raw video has the palette as
11204          * an extra plane that we append to the output buffers before we push
11205          * them*/
11206         if (!gst_structure_has_name (s, "video/x-raw")) {
11207           GstBuffer *palette;
11208
11209           palette = gst_buffer_new ();
11210           gst_buffer_append_memory (palette, entry->rgb8_palette);
11211           entry->rgb8_palette = NULL;
11212
11213           gst_caps_set_simple (entry->caps, "palette_data",
11214               GST_TYPE_BUFFER, palette, NULL);
11215           gst_buffer_unref (palette);
11216         }
11217       } else if (palette_count != 0) {
11218         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11219             (NULL), ("Unsupported palette depth %d", depth));
11220       }
11221
11222       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11223           QT_UINT16 (stsd_entry_data + offset + 32));
11224
11225       esds = NULL;
11226       pasp = NULL;
11227       colr = NULL;
11228       fiel = NULL;
11229       /* pick 'the' stsd child */
11230       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11231       // We should skip parsing the stsd for non-protected streams if
11232       // the entry doesn't match the fourcc, since they don't change
11233       // format. However, for protected streams we can have partial
11234       // encryption, where parts of the stream are encrypted and parts
11235       // not. For both parts of such streams, we should ensure the
11236       // esds overrides are parsed for both from the stsd.
11237       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11238         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11239           mp4v = NULL;
11240         else if (!stream->protected)
11241           mp4v = NULL;
11242       }
11243
11244       if (mp4v) {
11245         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11246         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11247         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11248         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11249       }
11250
11251       if (pasp) {
11252         const guint8 *pasp_data = (const guint8 *) pasp->data;
11253         gint len = QT_UINT32 (pasp_data);
11254
11255         if (len == 16) {
11256           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11257           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11258         } else {
11259           CUR_STREAM (stream)->par_w = 0;
11260           CUR_STREAM (stream)->par_h = 0;
11261         }
11262       } else {
11263         CUR_STREAM (stream)->par_w = 0;
11264         CUR_STREAM (stream)->par_h = 0;
11265       }
11266
11267       if (fiel) {
11268         const guint8 *fiel_data = (const guint8 *) fiel->data;
11269         gint len = QT_UINT32 (fiel_data);
11270
11271         if (len == 10) {
11272           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11273           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11274         }
11275       }
11276
11277       if (colr) {
11278         const guint8 *colr_data = (const guint8 *) colr->data;
11279         gint len = QT_UINT32 (colr_data);
11280
11281         if (len == 19 || len == 18) {
11282           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11283
11284           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11285             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11286             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11287             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11288             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11289
11290             CUR_STREAM (stream)->colorimetry.primaries =
11291                 gst_video_color_primaries_from_iso (primaries);
11292             CUR_STREAM (stream)->colorimetry.transfer =
11293                 gst_video_transfer_function_from_iso (transfer_function);
11294             CUR_STREAM (stream)->colorimetry.matrix =
11295                 gst_video_color_matrix_from_iso (matrix);
11296             CUR_STREAM (stream)->colorimetry.range =
11297                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11298                 GST_VIDEO_COLOR_RANGE_16_235;
11299           } else {
11300             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11301           }
11302         } else {
11303           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11304         }
11305       }
11306
11307       if (esds) {
11308         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11309             stream->stream_tags);
11310       } else {
11311         switch (fourcc) {
11312           case FOURCC_H264:
11313           case FOURCC_avc1:
11314           case FOURCC_avc3:
11315           {
11316             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11317             const guint8 *avc_data = stsd_entry_data + 0x56;
11318
11319             /* find avcC */
11320             while (len >= 0x8) {
11321               gint size;
11322
11323               if (QT_UINT32 (avc_data) <= len)
11324                 size = QT_UINT32 (avc_data) - 0x8;
11325               else
11326                 size = len - 0x8;
11327
11328               if (size < 1)
11329                 /* No real data, so break out */
11330                 break;
11331
11332               switch (QT_FOURCC (avc_data + 0x4)) {
11333                 case FOURCC_avcC:
11334                 {
11335                   /* parse, if found */
11336                   GstBuffer *buf;
11337
11338                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11339
11340                   /* First 4 bytes are the length of the atom, the next 4 bytes
11341                    * are the fourcc, the next 1 byte is the version, and the
11342                    * subsequent bytes are profile_tier_level structure like data. */
11343                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11344                       avc_data + 8 + 1, size - 1);
11345                   buf = gst_buffer_new_and_alloc (size);
11346                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11347                   gst_caps_set_simple (entry->caps,
11348                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11349                   gst_buffer_unref (buf);
11350
11351                   break;
11352                 }
11353                 case FOURCC_strf:
11354                 {
11355                   GstBuffer *buf;
11356
11357                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11358
11359                   /* First 4 bytes are the length of the atom, the next 4 bytes
11360                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11361                    * next 1 byte is the version, and the
11362                    * subsequent bytes are sequence parameter set like data. */
11363
11364                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11365                   if (size > 1) {
11366                     gst_codec_utils_h264_caps_set_level_and_profile
11367                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11368
11369                     buf = gst_buffer_new_and_alloc (size);
11370                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11371                     gst_caps_set_simple (entry->caps,
11372                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11373                     gst_buffer_unref (buf);
11374                   }
11375                   break;
11376                 }
11377                 case FOURCC_btrt:
11378                 {
11379                   guint avg_bitrate, max_bitrate;
11380
11381                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11382                   if (size < 12)
11383                     break;
11384
11385                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11386                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11387
11388                   if (!max_bitrate && !avg_bitrate)
11389                     break;
11390
11391                   /* Some muxers seem to swap the average and maximum bitrates
11392                    * (I'm looking at you, YouTube), so we swap for sanity. */
11393                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11394                     guint temp = avg_bitrate;
11395
11396                     avg_bitrate = max_bitrate;
11397                     max_bitrate = temp;
11398                   }
11399
11400                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11401                     gst_tag_list_add (stream->stream_tags,
11402                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11403                         max_bitrate, NULL);
11404                   }
11405                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11406                     gst_tag_list_add (stream->stream_tags,
11407                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11408                         NULL);
11409                   }
11410
11411                   break;
11412                 }
11413
11414                 default:
11415                   break;
11416               }
11417
11418               len -= size + 8;
11419               avc_data += size + 8;
11420             }
11421
11422             break;
11423           }
11424           case FOURCC_H265:
11425           case FOURCC_hvc1:
11426           case FOURCC_hev1:
11427           case FOURCC_dvh1:
11428           case FOURCC_dvhe:
11429           {
11430             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11431             const guint8 *hevc_data = stsd_entry_data + 0x56;
11432
11433             /* find hevc */
11434             while (len >= 0x8) {
11435               gint size;
11436
11437               if (QT_UINT32 (hevc_data) <= len)
11438                 size = QT_UINT32 (hevc_data) - 0x8;
11439               else
11440                 size = len - 0x8;
11441
11442               if (size < 1)
11443                 /* No real data, so break out */
11444                 break;
11445
11446               switch (QT_FOURCC (hevc_data + 0x4)) {
11447                 case FOURCC_hvcC:
11448                 {
11449                   /* parse, if found */
11450                   GstBuffer *buf;
11451
11452                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11453
11454                   /* First 4 bytes are the length of the atom, the next 4 bytes
11455                    * are the fourcc, the next 1 byte is the version, and the
11456                    * subsequent bytes are sequence parameter set like data. */
11457                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11458                       (entry->caps, hevc_data + 8 + 1, size - 1);
11459
11460                   buf = gst_buffer_new_and_alloc (size);
11461                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11462                   gst_caps_set_simple (entry->caps,
11463                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11464                   gst_buffer_unref (buf);
11465                   break;
11466                 }
11467                 default:
11468                   break;
11469               }
11470               len -= size + 8;
11471               hevc_data += size + 8;
11472             }
11473             break;
11474           }
11475           case FOURCC_mp4v:
11476           case FOURCC_MP4V:
11477           case FOURCC_fmp4:
11478           case FOURCC_FMP4:
11479           case FOURCC_xvid:
11480           case FOURCC_XVID:
11481           {
11482             GNode *glbl;
11483
11484             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11485                 GST_FOURCC_ARGS (fourcc));
11486
11487             /* codec data might be in glbl extension atom */
11488             glbl = mp4v ?
11489                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11490             if (glbl) {
11491               guint8 *data;
11492               GstBuffer *buf;
11493               gint len;
11494
11495               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11496               data = glbl->data;
11497               len = QT_UINT32 (data);
11498               if (len > 0x8) {
11499                 len -= 0x8;
11500                 buf = gst_buffer_new_and_alloc (len);
11501                 gst_buffer_fill (buf, 0, data + 8, len);
11502                 gst_caps_set_simple (entry->caps,
11503                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11504                 gst_buffer_unref (buf);
11505               }
11506             }
11507             break;
11508           }
11509           case FOURCC_mjp2:
11510           {
11511             /* see annex I of the jpeg2000 spec */
11512             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11513             const guint8 *data;
11514             const gchar *colorspace = NULL;
11515             gint ncomp = 0;
11516             guint32 ncomp_map = 0;
11517             gint32 *comp_map = NULL;
11518             guint32 nchan_def = 0;
11519             gint32 *chan_def = NULL;
11520
11521             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11522             /* some required atoms */
11523             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11524             if (!mjp2)
11525               break;
11526             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11527             if (!jp2h)
11528               break;
11529
11530             /* number of components; redundant with info in codestream, but useful
11531                to a muxer */
11532             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11533             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11534               break;
11535             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11536
11537             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11538             if (!colr)
11539               break;
11540             GST_DEBUG_OBJECT (qtdemux, "found colr");
11541             /* extract colour space info */
11542             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11543               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11544                 case 16:
11545                   colorspace = "sRGB";
11546                   break;
11547                 case 17:
11548                   colorspace = "GRAY";
11549                   break;
11550                 case 18:
11551                   colorspace = "sYUV";
11552                   break;
11553                 default:
11554                   colorspace = NULL;
11555                   break;
11556               }
11557             }
11558             if (!colorspace)
11559               /* colr is required, and only values 16, 17, and 18 are specified,
11560                  so error if we have no colorspace */
11561               break;
11562
11563             /* extract component mapping */
11564             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11565             if (cmap) {
11566               guint32 cmap_len = 0;
11567               int i;
11568               cmap_len = QT_UINT32 (cmap->data);
11569               if (cmap_len >= 8) {
11570                 /* normal box, subtract off header */
11571                 cmap_len -= 8;
11572                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11573                 if (cmap_len % 4 == 0) {
11574                   ncomp_map = (cmap_len / 4);
11575                   comp_map = g_new0 (gint32, ncomp_map);
11576                   for (i = 0; i < ncomp_map; i++) {
11577                     guint16 cmp;
11578                     guint8 mtyp, pcol;
11579                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11580                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11581                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11582                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11583                   }
11584                 }
11585               }
11586             }
11587             /* extract channel definitions */
11588             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11589             if (cdef) {
11590               guint32 cdef_len = 0;
11591               int i;
11592               cdef_len = QT_UINT32 (cdef->data);
11593               if (cdef_len >= 10) {
11594                 /* normal box, subtract off header and len */
11595                 cdef_len -= 10;
11596                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11597                 if (cdef_len % 6 == 0) {
11598                   nchan_def = (cdef_len / 6);
11599                   chan_def = g_new0 (gint32, nchan_def);
11600                   for (i = 0; i < nchan_def; i++)
11601                     chan_def[i] = -1;
11602                   for (i = 0; i < nchan_def; i++) {
11603                     guint16 cn, typ, asoc;
11604                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11605                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11606                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11607                     if (cn < nchan_def) {
11608                       switch (typ) {
11609                         case 0:
11610                           chan_def[cn] = asoc;
11611                           break;
11612                         case 1:
11613                           chan_def[cn] = 0;     /* alpha */
11614                           break;
11615                         default:
11616                           chan_def[cn] = -typ;
11617                       }
11618                     }
11619                   }
11620                 }
11621               }
11622             }
11623
11624             gst_caps_set_simple (entry->caps,
11625                 "num-components", G_TYPE_INT, ncomp, NULL);
11626             gst_caps_set_simple (entry->caps,
11627                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11628
11629             if (comp_map) {
11630               GValue arr = { 0, };
11631               GValue elt = { 0, };
11632               int i;
11633               g_value_init (&arr, GST_TYPE_ARRAY);
11634               g_value_init (&elt, G_TYPE_INT);
11635               for (i = 0; i < ncomp_map; i++) {
11636                 g_value_set_int (&elt, comp_map[i]);
11637                 gst_value_array_append_value (&arr, &elt);
11638               }
11639               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11640                   "component-map", &arr);
11641               g_value_unset (&elt);
11642               g_value_unset (&arr);
11643               g_free (comp_map);
11644             }
11645
11646             if (chan_def) {
11647               GValue arr = { 0, };
11648               GValue elt = { 0, };
11649               int i;
11650               g_value_init (&arr, GST_TYPE_ARRAY);
11651               g_value_init (&elt, G_TYPE_INT);
11652               for (i = 0; i < nchan_def; i++) {
11653                 g_value_set_int (&elt, chan_def[i]);
11654                 gst_value_array_append_value (&arr, &elt);
11655               }
11656               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11657                   "channel-definitions", &arr);
11658               g_value_unset (&elt);
11659               g_value_unset (&arr);
11660               g_free (chan_def);
11661             }
11662
11663             /* some optional atoms */
11664             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11665             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11666
11667             /* indicate possible fields in caps */
11668             if (field) {
11669               data = (guint8 *) field->data + 8;
11670               if (*data != 1)
11671                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11672                     (gint) * data, NULL);
11673             }
11674             /* add codec_data if provided */
11675             if (prefix) {
11676               GstBuffer *buf;
11677               gint len;
11678
11679               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11680               data = prefix->data;
11681               len = QT_UINT32 (data);
11682               if (len > 0x8) {
11683                 len -= 0x8;
11684                 buf = gst_buffer_new_and_alloc (len);
11685                 gst_buffer_fill (buf, 0, data + 8, len);
11686                 gst_caps_set_simple (entry->caps,
11687                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11688                 gst_buffer_unref (buf);
11689               }
11690             }
11691             break;
11692           }
11693           case FOURCC_SVQ3:
11694           case FOURCC_VP31:
11695           {
11696             GstBuffer *buf;
11697             GstBuffer *seqh = NULL;
11698             const guint8 *gamma_data = NULL;
11699             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11700
11701             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11702                 &seqh);
11703             if (gamma_data) {
11704               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11705                   QT_FP32 (gamma_data), NULL);
11706             }
11707             if (seqh) {
11708               /* sorry for the bad name, but we don't know what this is, other
11709                * than its own fourcc */
11710               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11711                   NULL);
11712               gst_buffer_unref (seqh);
11713             }
11714
11715             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11716             buf = gst_buffer_new_and_alloc (len);
11717             gst_buffer_fill (buf, 0, stsd_data, len);
11718             gst_caps_set_simple (entry->caps,
11719                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11720             gst_buffer_unref (buf);
11721             break;
11722           }
11723           case FOURCC_jpeg:
11724           {
11725             /* https://developer.apple.com/standards/qtff-2001.pdf,
11726              * page 92, "Video Sample Description", under table 3.1 */
11727             GstByteReader br;
11728
11729             const gint compressor_offset =
11730                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11731             const gint min_size = compressor_offset + 32 + 2 + 2;
11732             GNode *jpeg;
11733             guint32 len;
11734             guint16 color_table_id = 0;
11735             gboolean ok;
11736
11737             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11738
11739             /* recover information on interlaced/progressive */
11740             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11741             if (!jpeg)
11742               break;
11743
11744             len = QT_UINT32 (jpeg->data);
11745             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11746                 min_size);
11747             if (len >= min_size) {
11748               gst_byte_reader_init (&br, jpeg->data, len);
11749
11750               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11751               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11752               if (color_table_id != 0) {
11753                 /* the spec says there can be concatenated chunks in the data, and we want
11754                  * to find one called field. Walk through them. */
11755                 gint offset = min_size;
11756                 while (offset + 8 < len) {
11757                   guint32 size = 0, tag;
11758                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11759                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11760                   if (!ok || size < 8) {
11761                     GST_WARNING_OBJECT (qtdemux,
11762                         "Failed to walk optional chunk list");
11763                     break;
11764                   }
11765                   GST_DEBUG_OBJECT (qtdemux,
11766                       "Found optional %4.4s chunk, size %u",
11767                       (const char *) &tag, size);
11768                   if (tag == FOURCC_fiel) {
11769                     guint8 n_fields = 0, ordering = 0;
11770                     gst_byte_reader_get_uint8 (&br, &n_fields);
11771                     gst_byte_reader_get_uint8 (&br, &ordering);
11772                     if (n_fields == 1 || n_fields == 2) {
11773                       GST_DEBUG_OBJECT (qtdemux,
11774                           "Found fiel tag with %u fields, ordering %u",
11775                           n_fields, ordering);
11776                       if (n_fields == 2)
11777                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11778                             "interlace-mode", G_TYPE_STRING, "interleaved",
11779                             NULL);
11780                     } else {
11781                       GST_WARNING_OBJECT (qtdemux,
11782                           "Found fiel tag with invalid fields (%u)", n_fields);
11783                     }
11784                   }
11785                   offset += size;
11786                 }
11787               } else {
11788                 GST_DEBUG_OBJECT (qtdemux,
11789                     "Color table ID is 0, not trying to get interlacedness");
11790               }
11791             } else {
11792               GST_WARNING_OBJECT (qtdemux,
11793                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11794             }
11795
11796             break;
11797           }
11798           case FOURCC_rle_:
11799           case FOURCC_WRLE:
11800           {
11801             gst_caps_set_simple (entry->caps,
11802                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11803                 NULL);
11804             break;
11805           }
11806           case FOURCC_XiTh:
11807           {
11808             GNode *xith, *xdxt;
11809
11810             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11811             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11812             if (!xith)
11813               break;
11814
11815             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11816             if (!xdxt)
11817               break;
11818
11819             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11820             /* collect the headers and store them in a stream list so that we can
11821              * send them out first */
11822             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11823             break;
11824           }
11825           case FOURCC_ovc1:
11826           {
11827             GNode *ovc1;
11828             guint8 *ovc1_data;
11829             guint ovc1_len;
11830             GstBuffer *buf;
11831
11832             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11833             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11834             if (!ovc1)
11835               break;
11836             ovc1_data = ovc1->data;
11837             ovc1_len = QT_UINT32 (ovc1_data);
11838             if (ovc1_len <= 198) {
11839               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11840               break;
11841             }
11842             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11843             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11844             gst_caps_set_simple (entry->caps,
11845                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11846             gst_buffer_unref (buf);
11847             break;
11848           }
11849           case FOURCC_vc_1:
11850           {
11851             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11852             const guint8 *vc1_data = stsd_entry_data + 0x56;
11853
11854             /* find dvc1 */
11855             while (len >= 8) {
11856               gint size;
11857
11858               if (QT_UINT32 (vc1_data) <= len)
11859                 size = QT_UINT32 (vc1_data) - 8;
11860               else
11861                 size = len - 8;
11862
11863               if (size < 1)
11864                 /* No real data, so break out */
11865                 break;
11866
11867               switch (QT_FOURCC (vc1_data + 0x4)) {
11868                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11869                 {
11870                   GstBuffer *buf;
11871
11872                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11873                   buf = gst_buffer_new_and_alloc (size);
11874                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11875                   gst_caps_set_simple (entry->caps,
11876                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11877                   gst_buffer_unref (buf);
11878                   break;
11879                 }
11880                 default:
11881                   break;
11882               }
11883               len -= size + 8;
11884               vc1_data += size + 8;
11885             }
11886             break;
11887           }
11888           case FOURCC_av01:
11889           {
11890             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11891             const guint8 *av1_data = stsd_entry_data + 0x56;
11892
11893             /* find av1C */
11894             while (len >= 0x8) {
11895               gint size;
11896
11897               if (QT_UINT32 (av1_data) <= len)
11898                 size = QT_UINT32 (av1_data) - 0x8;
11899               else
11900                 size = len - 0x8;
11901
11902               if (size < 1)
11903                 /* No real data, so break out */
11904                 break;
11905
11906               switch (QT_FOURCC (av1_data + 0x4)) {
11907                 case FOURCC_av1C:
11908                 {
11909                   /* parse, if found */
11910                   GstBuffer *buf;
11911                   guint8 pres_delay_field;
11912
11913                   GST_DEBUG_OBJECT (qtdemux,
11914                       "found av1C codec_data in stsd of size %d", size);
11915
11916                   /* not enough data, just ignore and hope for the best */
11917                   if (size < 5)
11918                     break;
11919
11920                   /* Content is:
11921                    * 4 bytes: atom length
11922                    * 4 bytes: fourcc
11923                    * 1 byte: version
11924                    * 3 bytes: flags
11925                    * 3 bits: reserved
11926                    * 1 bits:  initial_presentation_delay_present
11927                    * 4 bits: initial_presentation_delay (if present else reserved
11928                    * rest: OBUs.
11929                    */
11930
11931                   if (av1_data[9] != 0) {
11932                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11933                     break;
11934                   }
11935
11936                   /* We skip initial_presentation_delay* for now */
11937                   pres_delay_field = *(av1_data + 12);
11938                   if (pres_delay_field & (1 << 5)) {
11939                     gst_caps_set_simple (entry->caps,
11940                         "presentation-delay", G_TYPE_INT,
11941                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11942                   }
11943                   if (size > 5) {
11944                     buf = gst_buffer_new_and_alloc (size - 5);
11945                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11946                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11947                     gst_caps_set_simple (entry->caps,
11948                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11949                     gst_buffer_unref (buf);
11950                   }
11951                   break;
11952                 }
11953                 default:
11954                   break;
11955               }
11956
11957               len -= size + 8;
11958               av1_data += size + 8;
11959             }
11960
11961             break;
11962           }
11963
11964             /* TODO: Need to parse vpcC for VP8 codec too.
11965              * Note that VPCodecConfigurationBox (vpcC) is defined for
11966              * vp08, vp09, and vp10 fourcc. */
11967           case FOURCC_vp09:
11968           {
11969             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11970             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11971
11972             /* find vpcC */
11973             while (len >= 0x8) {
11974               gint size;
11975
11976               if (QT_UINT32 (vpcc_data) <= len)
11977                 size = QT_UINT32 (vpcc_data) - 0x8;
11978               else
11979                 size = len - 0x8;
11980
11981               if (size < 1)
11982                 /* No real data, so break out */
11983                 break;
11984
11985               switch (QT_FOURCC (vpcc_data + 0x4)) {
11986                 case FOURCC_vpcC:
11987                 {
11988                   const gchar *profile_str = NULL;
11989                   const gchar *chroma_format_str = NULL;
11990                   guint8 profile;
11991                   guint8 bitdepth;
11992                   guint8 chroma_format;
11993                   GstVideoColorimetry cinfo;
11994
11995                   /* parse, if found */
11996                   GST_DEBUG_OBJECT (qtdemux,
11997                       "found vp codec_data in stsd of size %d", size);
11998
11999                   /* the meaning of "size" is length of the atom body, excluding
12000                    * atom length and fourcc fields */
12001                   if (size < 12)
12002                     break;
12003
12004                   /* Content is:
12005                    * 4 bytes: atom length
12006                    * 4 bytes: fourcc
12007                    * 1 byte: version
12008                    * 3 bytes: flags
12009                    * 1 byte: profile
12010                    * 1 byte: level
12011                    * 4 bits: bitDepth
12012                    * 3 bits: chromaSubsampling
12013                    * 1 bit: videoFullRangeFlag
12014                    * 1 byte: colourPrimaries
12015                    * 1 byte: transferCharacteristics
12016                    * 1 byte: matrixCoefficients
12017                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12018                    * rest: codecIntializationData (not used for vp8 and vp9)
12019                    */
12020
12021                   if (vpcc_data[8] != 1) {
12022                     GST_WARNING_OBJECT (qtdemux,
12023                         "unknown vpcC version %d", vpcc_data[8]);
12024                     break;
12025                   }
12026
12027                   profile = vpcc_data[12];
12028                   switch (profile) {
12029                     case 0:
12030                       profile_str = "0";
12031                       break;
12032                     case 1:
12033                       profile_str = "1";
12034                       break;
12035                     case 2:
12036                       profile_str = "2";
12037                       break;
12038                     case 3:
12039                       profile_str = "3";
12040                       break;
12041                     default:
12042                       break;
12043                   }
12044
12045                   if (profile_str) {
12046                     gst_caps_set_simple (entry->caps,
12047                         "profile", G_TYPE_STRING, profile_str, NULL);
12048                   }
12049
12050                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12051                    * but webm spec define various ones. Add level to caps
12052                    * if we really need it then */
12053
12054                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12055                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12056                     gst_caps_set_simple (entry->caps,
12057                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12058                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12059                   }
12060
12061                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12062                   switch (chroma_format) {
12063                     case 0:
12064                     case 1:
12065                       chroma_format_str = "4:2:0";
12066                       break;
12067                     case 2:
12068                       chroma_format_str = "4:2:2";
12069                       break;
12070                     case 3:
12071                       chroma_format_str = "4:4:4";
12072                       break;
12073                     default:
12074                       break;
12075                   }
12076
12077                   if (chroma_format_str) {
12078                     gst_caps_set_simple (entry->caps,
12079                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12080                         NULL);
12081                   }
12082
12083                   if ((vpcc_data[14] & 0x1) != 0)
12084                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12085                   else
12086                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12087                   cinfo.primaries =
12088                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12089                   cinfo.transfer =
12090                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12091                   cinfo.matrix =
12092                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12093
12094                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12095                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12096                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12097                     /* set this only if all values are known, otherwise this
12098                      * might overwrite valid ones parsed from other color box */
12099                     CUR_STREAM (stream)->colorimetry = cinfo;
12100                   }
12101                   break;
12102                 }
12103                 default:
12104                   break;
12105               }
12106
12107               len -= size + 8;
12108               vpcc_data += size + 8;
12109             }
12110
12111             break;
12112           }
12113           default:
12114             break;
12115         }
12116       }
12117
12118       GST_INFO_OBJECT (qtdemux,
12119           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12120           GST_FOURCC_ARGS (fourcc), entry->caps);
12121
12122     } else if (stream->subtype == FOURCC_soun) {
12123       GNode *wave;
12124       int version, samplesize;
12125       guint16 compression_id;
12126       gboolean amrwb = FALSE;
12127
12128       offset = 16;
12129       /* sample description entry (16) + sound sample description v0 (20) */
12130       if (len < 36)
12131         goto corrupt_file;
12132
12133       version = QT_UINT32 (stsd_entry_data + offset);
12134       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12135       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12136       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12137       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12138
12139       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12140       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12141           QT_UINT32 (stsd_entry_data + offset + 4));
12142       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12143       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12144       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12145       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12146           QT_UINT16 (stsd_entry_data + offset + 14));
12147       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12148
12149       if (compression_id == 0xfffe)
12150         entry->sampled = TRUE;
12151
12152       /* first assume uncompressed audio */
12153       entry->bytes_per_sample = samplesize / 8;
12154       entry->samples_per_frame = entry->n_channels;
12155       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12156       entry->samples_per_packet = entry->samples_per_frame;
12157       entry->bytes_per_packet = entry->bytes_per_sample;
12158
12159       offset = 36;
12160
12161       if (version == 0x00010000) {
12162         /* sample description entry (16) + sound sample description v1 (20+16) */
12163         if (len < 52)
12164           goto corrupt_file;
12165
12166         /* take information from here over the normal sample description */
12167         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12168         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12169         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12170         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12171
12172         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12173         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12174             entry->samples_per_packet);
12175         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12176             entry->bytes_per_packet);
12177         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12178             entry->bytes_per_frame);
12179         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12180             entry->bytes_per_sample);
12181
12182         if (!entry->sampled && entry->bytes_per_packet) {
12183           entry->samples_per_frame = (entry->bytes_per_frame /
12184               entry->bytes_per_packet) * entry->samples_per_packet;
12185           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12186               entry->samples_per_frame);
12187         }
12188       } else if (version == 0x00020000) {
12189         /* sample description entry (16) + sound sample description v2 (56) */
12190         if (len < 72)
12191           goto corrupt_file;
12192
12193         /* take information from here over the normal sample description */
12194         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12195         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12196         entry->samples_per_frame = entry->n_channels;
12197         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12198         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12199         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12200         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12201
12202         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12203         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12204         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12205         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12206             entry->bytes_per_sample * 8);
12207         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12208             QT_UINT32 (stsd_entry_data + offset + 24));
12209         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12210             entry->bytes_per_packet);
12211         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12212             entry->samples_per_packet);
12213       } else if (version != 0x00000) {
12214         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12215             version);
12216       }
12217
12218       switch (fourcc) {
12219           /* Yes, these have to be hard-coded */
12220         case FOURCC_MAC6:
12221         {
12222           entry->samples_per_packet = 6;
12223           entry->bytes_per_packet = 1;
12224           entry->bytes_per_frame = 1 * entry->n_channels;
12225           entry->bytes_per_sample = 1;
12226           entry->samples_per_frame = 6 * entry->n_channels;
12227           break;
12228         }
12229         case FOURCC_MAC3:
12230         {
12231           entry->samples_per_packet = 3;
12232           entry->bytes_per_packet = 1;
12233           entry->bytes_per_frame = 1 * entry->n_channels;
12234           entry->bytes_per_sample = 1;
12235           entry->samples_per_frame = 3 * entry->n_channels;
12236           break;
12237         }
12238         case FOURCC_ima4:
12239         {
12240           entry->samples_per_packet = 64;
12241           entry->bytes_per_packet = 34;
12242           entry->bytes_per_frame = 34 * entry->n_channels;
12243           entry->bytes_per_sample = 2;
12244           entry->samples_per_frame = 64 * entry->n_channels;
12245           break;
12246         }
12247         case FOURCC_ulaw:
12248         case FOURCC_alaw:
12249         {
12250           entry->samples_per_packet = 1;
12251           entry->bytes_per_packet = 1;
12252           entry->bytes_per_frame = 1 * entry->n_channels;
12253           entry->bytes_per_sample = 1;
12254           entry->samples_per_frame = 1 * entry->n_channels;
12255           break;
12256         }
12257         case FOURCC_agsm:
12258         {
12259           entry->samples_per_packet = 160;
12260           entry->bytes_per_packet = 33;
12261           entry->bytes_per_frame = 33 * entry->n_channels;
12262           entry->bytes_per_sample = 2;
12263           entry->samples_per_frame = 160 * entry->n_channels;
12264           break;
12265         }
12266           /* fix up any invalid header information from above */
12267         case FOURCC_twos:
12268         case FOURCC_sowt:
12269         case FOURCC_raw_:
12270         case FOURCC_lpcm:
12271           /* Sometimes these are set to 0 in the sound sample descriptions so
12272            * let's try to infer useful values from the other information we
12273            * have available */
12274           if (entry->bytes_per_sample == 0)
12275             entry->bytes_per_sample =
12276                 entry->bytes_per_frame / entry->n_channels;
12277           if (entry->bytes_per_sample == 0)
12278             entry->bytes_per_sample = samplesize / 8;
12279
12280           if (entry->bytes_per_frame == 0)
12281             entry->bytes_per_frame =
12282                 entry->bytes_per_sample * entry->n_channels;
12283
12284           if (entry->bytes_per_packet == 0)
12285             entry->bytes_per_packet = entry->bytes_per_sample;
12286
12287           if (entry->samples_per_frame == 0)
12288             entry->samples_per_frame = entry->n_channels;
12289
12290           if (entry->samples_per_packet == 0)
12291             entry->samples_per_packet = entry->samples_per_frame;
12292
12293           break;
12294         case FOURCC_in24:
12295         case FOURCC_in32:
12296         case FOURCC_fl32:
12297         case FOURCC_fl64:
12298         case FOURCC_s16l:{
12299           switch (fourcc) {
12300             case FOURCC_in24:
12301               entry->bytes_per_sample = 3;
12302               break;
12303             case FOURCC_in32:
12304             case FOURCC_fl32:
12305               entry->bytes_per_sample = 4;
12306               break;
12307             case FOURCC_fl64:
12308               entry->bytes_per_sample = 8;
12309               break;
12310             case FOURCC_s16l:
12311               entry->bytes_per_sample = 2;
12312               break;
12313             default:
12314               g_assert_not_reached ();
12315               break;
12316           }
12317           entry->samples_per_frame = entry->n_channels;
12318           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12319           entry->samples_per_packet = entry->samples_per_frame;
12320           entry->bytes_per_packet = entry->bytes_per_sample;
12321           break;
12322         }
12323         default:
12324           break;
12325       }
12326
12327       if (entry->caps)
12328         gst_caps_unref (entry->caps);
12329
12330       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12331           stsd_entry_data + 32, len - 16, &codec);
12332
12333       switch (fourcc) {
12334         case FOURCC_in24:
12335         case FOURCC_in32:
12336         case FOURCC_fl32:
12337         case FOURCC_fl64:
12338         {
12339           GNode *enda;
12340           GNode *fmt;
12341
12342           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12343
12344           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12345           if (!enda) {
12346             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12347             if (wave)
12348               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12349           }
12350           if (enda) {
12351             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12352             const gchar *format_str;
12353
12354             switch (fourcc) {
12355               case FOURCC_in24:
12356                 format_str = (enda_value) ? "S24LE" : "S24BE";
12357                 break;
12358               case FOURCC_in32:
12359                 format_str = (enda_value) ? "S32LE" : "S32BE";
12360                 break;
12361               case FOURCC_fl32:
12362                 format_str = (enda_value) ? "F32LE" : "F32BE";
12363                 break;
12364               case FOURCC_fl64:
12365                 format_str = (enda_value) ? "F64LE" : "F64BE";
12366                 break;
12367               default:
12368                 g_assert_not_reached ();
12369                 break;
12370             }
12371             gst_caps_set_simple (entry->caps,
12372                 "format", G_TYPE_STRING, format_str, NULL);
12373           }
12374           break;
12375         }
12376         case FOURCC_owma:
12377         {
12378           const guint8 *owma_data;
12379           const gchar *codec_name = NULL;
12380           guint owma_len;
12381           GstBuffer *buf;
12382           gint version = 1;
12383           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12384           /* FIXME this should also be gst_riff_strf_auds,
12385            * but the latter one is actually missing bits-per-sample :( */
12386           typedef struct
12387           {
12388             gint16 wFormatTag;
12389             gint16 nChannels;
12390             gint32 nSamplesPerSec;
12391             gint32 nAvgBytesPerSec;
12392             gint16 nBlockAlign;
12393             gint16 wBitsPerSample;
12394             gint16 cbSize;
12395           } WAVEFORMATEX;
12396           WAVEFORMATEX *wfex;
12397
12398           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12399           owma_data = stsd_entry_data;
12400           owma_len = QT_UINT32 (owma_data);
12401           if (owma_len <= 54) {
12402             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12403             break;
12404           }
12405           wfex = (WAVEFORMATEX *) (owma_data + 36);
12406           buf = gst_buffer_new_and_alloc (owma_len - 54);
12407           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12408           if (wfex->wFormatTag == 0x0161) {
12409             codec_name = "Windows Media Audio";
12410             version = 2;
12411           } else if (wfex->wFormatTag == 0x0162) {
12412             codec_name = "Windows Media Audio 9 Pro";
12413             version = 3;
12414           } else if (wfex->wFormatTag == 0x0163) {
12415             codec_name = "Windows Media Audio 9 Lossless";
12416             /* is that correct? gstffmpegcodecmap.c is missing it, but
12417              * fluendo codec seems to support it */
12418             version = 4;
12419           }
12420
12421           gst_caps_set_simple (entry->caps,
12422               "codec_data", GST_TYPE_BUFFER, buf,
12423               "wmaversion", G_TYPE_INT, version,
12424               "block_align", G_TYPE_INT,
12425               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12426               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12427               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12428               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12429           gst_buffer_unref (buf);
12430
12431           if (codec_name) {
12432             g_free (codec);
12433             codec = g_strdup (codec_name);
12434           }
12435           break;
12436         }
12437         case FOURCC_wma_:
12438         {
12439           gint len = QT_UINT32 (stsd_entry_data) - offset;
12440           const guint8 *wfex_data = stsd_entry_data + offset;
12441           const gchar *codec_name = NULL;
12442           gint version = 1;
12443           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12444           /* FIXME this should also be gst_riff_strf_auds,
12445            * but the latter one is actually missing bits-per-sample :( */
12446           typedef struct
12447           {
12448             gint16 wFormatTag;
12449             gint16 nChannels;
12450             gint32 nSamplesPerSec;
12451             gint32 nAvgBytesPerSec;
12452             gint16 nBlockAlign;
12453             gint16 wBitsPerSample;
12454             gint16 cbSize;
12455           } WAVEFORMATEX;
12456           WAVEFORMATEX wfex;
12457
12458           /* FIXME: unify with similar wavformatex parsing code above */
12459           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12460
12461           /* find wfex */
12462           while (len >= 8) {
12463             gint size;
12464
12465             if (QT_UINT32 (wfex_data) <= len)
12466               size = QT_UINT32 (wfex_data) - 8;
12467             else
12468               size = len - 8;
12469
12470             if (size < 1)
12471               /* No real data, so break out */
12472               break;
12473
12474             switch (QT_FOURCC (wfex_data + 4)) {
12475               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12476               {
12477                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12478
12479                 if (size < 8 + 18)
12480                   break;
12481
12482                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12483                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12484                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12485                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12486                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12487                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12488                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12489
12490                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12491                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12492                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12493                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12494                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12495                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12496
12497                 if (wfex.wFormatTag == 0x0161) {
12498                   codec_name = "Windows Media Audio";
12499                   version = 2;
12500                 } else if (wfex.wFormatTag == 0x0162) {
12501                   codec_name = "Windows Media Audio 9 Pro";
12502                   version = 3;
12503                 } else if (wfex.wFormatTag == 0x0163) {
12504                   codec_name = "Windows Media Audio 9 Lossless";
12505                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12506                    * fluendo codec seems to support it */
12507                   version = 4;
12508                 }
12509
12510                 gst_caps_set_simple (entry->caps,
12511                     "wmaversion", G_TYPE_INT, version,
12512                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12513                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12514                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12515                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12516
12517                 if (size > wfex.cbSize) {
12518                   GstBuffer *buf;
12519
12520                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12521                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12522                       size - wfex.cbSize);
12523                   gst_caps_set_simple (entry->caps,
12524                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12525                   gst_buffer_unref (buf);
12526                 } else {
12527                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12528                 }
12529
12530                 if (codec_name) {
12531                   g_free (codec);
12532                   codec = g_strdup (codec_name);
12533                 }
12534                 break;
12535               }
12536               default:
12537                 break;
12538             }
12539             len -= size + 8;
12540             wfex_data += size + 8;
12541           }
12542           break;
12543         }
12544         case FOURCC_opus:
12545         {
12546           const guint8 *dops_data;
12547           guint8 *channel_mapping = NULL;
12548           guint32 rate;
12549           guint8 channels;
12550           guint8 channel_mapping_family;
12551           guint8 stream_count;
12552           guint8 coupled_count;
12553           guint8 i;
12554
12555           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12556           if (version == 1)
12557             dops_data = stsd_entry_data + 51;
12558           else
12559             dops_data = stsd_entry_data + 35;
12560
12561           channels = GST_READ_UINT8 (dops_data + 10);
12562           rate = GST_READ_UINT32_LE (dops_data + 13);
12563           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12564           stream_count = GST_READ_UINT8 (dops_data + 20);
12565           coupled_count = GST_READ_UINT8 (dops_data + 21);
12566
12567           if (channels > 0) {
12568             channel_mapping = g_malloc (channels * sizeof (guint8));
12569             for (i = 0; i < channels; i++)
12570               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12571           }
12572
12573           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12574               channel_mapping_family, stream_count, coupled_count,
12575               channel_mapping);
12576           break;
12577         }
12578         default:
12579           break;
12580       }
12581
12582       if (codec) {
12583         GstStructure *s;
12584         gint bitrate = 0;
12585
12586         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12587             GST_TAG_AUDIO_CODEC, codec, NULL);
12588         g_free (codec);
12589         codec = NULL;
12590
12591         /* some bitrate info may have ended up in caps */
12592         s = gst_caps_get_structure (entry->caps, 0);
12593         gst_structure_get_int (s, "bitrate", &bitrate);
12594         if (bitrate > 0)
12595           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12596               GST_TAG_BITRATE, bitrate, NULL);
12597       }
12598
12599       esds = NULL;
12600       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12601       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12602         if (stream->protected) {
12603           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12604             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12605           }
12606           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12607             mp4a = NULL;
12608           }
12609         } else {
12610           mp4a = NULL;
12611         }
12612       }
12613
12614       wave = NULL;
12615       if (mp4a) {
12616         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12617         if (wave)
12618           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12619         if (!esds)
12620           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12621       }
12622
12623
12624       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12625          16 bits is a byte-swapped wave-style codec identifier,
12626          and we can find a WAVE header internally to a 'wave' atom here.
12627          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12628          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12629          is big-endian).
12630        */
12631       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12632         if (len < offset + 20) {
12633           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12634         } else {
12635           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12636           const guint8 *data = stsd_entry_data + offset + 16;
12637           GNode *wavenode;
12638           GNode *waveheadernode;
12639
12640           wavenode = g_node_new ((guint8 *) data);
12641           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12642             const guint8 *waveheader;
12643             guint32 headerlen;
12644
12645             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12646             if (waveheadernode) {
12647               waveheader = (const guint8 *) waveheadernode->data;
12648               headerlen = QT_UINT32 (waveheader);
12649
12650               if (headerlen > 8) {
12651                 gst_riff_strf_auds *header = NULL;
12652                 GstBuffer *headerbuf;
12653                 GstBuffer *extra;
12654
12655                 waveheader += 8;
12656                 headerlen -= 8;
12657
12658                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12659                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12660
12661                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12662                         headerbuf, &header, &extra)) {
12663                   gst_caps_unref (entry->caps);
12664                   /* FIXME: Need to do something with the channel reorder map */
12665                   entry->caps =
12666                       gst_riff_create_audio_caps (header->format, NULL, header,
12667                       extra, NULL, NULL, NULL);
12668
12669                   if (extra)
12670                     gst_buffer_unref (extra);
12671                   g_free (header);
12672                 }
12673               }
12674             } else
12675               GST_DEBUG ("Didn't find waveheadernode for this codec");
12676           }
12677           g_node_destroy (wavenode);
12678         }
12679       } else if (esds) {
12680         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12681             stream->stream_tags);
12682       } else {
12683         switch (fourcc) {
12684 #if 0
12685             /* FIXME: what is in the chunk? */
12686           case FOURCC_QDMC:
12687           {
12688             gint len = QT_UINT32 (stsd_data);
12689
12690             /* seems to be always = 116 = 0x74 */
12691             break;
12692           }
12693 #endif
12694           case FOURCC_QDM2:
12695           {
12696             gint len = QT_UINT32 (stsd_entry_data);
12697
12698             if (len > 0x3C) {
12699               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12700
12701               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12702               gst_caps_set_simple (entry->caps,
12703                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12704               gst_buffer_unref (buf);
12705             }
12706             gst_caps_set_simple (entry->caps,
12707                 "samplesize", G_TYPE_INT, samplesize, NULL);
12708             break;
12709           }
12710           case FOURCC_alac:
12711           {
12712             GNode *alac, *wave = NULL;
12713
12714             /* apparently, m4a has this atom appended directly in the stsd entry,
12715              * while mov has it in a wave atom */
12716             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12717             if (alac) {
12718               /* alac now refers to stsd entry atom */
12719               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12720               if (wave)
12721                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12722               else
12723                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12724             }
12725             if (alac) {
12726               const guint8 *alac_data = alac->data;
12727               gint len = QT_UINT32 (alac->data);
12728               GstBuffer *buf;
12729
12730               if (len < 36) {
12731                 GST_DEBUG_OBJECT (qtdemux,
12732                     "discarding alac atom with unexpected len %d", len);
12733               } else {
12734                 /* codec-data contains alac atom size and prefix,
12735                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12736                 buf = gst_buffer_new_and_alloc (len);
12737                 gst_buffer_fill (buf, 0, alac->data, len);
12738                 gst_caps_set_simple (entry->caps,
12739                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12740                 gst_buffer_unref (buf);
12741
12742                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12743                 entry->n_channels = QT_UINT8 (alac_data + 21);
12744                 entry->rate = QT_UINT32 (alac_data + 32);
12745                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12746               }
12747             }
12748             gst_caps_set_simple (entry->caps,
12749                 "samplesize", G_TYPE_INT, samplesize, NULL);
12750             break;
12751           }
12752           case FOURCC_fLaC:
12753           {
12754             /* The codingname of the sample entry is 'fLaC' */
12755             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12756
12757             if (flac) {
12758               /* The 'dfLa' box is added to the sample entry to convey
12759                  initializing information for the decoder. */
12760               const GNode *dfla =
12761                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12762
12763               if (dfla) {
12764                 const guint32 len = QT_UINT32 (dfla->data);
12765
12766                 /* Must contain at least dfLa box header (12),
12767                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12768                 if (len < 50) {
12769                   GST_DEBUG_OBJECT (qtdemux,
12770                       "discarding dfla atom with unexpected len %d", len);
12771                 } else {
12772                   /* skip dfLa header to get the METADATA_BLOCKs */
12773                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12774                   const guint32 metadata_blocks_len = len - 12;
12775
12776                   gchar *stream_marker = g_strdup ("fLaC");
12777                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12778                       strlen (stream_marker));
12779
12780                   guint32 index = 0;
12781                   guint32 remainder = 0;
12782                   guint32 block_size = 0;
12783                   gboolean is_last = FALSE;
12784
12785                   GValue array = G_VALUE_INIT;
12786                   GValue value = G_VALUE_INIT;
12787
12788                   g_value_init (&array, GST_TYPE_ARRAY);
12789                   g_value_init (&value, GST_TYPE_BUFFER);
12790
12791                   gst_value_set_buffer (&value, block);
12792                   gst_value_array_append_value (&array, &value);
12793                   g_value_reset (&value);
12794
12795                   gst_buffer_unref (block);
12796
12797                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12798                    * of data, and we haven't already finished parsing */
12799                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12800                     remainder = metadata_blocks_len - index;
12801
12802                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12803                     block_size = 4 +
12804                         (metadata_blocks[index + 1] << 16) +
12805                         (metadata_blocks[index + 2] << 8) +
12806                         metadata_blocks[index + 3];
12807
12808                     /* be careful not to read off end of box */
12809                     if (block_size > remainder) {
12810                       break;
12811                     }
12812
12813                     is_last = metadata_blocks[index] >> 7;
12814
12815                     block = gst_buffer_new_and_alloc (block_size);
12816
12817                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12818                         block_size);
12819
12820                     gst_value_set_buffer (&value, block);
12821                     gst_value_array_append_value (&array, &value);
12822                     g_value_reset (&value);
12823
12824                     gst_buffer_unref (block);
12825
12826                     index += block_size;
12827                   }
12828
12829                   /* only append the metadata if we successfully read all of it */
12830                   if (is_last) {
12831                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12832                             (stream)->caps, 0), "streamheader", &array);
12833                   } else {
12834                     GST_WARNING_OBJECT (qtdemux,
12835                         "discarding all METADATA_BLOCKs due to invalid "
12836                         "block_size %d at idx %d, rem %d", block_size, index,
12837                         remainder);
12838                   }
12839
12840                   g_value_unset (&value);
12841                   g_value_unset (&array);
12842
12843                   /* The sample rate obtained from the stsd may not be accurate
12844                    * since it cannot represent rates greater than 65535Hz, so
12845                    * override that value with the sample rate from the
12846                    * METADATA_BLOCK_STREAMINFO block */
12847                   CUR_STREAM (stream)->rate =
12848                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12849                 }
12850               }
12851             }
12852             break;
12853           }
12854           case FOURCC_sawb:
12855             /* Fallthrough! */
12856             amrwb = TRUE;
12857           case FOURCC_samr:
12858           {
12859             gint len = QT_UINT32 (stsd_entry_data);
12860
12861             if (len > 0x24) {
12862               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12863               guint bitrate;
12864
12865               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12866
12867               /* If we have enough data, let's try to get the 'damr' atom. See
12868                * the 3GPP container spec (26.244) for more details. */
12869               if ((len - 0x34) > 8 &&
12870                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12871                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12872                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12873               }
12874
12875               gst_caps_set_simple (entry->caps,
12876                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12877               gst_buffer_unref (buf);
12878             }
12879             break;
12880           }
12881           case FOURCC_mp4a:
12882           {
12883             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12884             gint len = QT_UINT32 (stsd_entry_data);
12885             guint16 sound_version = 0;
12886             /* FIXME: Can this be determined somehow? There doesn't seem to be
12887              * anything in mp4a atom that specifis compression */
12888             gint profile = 2;
12889             guint16 channels = entry->n_channels;
12890             guint32 time_scale = (guint32) entry->rate;
12891             gint sample_rate_index = -1;
12892
12893             if (len >= 34) {
12894               sound_version = QT_UINT16 (stsd_entry_data + 16);
12895
12896               if (sound_version == 1) {
12897                 channels = QT_UINT16 (stsd_entry_data + 24);
12898                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12899               } else {
12900                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12901                     sound_version);
12902               }
12903             } else {
12904               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12905                   len);
12906             }
12907
12908             sample_rate_index =
12909                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12910             if (sample_rate_index >= 0 && channels > 0) {
12911               guint8 codec_data[2];
12912               GstBuffer *buf;
12913
12914               /* build AAC codec data */
12915               codec_data[0] = profile << 3;
12916               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12917               codec_data[1] = (sample_rate_index & 0x01) << 7;
12918               codec_data[1] |= (channels & 0xF) << 3;
12919
12920               buf = gst_buffer_new_and_alloc (2);
12921               gst_buffer_fill (buf, 0, codec_data, 2);
12922               gst_caps_set_simple (entry->caps,
12923                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12924               gst_buffer_unref (buf);
12925             }
12926             break;
12927           }
12928           case FOURCC_lpcm:
12929           case FOURCC_in24:
12930           case FOURCC_in32:
12931           case FOURCC_fl32:
12932           case FOURCC_fl64:
12933           case FOURCC_s16l:
12934             /* Fully handled elsewhere */
12935             break;
12936           default:
12937             GST_INFO_OBJECT (qtdemux,
12938                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12939             break;
12940         }
12941       }
12942       GST_INFO_OBJECT (qtdemux,
12943           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12944           GST_FOURCC_ARGS (fourcc), entry->caps);
12945
12946     } else if (stream->subtype == FOURCC_strm) {
12947       if (fourcc == FOURCC_rtsp) {
12948         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12949       } else {
12950         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12951             GST_FOURCC_ARGS (fourcc));
12952         goto unknown_stream;
12953       }
12954       entry->sampled = TRUE;
12955     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12956         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12957         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
12958
12959       entry->sampled = TRUE;
12960       entry->sparse = TRUE;
12961
12962       entry->caps =
12963           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12964           &codec);
12965       if (codec) {
12966         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12967             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12968         g_free (codec);
12969         codec = NULL;
12970       }
12971
12972       /* hunt for sort-of codec data */
12973       switch (fourcc) {
12974         case FOURCC_mp4s:
12975         {
12976           GNode *mp4s = NULL;
12977           GNode *esds = NULL;
12978
12979           /* look for palette in a stsd->mp4s->esds sub-atom */
12980           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12981           if (mp4s)
12982             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12983           if (esds == NULL) {
12984             /* Invalid STSD */
12985             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12986             break;
12987           }
12988
12989           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12990               stream->stream_tags);
12991           break;
12992         }
12993         default:
12994           GST_INFO_OBJECT (qtdemux,
12995               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12996           break;
12997       }
12998       GST_INFO_OBJECT (qtdemux,
12999           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13000           GST_FOURCC_ARGS (fourcc), entry->caps);
13001     } else {
13002       /* everything in 1 sample */
13003       entry->sampled = TRUE;
13004
13005       entry->caps =
13006           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13007           &codec);
13008
13009       if (entry->caps == NULL)
13010         goto unknown_stream;
13011
13012       if (codec) {
13013         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13014             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13015         g_free (codec);
13016         codec = NULL;
13017       }
13018     }
13019
13020     /* promote to sampled format */
13021     if (entry->fourcc == FOURCC_samr) {
13022       /* force mono 8000 Hz for AMR */
13023       entry->sampled = TRUE;
13024       entry->n_channels = 1;
13025       entry->rate = 8000;
13026     } else if (entry->fourcc == FOURCC_sawb) {
13027       /* force mono 16000 Hz for AMR-WB */
13028       entry->sampled = TRUE;
13029       entry->n_channels = 1;
13030       entry->rate = 16000;
13031     } else if (entry->fourcc == FOURCC_mp4a) {
13032       entry->sampled = TRUE;
13033     }
13034
13035
13036     stsd_entry_data += len;
13037     remaining_stsd_len -= len;
13038
13039   }
13040
13041   /* collect sample information */
13042   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13043     goto samples_failed;
13044
13045   if (qtdemux->fragmented) {
13046     guint64 offset;
13047
13048     /* need all moov samples as basis; probably not many if any at all */
13049     /* prevent moof parsing taking of at this time */
13050     offset = qtdemux->moof_offset;
13051     qtdemux->moof_offset = 0;
13052     if (stream->n_samples &&
13053         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13054       qtdemux->moof_offset = offset;
13055       goto samples_failed;
13056     }
13057     qtdemux->moof_offset = offset;
13058     /* movie duration more reliable in this case (e.g. mehd) */
13059     if (qtdemux->segment.duration &&
13060         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13061       stream->duration =
13062           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13063   }
13064
13065   /* configure segments */
13066   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13067     goto segments_failed;
13068
13069   /* add some language tag, if useful */
13070   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13071       strcmp (stream->lang_id, "und")) {
13072     const gchar *lang_code;
13073
13074     /* convert ISO 639-2 code to ISO 639-1 */
13075     lang_code = gst_tag_get_language_code (stream->lang_id);
13076     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13077         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13078   }
13079
13080   /* Check for UDTA tags */
13081   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13082     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13083   }
13084
13085   /* Insert and sort new stream in track-id order.
13086    * This will help in comparing old/new streams during stream update check */
13087   g_ptr_array_add (qtdemux->active_streams, stream);
13088   g_ptr_array_sort (qtdemux->active_streams,
13089       (GCompareFunc) qtdemux_track_id_compare_func);
13090   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13091       QTDEMUX_N_STREAMS (qtdemux));
13092
13093   return TRUE;
13094
13095 /* ERRORS */
13096 corrupt_file:
13097   {
13098     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13099         (_("This file is corrupt and cannot be played.")), (NULL));
13100     if (stream)
13101       gst_qtdemux_stream_unref (stream);
13102     return FALSE;
13103   }
13104 error_encrypted:
13105   {
13106     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13107     gst_qtdemux_stream_unref (stream);
13108     return FALSE;
13109   }
13110 samples_failed:
13111 segments_failed:
13112   {
13113     /* we posted an error already */
13114     /* free stbl sub-atoms */
13115     gst_qtdemux_stbl_free (stream);
13116     gst_qtdemux_stream_unref (stream);
13117     return FALSE;
13118   }
13119 existing_stream:
13120   {
13121     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13122         track_id);
13123     return TRUE;
13124   }
13125 unknown_stream:
13126   {
13127     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13128         GST_FOURCC_ARGS (stream->subtype));
13129     gst_qtdemux_stream_unref (stream);
13130     return TRUE;
13131   }
13132 }
13133
13134 /* If we can estimate the overall bitrate, and don't have information about the
13135  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13136  * the overall bitrate minus the sum of the bitrates of all other streams. This
13137  * should be useful for the common case where we have one audio and one video
13138  * stream and can estimate the bitrate of one, but not the other. */
13139 static void
13140 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13141 {
13142   QtDemuxStream *stream = NULL;
13143   gint64 size, sys_bitrate, sum_bitrate = 0;
13144   GstClockTime duration;
13145   guint bitrate;
13146   gint i;
13147
13148   if (qtdemux->fragmented)
13149     return;
13150
13151   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13152
13153   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13154       || size <= 0) {
13155     GST_DEBUG_OBJECT (qtdemux,
13156         "Size in bytes of the stream not known - bailing");
13157     return;
13158   }
13159
13160   /* Subtract the header size */
13161   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13162       size, qtdemux->header_size);
13163
13164   if (size < qtdemux->header_size)
13165     return;
13166
13167   size = size - qtdemux->header_size;
13168
13169   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13170     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13171     return;
13172   }
13173
13174   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13175     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13176     switch (str->subtype) {
13177       case FOURCC_soun:
13178       case FOURCC_vide:
13179         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13180             CUR_STREAM (str)->caps);
13181         /* retrieve bitrate, prefer avg then max */
13182         bitrate = 0;
13183         if (str->stream_tags) {
13184           if (gst_tag_list_get_uint (str->stream_tags,
13185                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13186             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13187           if (gst_tag_list_get_uint (str->stream_tags,
13188                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13189             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13190           if (gst_tag_list_get_uint (str->stream_tags,
13191                   GST_TAG_BITRATE, &bitrate))
13192             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13193         }
13194         if (bitrate)
13195           sum_bitrate += bitrate;
13196         else {
13197           if (stream) {
13198             GST_DEBUG_OBJECT (qtdemux,
13199                 ">1 stream with unknown bitrate - bailing");
13200             return;
13201           } else
13202             stream = str;
13203         }
13204
13205       default:
13206         /* For other subtypes, we assume no significant impact on bitrate */
13207         break;
13208     }
13209   }
13210
13211   if (!stream) {
13212     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13213     return;
13214   }
13215
13216   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13217
13218   if (sys_bitrate < sum_bitrate) {
13219     /* This can happen, since sum_bitrate might be derived from maximum
13220      * bitrates and not average bitrates */
13221     GST_DEBUG_OBJECT (qtdemux,
13222         "System bitrate less than sum bitrate - bailing");
13223     return;
13224   }
13225
13226   bitrate = sys_bitrate - sum_bitrate;
13227   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13228       ", Stream bitrate = %u", sys_bitrate, bitrate);
13229
13230   if (!stream->stream_tags)
13231     stream->stream_tags = gst_tag_list_new_empty ();
13232   else
13233     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13234
13235   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13236       GST_TAG_BITRATE, bitrate, NULL);
13237 }
13238
13239 static GstFlowReturn
13240 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13241 {
13242   GstFlowReturn ret = GST_FLOW_OK;
13243   gint i;
13244
13245   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13246
13247   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13248     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13249     guint32 sample_num = 0;
13250
13251     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13252         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13253
13254     if (qtdemux->fragmented && qtdemux->pullbased) {
13255       /* need all moov samples first */
13256       GST_OBJECT_LOCK (qtdemux);
13257       while (stream->n_samples == 0)
13258         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13259           break;
13260       GST_OBJECT_UNLOCK (qtdemux);
13261     } else {
13262       /* discard any stray moof */
13263       qtdemux->moof_offset = 0;
13264     }
13265
13266     /* prepare braking */
13267     if (ret != GST_FLOW_ERROR)
13268       ret = GST_FLOW_OK;
13269
13270     /* in pull mode, we should have parsed some sample info by now;
13271      * and quite some code will not handle no samples.
13272      * in push mode, we'll just have to deal with it */
13273     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13274       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13275       g_ptr_array_remove_index (qtdemux->active_streams, i);
13276       i--;
13277       continue;
13278     } else if (stream->track_id == qtdemux->chapters_track_id &&
13279         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13280       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13281          so that it doesn't look like a subtitle track */
13282       g_ptr_array_remove_index (qtdemux->active_streams, i);
13283       i--;
13284       continue;
13285     }
13286
13287     /* parse the initial sample for use in setting the frame rate cap */
13288     while (sample_num == 0 && sample_num < stream->n_samples) {
13289       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13290         break;
13291       ++sample_num;
13292     }
13293   }
13294
13295   return ret;
13296 }
13297
13298 static gboolean
13299 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13300 {
13301   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13302 }
13303
13304 static gboolean
13305 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13306 {
13307   gint i;
13308
13309   /* Different length, updated */
13310   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13311     return TRUE;
13312
13313   /* streams in list are sorted in track-id order */
13314   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13315     /* Different stream-id, updated */
13316     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13317             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13318       return TRUE;
13319   }
13320
13321   return FALSE;
13322 }
13323
13324 static gboolean
13325 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13326     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13327 {
13328   /* Connect old stream's srcpad to new stream */
13329   newstream->pad = oldstream->pad;
13330   oldstream->pad = NULL;
13331
13332   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13333    * case we need to force one through */
13334   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13335
13336   return gst_qtdemux_configure_stream (qtdemux, newstream);
13337 }
13338
13339 static gboolean
13340 qtdemux_update_streams (GstQTDemux * qtdemux)
13341 {
13342   gint i;
13343   g_assert (qtdemux->streams_aware);
13344
13345   /* At below, figure out which stream in active_streams has identical stream-id
13346    * with that of in old_streams. If there is matching stream-id,
13347    * corresponding newstream will not be exposed again,
13348    * but demux will reuse srcpad of matched old stream
13349    *
13350    * active_streams : newly created streams from the latest moov
13351    * old_streams : existing streams (belong to previous moov)
13352    */
13353
13354   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13355     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13356     QtDemuxStream *oldstream = NULL;
13357     guint target;
13358
13359     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13360         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13361
13362     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13363             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13364       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13365
13366       /* null pad stream cannot be reused */
13367       if (oldstream->pad == NULL)
13368         oldstream = NULL;
13369     }
13370
13371     if (oldstream) {
13372       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13373
13374       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13375         return FALSE;
13376
13377       /* we don't need to preserve order of old streams */
13378       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13379     } else {
13380       GstTagList *list;
13381
13382       /* now we have all info and can expose */
13383       list = stream->stream_tags;
13384       stream->stream_tags = NULL;
13385       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13386         return FALSE;
13387     }
13388   }
13389
13390   return TRUE;
13391 }
13392
13393 /* Must be called with expose lock */
13394 static GstFlowReturn
13395 qtdemux_expose_streams (GstQTDemux * qtdemux)
13396 {
13397   gint i;
13398
13399   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13400
13401   if (!qtdemux_is_streams_update (qtdemux)) {
13402     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13403     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13404       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13405       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13406       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13407         return GST_FLOW_ERROR;
13408     }
13409
13410     g_ptr_array_set_size (qtdemux->old_streams, 0);
13411     qtdemux->need_segment = TRUE;
13412
13413     return GST_FLOW_OK;
13414   }
13415
13416   if (qtdemux->streams_aware) {
13417     if (!qtdemux_update_streams (qtdemux))
13418       return GST_FLOW_ERROR;
13419   } else {
13420     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13421       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13422       GstTagList *list;
13423
13424       /* now we have all info and can expose */
13425       list = stream->stream_tags;
13426       stream->stream_tags = NULL;
13427       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13428         return GST_FLOW_ERROR;
13429
13430     }
13431   }
13432
13433   gst_qtdemux_guess_bitrate (qtdemux);
13434
13435   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13436
13437   /* If we have still old_streams, it's no more used stream */
13438   for (i = 0; i < qtdemux->old_streams->len; i++) {
13439     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13440
13441     if (stream->pad) {
13442       GstEvent *event;
13443
13444       event = gst_event_new_eos ();
13445       if (qtdemux->segment_seqnum)
13446         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13447
13448       gst_pad_push_event (stream->pad, event);
13449     }
13450   }
13451
13452   g_ptr_array_set_size (qtdemux->old_streams, 0);
13453
13454   /* check if we should post a redirect in case there is a single trak
13455    * and it is a redirecting trak */
13456   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13457       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13458     GstMessage *m;
13459
13460     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13461         "an external content");
13462     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13463         gst_structure_new ("redirect",
13464             "new-location", G_TYPE_STRING,
13465             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13466     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13467     g_free (qtdemux->redirect_location);
13468     qtdemux->redirect_location =
13469         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13470   }
13471
13472   g_ptr_array_foreach (qtdemux->active_streams,
13473       (GFunc) qtdemux_do_allocation, qtdemux);
13474
13475   qtdemux->need_segment = TRUE;
13476
13477   qtdemux->exposed = TRUE;
13478   return GST_FLOW_OK;
13479 }
13480
13481 typedef struct
13482 {
13483   GstStructure *structure;      /* helper for sort function */
13484   gchar *location;
13485   guint min_req_bitrate;
13486   guint min_req_qt_version;
13487 } GstQtReference;
13488
13489 static gint
13490 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13491 {
13492   GstQtReference *ref_a = (GstQtReference *) a;
13493   GstQtReference *ref_b = (GstQtReference *) b;
13494
13495   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13496     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13497
13498   /* known bitrates go before unknown; higher bitrates go first */
13499   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13500 }
13501
13502 /* sort the redirects and post a message for the application.
13503  */
13504 static void
13505 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13506 {
13507   GstQtReference *best;
13508   GstStructure *s;
13509   GstMessage *msg;
13510   GValue list_val = { 0, };
13511   GList *l;
13512
13513   g_assert (references != NULL);
13514
13515   references = g_list_sort (references, qtdemux_redirects_sort_func);
13516
13517   best = (GstQtReference *) references->data;
13518
13519   g_value_init (&list_val, GST_TYPE_LIST);
13520
13521   for (l = references; l != NULL; l = l->next) {
13522     GstQtReference *ref = (GstQtReference *) l->data;
13523     GValue struct_val = { 0, };
13524
13525     ref->structure = gst_structure_new ("redirect",
13526         "new-location", G_TYPE_STRING, ref->location, NULL);
13527
13528     if (ref->min_req_bitrate > 0) {
13529       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13530           ref->min_req_bitrate, NULL);
13531     }
13532
13533     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13534     g_value_set_boxed (&struct_val, ref->structure);
13535     gst_value_list_append_value (&list_val, &struct_val);
13536     g_value_unset (&struct_val);
13537     /* don't free anything here yet, since we need best->structure below */
13538   }
13539
13540   g_assert (best != NULL);
13541   s = gst_structure_copy (best->structure);
13542
13543   if (g_list_length (references) > 1) {
13544     gst_structure_set_value (s, "locations", &list_val);
13545   }
13546
13547   g_value_unset (&list_val);
13548
13549   for (l = references; l != NULL; l = l->next) {
13550     GstQtReference *ref = (GstQtReference *) l->data;
13551
13552     gst_structure_free (ref->structure);
13553     g_free (ref->location);
13554     g_free (ref);
13555   }
13556   g_list_free (references);
13557
13558   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13559   g_free (qtdemux->redirect_location);
13560   qtdemux->redirect_location =
13561       g_strdup (gst_structure_get_string (s, "new-location"));
13562   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13563   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13564 }
13565
13566 /* look for redirect nodes, collect all redirect information and
13567  * process it.
13568  */
13569 static gboolean
13570 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13571 {
13572   GNode *rmra, *rmda, *rdrf;
13573
13574   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13575   if (rmra) {
13576     GList *redirects = NULL;
13577
13578     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13579     while (rmda) {
13580       GstQtReference ref = { NULL, NULL, 0, 0 };
13581       GNode *rmdr, *rmvc;
13582
13583       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13584         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13585         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13586             ref.min_req_bitrate);
13587       }
13588
13589       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13590         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13591         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13592
13593 #ifndef GST_DISABLE_GST_DEBUG
13594         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13595 #endif
13596         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13597
13598         GST_LOG_OBJECT (qtdemux,
13599             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13600             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13601             bitmask, check_type);
13602         if (package == FOURCC_qtim && check_type == 0) {
13603           ref.min_req_qt_version = version;
13604         }
13605       }
13606
13607       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13608       if (rdrf) {
13609         guint32 ref_type;
13610         guint8 *ref_data;
13611         guint ref_len;
13612
13613         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13614         if (ref_len > 20) {
13615           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13616           ref_data = (guint8 *) rdrf->data + 20;
13617           if (ref_type == FOURCC_alis) {
13618             guint record_len, record_version, fn_len;
13619
13620             if (ref_len > 70) {
13621               /* MacOSX alias record, google for alias-layout.txt */
13622               record_len = QT_UINT16 (ref_data + 4);
13623               record_version = QT_UINT16 (ref_data + 4 + 2);
13624               fn_len = QT_UINT8 (ref_data + 50);
13625               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13626                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13627               }
13628             } else {
13629               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13630                   ref_len);
13631             }
13632           } else if (ref_type == FOURCC_url_) {
13633             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13634           } else {
13635             GST_DEBUG_OBJECT (qtdemux,
13636                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13637                 GST_FOURCC_ARGS (ref_type));
13638           }
13639           if (ref.location != NULL) {
13640             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13641             redirects =
13642                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13643           } else {
13644             GST_WARNING_OBJECT (qtdemux,
13645                 "Failed to extract redirect location from rdrf atom");
13646           }
13647         } else {
13648           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13649         }
13650       }
13651
13652       /* look for others */
13653       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13654     }
13655
13656     if (redirects != NULL) {
13657       qtdemux_process_redirects (qtdemux, redirects);
13658     }
13659   }
13660   return TRUE;
13661 }
13662
13663 static GstTagList *
13664 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13665 {
13666   const gchar *fmt;
13667
13668   if (tags == NULL) {
13669     tags = gst_tag_list_new_empty ();
13670     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13671   }
13672
13673   if (qtdemux->major_brand == FOURCC_mjp2)
13674     fmt = "Motion JPEG 2000";
13675   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13676     fmt = "3GP";
13677   else if (qtdemux->major_brand == FOURCC_qt__)
13678     fmt = "Quicktime";
13679   else if (qtdemux->fragmented)
13680     fmt = "ISO fMP4";
13681   else
13682     fmt = "ISO MP4/M4A";
13683
13684   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13685       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13686
13687   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13688       fmt, NULL);
13689
13690   return tags;
13691 }
13692
13693 /* we have read the complete moov node now.
13694  * This function parses all of the relevant info, creates the traks and
13695  * prepares all data structures for playback
13696  */
13697 static gboolean
13698 qtdemux_parse_tree (GstQTDemux * qtdemux)
13699 {
13700   GNode *mvhd;
13701   GNode *trak;
13702   GNode *udta;
13703   GNode *mvex;
13704   GNode *pssh;
13705   guint64 creation_time;
13706   GstDateTime *datetime = NULL;
13707   gint version;
13708
13709   /* make sure we have a usable taglist */
13710   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13711
13712   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13713   if (mvhd == NULL) {
13714     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13715     return qtdemux_parse_redirects (qtdemux);
13716   }
13717
13718   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13719   if (version == 1) {
13720     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13721     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13722     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13723   } else if (version == 0) {
13724     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13725     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13726     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13727   } else {
13728     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13729     return FALSE;
13730   }
13731
13732   /* Moving qt creation time (secs since 1904) to unix time */
13733   if (creation_time != 0) {
13734     /* Try to use epoch first as it should be faster and more commonly found */
13735     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13736       gint64 now_s;
13737
13738       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13739       /* some data cleansing sanity */
13740       now_s = g_get_real_time () / G_USEC_PER_SEC;
13741       if (now_s + 24 * 3600 < creation_time) {
13742         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13743       } else {
13744         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13745       }
13746     } else {
13747       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13748       GDateTime *dt, *dt_local;
13749
13750       dt = g_date_time_add_seconds (base_dt, creation_time);
13751       dt_local = g_date_time_to_local (dt);
13752       datetime = gst_date_time_new_from_g_date_time (dt_local);
13753
13754       g_date_time_unref (base_dt);
13755       g_date_time_unref (dt);
13756     }
13757   }
13758   if (datetime) {
13759     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13760     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13761         datetime, NULL);
13762     gst_date_time_unref (datetime);
13763   }
13764
13765   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13766   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13767
13768   /* check for fragmented file and get some (default) data */
13769   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13770   if (mvex) {
13771     GNode *mehd;
13772     GstByteReader mehd_data;
13773
13774     /* let track parsing or anyone know weird stuff might happen ... */
13775     qtdemux->fragmented = TRUE;
13776
13777     /* compensate for total duration */
13778     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13779     if (mehd)
13780       qtdemux_parse_mehd (qtdemux, &mehd_data);
13781   }
13782
13783   /* Update the movie segment duration, unless it was directly given to us
13784    * by upstream. Otherwise let it as is, as we don't want to mangle the
13785    * duration provided by upstream that may come e.g. from a MPD file. */
13786   if (!qtdemux->upstream_format_is_time) {
13787     GstClockTime duration;
13788     /* set duration in the segment info */
13789     gst_qtdemux_get_duration (qtdemux, &duration);
13790     qtdemux->segment.duration = duration;
13791     /* also do not exceed duration; stop is set that way post seek anyway,
13792      * and segment activation falls back to duration,
13793      * whereas loop only checks stop, so let's align this here as well */
13794     qtdemux->segment.stop = duration;
13795   }
13796
13797   /* parse all traks */
13798   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13799   while (trak) {
13800     qtdemux_parse_trak (qtdemux, trak);
13801     /* iterate all siblings */
13802     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13803   }
13804
13805   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13806
13807   /* find tags */
13808   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13809   if (udta) {
13810     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13811   } else {
13812     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13813   }
13814
13815   /* maybe also some tags in meta box */
13816   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13817   if (udta) {
13818     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13819     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13820   } else {
13821     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13822   }
13823
13824   /* parse any protection system info */
13825   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13826   while (pssh) {
13827     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13828     qtdemux_parse_pssh (qtdemux, pssh);
13829     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13830   }
13831
13832   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13833
13834   return TRUE;
13835 }
13836
13837 /* taken from ffmpeg */
13838 static int
13839 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13840 {
13841   int count = 4;
13842   int len = 0;
13843
13844   while (count--) {
13845     int c;
13846
13847     if (ptr >= end)
13848       return -1;
13849
13850     c = *ptr++;
13851     len = (len << 7) | (c & 0x7f);
13852     if (!(c & 0x80))
13853       break;
13854   }
13855   *end_out = ptr;
13856   return len;
13857 }
13858
13859 static GList *
13860 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13861     gsize codec_data_size)
13862 {
13863   GList *list = NULL;
13864   guint8 *p = codec_data;
13865   gint i, offset, num_packets;
13866   guint *length, last;
13867
13868   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13869
13870   if (codec_data == NULL || codec_data_size == 0)
13871     goto error;
13872
13873   /* start of the stream and vorbis audio or theora video, need to
13874    * send the codec_priv data as first three packets */
13875   num_packets = p[0] + 1;
13876   GST_DEBUG_OBJECT (qtdemux,
13877       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13878       (guint) num_packets, codec_data_size);
13879
13880   /* Let's put some limits, Don't think there even is a xiph codec
13881    * with more than 3-4 headers */
13882   if (G_UNLIKELY (num_packets > 16)) {
13883     GST_WARNING_OBJECT (qtdemux,
13884         "Unlikely number of xiph headers, most likely not valid");
13885     goto error;
13886   }
13887
13888   length = g_alloca (num_packets * sizeof (guint));
13889   last = 0;
13890   offset = 1;
13891
13892   /* first packets, read length values */
13893   for (i = 0; i < num_packets - 1; i++) {
13894     length[i] = 0;
13895     while (offset < codec_data_size) {
13896       length[i] += p[offset];
13897       if (p[offset++] != 0xff)
13898         break;
13899     }
13900     last += length[i];
13901   }
13902   if (offset + last > codec_data_size)
13903     goto error;
13904
13905   /* last packet is the remaining size */
13906   length[i] = codec_data_size - offset - last;
13907
13908   for (i = 0; i < num_packets; i++) {
13909     GstBuffer *hdr;
13910
13911     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13912
13913     if (offset + length[i] > codec_data_size)
13914       goto error;
13915
13916     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13917     list = g_list_append (list, hdr);
13918
13919     offset += length[i];
13920   }
13921
13922   return list;
13923
13924   /* ERRORS */
13925 error:
13926   {
13927     if (list != NULL)
13928       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13929     return NULL;
13930   }
13931
13932 }
13933
13934 /* this can change the codec originally present in @list */
13935 static void
13936 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13937     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13938 {
13939   int len = QT_UINT32 (esds->data);
13940   guint8 *ptr = esds->data;
13941   guint8 *end = ptr + len;
13942   int tag;
13943   guint8 *data_ptr = NULL;
13944   int data_len = 0;
13945   guint8 object_type_id = 0;
13946   guint8 stream_type = 0;
13947   const char *codec_name = NULL;
13948   GstCaps *caps = NULL;
13949
13950   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13951   ptr += 8;
13952   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13953   ptr += 4;
13954   while (ptr + 1 < end) {
13955     tag = QT_UINT8 (ptr);
13956     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13957     ptr++;
13958     len = read_descr_size (ptr, end, &ptr);
13959     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13960
13961     /* Check the stated amount of data is available for reading */
13962     if (len < 0 || ptr + len > end)
13963       break;
13964
13965     switch (tag) {
13966       case ES_DESCRIPTOR_TAG:
13967         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13968         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13969         ptr += 3;
13970         break;
13971       case DECODER_CONFIG_DESC_TAG:{
13972         guint max_bitrate, avg_bitrate;
13973
13974         object_type_id = QT_UINT8 (ptr);
13975         stream_type = QT_UINT8 (ptr + 1) >> 2;
13976         max_bitrate = QT_UINT32 (ptr + 5);
13977         avg_bitrate = QT_UINT32 (ptr + 9);
13978         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13979         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13980         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13981         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13982         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13983         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13984           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13985               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13986         }
13987         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13988           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13989               avg_bitrate, NULL);
13990         }
13991         ptr += 13;
13992         break;
13993       }
13994       case DECODER_SPECIFIC_INFO_TAG:
13995         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13996         if (object_type_id == 0xe0 && len == 0x40) {
13997           guint8 *data;
13998           GstStructure *s;
13999           guint32 clut[16];
14000           gint i;
14001
14002           GST_DEBUG_OBJECT (qtdemux,
14003               "Have VOBSUB palette. Creating palette event");
14004           /* move to decConfigDescr data and read palette */
14005           data = ptr;
14006           for (i = 0; i < 16; i++) {
14007             clut[i] = QT_UINT32 (data);
14008             data += 4;
14009           }
14010
14011           s = gst_structure_new ("application/x-gst-dvd", "event",
14012               G_TYPE_STRING, "dvd-spu-clut-change",
14013               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14014               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14015               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14016               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14017               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14018               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14019               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14020               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14021               NULL);
14022
14023           /* store event and trigger custom processing */
14024           stream->pending_event =
14025               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14026         } else {
14027           /* Generic codec_data handler puts it on the caps */
14028           data_ptr = ptr;
14029           data_len = len;
14030         }
14031
14032         ptr += len;
14033         break;
14034       case SL_CONFIG_DESC_TAG:
14035         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14036         ptr += 1;
14037         break;
14038       default:
14039         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14040             tag);
14041         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14042         ptr += len;
14043         break;
14044     }
14045   }
14046
14047   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14048    * in use, and should also be used to override some other parameters for some
14049    * codecs. */
14050   switch (object_type_id) {
14051     case 0x20:                 /* MPEG-4 */
14052       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14053        * profile_and_level_indication */
14054       if (data_ptr != NULL && data_len >= 5 &&
14055           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14056         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14057             data_ptr + 4, data_len - 4);
14058       }
14059       break;                    /* Nothing special needed here */
14060     case 0x21:                 /* H.264 */
14061       codec_name = "H.264 / AVC";
14062       caps = gst_caps_new_simple ("video/x-h264",
14063           "stream-format", G_TYPE_STRING, "avc",
14064           "alignment", G_TYPE_STRING, "au", NULL);
14065       break;
14066     case 0x40:                 /* AAC (any) */
14067     case 0x66:                 /* AAC Main */
14068     case 0x67:                 /* AAC LC */
14069     case 0x68:                 /* AAC SSR */
14070       /* Override channels and rate based on the codec_data, as it's often
14071        * wrong. */
14072       /* Only do so for basic setup without HE-AAC extension */
14073       if (data_ptr && data_len == 2) {
14074         guint channels, rate;
14075
14076         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14077         if (channels > 0)
14078           entry->n_channels = channels;
14079
14080         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14081         if (rate > 0)
14082           entry->rate = rate;
14083       }
14084
14085       /* Set level and profile if possible */
14086       if (data_ptr != NULL && data_len >= 2) {
14087         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14088             data_ptr, data_len);
14089       } else {
14090         const gchar *profile_str = NULL;
14091         GstBuffer *buffer;
14092         GstMapInfo map;
14093         guint8 *codec_data;
14094         gint rate_idx, profile;
14095
14096         /* No codec_data, let's invent something.
14097          * FIXME: This is wrong for SBR! */
14098
14099         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14100
14101         buffer = gst_buffer_new_and_alloc (2);
14102         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14103         codec_data = map.data;
14104
14105         rate_idx =
14106             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14107             (stream)->rate);
14108
14109         switch (object_type_id) {
14110           case 0x66:
14111             profile_str = "main";
14112             profile = 0;
14113             break;
14114           case 0x67:
14115             profile_str = "lc";
14116             profile = 1;
14117             break;
14118           case 0x68:
14119             profile_str = "ssr";
14120             profile = 2;
14121             break;
14122           default:
14123             profile = 3;
14124             break;
14125         }
14126
14127         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14128         codec_data[1] =
14129             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14130
14131         gst_buffer_unmap (buffer, &map);
14132         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14133             GST_TYPE_BUFFER, buffer, NULL);
14134         gst_buffer_unref (buffer);
14135
14136         if (profile_str) {
14137           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14138               G_TYPE_STRING, profile_str, NULL);
14139         }
14140       }
14141       break;
14142     case 0x60:                 /* MPEG-2, various profiles */
14143     case 0x61:
14144     case 0x62:
14145     case 0x63:
14146     case 0x64:
14147     case 0x65:
14148       codec_name = "MPEG-2 video";
14149       caps = gst_caps_new_simple ("video/mpeg",
14150           "mpegversion", G_TYPE_INT, 2,
14151           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14152       break;
14153     case 0x69:                 /* MPEG-2 BC audio */
14154     case 0x6B:                 /* MPEG-1 audio */
14155       caps = gst_caps_new_simple ("audio/mpeg",
14156           "mpegversion", G_TYPE_INT, 1, NULL);
14157       codec_name = "MPEG-1 audio";
14158       break;
14159     case 0x6A:                 /* MPEG-1 */
14160       codec_name = "MPEG-1 video";
14161       caps = gst_caps_new_simple ("video/mpeg",
14162           "mpegversion", G_TYPE_INT, 1,
14163           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14164       break;
14165     case 0x6C:                 /* MJPEG */
14166       caps =
14167           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14168           NULL);
14169       codec_name = "Motion-JPEG";
14170       break;
14171     case 0x6D:                 /* PNG */
14172       caps =
14173           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14174           NULL);
14175       codec_name = "PNG still images";
14176       break;
14177     case 0x6E:                 /* JPEG2000 */
14178       codec_name = "JPEG-2000";
14179       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14180       break;
14181     case 0xA4:                 /* Dirac */
14182       codec_name = "Dirac";
14183       caps = gst_caps_new_empty_simple ("video/x-dirac");
14184       break;
14185     case 0xA5:                 /* AC3 */
14186       codec_name = "AC-3 audio";
14187       caps = gst_caps_new_simple ("audio/x-ac3",
14188           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14189       break;
14190     case 0xA9:                 /* AC3 */
14191       codec_name = "DTS audio";
14192       caps = gst_caps_new_simple ("audio/x-dts",
14193           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14194       break;
14195     case 0xDD:
14196       if (stream_type == 0x05 && data_ptr) {
14197         GList *headers =
14198             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14199         if (headers) {
14200           GList *tmp;
14201           GValue arr_val = G_VALUE_INIT;
14202           GValue buf_val = G_VALUE_INIT;
14203           GstStructure *s;
14204
14205           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14206           codec_name = "Vorbis";
14207           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14208           g_value_init (&arr_val, GST_TYPE_ARRAY);
14209           g_value_init (&buf_val, GST_TYPE_BUFFER);
14210           for (tmp = headers; tmp; tmp = tmp->next) {
14211             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14212             gst_value_array_append_value (&arr_val, &buf_val);
14213           }
14214           s = gst_caps_get_structure (caps, 0);
14215           gst_structure_take_value (s, "streamheader", &arr_val);
14216           g_value_unset (&buf_val);
14217           g_list_free (headers);
14218
14219           data_ptr = NULL;
14220           data_len = 0;
14221         }
14222       }
14223       break;
14224     case 0xE1:                 /* QCELP */
14225       /* QCELP, the codec_data is a riff tag (little endian) with
14226        * 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). */
14227       caps = gst_caps_new_empty_simple ("audio/qcelp");
14228       codec_name = "QCELP";
14229       break;
14230     default:
14231       break;
14232   }
14233
14234   /* If we have a replacement caps, then change our caps for this stream */
14235   if (caps) {
14236     gst_caps_unref (entry->caps);
14237     entry->caps = caps;
14238   }
14239
14240   if (codec_name && list)
14241     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14242         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14243
14244   /* Add the codec_data attribute to caps, if we have it */
14245   if (data_ptr) {
14246     GstBuffer *buffer;
14247
14248     buffer = gst_buffer_new_and_alloc (data_len);
14249     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14250
14251     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14252     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14253
14254     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14255         buffer, NULL);
14256     gst_buffer_unref (buffer);
14257   }
14258
14259 }
14260
14261 static inline GstCaps *
14262 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14263 {
14264   GstCaps *caps;
14265   guint i;
14266   char *s, fourstr[5];
14267
14268   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14269   for (i = 0; i < 4; i++) {
14270     if (!g_ascii_isalnum (fourstr[i]))
14271       fourstr[i] = '_';
14272   }
14273   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14274   caps = gst_caps_new_empty_simple (s);
14275   g_free (s);
14276   return caps;
14277 }
14278
14279 #define _codec(name) \
14280   do { \
14281     if (codec_name) { \
14282       *codec_name = g_strdup (name); \
14283     } \
14284   } while (0)
14285
14286 static GstCaps *
14287 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14288     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14289     const guint8 * stsd_entry_data, gchar ** codec_name)
14290 {
14291   GstCaps *caps = NULL;
14292   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14293
14294   switch (fourcc) {
14295     case FOURCC_png:
14296       _codec ("PNG still images");
14297       caps = gst_caps_new_empty_simple ("image/png");
14298       break;
14299     case FOURCC_jpeg:
14300       _codec ("JPEG still images");
14301       caps =
14302           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14303           NULL);
14304       break;
14305     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14306     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14307     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14308     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14309       _codec ("Motion-JPEG");
14310       caps =
14311           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14312           NULL);
14313       break;
14314     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14315       _codec ("Motion-JPEG format B");
14316       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14317       break;
14318     case FOURCC_mjp2:
14319       _codec ("JPEG-2000");
14320       /* override to what it should be according to spec, avoid palette_data */
14321       entry->bits_per_sample = 24;
14322       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14323       break;
14324     case FOURCC_SVQ3:
14325       _codec ("Sorensen video v.3");
14326       caps = gst_caps_new_simple ("video/x-svq",
14327           "svqversion", G_TYPE_INT, 3, NULL);
14328       break;
14329     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14330     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14331       _codec ("Sorensen video v.1");
14332       caps = gst_caps_new_simple ("video/x-svq",
14333           "svqversion", G_TYPE_INT, 1, NULL);
14334       break;
14335     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14336       caps = gst_caps_new_empty_simple ("video/x-raw");
14337       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14338       _codec ("Windows Raw RGB");
14339       stream->alignment = 32;
14340       break;
14341     case FOURCC_raw_:
14342     {
14343       guint16 bps;
14344
14345       bps = QT_UINT16 (stsd_entry_data + 82);
14346       switch (bps) {
14347         case 15:
14348           format = GST_VIDEO_FORMAT_RGB15;
14349           break;
14350         case 16:
14351           format = GST_VIDEO_FORMAT_RGB16;
14352           break;
14353         case 24:
14354           format = GST_VIDEO_FORMAT_RGB;
14355           break;
14356         case 32:
14357           format = GST_VIDEO_FORMAT_ARGB;
14358           break;
14359         default:
14360           /* unknown */
14361           break;
14362       }
14363       break;
14364     }
14365     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14366       format = GST_VIDEO_FORMAT_I420;
14367       break;
14368     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14369     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14370       format = GST_VIDEO_FORMAT_I420;
14371       break;
14372     case FOURCC_2vuy:
14373     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14374       format = GST_VIDEO_FORMAT_UYVY;
14375       break;
14376     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14377       format = GST_VIDEO_FORMAT_v308;
14378       break;
14379     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14380       format = GST_VIDEO_FORMAT_v216;
14381       break;
14382     case FOURCC_v210:
14383       format = GST_VIDEO_FORMAT_v210;
14384       break;
14385     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14386       format = GST_VIDEO_FORMAT_r210;
14387       break;
14388       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14389          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14390          format = GST_VIDEO_FORMAT_v410;
14391          break;
14392        */
14393       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14394        * but different order than AYUV
14395        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14396        format = GST_VIDEO_FORMAT_v408;
14397        break;
14398        */
14399     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14400     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14401       _codec ("MPEG-1 video");
14402       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14403           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14404       break;
14405     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14406     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14407     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14408     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14409     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14410     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14411     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14412     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14413     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14414     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14415     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14416     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14417     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14418     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14419     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14420     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14421     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14422     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14423     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14424     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14425     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14426     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14427     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14428     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14429     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14430     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14431     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14432     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14433     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14434     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14435     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14436     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14437     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14438     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14439     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14440     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14441     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14442     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14443     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14444     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14445     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14446     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14447     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14448     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14449     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14450     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14451     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14452       _codec ("MPEG-2 video");
14453       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14454           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14455       break;
14456     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14457       _codec ("GIF still images");
14458       caps = gst_caps_new_empty_simple ("image/gif");
14459       break;
14460     case FOURCC_h263:
14461     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14462     case FOURCC_s263:
14463     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14464       _codec ("H.263");
14465       /* ffmpeg uses the height/width props, don't know why */
14466       caps = gst_caps_new_simple ("video/x-h263",
14467           "variant", G_TYPE_STRING, "itu", NULL);
14468       break;
14469     case FOURCC_mp4v:
14470     case FOURCC_MP4V:
14471       _codec ("MPEG-4 video");
14472       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14473           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14474       break;
14475     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14476     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14477       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14478       caps = gst_caps_new_simple ("video/x-msmpeg",
14479           "msmpegversion", G_TYPE_INT, 43, NULL);
14480       break;
14481     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14482       _codec ("DivX 3");
14483       caps = gst_caps_new_simple ("video/x-divx",
14484           "divxversion", G_TYPE_INT, 3, NULL);
14485       break;
14486     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14487     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14488       _codec ("DivX 4");
14489       caps = gst_caps_new_simple ("video/x-divx",
14490           "divxversion", G_TYPE_INT, 4, NULL);
14491       break;
14492     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14493       _codec ("DivX 5");
14494       caps = gst_caps_new_simple ("video/x-divx",
14495           "divxversion", G_TYPE_INT, 5, NULL);
14496       break;
14497
14498     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14499       _codec ("FFV1");
14500       caps = gst_caps_new_simple ("video/x-ffv",
14501           "ffvversion", G_TYPE_INT, 1, NULL);
14502       break;
14503
14504     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14505     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14506     case FOURCC_XVID:
14507     case FOURCC_xvid:
14508     case FOURCC_FMP4:
14509     case FOURCC_fmp4:
14510     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14511       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14512           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14513       _codec ("MPEG-4");
14514       break;
14515
14516     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14517       _codec ("Cinepak");
14518       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14519       break;
14520     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14521       _codec ("Apple QuickDraw");
14522       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14523       break;
14524     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14525       _codec ("Apple video");
14526       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14527       break;
14528     case FOURCC_H264:
14529     case FOURCC_avc1:
14530     case FOURCC_dva1:
14531       _codec ("H.264 / AVC");
14532       caps = gst_caps_new_simple ("video/x-h264",
14533           "stream-format", G_TYPE_STRING, "avc",
14534           "alignment", G_TYPE_STRING, "au", NULL);
14535       break;
14536     case FOURCC_avc3:
14537     case FOURCC_dvav:
14538       _codec ("H.264 / AVC");
14539       caps = gst_caps_new_simple ("video/x-h264",
14540           "stream-format", G_TYPE_STRING, "avc3",
14541           "alignment", G_TYPE_STRING, "au", NULL);
14542       break;
14543     case FOURCC_H265:
14544     case FOURCC_hvc1:
14545     case FOURCC_dvh1:
14546       _codec ("H.265 / HEVC");
14547       caps = gst_caps_new_simple ("video/x-h265",
14548           "stream-format", G_TYPE_STRING, "hvc1",
14549           "alignment", G_TYPE_STRING, "au", NULL);
14550       break;
14551     case FOURCC_hev1:
14552     case FOURCC_dvhe:
14553       _codec ("H.265 / HEVC");
14554       caps = gst_caps_new_simple ("video/x-h265",
14555           "stream-format", G_TYPE_STRING, "hev1",
14556           "alignment", G_TYPE_STRING, "au", NULL);
14557       break;
14558     case FOURCC_rle_:
14559       _codec ("Run-length encoding");
14560       caps = gst_caps_new_simple ("video/x-rle",
14561           "layout", G_TYPE_STRING, "quicktime", NULL);
14562       break;
14563     case FOURCC_WRLE:
14564       _codec ("Run-length encoding");
14565       caps = gst_caps_new_simple ("video/x-rle",
14566           "layout", G_TYPE_STRING, "microsoft", NULL);
14567       break;
14568     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14569     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14570       _codec ("Indeo Video 3");
14571       caps = gst_caps_new_simple ("video/x-indeo",
14572           "indeoversion", G_TYPE_INT, 3, NULL);
14573       break;
14574     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14575     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14576       _codec ("Intel Video 4");
14577       caps = gst_caps_new_simple ("video/x-indeo",
14578           "indeoversion", G_TYPE_INT, 4, NULL);
14579       break;
14580     case FOURCC_dvcp:
14581     case FOURCC_dvc_:
14582     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14583     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14584     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14585     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14586     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14587     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14588       _codec ("DV Video");
14589       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14590           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14591       break;
14592     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14593     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14594       _codec ("DVCPro50 Video");
14595       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14596           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14597       break;
14598     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14599     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14600       _codec ("DVCProHD Video");
14601       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14602           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14603       break;
14604     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14605       _codec ("Apple Graphics (SMC)");
14606       caps = gst_caps_new_empty_simple ("video/x-smc");
14607       break;
14608     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14609       _codec ("VP3");
14610       caps = gst_caps_new_empty_simple ("video/x-vp3");
14611       break;
14612     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14613       _codec ("VP6 Flash");
14614       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14615       break;
14616     case FOURCC_XiTh:
14617       _codec ("Theora");
14618       caps = gst_caps_new_empty_simple ("video/x-theora");
14619       /* theora uses one byte of padding in the data stream because it does not
14620        * allow 0 sized packets while theora does */
14621       entry->padding = 1;
14622       break;
14623     case FOURCC_drac:
14624       _codec ("Dirac");
14625       caps = gst_caps_new_empty_simple ("video/x-dirac");
14626       break;
14627     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14628       _codec ("TIFF still images");
14629       caps = gst_caps_new_empty_simple ("image/tiff");
14630       break;
14631     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14632       _codec ("Apple Intermediate Codec");
14633       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14634       break;
14635     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14636       _codec ("AVID DNxHD");
14637       caps = gst_caps_from_string ("video/x-dnxhd");
14638       break;
14639     case FOURCC_VP80:
14640     case FOURCC_vp08:
14641       _codec ("On2 VP8");
14642       caps = gst_caps_from_string ("video/x-vp8");
14643       break;
14644     case FOURCC_vp09:
14645       _codec ("Google VP9");
14646       caps = gst_caps_from_string ("video/x-vp9");
14647       break;
14648     case FOURCC_apcs:
14649       _codec ("Apple ProRes LT");
14650       caps =
14651           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14652           NULL);
14653       break;
14654     case FOURCC_apch:
14655       _codec ("Apple ProRes HQ");
14656       caps =
14657           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14658           NULL);
14659       break;
14660     case FOURCC_apcn:
14661       _codec ("Apple ProRes");
14662       caps =
14663           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14664           "standard", NULL);
14665       break;
14666     case FOURCC_apco:
14667       _codec ("Apple ProRes Proxy");
14668       caps =
14669           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14670           "proxy", NULL);
14671       break;
14672     case FOURCC_ap4h:
14673       _codec ("Apple ProRes 4444");
14674       caps =
14675           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14676           "4444", NULL);
14677
14678       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14679       if (entry->bits_per_sample > 0) {
14680         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14681             NULL);
14682       }
14683       break;
14684     case FOURCC_ap4x:
14685       _codec ("Apple ProRes 4444 XQ");
14686       caps =
14687           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14688           "4444xq", NULL);
14689
14690       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14691       if (entry->bits_per_sample > 0) {
14692         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14693             NULL);
14694       }
14695       break;
14696     case FOURCC_cfhd:
14697       _codec ("GoPro CineForm");
14698       caps = gst_caps_from_string ("video/x-cineform");
14699       break;
14700     case FOURCC_vc_1:
14701     case FOURCC_ovc1:
14702       _codec ("VC-1");
14703       caps = gst_caps_new_simple ("video/x-wmv",
14704           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14705       break;
14706     case FOURCC_av01:
14707       _codec ("AV1");
14708       caps = gst_caps_new_empty_simple ("video/x-av1");
14709       break;
14710     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14711     default:
14712     {
14713       caps = _get_unknown_codec_name ("video", fourcc);
14714       break;
14715     }
14716   }
14717
14718   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14719     GstVideoInfo info;
14720
14721     gst_video_info_init (&info);
14722     gst_video_info_set_format (&info, format, entry->width, entry->height);
14723
14724     caps = gst_video_info_to_caps (&info);
14725     *codec_name = gst_pb_utils_get_codec_description (caps);
14726
14727     /* enable clipping for raw video streams */
14728     stream->need_clip = TRUE;
14729     stream->alignment = 32;
14730   }
14731
14732   return caps;
14733 }
14734
14735 static guint
14736 round_up_pow2 (guint n)
14737 {
14738   n = n - 1;
14739   n = n | (n >> 1);
14740   n = n | (n >> 2);
14741   n = n | (n >> 4);
14742   n = n | (n >> 8);
14743   n = n | (n >> 16);
14744   return n + 1;
14745 }
14746
14747 static GstCaps *
14748 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14749     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14750     int len, gchar ** codec_name)
14751 {
14752   GstCaps *caps;
14753   const GstStructure *s;
14754   const gchar *name;
14755   gint endian = 0;
14756   GstAudioFormat format = 0;
14757   gint depth;
14758
14759   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14760
14761   depth = entry->bytes_per_packet * 8;
14762
14763   switch (fourcc) {
14764     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14765     case FOURCC_raw_:
14766       /* 8-bit audio is unsigned */
14767       if (depth == 8)
14768         format = GST_AUDIO_FORMAT_U8;
14769       /* otherwise it's signed and big-endian just like 'twos' */
14770     case FOURCC_twos:
14771       endian = G_BIG_ENDIAN;
14772       /* fall-through */
14773     case FOURCC_sowt:
14774     {
14775       gchar *str;
14776
14777       if (!endian)
14778         endian = G_LITTLE_ENDIAN;
14779
14780       if (!format)
14781         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14782
14783       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14784       _codec (str);
14785       g_free (str);
14786
14787       caps = gst_caps_new_simple ("audio/x-raw",
14788           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14789           "layout", G_TYPE_STRING, "interleaved", NULL);
14790       stream->alignment = GST_ROUND_UP_8 (depth);
14791       stream->alignment = round_up_pow2 (stream->alignment);
14792       break;
14793     }
14794     case FOURCC_fl64:
14795       _codec ("Raw 64-bit floating-point audio");
14796       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14797        * endian later */
14798       caps = gst_caps_new_simple ("audio/x-raw",
14799           "format", G_TYPE_STRING, "F64BE",
14800           "layout", G_TYPE_STRING, "interleaved", NULL);
14801       stream->alignment = 8;
14802       break;
14803     case FOURCC_fl32:
14804       _codec ("Raw 32-bit floating-point audio");
14805       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14806        * endian later */
14807       caps = gst_caps_new_simple ("audio/x-raw",
14808           "format", G_TYPE_STRING, "F32BE",
14809           "layout", G_TYPE_STRING, "interleaved", NULL);
14810       stream->alignment = 4;
14811       break;
14812     case FOURCC_in24:
14813       _codec ("Raw 24-bit PCM audio");
14814       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14815        * endian later */
14816       caps = gst_caps_new_simple ("audio/x-raw",
14817           "format", G_TYPE_STRING, "S24BE",
14818           "layout", G_TYPE_STRING, "interleaved", NULL);
14819       stream->alignment = 4;
14820       break;
14821     case FOURCC_in32:
14822       _codec ("Raw 32-bit PCM audio");
14823       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14824        * endian later */
14825       caps = gst_caps_new_simple ("audio/x-raw",
14826           "format", G_TYPE_STRING, "S32BE",
14827           "layout", G_TYPE_STRING, "interleaved", NULL);
14828       stream->alignment = 4;
14829       break;
14830     case FOURCC_s16l:
14831       _codec ("Raw 16-bit PCM audio");
14832       caps = gst_caps_new_simple ("audio/x-raw",
14833           "format", G_TYPE_STRING, "S16LE",
14834           "layout", G_TYPE_STRING, "interleaved", NULL);
14835       stream->alignment = 2;
14836       break;
14837     case FOURCC_ulaw:
14838       _codec ("Mu-law audio");
14839       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14840       break;
14841     case FOURCC_alaw:
14842       _codec ("A-law audio");
14843       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14844       break;
14845     case 0x0200736d:
14846     case 0x6d730002:
14847       _codec ("Microsoft ADPCM");
14848       /* Microsoft ADPCM-ACM code 2 */
14849       caps = gst_caps_new_simple ("audio/x-adpcm",
14850           "layout", G_TYPE_STRING, "microsoft", NULL);
14851       break;
14852     case 0x1100736d:
14853     case 0x6d730011:
14854       _codec ("DVI/IMA ADPCM");
14855       caps = gst_caps_new_simple ("audio/x-adpcm",
14856           "layout", G_TYPE_STRING, "dvi", NULL);
14857       break;
14858     case 0x1700736d:
14859     case 0x6d730017:
14860       _codec ("DVI/Intel IMA ADPCM");
14861       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14862       caps = gst_caps_new_simple ("audio/x-adpcm",
14863           "layout", G_TYPE_STRING, "quicktime", NULL);
14864       break;
14865     case 0x5500736d:
14866     case 0x6d730055:
14867       /* MPEG layer 3, CBR only (pre QT4.1) */
14868     case FOURCC__mp3:
14869     case FOURCC_mp3_:
14870       _codec ("MPEG-1 layer 3");
14871       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14872       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14873           "mpegversion", G_TYPE_INT, 1, NULL);
14874       break;
14875     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14876       _codec ("MPEG-1 layer 2");
14877       /* MPEG layer 2 */
14878       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14879           "mpegversion", G_TYPE_INT, 1, NULL);
14880       break;
14881     case 0x20736d:
14882     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14883       _codec ("EAC-3 audio");
14884       caps = gst_caps_new_simple ("audio/x-eac3",
14885           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14886       entry->sampled = TRUE;
14887       break;
14888     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14889     case FOURCC_ac_3:
14890       _codec ("AC-3 audio");
14891       caps = gst_caps_new_simple ("audio/x-ac3",
14892           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14893       entry->sampled = TRUE;
14894       break;
14895     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14896     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14897       _codec ("DTS audio");
14898       caps = gst_caps_new_simple ("audio/x-dts",
14899           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14900       entry->sampled = TRUE;
14901       break;
14902     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14903     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14904       _codec ("DTS-HD audio");
14905       caps = gst_caps_new_simple ("audio/x-dts",
14906           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14907       entry->sampled = TRUE;
14908       break;
14909     case FOURCC_MAC3:
14910       _codec ("MACE-3");
14911       caps = gst_caps_new_simple ("audio/x-mace",
14912           "maceversion", G_TYPE_INT, 3, NULL);
14913       break;
14914     case FOURCC_MAC6:
14915       _codec ("MACE-6");
14916       caps = gst_caps_new_simple ("audio/x-mace",
14917           "maceversion", G_TYPE_INT, 6, NULL);
14918       break;
14919     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14920       /* ogg/vorbis */
14921       caps = gst_caps_new_empty_simple ("application/ogg");
14922       break;
14923     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14924       _codec ("DV audio");
14925       caps = gst_caps_new_empty_simple ("audio/x-dv");
14926       break;
14927     case FOURCC_mp4a:
14928       _codec ("MPEG-4 AAC audio");
14929       caps = gst_caps_new_simple ("audio/mpeg",
14930           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14931           "stream-format", G_TYPE_STRING, "raw", NULL);
14932       break;
14933     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14934       _codec ("QDesign Music");
14935       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14936       break;
14937     case FOURCC_QDM2:
14938       _codec ("QDesign Music v.2");
14939       /* FIXME: QDesign music version 2 (no constant) */
14940       if (FALSE && data) {
14941         caps = gst_caps_new_simple ("audio/x-qdm2",
14942             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14943             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14944             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14945       } else {
14946         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14947       }
14948       break;
14949     case FOURCC_agsm:
14950       _codec ("GSM audio");
14951       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14952       break;
14953     case FOURCC_samr:
14954       _codec ("AMR audio");
14955       caps = gst_caps_new_empty_simple ("audio/AMR");
14956       break;
14957     case FOURCC_sawb:
14958       _codec ("AMR-WB audio");
14959       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14960       break;
14961     case FOURCC_ima4:
14962       _codec ("Quicktime IMA ADPCM");
14963       caps = gst_caps_new_simple ("audio/x-adpcm",
14964           "layout", G_TYPE_STRING, "quicktime", NULL);
14965       break;
14966     case FOURCC_alac:
14967       _codec ("Apple lossless audio");
14968       caps = gst_caps_new_empty_simple ("audio/x-alac");
14969       break;
14970     case FOURCC_fLaC:
14971       _codec ("Free Lossless Audio Codec");
14972       caps = gst_caps_new_simple ("audio/x-flac",
14973           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14974       break;
14975     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14976       _codec ("QualComm PureVoice");
14977       caps = gst_caps_from_string ("audio/qcelp");
14978       break;
14979     case FOURCC_wma_:
14980     case FOURCC_owma:
14981       _codec ("WMA");
14982       caps = gst_caps_new_empty_simple ("audio/x-wma");
14983       break;
14984     case FOURCC_opus:
14985       _codec ("Opus");
14986       caps = gst_caps_new_empty_simple ("audio/x-opus");
14987       break;
14988     case FOURCC_lpcm:
14989     {
14990       guint32 flags = 0;
14991       guint32 depth = 0;
14992       guint32 width = 0;
14993       GstAudioFormat format;
14994       enum
14995       {
14996         FLAG_IS_FLOAT = 0x1,
14997         FLAG_IS_BIG_ENDIAN = 0x2,
14998         FLAG_IS_SIGNED = 0x4,
14999         FLAG_IS_PACKED = 0x8,
15000         FLAG_IS_ALIGNED_HIGH = 0x10,
15001         FLAG_IS_NON_INTERLEAVED = 0x20
15002       };
15003       _codec ("Raw LPCM audio");
15004
15005       if (data && len >= 36) {
15006         depth = QT_UINT32 (data + 24);
15007         flags = QT_UINT32 (data + 28);
15008         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15009       }
15010       if ((flags & FLAG_IS_FLOAT) == 0) {
15011         if (depth == 0)
15012           depth = 16;
15013         if (width == 0)
15014           width = 16;
15015         if ((flags & FLAG_IS_ALIGNED_HIGH))
15016           depth = width;
15017
15018         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15019             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15020             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15021         caps = gst_caps_new_simple ("audio/x-raw",
15022             "format", G_TYPE_STRING,
15023             format !=
15024             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15025             "UNKNOWN", "layout", G_TYPE_STRING,
15026             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15027             "interleaved", NULL);
15028         stream->alignment = GST_ROUND_UP_8 (depth);
15029         stream->alignment = round_up_pow2 (stream->alignment);
15030       } else {
15031         if (width == 0)
15032           width = 32;
15033         if (width == 64) {
15034           if (flags & FLAG_IS_BIG_ENDIAN)
15035             format = GST_AUDIO_FORMAT_F64BE;
15036           else
15037             format = GST_AUDIO_FORMAT_F64LE;
15038         } else {
15039           if (flags & FLAG_IS_BIG_ENDIAN)
15040             format = GST_AUDIO_FORMAT_F32BE;
15041           else
15042             format = GST_AUDIO_FORMAT_F32LE;
15043         }
15044         caps = gst_caps_new_simple ("audio/x-raw",
15045             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15046             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15047             "non-interleaved" : "interleaved", NULL);
15048         stream->alignment = width / 8;
15049       }
15050       break;
15051     }
15052     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15053     {
15054       _codec ("AC4");
15055       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15056       break;
15057     }
15058     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15059       /* ? */
15060     default:
15061     {
15062       caps = _get_unknown_codec_name ("audio", fourcc);
15063       break;
15064     }
15065   }
15066
15067   if (caps) {
15068     GstCaps *templ_caps =
15069         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15070     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15071     gst_caps_unref (caps);
15072     gst_caps_unref (templ_caps);
15073     caps = intersection;
15074   }
15075
15076   /* enable clipping for raw audio streams */
15077   s = gst_caps_get_structure (caps, 0);
15078   name = gst_structure_get_name (s);
15079   if (g_str_has_prefix (name, "audio/x-raw")) {
15080     stream->need_clip = TRUE;
15081     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15082     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15083     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15084         stream->max_buffer_size);
15085   }
15086   return caps;
15087 }
15088
15089 static GstCaps *
15090 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15091     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15092     const guint8 * stsd_entry_data, gchar ** codec_name)
15093 {
15094   GstCaps *caps;
15095
15096   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15097
15098   switch (fourcc) {
15099     case FOURCC_mp4s:
15100       _codec ("DVD subtitle");
15101       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15102       stream->process_func = gst_qtdemux_process_buffer_dvd;
15103       break;
15104     case FOURCC_text:
15105       _codec ("Quicktime timed text");
15106       goto text;
15107     case FOURCC_tx3g:
15108       _codec ("3GPP timed text");
15109     text:
15110       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15111           "utf8", NULL);
15112       /* actual text piece needs to be extracted */
15113       stream->process_func = gst_qtdemux_process_buffer_text;
15114       break;
15115     case FOURCC_stpp:
15116       _codec ("XML subtitles");
15117       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15118       break;
15119     case FOURCC_wvtt:
15120     {
15121       GstBuffer *buffer;
15122       const gchar *buf = "WEBVTT\n\n";
15123
15124       _codec ("WebVTT subtitles");
15125       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15126       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15127
15128       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15129       buffer = gst_buffer_new_and_alloc (8);
15130       gst_buffer_fill (buffer, 0, buf, 8);
15131       stream->buffers = g_slist_append (stream->buffers, buffer);
15132
15133       break;
15134     }
15135     case FOURCC_c608:
15136       _codec ("CEA 608 Closed Caption");
15137       caps =
15138           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15139           G_TYPE_STRING, "s334-1a", NULL);
15140       stream->process_func = gst_qtdemux_process_buffer_clcp;
15141       stream->need_split = TRUE;
15142       break;
15143     case FOURCC_c708:
15144       _codec ("CEA 708 Closed Caption");
15145       caps =
15146           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15147           G_TYPE_STRING, "cdp", NULL);
15148       stream->process_func = gst_qtdemux_process_buffer_clcp;
15149       break;
15150
15151     default:
15152     {
15153       caps = _get_unknown_codec_name ("text", fourcc);
15154       break;
15155     }
15156   }
15157   return caps;
15158 }
15159
15160 static GstCaps *
15161 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15162     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15163     const guint8 * stsd_entry_data, gchar ** codec_name)
15164 {
15165   GstCaps *caps;
15166
15167   switch (fourcc) {
15168     case FOURCC_m1v:
15169       _codec ("MPEG 1 video");
15170       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15171           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15172       break;
15173     default:
15174       caps = NULL;
15175       break;
15176   }
15177   return caps;
15178 }
15179
15180 static void
15181 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15182     const gchar * system_id)
15183 {
15184   gint i;
15185
15186   if (!qtdemux->protection_system_ids)
15187     qtdemux->protection_system_ids =
15188         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15189   /* Check whether we already have an entry for this system ID. */
15190   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15191     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15192     if (g_ascii_strcasecmp (system_id, id) == 0) {
15193       return;
15194     }
15195   }
15196   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15197   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15198           -1));
15199 }