qtdemux: use g_memdup2() as g_memdup() is deprecated
[platform/upstream/gstreamer.git] / 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
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
97
98 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
99
100 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
101
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
104 #define QTDEMUX_NTH_STREAM(demux,idx) \
105    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
106 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
107    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
108
109 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
110
111 GST_DEBUG_CATEGORY (qtdemux_debug);
112 #define GST_CAT_DEFAULT qtdemux_debug
113
114 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
115 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
116
117 /* Macros for converting to/from timescale */
118 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
119 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
120
121 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
122 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
123
124 /* timestamp is the DTS */
125 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
126 /* timestamp + offset + cslg_shift is the outgoing PTS */
127 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
128 /* timestamp + offset is the PTS used for internal seek calculations */
129 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
130 /* timestamp + duration - dts is the duration */
131 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
132
133 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
134
135 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
136 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
137     GST_TRACE("Locking from thread %p", g_thread_self()); \
138     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
139     GST_TRACE("Locked from thread %p", g_thread_self()); \
140  } G_STMT_END
141
142 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
143     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
144     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
145  } G_STMT_END
146
147 /*
148  * Quicktime has tracks and segments. A track is a continuous piece of
149  * multimedia content. The track is not always played from start to finish but
150  * instead, pieces of the track are 'cut out' and played in sequence. This is
151  * what the segments do.
152  *
153  * Inside the track we have keyframes (K) and delta frames. The track has its
154  * own timing, which starts from 0 and extends to end. The position in the track
155  * is called the media_time.
156  *
157  * The segments now describe the pieces that should be played from this track
158  * and are basically tuples of media_time/duration/rate entries. We can have
159  * multiple segments and they are all played after one another. An example:
160  *
161  * segment 1: media_time: 1 second, duration: 1 second, rate 1
162  * segment 2: media_time: 3 second, duration: 2 second, rate 2
163  *
164  * To correctly play back this track, one must play: 1 second of media starting
165  * from media_time 1 followed by 2 seconds of media starting from media_time 3
166  * at a rate of 2.
167  *
168  * Each of the segments will be played at a specific time, the first segment at
169  * time 0, the second one after the duration of the first one, etc.. Note that
170  * the time in resulting playback is not identical to the media_time of the
171  * track anymore.
172  *
173  * Visually, assuming the track has 4 second of media_time:
174  *
175  *                (a)                   (b)          (c)              (d)
176  *         .-----------------------------------------------------------.
177  * track:  | K.....K.........K........K.......K.......K...........K... |
178  *         '-----------------------------------------------------------'
179  *         0              1              2              3              4
180  *           .------------^              ^   .----------^              ^
181  *          /              .-------------'  /       .------------------'
182  *         /              /          .-----'       /
183  *         .--------------.         .--------------.
184  *         | segment 1    |         | segment 2    |
185  *         '--------------'         '--------------'
186  *
187  * The challenge here is to cut out the right pieces of the track for each of
188  * the playback segments. This fortunately can easily be done with the SEGMENT
189  * events of GStreamer.
190  *
191  * For playback of segment 1, we need to provide the decoder with the keyframe
192  * (a), in the above figure, but we must instruct it only to output the decoded
193  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
194  * position set to the time of the segment: 0.
195  *
196  * We then proceed to push data from keyframe (a) to frame (b). The decoder
197  * decodes but clips all before media_time 1.
198  *
199  * After finishing a segment, we push out a new SEGMENT event with the clipping
200  * boundaries of the new data.
201  *
202  * This is a good usecase for the GStreamer accumulated SEGMENT events.
203  */
204
205 struct _QtDemuxSegment
206 {
207   /* global time and duration, all gst time */
208   GstClockTime time;
209   GstClockTime stop_time;
210   GstClockTime duration;
211   /* media time of trak, all gst time */
212   GstClockTime media_start;
213   GstClockTime media_stop;
214   gdouble rate;
215   /* Media start time in trak timescale units */
216   guint32 trak_media_start;
217 };
218
219 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
220
221 /* Used with fragmented MP4 files (mfra atom) */
222 struct _QtDemuxRandomAccessEntry
223 {
224   GstClockTime ts;
225   guint64 moof_offset;
226 };
227
228
229 /* Contains properties and cryptographic info for a set of samples from a
230  * track protected using Common Encryption (cenc) */
231 struct _QtDemuxCencSampleSetInfo
232 {
233   GstStructure *default_properties;
234
235   /* @crypto_info holds one GstStructure per sample */
236   GPtrArray *crypto_info;
237 };
238
239 struct _QtDemuxAavdEncryptionInfo
240 {
241   GstStructure *default_properties;
242 };
243
244 static const gchar *
245 qt_demux_state_string (enum QtDemuxState state)
246 {
247   switch (state) {
248     case QTDEMUX_STATE_INITIAL:
249       return "<INITIAL>";
250     case QTDEMUX_STATE_HEADER:
251       return "<HEADER>";
252     case QTDEMUX_STATE_MOVIE:
253       return "<MOVIE>";
254     case QTDEMUX_STATE_BUFFER_MDAT:
255       return "<BUFFER_MDAT>";
256     default:
257       return "<UNKNOWN>";
258   }
259 }
260
261 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
262
263 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
264
265 static GstStaticPadTemplate gst_qtdemux_sink_template =
266     GST_STATIC_PAD_TEMPLATE ("sink",
267     GST_PAD_SINK,
268     GST_PAD_ALWAYS,
269     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
270         "application/x-3gp")
271     );
272
273 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
274 GST_STATIC_PAD_TEMPLATE ("video_%u",
275     GST_PAD_SRC,
276     GST_PAD_SOMETIMES,
277     GST_STATIC_CAPS_ANY);
278
279 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
280 GST_STATIC_PAD_TEMPLATE ("audio_%u",
281     GST_PAD_SRC,
282     GST_PAD_SOMETIMES,
283     GST_STATIC_CAPS_ANY);
284
285 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
286 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
287     GST_PAD_SRC,
288     GST_PAD_SOMETIMES,
289     GST_STATIC_CAPS_ANY);
290
291 #define gst_qtdemux_parent_class parent_class
292 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
293 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
294     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
295
296 static void gst_qtdemux_dispose (GObject * object);
297 static void gst_qtdemux_finalize (GObject * object);
298
299 static guint32
300 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
301     GstClockTime media_time);
302 static guint32
303 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
304     QtDemuxStream * str, gint64 media_offset);
305
306 #if 0
307 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
308 static GstIndex *gst_qtdemux_get_index (GstElement * element);
309 #endif
310 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
311     GstStateChange transition);
312 static void gst_qtdemux_set_context (GstElement * element,
313     GstContext * context);
314 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
315 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
316     GstObject * parent, GstPadMode mode, gboolean active);
317
318 static void gst_qtdemux_loop (GstPad * pad);
319 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
320     GstBuffer * inbuf);
321 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
322     GstEvent * event);
323 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
324     GstQuery * query);
325 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
326 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
327     QtDemuxStream * stream);
328 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
329     QtDemuxStream * stream);
330 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
331     gboolean force);
332
333 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
334
335 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
336     const guint8 * buffer, guint length);
337 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
338     const guint8 * buffer, guint length);
339 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
340
341 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
342     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
343     GstTagList * list);
344 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
345     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
346     const guint8 * stsd_entry_data, gchar ** codec_name);
347 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
348     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
349     const guint8 * data, int len, gchar ** codec_name);
350 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
351     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
352     gchar ** codec_name);
353 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
354     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
355     const guint8 * stsd_entry_data, gchar ** codec_name);
356
357 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
358     QtDemuxStream * stream, guint32 n);
359 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
360 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
361 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
363 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
364 static void qtdemux_do_allocation (QtDemuxStream * stream,
365     GstQTDemux * qtdemux);
366 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
367     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
368 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
369     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
370     GstClockTime * _start, GstClockTime * _stop);
371 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
372     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
373
374 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
375 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
376
377 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
378
379 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
380     QtDemuxStream * stream, guint sample_index);
381 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
382     const gchar * id);
383 static void qtdemux_gst_structure_free (GstStructure * gststructure);
384 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
385
386 static void
387 gst_qtdemux_class_init (GstQTDemuxClass * klass)
388 {
389   GObjectClass *gobject_class;
390   GstElementClass *gstelement_class;
391
392   gobject_class = (GObjectClass *) klass;
393   gstelement_class = (GstElementClass *) klass;
394
395   parent_class = g_type_class_peek_parent (klass);
396
397   gobject_class->dispose = gst_qtdemux_dispose;
398   gobject_class->finalize = gst_qtdemux_finalize;
399
400   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
401 #if 0
402   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
403   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
404 #endif
405   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
406
407   gst_tag_register_musicbrainz_tags ();
408
409   gst_element_class_add_static_pad_template (gstelement_class,
410       &gst_qtdemux_sink_template);
411   gst_element_class_add_static_pad_template (gstelement_class,
412       &gst_qtdemux_videosrc_template);
413   gst_element_class_add_static_pad_template (gstelement_class,
414       &gst_qtdemux_audiosrc_template);
415   gst_element_class_add_static_pad_template (gstelement_class,
416       &gst_qtdemux_subsrc_template);
417   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
418       "Codec/Demuxer",
419       "Demultiplex a QuickTime file into audio and video streams",
420       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
421
422   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
423   gst_riff_init ();
424 }
425
426 static void
427 gst_qtdemux_init (GstQTDemux * qtdemux)
428 {
429   qtdemux->sinkpad =
430       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
431   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
432   gst_pad_set_activatemode_function (qtdemux->sinkpad,
433       qtdemux_sink_activate_mode);
434   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
435   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
436   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
437   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
438
439   qtdemux->adapter = gst_adapter_new ();
440   g_queue_init (&qtdemux->protection_event_queue);
441   qtdemux->flowcombiner = gst_flow_combiner_new ();
442   g_mutex_init (&qtdemux->expose_lock);
443
444   qtdemux->active_streams = g_ptr_array_new_with_free_func
445       ((GDestroyNotify) gst_qtdemux_stream_unref);
446   qtdemux->old_streams = g_ptr_array_new_with_free_func
447       ((GDestroyNotify) gst_qtdemux_stream_unref);
448
449   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
450
451   gst_qtdemux_reset (qtdemux, TRUE);
452 }
453
454 static void
455 gst_qtdemux_finalize (GObject * object)
456 {
457   GstQTDemux *qtdemux = GST_QTDEMUX (object);
458
459   g_free (qtdemux->redirect_location);
460
461   G_OBJECT_CLASS (parent_class)->finalize (object);
462 }
463
464 static void
465 gst_qtdemux_dispose (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   if (qtdemux->adapter) {
470     g_object_unref (G_OBJECT (qtdemux->adapter));
471     qtdemux->adapter = NULL;
472   }
473   gst_tag_list_unref (qtdemux->tag_list);
474   gst_flow_combiner_free (qtdemux->flowcombiner);
475   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
476       NULL);
477   g_queue_clear (&qtdemux->protection_event_queue);
478
479   g_free (qtdemux->cenc_aux_info_sizes);
480   qtdemux->cenc_aux_info_sizes = NULL;
481   g_mutex_clear (&qtdemux->expose_lock);
482
483   g_ptr_array_free (qtdemux->active_streams, TRUE);
484   g_ptr_array_free (qtdemux->old_streams, TRUE);
485
486   G_OBJECT_CLASS (parent_class)->dispose (object);
487 }
488
489 static void
490 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
491 {
492   if (qtdemux->redirect_location) {
493     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
494         (_("This file contains no playable streams.")),
495         ("no known streams found, a redirect message has been posted"),
496         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
497   } else {
498     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
499         (_("This file contains no playable streams.")),
500         ("no known streams found"));
501   }
502 }
503
504 static GstBuffer *
505 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
506 {
507   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
508       mem, size, 0, size, mem, free_func);
509 }
510
511 static GstFlowReturn
512 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
513     GstBuffer ** buf)
514 {
515   GstFlowReturn flow;
516   GstMapInfo map;
517   gsize bsize;
518
519   if (G_UNLIKELY (size == 0)) {
520     GstFlowReturn ret;
521     GstBuffer *tmp = NULL;
522
523     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
524     if (ret != GST_FLOW_OK)
525       return ret;
526
527     gst_buffer_map (tmp, &map, GST_MAP_READ);
528     size = QT_UINT32 (map.data);
529     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
530
531     gst_buffer_unmap (tmp, &map);
532     gst_buffer_unref (tmp);
533   }
534
535   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
536   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
537     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
538       /* we're pulling header but already got most interesting bits,
539        * so never mind the rest (e.g. tags) (that much) */
540       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
541           size);
542       return GST_FLOW_EOS;
543     } else {
544       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
545           (_("This file is invalid and cannot be played.")),
546           ("atom has bogus size %" G_GUINT64_FORMAT, size));
547       return GST_FLOW_ERROR;
548     }
549   }
550
551   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
552
553   if (G_UNLIKELY (flow != GST_FLOW_OK))
554     return flow;
555
556   bsize = gst_buffer_get_size (*buf);
557   /* Catch short reads - we don't want any partial atoms */
558   if (G_UNLIKELY (bsize < size)) {
559     GST_WARNING_OBJECT (qtdemux,
560         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
561     gst_buffer_unref (*buf);
562     *buf = NULL;
563     return GST_FLOW_EOS;
564   }
565
566   return flow;
567 }
568
569 #if 1
570 static gboolean
571 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
572     GstFormat src_format, gint64 src_value, GstFormat dest_format,
573     gint64 * dest_value)
574 {
575   gboolean res = TRUE;
576   QtDemuxStream *stream = gst_pad_get_element_private (pad);
577   gint32 index;
578
579   if (stream->subtype != FOURCC_vide) {
580     res = FALSE;
581     goto done;
582   }
583
584   switch (src_format) {
585     case GST_FORMAT_TIME:
586       switch (dest_format) {
587         case GST_FORMAT_BYTES:{
588           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
589           if (-1 == index) {
590             res = FALSE;
591             goto done;
592           }
593
594           *dest_value = stream->samples[index].offset;
595
596           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
597               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
598               GST_TIME_ARGS (src_value), *dest_value);
599           break;
600         }
601         default:
602           res = FALSE;
603           break;
604       }
605       break;
606     case GST_FORMAT_BYTES:
607       switch (dest_format) {
608         case GST_FORMAT_TIME:{
609           index =
610               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
611               stream, src_value);
612
613           if (-1 == index) {
614             res = FALSE;
615             goto done;
616           }
617
618           *dest_value =
619               QTSTREAMTIME_TO_GSTTIME (stream,
620               stream->samples[index].timestamp);
621           GST_DEBUG_OBJECT (qtdemux,
622               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
623               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
624           break;
625         }
626         default:
627           res = FALSE;
628           break;
629       }
630       break;
631     default:
632       res = FALSE;
633       break;
634   }
635
636 done:
637   return res;
638 }
639 #endif
640
641 static gboolean
642 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
643 {
644   gboolean res = FALSE;
645
646   *duration = GST_CLOCK_TIME_NONE;
647
648   if (qtdemux->duration != 0 &&
649       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
650     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
651     res = TRUE;
652   } else {
653     *duration = GST_CLOCK_TIME_NONE;
654   }
655
656   return res;
657 }
658
659 static gboolean
660 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
661     GstQuery * query)
662 {
663   gboolean res = FALSE;
664   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
665
666   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
667
668   switch (GST_QUERY_TYPE (query)) {
669     case GST_QUERY_POSITION:{
670       GstFormat fmt;
671
672       gst_query_parse_position (query, &fmt, NULL);
673       if (fmt == GST_FORMAT_TIME
674           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
675         gst_query_set_position (query, GST_FORMAT_TIME,
676             qtdemux->segment.position);
677         res = TRUE;
678       }
679     }
680       break;
681     case GST_QUERY_DURATION:{
682       GstFormat fmt;
683
684       gst_query_parse_duration (query, &fmt, NULL);
685       if (fmt == GST_FORMAT_TIME) {
686         /* First try to query upstream */
687         res = gst_pad_query_default (pad, parent, query);
688         if (!res) {
689           GstClockTime duration;
690           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
691             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
692             res = TRUE;
693           }
694         }
695       }
696       break;
697     }
698     case GST_QUERY_CONVERT:{
699       GstFormat src_fmt, dest_fmt;
700       gint64 src_value, dest_value = 0;
701
702       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
703
704       res = gst_qtdemux_src_convert (qtdemux, pad,
705           src_fmt, src_value, dest_fmt, &dest_value);
706       if (res)
707         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
708
709       break;
710     }
711     case GST_QUERY_FORMATS:
712       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
713       res = TRUE;
714       break;
715     case GST_QUERY_SEEKING:{
716       GstFormat fmt;
717       gboolean seekable;
718
719       /* try upstream first */
720       res = gst_pad_query_default (pad, parent, query);
721
722       if (!res) {
723         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
724         if (fmt == GST_FORMAT_TIME) {
725           GstClockTime duration;
726
727           gst_qtdemux_get_duration (qtdemux, &duration);
728           seekable = TRUE;
729           if (!qtdemux->pullbased) {
730             GstQuery *q;
731
732             /* we might be able with help from upstream */
733             seekable = FALSE;
734             q = gst_query_new_seeking (GST_FORMAT_BYTES);
735             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
736               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
737               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
738             }
739             gst_query_unref (q);
740           }
741           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
742           res = TRUE;
743         }
744       }
745       break;
746     }
747     case GST_QUERY_SEGMENT:
748     {
749       GstFormat format;
750       gint64 start, stop;
751
752       format = qtdemux->segment.format;
753
754       start =
755           gst_segment_to_stream_time (&qtdemux->segment, format,
756           qtdemux->segment.start);
757       if ((stop = qtdemux->segment.stop) == -1)
758         stop = qtdemux->segment.duration;
759       else
760         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
761
762       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
763       res = TRUE;
764       break;
765     }
766     default:
767       res = gst_pad_query_default (pad, parent, query);
768       break;
769   }
770
771   return res;
772 }
773
774 static void
775 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
776 {
777   if (G_LIKELY (stream->pad)) {
778     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
779         GST_DEBUG_PAD_NAME (stream->pad));
780
781     if (!gst_tag_list_is_empty (stream->stream_tags)) {
782       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
783           stream->stream_tags);
784       gst_pad_push_event (stream->pad,
785           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
786     }
787
788     if (G_UNLIKELY (stream->send_global_tags)) {
789       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
790           qtdemux->tag_list);
791       gst_pad_push_event (stream->pad,
792           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
793       stream->send_global_tags = FALSE;
794     }
795   }
796 }
797
798 /* push event on all source pads; takes ownership of the event */
799 static void
800 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
801 {
802   gboolean has_valid_stream = FALSE;
803   GstEventType etype = GST_EVENT_TYPE (event);
804   guint i;
805
806   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
807       GST_EVENT_TYPE_NAME (event));
808
809   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
810     GstPad *pad;
811     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
812     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
813
814     if ((pad = stream->pad)) {
815       has_valid_stream = TRUE;
816
817       if (etype == GST_EVENT_EOS) {
818         /* let's not send twice */
819         if (stream->sent_eos)
820           continue;
821         stream->sent_eos = TRUE;
822       }
823
824       gst_pad_push_event (pad, gst_event_ref (event));
825     }
826   }
827
828   gst_event_unref (event);
829
830   /* if it is EOS and there are no pads, post an error */
831   if (!has_valid_stream && etype == GST_EVENT_EOS) {
832     gst_qtdemux_post_no_playable_stream_error (qtdemux);
833   }
834 }
835
836 typedef struct
837 {
838   guint64 media_time;
839 } FindData;
840
841 static gint
842 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
843 {
844   if ((gint64) s1->timestamp > *media_time)
845     return 1;
846   if ((gint64) s1->timestamp == *media_time)
847     return 0;
848
849   return -1;
850 }
851
852 /* find the index of the sample that includes the data for @media_time using a
853  * binary search.  Only to be called in optimized cases of linear search below.
854  *
855  * Returns the index of the sample with the corresponding *DTS*.
856  */
857 static guint32
858 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
859     guint64 media_time)
860 {
861   QtDemuxSample *result;
862   guint32 index;
863
864   /* convert media_time to mov format */
865   media_time =
866       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
867
868   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
869       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
870       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
871
872   if (G_LIKELY (result))
873     index = result - str->samples;
874   else
875     index = 0;
876
877   return index;
878 }
879
880
881
882 /* find the index of the sample that includes the data for @media_offset using a
883  * linear search
884  *
885  * Returns the index of the sample.
886  */
887 static guint32
888 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
889     QtDemuxStream * str, gint64 media_offset)
890 {
891   QtDemuxSample *result = str->samples;
892   guint32 index = 0;
893
894   if (result == NULL || str->n_samples == 0)
895     return -1;
896
897   if (media_offset == result->offset)
898     return index;
899
900   result++;
901   while (index < str->n_samples - 1) {
902     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
903       goto parse_failed;
904
905     if (media_offset < result->offset)
906       break;
907
908     index++;
909     result++;
910   }
911   return index;
912
913   /* ERRORS */
914 parse_failed:
915   {
916     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
917     return -1;
918   }
919 }
920
921 /* find the index of the sample that includes the data for @media_time using a
922  * linear search, and keeping in mind that not all samples may have been parsed
923  * yet.  If possible, it will delegate to binary search.
924  *
925  * Returns the index of the sample.
926  */
927 static guint32
928 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
929     GstClockTime media_time)
930 {
931   guint32 index = 0;
932   guint64 mov_time;
933   QtDemuxSample *sample;
934
935   /* convert media_time to mov format */
936   mov_time =
937       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
938
939   sample = str->samples;
940   if (mov_time == sample->timestamp + sample->pts_offset)
941     return index;
942
943   /* use faster search if requested time in already parsed range */
944   sample = str->samples + str->stbl_index;
945   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
946     index = gst_qtdemux_find_index (qtdemux, str, media_time);
947     sample = str->samples + index;
948   } else {
949     while (index < str->n_samples - 1) {
950       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
951         goto parse_failed;
952
953       sample = str->samples + index + 1;
954       if (mov_time < sample->timestamp) {
955         sample = str->samples + index;
956         break;
957       }
958
959       index++;
960     }
961   }
962
963   /* sample->timestamp is now <= media_time, need to find the corresponding
964    * PTS now by looking backwards */
965   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
966     index--;
967     sample = str->samples + index;
968   }
969
970   return index;
971
972   /* ERRORS */
973 parse_failed:
974   {
975     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
976     return -1;
977   }
978 }
979
980 /* find the index of the keyframe needed to decode the sample at @index
981  * of stream @str, or of a subsequent keyframe (depending on @next)
982  *
983  * Returns the index of the keyframe.
984  */
985 static guint32
986 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
987     guint32 index, gboolean next)
988 {
989   guint32 new_index = index;
990
991   if (index >= str->n_samples) {
992     new_index = str->n_samples;
993     goto beach;
994   }
995
996   /* all keyframes, return index */
997   if (str->all_keyframe) {
998     new_index = index;
999     goto beach;
1000   }
1001
1002   /* else search until we have a keyframe */
1003   while (new_index < str->n_samples) {
1004     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1005       goto parse_failed;
1006
1007     if (str->samples[new_index].keyframe)
1008       break;
1009
1010     if (new_index == 0)
1011       break;
1012
1013     if (next)
1014       new_index++;
1015     else
1016       new_index--;
1017   }
1018
1019   if (new_index == str->n_samples) {
1020     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1021     new_index = -1;
1022   }
1023
1024 beach:
1025   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1026       "gave %u", next ? "after" : "before", index, new_index);
1027
1028   return new_index;
1029
1030   /* ERRORS */
1031 parse_failed:
1032   {
1033     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1034     return -1;
1035   }
1036 }
1037
1038 /* find the segment for @time_position for @stream
1039  *
1040  * Returns the index of the segment containing @time_position.
1041  * Returns the last segment and sets the @eos variable to TRUE
1042  * if the time is beyond the end. @eos may be NULL
1043  */
1044 static guint32
1045 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1046     GstClockTime time_position)
1047 {
1048   gint i;
1049   guint32 seg_idx;
1050
1051   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1052       GST_TIME_ARGS (time_position));
1053
1054   seg_idx = -1;
1055   for (i = 0; i < stream->n_segments; i++) {
1056     QtDemuxSegment *segment = &stream->segments[i];
1057
1058     GST_LOG_OBJECT (stream->pad,
1059         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1060         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1061
1062     /* For the last segment we include stop_time in the last segment */
1063     if (i < stream->n_segments - 1) {
1064       if (segment->time <= time_position && time_position < segment->stop_time) {
1065         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1066         seg_idx = i;
1067         break;
1068       }
1069     } else {
1070       /* Last segment always matches */
1071       seg_idx = i;
1072       break;
1073     }
1074   }
1075   return seg_idx;
1076 }
1077
1078 /* move the stream @str to the sample position @index.
1079  *
1080  * Updates @str->sample_index and marks discontinuity if needed.
1081  */
1082 static void
1083 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1084     guint32 index)
1085 {
1086   /* no change needed */
1087   if (index == str->sample_index)
1088     return;
1089
1090   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1091       str->n_samples);
1092
1093   /* position changed, we have a discont */
1094   str->sample_index = index;
1095   str->offset_in_sample = 0;
1096   /* Each time we move in the stream we store the position where we are
1097    * starting from */
1098   str->from_sample = index;
1099   str->discont = TRUE;
1100 }
1101
1102 static void
1103 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1104     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1105 {
1106   guint64 min_offset;
1107   gint64 min_byte_offset = -1;
1108   guint i;
1109
1110   min_offset = desired_time;
1111
1112   /* for each stream, find the index of the sample in the segment
1113    * and move back to the previous keyframe. */
1114   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1115     QtDemuxStream *str;
1116     guint32 index, kindex;
1117     guint32 seg_idx;
1118     GstClockTime media_start;
1119     GstClockTime media_time;
1120     GstClockTime seg_time;
1121     QtDemuxSegment *seg;
1122     gboolean empty_segment = FALSE;
1123
1124     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1125
1126     if (CUR_STREAM (str)->sparse && !use_sparse)
1127       continue;
1128
1129     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1130     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1131
1132     /* get segment and time in the segment */
1133     seg = &str->segments[seg_idx];
1134     seg_time = (desired_time - seg->time) * seg->rate;
1135
1136     while (QTSEGMENT_IS_EMPTY (seg)) {
1137       seg_time = 0;
1138       empty_segment = TRUE;
1139       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1140           seg_idx);
1141       seg_idx++;
1142       if (seg_idx == str->n_segments)
1143         break;
1144       seg = &str->segments[seg_idx];
1145     }
1146
1147     if (seg_idx == str->n_segments) {
1148       /* FIXME track shouldn't have the last segment as empty, but if it
1149        * happens we better handle it */
1150       continue;
1151     }
1152
1153     /* get the media time in the segment */
1154     media_start = seg->media_start + seg_time;
1155
1156     /* get the index of the sample with media time */
1157     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1158     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1159         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1160         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1161         empty_segment);
1162
1163     /* shift to next frame if we are looking for next keyframe */
1164     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1165         && index < str->stbl_index)
1166       index++;
1167
1168     if (!empty_segment) {
1169       /* find previous keyframe */
1170       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1171
1172       /* we will settle for one before if none found after */
1173       if (next && kindex == -1)
1174         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1175
1176       /* Update the requested time whenever a keyframe was found, to make it
1177        * accurate and avoid having the first buffer fall outside of the segment
1178        */
1179       if (kindex != -1) {
1180         index = kindex;
1181
1182         /* get timestamp of keyframe */
1183         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1184         GST_DEBUG_OBJECT (qtdemux,
1185             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1186             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1187             str->samples[kindex].offset);
1188
1189         /* keyframes in the segment get a chance to change the
1190          * desired_offset. keyframes out of the segment are
1191          * ignored. */
1192         if (media_time >= seg->media_start) {
1193           GstClockTime seg_time;
1194
1195           /* this keyframe is inside the segment, convert back to
1196            * segment time */
1197           seg_time = (media_time - seg->media_start) + seg->time;
1198           if ((!next && (seg_time < min_offset)) ||
1199               (next && (seg_time > min_offset)))
1200             min_offset = seg_time;
1201         }
1202       }
1203     }
1204
1205     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1206       min_byte_offset = str->samples[index].offset;
1207   }
1208
1209   if (key_time)
1210     *key_time = min_offset;
1211   if (key_offset)
1212     *key_offset = min_byte_offset;
1213 }
1214
1215 static gboolean
1216 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1217     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1218 {
1219   gboolean res;
1220
1221   g_return_val_if_fail (format != NULL, FALSE);
1222   g_return_val_if_fail (cur != NULL, FALSE);
1223   g_return_val_if_fail (stop != NULL, FALSE);
1224
1225   if (*format == GST_FORMAT_TIME)
1226     return TRUE;
1227
1228   res = TRUE;
1229   if (cur_type != GST_SEEK_TYPE_NONE)
1230     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1231   if (res && stop_type != GST_SEEK_TYPE_NONE)
1232     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1233
1234   if (res)
1235     *format = GST_FORMAT_TIME;
1236
1237   return res;
1238 }
1239
1240 /* perform seek in push based mode:
1241    find BYTE position to move to based on time and delegate to upstream
1242 */
1243 static gboolean
1244 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1245 {
1246   gdouble rate;
1247   GstFormat format;
1248   GstSeekFlags flags;
1249   GstSeekType cur_type, stop_type;
1250   gint64 cur, stop, key_cur;
1251   gboolean res;
1252   gint64 byte_cur;
1253   gint64 original_stop;
1254   guint32 seqnum;
1255
1256   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1257
1258   gst_event_parse_seek (event, &rate, &format, &flags,
1259       &cur_type, &cur, &stop_type, &stop);
1260   seqnum = gst_event_get_seqnum (event);
1261
1262   /* Directly send the instant-rate-change event here before taking the
1263    * stream-lock so that it can be applied as soon as possible */
1264   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1265     GstEvent *ev;
1266
1267     /* instant rate change only supported if direction does not change. All
1268      * other requirements are already checked before creating the seek event
1269      * but let's double-check here to be sure */
1270     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1271         (qtdemux->segment.rate < 0 && rate > 0) ||
1272         cur_type != GST_SEEK_TYPE_NONE ||
1273         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1274       GST_ERROR_OBJECT (qtdemux,
1275           "Instant rate change seeks only supported in the "
1276           "same direction, without flushing and position change");
1277       return FALSE;
1278     }
1279
1280     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1281         (GstSegmentFlags) flags);
1282     gst_event_set_seqnum (ev, seqnum);
1283     gst_qtdemux_push_event (qtdemux, ev);
1284     return TRUE;
1285   }
1286
1287   /* only forward streaming and seeking is possible */
1288   if (rate <= 0)
1289     goto unsupported_seek;
1290
1291   /* convert to TIME if needed and possible */
1292   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1293           stop_type, &stop))
1294     goto no_format;
1295
1296   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1297    * the original stop position to use when upstream pushes the new segment
1298    * for this seek */
1299   original_stop = stop;
1300   stop = -1;
1301
1302   /* find reasonable corresponding BYTE position,
1303    * also try to mind about keyframes, since we can not go back a bit for them
1304    * later on */
1305   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1306    * mostly just work, but let's not yet boldly go there  ... */
1307   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1308
1309   if (byte_cur == -1)
1310     goto abort_seek;
1311
1312   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1313       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1314       stop);
1315
1316   GST_OBJECT_LOCK (qtdemux);
1317   qtdemux->seek_offset = byte_cur;
1318   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1319     qtdemux->push_seek_start = cur;
1320   } else {
1321     qtdemux->push_seek_start = key_cur;
1322   }
1323
1324   if (stop_type == GST_SEEK_TYPE_NONE) {
1325     qtdemux->push_seek_stop = qtdemux->segment.stop;
1326   } else {
1327     qtdemux->push_seek_stop = original_stop;
1328   }
1329   GST_OBJECT_UNLOCK (qtdemux);
1330
1331   qtdemux->segment_seqnum = seqnum;
1332   /* BYTE seek event */
1333   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1334       stop_type, stop);
1335   gst_event_set_seqnum (event, seqnum);
1336   res = gst_pad_push_event (qtdemux->sinkpad, event);
1337
1338   return res;
1339
1340   /* ERRORS */
1341 abort_seek:
1342   {
1343     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1344         "seek aborted.");
1345     return FALSE;
1346   }
1347 unsupported_seek:
1348   {
1349     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1350     return FALSE;
1351   }
1352 no_format:
1353   {
1354     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1355     return FALSE;
1356   }
1357 }
1358
1359 /* perform the seek.
1360  *
1361  * We set all segment_indexes in the streams to unknown and
1362  * adjust the time_position to the desired position. this is enough
1363  * to trigger a segment switch in the streaming thread to start
1364  * streaming from the desired position.
1365  *
1366  * Keyframe seeking is a little more complicated when dealing with
1367  * segments. Ideally we want to move to the previous keyframe in
1368  * the segment but there might not be a keyframe in the segment. In
1369  * fact, none of the segments could contain a keyframe. We take a
1370  * practical approach: seek to the previous keyframe in the segment,
1371  * if there is none, seek to the beginning of the segment.
1372  *
1373  * Called with STREAM_LOCK
1374  */
1375 static gboolean
1376 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1377     guint32 seqnum, GstSeekFlags flags)
1378 {
1379   gint64 desired_offset;
1380   guint i;
1381
1382   desired_offset = segment->position;
1383
1384   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1385       GST_TIME_ARGS (desired_offset));
1386
1387   /* may not have enough fragmented info to do this adjustment,
1388    * and we can't scan (and probably should not) at this time with
1389    * possibly flushing upstream */
1390   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1391     gint64 min_offset;
1392     gboolean next, before, after;
1393
1394     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1395     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1396     next = after && !before;
1397     if (segment->rate < 0)
1398       next = !next;
1399
1400     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1401         NULL);
1402     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1403         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1404     desired_offset = min_offset;
1405   }
1406
1407   /* and set all streams to the final position */
1408   GST_OBJECT_LOCK (qtdemux);
1409   gst_flow_combiner_reset (qtdemux->flowcombiner);
1410   GST_OBJECT_UNLOCK (qtdemux);
1411   qtdemux->segment_seqnum = seqnum;
1412   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1413     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1414
1415     stream->time_position = desired_offset;
1416     stream->accumulated_base = 0;
1417     stream->sample_index = -1;
1418     stream->offset_in_sample = 0;
1419     stream->segment_index = -1;
1420     stream->sent_eos = FALSE;
1421     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1422
1423     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1424       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1425   }
1426   segment->position = desired_offset;
1427   if (segment->rate >= 0) {
1428     segment->start = desired_offset;
1429     /* We need to update time as we update start in that direction */
1430     segment->time = desired_offset;
1431
1432     /* we stop at the end */
1433     if (segment->stop == -1)
1434       segment->stop = segment->duration;
1435   } else {
1436     segment->stop = desired_offset;
1437   }
1438
1439   if (qtdemux->fragmented)
1440     qtdemux->fragmented_seek_pending = TRUE;
1441
1442   return TRUE;
1443 }
1444
1445 /* do a seek in pull based mode */
1446 static gboolean
1447 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1448 {
1449   gdouble rate = 1.0;
1450   GstFormat format;
1451   GstSeekFlags flags;
1452   GstSeekType cur_type, stop_type;
1453   gint64 cur, stop;
1454   gboolean flush, instant_rate_change;
1455   gboolean update;
1456   GstSegment seeksegment;
1457   guint32 seqnum = GST_SEQNUM_INVALID;
1458   GstEvent *flush_event;
1459   gboolean ret;
1460
1461   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1462
1463   gst_event_parse_seek (event, &rate, &format, &flags,
1464       &cur_type, &cur, &stop_type, &stop);
1465   seqnum = gst_event_get_seqnum (event);
1466
1467   /* we have to have a format as the segment format. Try to convert
1468    * if not. */
1469   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1470           stop_type, &stop))
1471     goto no_format;
1472
1473   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1474
1475   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1476   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1477
1478   /* Directly send the instant-rate-change event here before taking the
1479    * stream-lock so that it can be applied as soon as possible */
1480   if (instant_rate_change) {
1481     GstEvent *ev;
1482
1483     /* instant rate change only supported if direction does not change. All
1484      * other requirements are already checked before creating the seek event
1485      * but let's double-check here to be sure */
1486     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1487         (qtdemux->segment.rate < 0 && rate > 0) ||
1488         cur_type != GST_SEEK_TYPE_NONE ||
1489         stop_type != GST_SEEK_TYPE_NONE || flush) {
1490       GST_ERROR_OBJECT (qtdemux,
1491           "Instant rate change seeks only supported in the "
1492           "same direction, without flushing and position change");
1493       return FALSE;
1494     }
1495
1496     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1497         (GstSegmentFlags) flags);
1498     gst_event_set_seqnum (ev, seqnum);
1499     gst_qtdemux_push_event (qtdemux, ev);
1500     return TRUE;
1501   }
1502
1503   /* stop streaming, either by flushing or by pausing the task */
1504   if (flush) {
1505     flush_event = gst_event_new_flush_start ();
1506     if (seqnum != GST_SEQNUM_INVALID)
1507       gst_event_set_seqnum (flush_event, seqnum);
1508     /* unlock upstream pull_range */
1509     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1510     /* make sure out loop function exits */
1511     gst_qtdemux_push_event (qtdemux, flush_event);
1512   } else {
1513     /* non flushing seek, pause the task */
1514     gst_pad_pause_task (qtdemux->sinkpad);
1515   }
1516
1517   /* wait for streaming to finish */
1518   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1519
1520   /* copy segment, we need this because we still need the old
1521    * segment when we close the current segment. */
1522   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1523
1524   /* configure the segment with the seek variables */
1525   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1526   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1527           cur_type, cur, stop_type, stop, &update)) {
1528     ret = FALSE;
1529     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1530   } else {
1531     /* now do the seek */
1532     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1533   }
1534
1535   /* prepare for streaming again */
1536   if (flush) {
1537     flush_event = gst_event_new_flush_stop (TRUE);
1538     if (seqnum != GST_SEQNUM_INVALID)
1539       gst_event_set_seqnum (flush_event, seqnum);
1540
1541     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1542     gst_qtdemux_push_event (qtdemux, flush_event);
1543   }
1544
1545   /* commit the new segment */
1546   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1547
1548   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1549     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1550         qtdemux->segment.format, qtdemux->segment.position);
1551     if (seqnum != GST_SEQNUM_INVALID)
1552       gst_message_set_seqnum (msg, seqnum);
1553     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1554   }
1555
1556   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1557   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1558       qtdemux->sinkpad, NULL);
1559
1560   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1561
1562   return ret;
1563
1564   /* ERRORS */
1565 no_format:
1566   {
1567     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1568     return FALSE;
1569   }
1570 }
1571
1572 static gboolean
1573 qtdemux_ensure_index (GstQTDemux * qtdemux)
1574 {
1575   guint i;
1576
1577   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1578
1579   /* Build complete index */
1580   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1581     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1582
1583     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1584       GST_LOG_OBJECT (qtdemux,
1585           "Building complete index of track-id %u for seeking failed!",
1586           stream->track_id);
1587       return FALSE;
1588     }
1589   }
1590
1591   return TRUE;
1592 }
1593
1594 static gboolean
1595 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1596     GstEvent * event)
1597 {
1598   gboolean res = TRUE;
1599   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1600
1601   switch (GST_EVENT_TYPE (event)) {
1602     case GST_EVENT_RECONFIGURE:
1603       GST_OBJECT_LOCK (qtdemux);
1604       gst_flow_combiner_reset (qtdemux->flowcombiner);
1605       GST_OBJECT_UNLOCK (qtdemux);
1606       res = gst_pad_event_default (pad, parent, event);
1607       break;
1608     case GST_EVENT_SEEK:
1609     {
1610       GstSeekFlags flags = 0;
1611       gboolean instant_rate_change;
1612
1613 #ifndef GST_DISABLE_GST_DEBUG
1614       GstClockTime ts = gst_util_get_timestamp ();
1615 #endif
1616       guint32 seqnum = gst_event_get_seqnum (event);
1617
1618       qtdemux->received_seek = TRUE;
1619
1620       gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL);
1621       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1622
1623       if (seqnum == qtdemux->segment_seqnum) {
1624         GST_LOG_OBJECT (pad,
1625             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1626         gst_event_unref (event);
1627         return TRUE;
1628       }
1629
1630       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1631         /* seek should be handled by upstream, we might need to re-download fragments */
1632         GST_DEBUG_OBJECT (qtdemux,
1633             "let upstream handle seek for fragmented playback");
1634         goto upstream;
1635       }
1636
1637       gst_event_parse_seek_trickmode_interval (event,
1638           &qtdemux->trickmode_interval);
1639
1640       /* Build complete index for seeking;
1641        * if not a fragmented file at least and we're really doing a seek,
1642        * not just an instant-rate-change */
1643       if (!qtdemux->fragmented && !instant_rate_change) {
1644         if (!qtdemux_ensure_index (qtdemux))
1645           goto index_failed;
1646       }
1647 #ifndef GST_DISABLE_GST_DEBUG
1648       ts = gst_util_get_timestamp () - ts;
1649       GST_INFO_OBJECT (qtdemux,
1650           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1651 #endif
1652       if (qtdemux->pullbased) {
1653         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1654       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1655         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1656         res = TRUE;
1657       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1658           && QTDEMUX_N_STREAMS (qtdemux)
1659           && !qtdemux->fragmented) {
1660         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1661       } else {
1662         GST_DEBUG_OBJECT (qtdemux,
1663             "ignoring seek in push mode in current state");
1664         res = FALSE;
1665       }
1666       gst_event_unref (event);
1667     }
1668       break;
1669     default:
1670     upstream:
1671       res = gst_pad_event_default (pad, parent, event);
1672       break;
1673   }
1674
1675 done:
1676   return res;
1677
1678   /* ERRORS */
1679 index_failed:
1680   {
1681     GST_ERROR_OBJECT (qtdemux, "Index failed");
1682     gst_event_unref (event);
1683     res = FALSE;
1684     goto done;
1685   }
1686 }
1687
1688 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1689  *
1690  * If @fw is false, the coding order is explored backwards.
1691  *
1692  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1693  * sample is found for that track.
1694  *
1695  * The stream and sample index of the sample with the minimum offset in the direction explored
1696  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1697  *
1698  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1699  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1700  * @_stream and @_index. */
1701 static void
1702 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1703     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1704 {
1705   gint i, index;
1706   gint64 time, min_time;
1707   QtDemuxStream *stream;
1708   gint iter;
1709
1710   min_time = -1;
1711   stream = NULL;
1712   index = -1;
1713
1714   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1715     QtDemuxStream *str;
1716     gint inc;
1717     gboolean set_sample;
1718
1719     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1720     set_sample = !set;
1721
1722     if (fw) {
1723       i = 0;
1724       inc = 1;
1725     } else {
1726       i = str->n_samples - 1;
1727       inc = -1;
1728     }
1729
1730     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1731       if (str->samples[i].size == 0)
1732         continue;
1733
1734       if (fw && (str->samples[i].offset < byte_pos))
1735         continue;
1736
1737       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1738         continue;
1739
1740       /* move stream to first available sample */
1741       if (set) {
1742         gst_qtdemux_move_stream (qtdemux, str, i);
1743         set_sample = TRUE;
1744       }
1745
1746       /* avoid index from sparse streams since they might be far away */
1747       if (!CUR_STREAM (str)->sparse) {
1748         /* determine min/max time */
1749         time = QTSAMPLE_PTS (str, &str->samples[i]);
1750         if (min_time == -1 || (!fw && time > min_time) ||
1751             (fw && time < min_time)) {
1752           min_time = time;
1753         }
1754
1755         /* determine stream with leading sample, to get its position */
1756         if (!stream ||
1757             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1758             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1759           stream = str;
1760           index = i;
1761         }
1762       }
1763       break;
1764     }
1765
1766     /* no sample for this stream, mark eos */
1767     if (!set_sample)
1768       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1769   }
1770
1771   if (_time)
1772     *_time = min_time;
1773   if (_stream)
1774     *_stream = stream;
1775   if (_index)
1776     *_index = index;
1777 }
1778
1779 /* Copied from mpegtsbase code */
1780 /* FIXME: replace this function when we add new util function for stream-id creation */
1781 static gchar *
1782 _get_upstream_id (GstQTDemux * demux)
1783 {
1784   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1785
1786   if (!upstream_id) {
1787     /* Try to create one from the upstream URI, else use a randome number */
1788     GstQuery *query;
1789     gchar *uri = NULL;
1790
1791     /* Try to generate one from the URI query and
1792      * if it fails take a random number instead */
1793     query = gst_query_new_uri ();
1794     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1795       gst_query_parse_uri (query, &uri);
1796     }
1797
1798     if (uri) {
1799       GChecksum *cs;
1800
1801       /* And then generate an SHA256 sum of the URI */
1802       cs = g_checksum_new (G_CHECKSUM_SHA256);
1803       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1804       g_free (uri);
1805       upstream_id = g_strdup (g_checksum_get_string (cs));
1806       g_checksum_free (cs);
1807     } else {
1808       /* Just get some random number if the URI query fails */
1809       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1810           "implementing a deterministic way of creating a stream-id");
1811       upstream_id =
1812           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1813           g_random_int (), g_random_int ());
1814     }
1815
1816     gst_query_unref (query);
1817   }
1818   return upstream_id;
1819 }
1820
1821 static QtDemuxStream *
1822 _create_stream (GstQTDemux * demux, guint32 track_id)
1823 {
1824   QtDemuxStream *stream;
1825   gchar *upstream_id;
1826
1827   stream = g_new0 (QtDemuxStream, 1);
1828   stream->demux = demux;
1829   stream->track_id = track_id;
1830   upstream_id = _get_upstream_id (demux);
1831   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1832   g_free (upstream_id);
1833   /* new streams always need a discont */
1834   stream->discont = TRUE;
1835   /* we enable clipping for raw audio/video streams */
1836   stream->need_clip = FALSE;
1837   stream->need_process = FALSE;
1838   stream->segment_index = -1;
1839   stream->time_position = 0;
1840   stream->sample_index = -1;
1841   stream->offset_in_sample = 0;
1842   stream->new_stream = TRUE;
1843   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1844   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1845   stream->protected = FALSE;
1846   stream->protection_scheme_type = 0;
1847   stream->protection_scheme_version = 0;
1848   stream->protection_scheme_info = NULL;
1849   stream->n_samples_moof = 0;
1850   stream->duration_moof = 0;
1851   stream->duration_last_moof = 0;
1852   stream->alignment = 1;
1853   stream->stream_tags = gst_tag_list_new_empty ();
1854   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1855   g_queue_init (&stream->protection_scheme_event_queue);
1856   stream->ref_count = 1;
1857   /* consistent default for push based mode */
1858   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1859   return stream;
1860 }
1861
1862 static gboolean
1863 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1864 {
1865   GstStructure *structure;
1866   const gchar *variant;
1867   const GstCaps *mediacaps = NULL;
1868
1869   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1870
1871   structure = gst_caps_get_structure (caps, 0);
1872   variant = gst_structure_get_string (structure, "variant");
1873
1874   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1875     QtDemuxStream *stream;
1876     const GValue *value;
1877
1878     demux->fragmented = TRUE;
1879     demux->mss_mode = TRUE;
1880
1881     if (QTDEMUX_N_STREAMS (demux) > 1) {
1882       /* can't do this, we can only renegotiate for another mss format */
1883       return FALSE;
1884     }
1885
1886     value = gst_structure_get_value (structure, "media-caps");
1887     /* create stream */
1888     if (value) {
1889       const GValue *timescale_v;
1890
1891       /* TODO update when stream changes during playback */
1892
1893       if (QTDEMUX_N_STREAMS (demux) == 0) {
1894         stream = _create_stream (demux, 1);
1895         g_ptr_array_add (demux->active_streams, stream);
1896         /* mss has no stsd/stsd entry, use id 0 as default */
1897         stream->stsd_entries_length = 1;
1898         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1899         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1900       } else {
1901         stream = QTDEMUX_NTH_STREAM (demux, 0);
1902       }
1903
1904       timescale_v = gst_structure_get_value (structure, "timescale");
1905       if (timescale_v) {
1906         stream->timescale = g_value_get_uint64 (timescale_v);
1907       } else {
1908         /* default mss timescale */
1909         stream->timescale = 10000000;
1910       }
1911       demux->timescale = stream->timescale;
1912
1913       mediacaps = gst_value_get_caps (value);
1914       if (!CUR_STREAM (stream)->caps
1915           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1916         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1917             mediacaps);
1918         stream->new_caps = TRUE;
1919       }
1920       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1921       structure = gst_caps_get_structure (mediacaps, 0);
1922       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1923         stream->subtype = FOURCC_vide;
1924
1925         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1926         gst_structure_get_int (structure, "height",
1927             &CUR_STREAM (stream)->height);
1928         gst_structure_get_fraction (structure, "framerate",
1929             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1930       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1931         gint rate = 0;
1932         stream->subtype = FOURCC_soun;
1933         gst_structure_get_int (structure, "channels",
1934             &CUR_STREAM (stream)->n_channels);
1935         gst_structure_get_int (structure, "rate", &rate);
1936         CUR_STREAM (stream)->rate = rate;
1937       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1938         if (gst_structure_has_field (structure, "original-media-type")) {
1939           const gchar *media_type =
1940               gst_structure_get_string (structure, "original-media-type");
1941           if (g_str_has_prefix (media_type, "video")) {
1942             stream->subtype = FOURCC_vide;
1943           } else if (g_str_has_prefix (media_type, "audio")) {
1944             stream->subtype = FOURCC_soun;
1945           }
1946         }
1947       }
1948     }
1949     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1950   } else {
1951     demux->mss_mode = FALSE;
1952   }
1953
1954   return TRUE;
1955 }
1956
1957 static void
1958 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1959 {
1960   gint i;
1961
1962   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1963   gst_pad_stop_task (qtdemux->sinkpad);
1964
1965   if (hard || qtdemux->upstream_format_is_time) {
1966     qtdemux->state = QTDEMUX_STATE_INITIAL;
1967     qtdemux->neededbytes = 16;
1968     qtdemux->todrop = 0;
1969     qtdemux->pullbased = FALSE;
1970     g_clear_pointer (&qtdemux->redirect_location, g_free);
1971     qtdemux->first_mdat = -1;
1972     qtdemux->header_size = 0;
1973     qtdemux->mdatoffset = -1;
1974     qtdemux->restoredata_offset = -1;
1975     if (qtdemux->mdatbuffer)
1976       gst_buffer_unref (qtdemux->mdatbuffer);
1977     if (qtdemux->restoredata_buffer)
1978       gst_buffer_unref (qtdemux->restoredata_buffer);
1979     qtdemux->mdatbuffer = NULL;
1980     qtdemux->restoredata_buffer = NULL;
1981     qtdemux->mdatleft = 0;
1982     qtdemux->mdatsize = 0;
1983     if (qtdemux->comp_brands)
1984       gst_buffer_unref (qtdemux->comp_brands);
1985     qtdemux->comp_brands = NULL;
1986     qtdemux->last_moov_offset = -1;
1987     if (qtdemux->moov_node_compressed) {
1988       g_node_destroy (qtdemux->moov_node_compressed);
1989       if (qtdemux->moov_node)
1990         g_free (qtdemux->moov_node->data);
1991     }
1992     qtdemux->moov_node_compressed = NULL;
1993     if (qtdemux->moov_node)
1994       g_node_destroy (qtdemux->moov_node);
1995     qtdemux->moov_node = NULL;
1996     if (qtdemux->tag_list)
1997       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1998     qtdemux->tag_list = gst_tag_list_new_empty ();
1999     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2000 #if 0
2001     if (qtdemux->element_index)
2002       gst_object_unref (qtdemux->element_index);
2003     qtdemux->element_index = NULL;
2004 #endif
2005     qtdemux->major_brand = 0;
2006     qtdemux->upstream_format_is_time = FALSE;
2007     qtdemux->upstream_seekable = FALSE;
2008     qtdemux->upstream_size = 0;
2009
2010     qtdemux->fragment_start = -1;
2011     qtdemux->fragment_start_offset = -1;
2012     qtdemux->duration = 0;
2013     qtdemux->moof_offset = 0;
2014     qtdemux->chapters_track_id = 0;
2015     qtdemux->have_group_id = FALSE;
2016     qtdemux->group_id = G_MAXUINT;
2017
2018     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2019         NULL);
2020     g_queue_clear (&qtdemux->protection_event_queue);
2021
2022     qtdemux->received_seek = FALSE;
2023     qtdemux->first_moof_already_parsed = FALSE;
2024   }
2025   qtdemux->offset = 0;
2026   gst_adapter_clear (qtdemux->adapter);
2027   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2028   qtdemux->need_segment = TRUE;
2029
2030   if (hard) {
2031     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2032     qtdemux->trickmode_interval = 0;
2033     g_ptr_array_set_size (qtdemux->active_streams, 0);
2034     g_ptr_array_set_size (qtdemux->old_streams, 0);
2035     qtdemux->n_video_streams = 0;
2036     qtdemux->n_audio_streams = 0;
2037     qtdemux->n_sub_streams = 0;
2038     qtdemux->exposed = FALSE;
2039     qtdemux->fragmented = FALSE;
2040     qtdemux->mss_mode = FALSE;
2041     gst_caps_replace (&qtdemux->media_caps, NULL);
2042     qtdemux->timescale = 0;
2043     qtdemux->got_moov = FALSE;
2044     qtdemux->cenc_aux_info_offset = 0;
2045     qtdemux->cenc_aux_info_sizes = NULL;
2046     qtdemux->cenc_aux_sample_count = 0;
2047     if (qtdemux->protection_system_ids) {
2048       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2049       qtdemux->protection_system_ids = NULL;
2050     }
2051     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2052         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2053         GST_BIN_FLAG_STREAMS_AWARE);
2054
2055     if (qtdemux->preferred_protection_system_id) {
2056       g_free (qtdemux->preferred_protection_system_id);
2057       qtdemux->preferred_protection_system_id = NULL;
2058     }
2059   } else if (qtdemux->mss_mode) {
2060     gst_flow_combiner_reset (qtdemux->flowcombiner);
2061     g_ptr_array_foreach (qtdemux->active_streams,
2062         (GFunc) gst_qtdemux_stream_clear, NULL);
2063   } else {
2064     gst_flow_combiner_reset (qtdemux->flowcombiner);
2065     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2066       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2067       stream->sent_eos = FALSE;
2068       stream->time_position = 0;
2069       stream->accumulated_base = 0;
2070       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2071     }
2072   }
2073 }
2074
2075
2076 /* Maps the @segment to the qt edts internal segments and pushes
2077  * the corresponding segment event.
2078  *
2079  * If it ends up being at a empty segment, a gap will be pushed and the next
2080  * edts segment will be activated in sequence.
2081  *
2082  * To be used in push-mode only */
2083 static void
2084 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2085 {
2086   gint i, iter;
2087
2088   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2089     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2090
2091     stream->time_position = segment->start;
2092
2093     /* in push mode we should be guaranteed that we will have empty segments
2094      * at the beginning and then one segment after, other scenarios are not
2095      * supported and are discarded when parsing the edts */
2096     for (i = 0; i < stream->n_segments; i++) {
2097       if (stream->segments[i].stop_time > segment->start) {
2098         /* push the empty segment and move to the next one */
2099         gst_qtdemux_activate_segment (qtdemux, stream, i,
2100             stream->time_position);
2101         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2102           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2103               stream->time_position);
2104
2105           /* accumulate previous segments */
2106           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2107             stream->accumulated_base +=
2108                 (stream->segment.stop -
2109                 stream->segment.start) / ABS (stream->segment.rate);
2110           continue;
2111         }
2112
2113         g_assert (i == stream->n_segments - 1);
2114       }
2115     }
2116   }
2117 }
2118
2119 static void
2120 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2121     GPtrArray * src)
2122 {
2123   guint i;
2124   guint len;
2125
2126   len = src->len;
2127
2128   if (len == 0)
2129     return;
2130
2131   for (i = 0; i < len; i++) {
2132     QtDemuxStream *stream = g_ptr_array_index (src, i);
2133
2134 #ifndef GST_DISABLE_GST_DEBUG
2135     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2136         stream, GST_STR_NULL (stream->stream_id), dest);
2137 #endif
2138     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2139   }
2140
2141   g_ptr_array_set_size (src, 0);
2142 }
2143
2144 static gboolean
2145 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2146     GstEvent * event)
2147 {
2148   GstQTDemux *demux = GST_QTDEMUX (parent);
2149   gboolean res = TRUE;
2150
2151   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2152
2153   switch (GST_EVENT_TYPE (event)) {
2154     case GST_EVENT_SEGMENT:
2155     {
2156       gint64 offset = 0;
2157       QtDemuxStream *stream;
2158       gint idx;
2159       GstSegment segment;
2160
2161       /* some debug output */
2162       gst_event_copy_segment (event, &segment);
2163       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2164           &segment);
2165
2166       if (segment.format == GST_FORMAT_TIME) {
2167         demux->upstream_format_is_time = TRUE;
2168         demux->segment_seqnum = gst_event_get_seqnum (event);
2169       } else {
2170         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2171             "not in time format");
2172
2173         /* chain will send initial newsegment after pads have been added */
2174         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2175           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2176           goto exit;
2177         }
2178       }
2179
2180       /* check if this matches a time seek we received previously
2181        * FIXME for backwards compatibility reasons we use the
2182        * seek_offset here to compare. In the future we might want to
2183        * change this to use the seqnum as it uniquely should identify
2184        * the segment that corresponds to the seek. */
2185       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2186           ", received segment offset %" G_GINT64_FORMAT,
2187           demux->seek_offset, segment.start);
2188       if (segment.format == GST_FORMAT_BYTES
2189           && demux->seek_offset == segment.start) {
2190         GST_OBJECT_LOCK (demux);
2191         offset = segment.start;
2192
2193         segment.format = GST_FORMAT_TIME;
2194         segment.start = demux->push_seek_start;
2195         segment.stop = demux->push_seek_stop;
2196         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2197             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2198             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2199         GST_OBJECT_UNLOCK (demux);
2200       }
2201
2202       /* we only expect a BYTE segment, e.g. following a seek */
2203       if (segment.format == GST_FORMAT_BYTES) {
2204         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2205           offset = segment.start;
2206
2207           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2208               NULL, (gint64 *) & segment.start);
2209           if ((gint64) segment.start < 0)
2210             segment.start = 0;
2211         }
2212         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2213           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2214               NULL, (gint64 *) & segment.stop);
2215           /* keyframe seeking should already arrange for start >= stop,
2216            * but make sure in other rare cases */
2217           segment.stop = MAX (segment.stop, segment.start);
2218         }
2219       } else if (segment.format == GST_FORMAT_TIME) {
2220         /* push all data on the adapter before starting this
2221          * new segment */
2222         gst_qtdemux_process_adapter (demux, TRUE);
2223       } else {
2224         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2225         goto exit;
2226       }
2227
2228       /* We shouldn't modify upstream driven TIME FORMAT segment */
2229       if (!demux->upstream_format_is_time) {
2230         /* accept upstream's notion of segment and distribute along */
2231         segment.format = GST_FORMAT_TIME;
2232         segment.position = segment.time = segment.start;
2233         segment.duration = demux->segment.duration;
2234         segment.base = gst_segment_to_running_time (&demux->segment,
2235             GST_FORMAT_TIME, demux->segment.position);
2236       }
2237
2238       gst_segment_copy_into (&segment, &demux->segment);
2239       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2240
2241       /* map segment to internal qt segments and push on each stream */
2242       if (QTDEMUX_N_STREAMS (demux)) {
2243         demux->need_segment = TRUE;
2244         gst_qtdemux_check_send_pending_segment (demux);
2245       }
2246
2247       /* clear leftover in current segment, if any */
2248       gst_adapter_clear (demux->adapter);
2249
2250       /* set up streaming thread */
2251       demux->offset = offset;
2252       if (demux->upstream_format_is_time) {
2253         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2254             "set values to restart reading from a new atom");
2255         demux->neededbytes = 16;
2256         demux->todrop = 0;
2257       } else {
2258         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2259             NULL);
2260         if (stream) {
2261           demux->todrop = stream->samples[idx].offset - offset;
2262           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2263         } else {
2264           /* set up for EOS */
2265           demux->neededbytes = -1;
2266           demux->todrop = 0;
2267         }
2268       }
2269     exit:
2270       gst_event_unref (event);
2271       res = TRUE;
2272       goto drop;
2273     }
2274     case GST_EVENT_FLUSH_START:
2275     {
2276       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2277         gst_event_unref (event);
2278         goto drop;
2279       }
2280       QTDEMUX_EXPOSE_LOCK (demux);
2281       res = gst_pad_event_default (demux->sinkpad, parent, event);
2282       QTDEMUX_EXPOSE_UNLOCK (demux);
2283       goto drop;
2284     }
2285     case GST_EVENT_FLUSH_STOP:
2286     {
2287       guint64 dur;
2288
2289       dur = demux->segment.duration;
2290       gst_qtdemux_reset (demux, FALSE);
2291       demux->segment.duration = dur;
2292
2293       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2294         gst_event_unref (event);
2295         goto drop;
2296       }
2297       break;
2298     }
2299     case GST_EVENT_EOS:
2300       /* If we are in push mode, and get an EOS before we've seen any streams,
2301        * then error out - we have nowhere to send the EOS */
2302       if (!demux->pullbased) {
2303         gint i;
2304         gboolean has_valid_stream = FALSE;
2305         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2306           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2307             has_valid_stream = TRUE;
2308             break;
2309           }
2310         }
2311         if (!has_valid_stream)
2312           gst_qtdemux_post_no_playable_stream_error (demux);
2313         else {
2314           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2315               (guint) gst_adapter_available (demux->adapter));
2316           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2317             res = FALSE;
2318           }
2319         }
2320       }
2321       break;
2322     case GST_EVENT_CAPS:{
2323       GstCaps *caps = NULL;
2324
2325       gst_event_parse_caps (event, &caps);
2326       gst_qtdemux_setcaps (demux, caps);
2327       res = TRUE;
2328       gst_event_unref (event);
2329       goto drop;
2330     }
2331     case GST_EVENT_PROTECTION:
2332     {
2333       const gchar *system_id = NULL;
2334
2335       gst_event_parse_protection (event, &system_id, NULL, NULL);
2336       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2337           system_id);
2338       gst_qtdemux_append_protection_system_id (demux, system_id);
2339       /* save the event for later, for source pads that have not been created */
2340       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2341       /* send it to all pads that already exist */
2342       gst_qtdemux_push_event (demux, event);
2343       res = TRUE;
2344       goto drop;
2345     }
2346     case GST_EVENT_STREAM_START:
2347     {
2348       res = TRUE;
2349       gst_event_unref (event);
2350
2351       /* Drain all the buffers */
2352       gst_qtdemux_process_adapter (demux, TRUE);
2353       gst_qtdemux_reset (demux, FALSE);
2354       /* We expect new moov box after new stream-start event */
2355       if (demux->exposed) {
2356         gst_qtdemux_stream_concat (demux,
2357             demux->old_streams, demux->active_streams);
2358       }
2359
2360       goto drop;
2361     }
2362     default:
2363       break;
2364   }
2365
2366   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2367
2368 drop:
2369   return res;
2370 }
2371
2372 static gboolean
2373 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2374     GstQuery * query)
2375 {
2376   GstQTDemux *demux = GST_QTDEMUX (parent);
2377   gboolean res = FALSE;
2378
2379   switch (GST_QUERY_TYPE (query)) {
2380     case GST_QUERY_BITRATE:
2381     {
2382       GstClockTime duration;
2383
2384       /* populate demux->upstream_size if not done yet */
2385       gst_qtdemux_check_seekability (demux);
2386
2387       if (demux->upstream_size != -1
2388           && gst_qtdemux_get_duration (demux, &duration)) {
2389         guint bitrate =
2390             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2391             duration);
2392
2393         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2394             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2395             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2396
2397         /* TODO: better results based on ranges/index tables */
2398         gst_query_set_bitrate (query, bitrate);
2399         res = TRUE;
2400       }
2401       break;
2402     }
2403     default:
2404       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2405       break;
2406   }
2407
2408   return res;
2409 }
2410
2411
2412 #if 0
2413 static void
2414 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2415 {
2416   GstQTDemux *demux = GST_QTDEMUX (element);
2417
2418   GST_OBJECT_LOCK (demux);
2419   if (demux->element_index)
2420     gst_object_unref (demux->element_index);
2421   if (index) {
2422     demux->element_index = gst_object_ref (index);
2423   } else {
2424     demux->element_index = NULL;
2425   }
2426   GST_OBJECT_UNLOCK (demux);
2427   /* object lock might be taken again */
2428   if (index)
2429     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2430   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2431       demux->element_index, demux->index_id);
2432 }
2433
2434 static GstIndex *
2435 gst_qtdemux_get_index (GstElement * element)
2436 {
2437   GstIndex *result = NULL;
2438   GstQTDemux *demux = GST_QTDEMUX (element);
2439
2440   GST_OBJECT_LOCK (demux);
2441   if (demux->element_index)
2442     result = gst_object_ref (demux->element_index);
2443   GST_OBJECT_UNLOCK (demux);
2444
2445   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2446
2447   return result;
2448 }
2449 #endif
2450
2451 static void
2452 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2453 {
2454   g_free ((gpointer) stream->stco.data);
2455   stream->stco.data = NULL;
2456   g_free ((gpointer) stream->stsz.data);
2457   stream->stsz.data = NULL;
2458   g_free ((gpointer) stream->stsc.data);
2459   stream->stsc.data = NULL;
2460   g_free ((gpointer) stream->stts.data);
2461   stream->stts.data = NULL;
2462   g_free ((gpointer) stream->stss.data);
2463   stream->stss.data = NULL;
2464   g_free ((gpointer) stream->stps.data);
2465   stream->stps.data = NULL;
2466   g_free ((gpointer) stream->ctts.data);
2467   stream->ctts.data = NULL;
2468 }
2469
2470 static void
2471 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2472 {
2473   g_free (stream->segments);
2474   stream->segments = NULL;
2475   stream->segment_index = -1;
2476   stream->accumulated_base = 0;
2477 }
2478
2479 static void
2480 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2481 {
2482   g_free (stream->samples);
2483   stream->samples = NULL;
2484   gst_qtdemux_stbl_free (stream);
2485
2486   /* fragments */
2487   g_free (stream->ra_entries);
2488   stream->ra_entries = NULL;
2489   stream->n_ra_entries = 0;
2490
2491   stream->sample_index = -1;
2492   stream->stbl_index = -1;
2493   stream->n_samples = 0;
2494   stream->time_position = 0;
2495
2496   stream->n_samples_moof = 0;
2497   stream->duration_moof = 0;
2498   stream->duration_last_moof = 0;
2499 }
2500
2501 static void
2502 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2503 {
2504   gint i;
2505   if (stream->allocator)
2506     gst_object_unref (stream->allocator);
2507   while (stream->buffers) {
2508     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2509     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2510   }
2511   for (i = 0; i < stream->stsd_entries_length; i++) {
2512     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2513     if (entry->rgb8_palette) {
2514       gst_memory_unref (entry->rgb8_palette);
2515       entry->rgb8_palette = NULL;
2516     }
2517     entry->sparse = FALSE;
2518   }
2519
2520   if (stream->stream_tags)
2521     gst_tag_list_unref (stream->stream_tags);
2522
2523   stream->stream_tags = gst_tag_list_new_empty ();
2524   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2525   g_free (stream->redirect_uri);
2526   stream->redirect_uri = NULL;
2527   stream->sent_eos = FALSE;
2528   stream->protected = FALSE;
2529   if (stream->protection_scheme_info) {
2530     if (stream->protection_scheme_type == FOURCC_cenc
2531         || stream->protection_scheme_type == FOURCC_cbcs) {
2532       QtDemuxCencSampleSetInfo *info =
2533           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2534       if (info->default_properties)
2535         gst_structure_free (info->default_properties);
2536       if (info->crypto_info)
2537         g_ptr_array_free (info->crypto_info, TRUE);
2538     }
2539     if (stream->protection_scheme_type == FOURCC_aavd) {
2540       QtDemuxAavdEncryptionInfo *info =
2541           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2542       if (info->default_properties)
2543         gst_structure_free (info->default_properties);
2544     }
2545     g_free (stream->protection_scheme_info);
2546     stream->protection_scheme_info = NULL;
2547   }
2548   stream->protection_scheme_type = 0;
2549   stream->protection_scheme_version = 0;
2550   g_queue_foreach (&stream->protection_scheme_event_queue,
2551       (GFunc) gst_event_unref, NULL);
2552   g_queue_clear (&stream->protection_scheme_event_queue);
2553   gst_qtdemux_stream_flush_segments_data (stream);
2554   gst_qtdemux_stream_flush_samples_data (stream);
2555 }
2556
2557 static void
2558 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2559 {
2560   gint i;
2561   gst_qtdemux_stream_clear (stream);
2562   for (i = 0; i < stream->stsd_entries_length; i++) {
2563     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2564     if (entry->caps) {
2565       gst_caps_unref (entry->caps);
2566       entry->caps = NULL;
2567     }
2568   }
2569   g_free (stream->stsd_entries);
2570   stream->stsd_entries = NULL;
2571   stream->stsd_entries_length = 0;
2572 }
2573
2574 static QtDemuxStream *
2575 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2576 {
2577   g_atomic_int_add (&stream->ref_count, 1);
2578
2579   return stream;
2580 }
2581
2582 static void
2583 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2584 {
2585   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2586     gst_qtdemux_stream_reset (stream);
2587     gst_tag_list_unref (stream->stream_tags);
2588     if (stream->pad) {
2589       GstQTDemux *demux = stream->demux;
2590       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2591       GST_OBJECT_LOCK (demux);
2592       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2593       GST_OBJECT_UNLOCK (demux);
2594     }
2595     g_free (stream->stream_id);
2596     g_free (stream);
2597   }
2598 }
2599
2600 static GstStateChangeReturn
2601 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2602 {
2603   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2604   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2605
2606   switch (transition) {
2607     case GST_STATE_CHANGE_READY_TO_PAUSED:
2608       gst_qtdemux_reset (qtdemux, TRUE);
2609       break;
2610     default:
2611       break;
2612   }
2613
2614   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2615
2616   switch (transition) {
2617     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2618       gst_qtdemux_reset (qtdemux, TRUE);
2619       break;
2620     }
2621     default:
2622       break;
2623   }
2624
2625   return result;
2626 }
2627
2628 static void
2629 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2630 {
2631   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2632
2633   g_return_if_fail (GST_IS_CONTEXT (context));
2634
2635   if (gst_context_has_context_type (context,
2636           "drm-preferred-decryption-system-id")) {
2637     const GstStructure *s;
2638
2639     s = gst_context_get_structure (context);
2640     g_free (qtdemux->preferred_protection_system_id);
2641     qtdemux->preferred_protection_system_id =
2642         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2643     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2644         qtdemux->preferred_protection_system_id);
2645   }
2646
2647   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2648 }
2649
2650 static void
2651 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2652 {
2653   /* counts as header data */
2654   qtdemux->header_size += length;
2655
2656   /* only consider at least a sufficiently complete ftyp atom */
2657   if (length >= 20) {
2658     GstBuffer *buf;
2659
2660     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2661     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2662         GST_FOURCC_ARGS (qtdemux->major_brand));
2663     if (qtdemux->comp_brands)
2664       gst_buffer_unref (qtdemux->comp_brands);
2665     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2666     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2667   }
2668 }
2669
2670 static void
2671 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2672     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2673     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2674     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2675     const guint8 * constant_iv)
2676 {
2677   const gchar *protection_scheme_type_mime =
2678       protection_scheme_type ==
2679       FOURCC_cbcs ? "application/x-cbcs" : "application/x-cenc";
2680   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2681   gst_buffer_fill (kid_buf, 0, kid, 16);
2682   if (info->default_properties)
2683     gst_structure_free (info->default_properties);
2684   info->default_properties =
2685       gst_structure_new (protection_scheme_type_mime,
2686       "iv_size", G_TYPE_UINT, iv_size,
2687       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2688       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2689   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2690       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2691   gst_buffer_unref (kid_buf);
2692   if (protection_scheme_type == FOURCC_cbcs) {
2693     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2694       gst_structure_set (info->default_properties, "crypt_byte_block",
2695           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2696           skip_byte_block, NULL);
2697     }
2698     if (constant_iv != NULL) {
2699       GstBuffer *constant_iv_buf =
2700           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2701       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2702       gst_structure_set (info->default_properties, "constant_iv_size",
2703           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2704           NULL);
2705       gst_buffer_unref (constant_iv_buf);
2706     }
2707   }
2708 }
2709
2710 static gboolean
2711 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2712     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2713 {
2714   guint32 algorithm_id = 0;
2715   const guint8 *kid;
2716   gboolean is_encrypted = TRUE;
2717   guint8 iv_size = 8;
2718
2719   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2720     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2721     return FALSE;
2722   }
2723
2724   algorithm_id >>= 8;
2725   if (algorithm_id == 0) {
2726     is_encrypted = FALSE;
2727   } else if (algorithm_id == 1) {
2728     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2729   } else if (algorithm_id == 2) {
2730     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2731   }
2732
2733   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2734     return FALSE;
2735
2736   if (!gst_byte_reader_get_data (br, 16, &kid))
2737     return FALSE;
2738
2739   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2740       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2741   gst_structure_set (info->default_properties, "piff_algorithm_id",
2742       G_TYPE_UINT, algorithm_id, NULL);
2743   return TRUE;
2744 }
2745
2746
2747 static void
2748 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2749     guint offset)
2750 {
2751   GstByteReader br;
2752   guint8 version;
2753   guint32 flags = 0;
2754   guint i;
2755   guint iv_size = 8;
2756   QtDemuxStream *stream;
2757   GstStructure *structure;
2758   QtDemuxCencSampleSetInfo *ss_info = NULL;
2759   const gchar *system_id;
2760   gboolean uses_sub_sample_encryption = FALSE;
2761   guint32 sample_count;
2762
2763   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2764     return;
2765
2766   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2767
2768   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2769   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2770     GST_WARNING_OBJECT (qtdemux,
2771         "Attempting PIFF box parsing on an unencrypted stream.");
2772     return;
2773   }
2774
2775   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2776       G_TYPE_STRING, &system_id, NULL);
2777   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2778
2779   stream->protected = TRUE;
2780   stream->protection_scheme_type = FOURCC_cenc;
2781
2782   if (!stream->protection_scheme_info)
2783     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2784
2785   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2786   if (!ss_info->default_properties) {
2787     ss_info->default_properties =
2788         gst_structure_new ("application/x-cenc",
2789         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2790         NULL);
2791
2792   }
2793
2794   if (ss_info->crypto_info) {
2795     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2796     g_ptr_array_free (ss_info->crypto_info, TRUE);
2797     ss_info->crypto_info = NULL;
2798   }
2799
2800   /* skip UUID */
2801   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2802
2803   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2804     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2805     return;
2806   }
2807
2808   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2809     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2810     return;
2811   }
2812
2813   if ((flags & 0x000001)) {
2814     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2815             &br))
2816       return;
2817   } else if ((flags & 0x000002)) {
2818     uses_sub_sample_encryption = TRUE;
2819   }
2820
2821   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2822           &iv_size)) {
2823     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2824     return;
2825   }
2826
2827   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2828     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2829     return;
2830   }
2831
2832   ss_info->crypto_info =
2833       g_ptr_array_new_full (sample_count,
2834       (GDestroyNotify) qtdemux_gst_structure_free);
2835
2836   for (i = 0; i < sample_count; ++i) {
2837     GstStructure *properties;
2838     guint8 *data;
2839     GstBuffer *buf;
2840
2841     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2842     if (properties == NULL) {
2843       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2844       qtdemux->cenc_aux_sample_count = i;
2845       return;
2846     }
2847
2848     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2849       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2850       gst_structure_free (properties);
2851       qtdemux->cenc_aux_sample_count = i;
2852       return;
2853     }
2854     buf = gst_buffer_new_wrapped (data, iv_size);
2855     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2856     gst_buffer_unref (buf);
2857
2858     if (uses_sub_sample_encryption) {
2859       guint16 n_subsamples;
2860       const GValue *kid_buf_value;
2861
2862       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2863           || n_subsamples == 0) {
2864         GST_ERROR_OBJECT (qtdemux,
2865             "failed to get subsample count for sample %u", i);
2866         gst_structure_free (properties);
2867         qtdemux->cenc_aux_sample_count = i;
2868         return;
2869       }
2870       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2871       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2872         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2873             i);
2874         gst_structure_free (properties);
2875         qtdemux->cenc_aux_sample_count = i;
2876         return;
2877       }
2878       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2879
2880       kid_buf_value =
2881           gst_structure_get_value (ss_info->default_properties, "kid");
2882
2883       gst_structure_set (properties,
2884           "subsample_count", G_TYPE_UINT, n_subsamples,
2885           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2886       gst_structure_set_value (properties, "kid", kid_buf_value);
2887       gst_buffer_unref (buf);
2888     } else {
2889       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2890     }
2891
2892     g_ptr_array_add (ss_info->crypto_info, properties);
2893   }
2894
2895   qtdemux->cenc_aux_sample_count = sample_count;
2896 }
2897
2898 static void
2899 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2900 {
2901   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2902     0x97, 0xA9, 0x42, 0xE8,
2903     0x9C, 0x71, 0x99, 0x94,
2904     0x91, 0xE3, 0xAF, 0xAC
2905   };
2906   static const guint8 playready_uuid[] = {
2907     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2908     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2909   };
2910
2911   static const guint8 piff_sample_encryption_uuid[] = {
2912     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2913     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2914   };
2915
2916   guint offset;
2917
2918   /* counts as header data */
2919   qtdemux->header_size += length;
2920
2921   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2922
2923   if (length <= offset + 16) {
2924     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2925     return;
2926   }
2927
2928   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2929     GstBuffer *buf;
2930     GstTagList *taglist;
2931
2932     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2933         length - offset - 16, NULL);
2934     taglist = gst_tag_list_from_xmp_buffer (buf);
2935     gst_buffer_unref (buf);
2936
2937     /* make sure we have a usable taglist */
2938     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2939
2940     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2941
2942   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2943     int len;
2944     const gunichar2 *s_utf16;
2945     char *contents;
2946
2947     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2948     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2949     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2950     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2951
2952     g_free (contents);
2953
2954     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2955         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2956         (NULL));
2957   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2958     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2959   } else {
2960     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2961         GST_READ_UINT32_LE (buffer + offset),
2962         GST_READ_UINT32_LE (buffer + offset + 4),
2963         GST_READ_UINT32_LE (buffer + offset + 8),
2964         GST_READ_UINT32_LE (buffer + offset + 12));
2965   }
2966 }
2967
2968 static void
2969 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2970 {
2971   GstSidxParser sidx_parser;
2972   GstIsoffParserResult res;
2973   guint consumed;
2974
2975   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2976
2977   res =
2978       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2979       &consumed);
2980   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2981   if (res == GST_ISOFF_QT_PARSER_DONE) {
2982     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2983   }
2984   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2985 }
2986
2987 /* caller verifies at least 8 bytes in buf */
2988 static void
2989 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2990     guint64 * plength, guint32 * pfourcc)
2991 {
2992   guint64 length;
2993   guint32 fourcc;
2994
2995   length = QT_UINT32 (data);
2996   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2997   fourcc = QT_FOURCC (data + 4);
2998   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2999
3000   if (length == 0) {
3001     length = G_MAXUINT64;
3002   } else if (length == 1 && size >= 16) {
3003     /* this means we have an extended size, which is the 64 bit value of
3004      * the next 8 bytes */
3005     length = QT_UINT64 (data + 8);
3006     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3007   }
3008
3009   if (plength)
3010     *plength = length;
3011   if (pfourcc)
3012     *pfourcc = fourcc;
3013 }
3014
3015 static gboolean
3016 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3017 {
3018   guint32 version = 0;
3019   GstClockTime duration = 0;
3020
3021   if (!gst_byte_reader_get_uint32_be (br, &version))
3022     goto failed;
3023
3024   version >>= 24;
3025   if (version == 1) {
3026     if (!gst_byte_reader_get_uint64_be (br, &duration))
3027       goto failed;
3028   } else {
3029     guint32 dur = 0;
3030
3031     if (!gst_byte_reader_get_uint32_be (br, &dur))
3032       goto failed;
3033     duration = dur;
3034   }
3035
3036   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3037   qtdemux->duration = duration;
3038
3039   return TRUE;
3040
3041 failed:
3042   {
3043     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3044     return FALSE;
3045   }
3046 }
3047
3048 static gboolean
3049 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3050     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3051 {
3052   if (!stream->parsed_trex && qtdemux->moov_node) {
3053     GNode *mvex, *trex;
3054     GstByteReader trex_data;
3055
3056     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3057     if (mvex) {
3058       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3059           &trex_data);
3060       while (trex) {
3061         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3062
3063         /* skip version/flags */
3064         if (!gst_byte_reader_skip (&trex_data, 4))
3065           goto next;
3066         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3067           goto next;
3068         if (id != stream->track_id)
3069           goto next;
3070         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3071           goto next;
3072         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3073           goto next;
3074         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3075           goto next;
3076         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3077           goto next;
3078
3079         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3080             "duration %d,  size %d, flags 0x%x", stream->track_id,
3081             dur, size, flags);
3082
3083         stream->parsed_trex = TRUE;
3084         stream->def_sample_description_index = sdi;
3085         stream->def_sample_duration = dur;
3086         stream->def_sample_size = size;
3087         stream->def_sample_flags = flags;
3088
3089       next:
3090         /* iterate all siblings */
3091         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3092             &trex_data);
3093       }
3094     }
3095   }
3096
3097   *ds_duration = stream->def_sample_duration;
3098   *ds_size = stream->def_sample_size;
3099   *ds_flags = stream->def_sample_flags;
3100
3101   /* even then, above values are better than random ... */
3102   if (G_UNLIKELY (!stream->parsed_trex)) {
3103     GST_WARNING_OBJECT (qtdemux,
3104         "failed to find fragment defaults for stream %d", stream->track_id);
3105     return FALSE;
3106   }
3107
3108   return TRUE;
3109 }
3110
3111 /* This method should be called whenever a more accurate duration might
3112  * have been found. It will update all relevant variables if/where needed
3113  */
3114 static void
3115 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3116 {
3117   guint i;
3118   guint64 movdur;
3119   GstClockTime prevdur;
3120
3121   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3122
3123   if (movdur > qtdemux->duration) {
3124     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3125     GST_DEBUG_OBJECT (qtdemux,
3126         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3127         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3128     qtdemux->duration = movdur;
3129     GST_DEBUG_OBJECT (qtdemux,
3130         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3131         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3132         GST_TIME_ARGS (qtdemux->segment.stop));
3133     if (qtdemux->segment.duration == prevdur) {
3134       /* If the current segment has duration/stop identical to previous duration
3135        * update them also (because they were set at that point in time with
3136        * the wrong duration */
3137       /* We convert the value *from* the timescale version to avoid rounding errors */
3138       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3139       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3140       qtdemux->segment.duration = fixeddur;
3141       qtdemux->segment.stop = fixeddur;
3142     }
3143   }
3144
3145   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3146     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3147
3148     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3149     if (movdur > stream->duration) {
3150       GST_DEBUG_OBJECT (qtdemux,
3151           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3152           GST_TIME_ARGS (duration));
3153       stream->duration = movdur;
3154       /* internal duration tracking state has been updated above, so */
3155       /* preserve an open-ended dummy segment rather than repeatedly updating
3156        * it and spamming downstream accordingly with segment events */
3157       /* also mangle the edit list end time when fragmented with a single edit
3158        * list that may only cover any non-fragmented data */
3159       if ((stream->dummy_segment ||
3160               (qtdemux->fragmented && stream->n_segments == 1)) &&
3161           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3162         /* Update all dummy values to new duration */
3163         stream->segments[0].stop_time = duration;
3164         stream->segments[0].duration = duration;
3165         stream->segments[0].media_stop = duration;
3166
3167         /* let downstream know we possibly have a new stop time */
3168         if (stream->segment_index != -1) {
3169           GstClockTime pos;
3170
3171           if (qtdemux->segment.rate >= 0) {
3172             pos = stream->segment.start;
3173           } else {
3174             pos = stream->segment.stop;
3175           }
3176
3177           gst_qtdemux_stream_update_segment (qtdemux, stream,
3178               stream->segment_index, pos, NULL, NULL);
3179         }
3180       }
3181     }
3182   }
3183 }
3184
3185 static gboolean
3186 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3187     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3188     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3189     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3190     gboolean has_tfdt)
3191 {
3192   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3193   guint64 timestamp;
3194   gint32 data_offset = 0;
3195   guint32 flags = 0, first_flags = 0, samples_count = 0;
3196   gint i;
3197   guint8 *data;
3198   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3199   QtDemuxSample *sample;
3200   gboolean ismv = FALSE;
3201   gint64 initial_offset;
3202
3203   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3204       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3205       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3206       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3207
3208   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3209     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3210     return TRUE;
3211   }
3212
3213   /* presence of stss or not can't really tell us much,
3214    * and flags and so on tend to be marginally reliable in these files */
3215   if (stream->subtype == FOURCC_soun) {
3216     GST_DEBUG_OBJECT (qtdemux,
3217         "sound track in fragmented file; marking all keyframes");
3218     stream->all_keyframe = TRUE;
3219   }
3220
3221   if (!gst_byte_reader_skip (trun, 1) ||
3222       !gst_byte_reader_get_uint24_be (trun, &flags))
3223     goto fail;
3224
3225   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3226     goto fail;
3227
3228   if (flags & TR_DATA_OFFSET) {
3229     /* note this is really signed */
3230     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3231       goto fail;
3232     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3233     /* default base offset = first byte of moof */
3234     if (*base_offset == -1) {
3235       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3236       *base_offset = moof_offset;
3237     }
3238     *running_offset = *base_offset + data_offset;
3239   } else {
3240     /* if no offset at all, that would mean data starts at moof start,
3241      * which is a bit wrong and is ismv crappy way, so compensate
3242      * assuming data is in mdat following moof */
3243     if (*base_offset == -1) {
3244       *base_offset = moof_offset + moof_length + 8;
3245       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3246       ismv = TRUE;
3247     }
3248     if (*running_offset == -1)
3249       *running_offset = *base_offset;
3250   }
3251
3252   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3253       *running_offset);
3254   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3255       data_offset, flags, samples_count);
3256
3257   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3258     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3259       GST_DEBUG_OBJECT (qtdemux,
3260           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3261       flags ^= TR_FIRST_SAMPLE_FLAGS;
3262     } else {
3263       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3264         goto fail;
3265       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3266     }
3267   }
3268
3269   /* FIXME ? spec says other bits should also be checked to determine
3270    * entry size (and prefix size for that matter) */
3271   entry_size = 0;
3272   dur_offset = size_offset = 0;
3273   if (flags & TR_SAMPLE_DURATION) {
3274     GST_LOG_OBJECT (qtdemux, "entry duration present");
3275     dur_offset = entry_size;
3276     entry_size += 4;
3277   }
3278   if (flags & TR_SAMPLE_SIZE) {
3279     GST_LOG_OBJECT (qtdemux, "entry size present");
3280     size_offset = entry_size;
3281     entry_size += 4;
3282   }
3283   if (flags & TR_SAMPLE_FLAGS) {
3284     GST_LOG_OBJECT (qtdemux, "entry flags present");
3285     flags_offset = entry_size;
3286     entry_size += 4;
3287   }
3288   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3289     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3290     ct_offset = entry_size;
3291     entry_size += 4;
3292   }
3293
3294   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3295     goto fail;
3296   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3297
3298   if (stream->n_samples + samples_count >=
3299       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3300     goto index_too_big;
3301
3302   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3303       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3304       (stream->n_samples + samples_count) *
3305       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3306
3307   /* create a new array of samples if it's the first sample parsed */
3308   if (stream->n_samples == 0) {
3309     g_assert (stream->samples == NULL);
3310     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3311     /* or try to reallocate it with space enough to insert the new samples */
3312   } else
3313     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3314         stream->n_samples + samples_count);
3315   if (stream->samples == NULL)
3316     goto out_of_memory;
3317
3318   if (qtdemux->fragment_start != -1) {
3319     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3320     qtdemux->fragment_start = -1;
3321   } else {
3322     if (stream->n_samples == 0) {
3323       if (decode_ts > 0) {
3324         timestamp = decode_ts;
3325       } else if (stream->pending_seek != NULL) {
3326         /* if we don't have a timestamp from a tfdt box, we'll use the one
3327          * from the mfra seek table */
3328         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3329             GST_TIME_ARGS (stream->pending_seek->ts));
3330
3331         /* FIXME: this is not fully correct, the timestamp refers to the random
3332          * access sample refered to in the tfra entry, which may not necessarily
3333          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3334         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3335       } else {
3336         timestamp = 0;
3337       }
3338
3339       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3340       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3341           GST_TIME_ARGS (gst_ts));
3342     } else {
3343       /* subsequent fragments extend stream */
3344       timestamp =
3345           stream->samples[stream->n_samples - 1].timestamp +
3346           stream->samples[stream->n_samples - 1].duration;
3347
3348       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3349        * difference (1 sec.) between decode_ts and timestamp, prefer the
3350        * former */
3351       if (has_tfdt && !qtdemux->upstream_format_is_time
3352           && ABSDIFF (decode_ts, timestamp) >
3353           MAX (stream->duration_last_moof / 2,
3354               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3355         GST_INFO_OBJECT (qtdemux,
3356             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3357             ") are significantly different (more than %" GST_TIME_FORMAT
3358             "), using decode_ts",
3359             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3360             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3361             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3362                     MAX (stream->duration_last_moof / 2,
3363                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3364         timestamp = decode_ts;
3365       }
3366
3367       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3368       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3369           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3370     }
3371   }
3372
3373   initial_offset = *running_offset;
3374
3375   sample = stream->samples + stream->n_samples;
3376   for (i = 0; i < samples_count; i++) {
3377     guint32 dur, size, sflags, ct;
3378
3379     /* first read sample data */
3380     if (flags & TR_SAMPLE_DURATION) {
3381       dur = QT_UINT32 (data + dur_offset);
3382     } else {
3383       dur = d_sample_duration;
3384     }
3385     if (flags & TR_SAMPLE_SIZE) {
3386       size = QT_UINT32 (data + size_offset);
3387     } else {
3388       size = d_sample_size;
3389     }
3390     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3391       if (i == 0) {
3392         sflags = first_flags;
3393       } else {
3394         sflags = d_sample_flags;
3395       }
3396     } else if (flags & TR_SAMPLE_FLAGS) {
3397       sflags = QT_UINT32 (data + flags_offset);
3398     } else {
3399       sflags = d_sample_flags;
3400     }
3401     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3402       ct = QT_UINT32 (data + ct_offset);
3403     } else {
3404       ct = 0;
3405     }
3406     data += entry_size;
3407
3408     /* fill the sample information */
3409     sample->offset = *running_offset;
3410     sample->pts_offset = ct;
3411     sample->size = size;
3412     sample->timestamp = timestamp;
3413     sample->duration = dur;
3414     /* sample-is-difference-sample */
3415     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3416      * now idea how it relates to bitfield other than massive LE/BE confusion */
3417     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3418     *running_offset += size;
3419     timestamp += dur;
3420     stream->duration_moof += dur;
3421     sample++;
3422   }
3423
3424   /* Update total duration if needed */
3425   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3426
3427   /* Pre-emptively figure out size of mdat based on trun information.
3428    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3429    * size, else we will still be able to use this when dealing with gap'ed
3430    * input */
3431   qtdemux->mdatleft = *running_offset - initial_offset;
3432   qtdemux->mdatoffset = initial_offset;
3433   qtdemux->mdatsize = qtdemux->mdatleft;
3434
3435   stream->n_samples += samples_count;
3436   stream->n_samples_moof += samples_count;
3437
3438   if (stream->pending_seek != NULL)
3439     stream->pending_seek = NULL;
3440
3441   return TRUE;
3442
3443 fail:
3444   {
3445     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3446     return FALSE;
3447   }
3448 out_of_memory:
3449   {
3450     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3451         stream->n_samples);
3452     return FALSE;
3453   }
3454 index_too_big:
3455   {
3456     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3457         "be larger than %uMB (broken file?)", stream->n_samples,
3458         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3459     return FALSE;
3460   }
3461 }
3462
3463 /* find stream with @id */
3464 static inline QtDemuxStream *
3465 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3466 {
3467   QtDemuxStream *stream;
3468   gint i;
3469
3470   /* check */
3471   if (G_UNLIKELY (!id)) {
3472     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3473     return NULL;
3474   }
3475
3476   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3477     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3478     if (stream->track_id == id)
3479       return stream;
3480   }
3481   if (qtdemux->mss_mode) {
3482     /* mss should have only 1 stream anyway */
3483     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3484   }
3485
3486   return NULL;
3487 }
3488
3489 static gboolean
3490 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3491     guint32 * fragment_number)
3492 {
3493   if (!gst_byte_reader_skip (mfhd, 4))
3494     goto fail;
3495   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3496     goto fail;
3497   return TRUE;
3498 fail:
3499   {
3500     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3501     return FALSE;
3502   }
3503 }
3504
3505 static gboolean
3506 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3507     QtDemuxStream ** stream, guint32 * default_sample_duration,
3508     guint32 * default_sample_size, guint32 * default_sample_flags,
3509     gint64 * base_offset)
3510 {
3511   guint32 flags = 0;
3512   guint32 track_id = 0;
3513
3514   if (!gst_byte_reader_skip (tfhd, 1) ||
3515       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3516     goto invalid_track;
3517
3518   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3519     goto invalid_track;
3520
3521   *stream = qtdemux_find_stream (qtdemux, track_id);
3522   if (G_UNLIKELY (!*stream))
3523     goto unknown_stream;
3524
3525   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3526     *base_offset = qtdemux->moof_offset;
3527
3528   if (flags & TF_BASE_DATA_OFFSET)
3529     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3530       goto invalid_track;
3531
3532   /* obtain stream defaults */
3533   qtdemux_parse_trex (qtdemux, *stream,
3534       default_sample_duration, default_sample_size, default_sample_flags);
3535
3536   (*stream)->stsd_sample_description_id =
3537       (*stream)->def_sample_description_index - 1;
3538
3539   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3540     guint32 sample_description_index;
3541     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3542       goto invalid_track;
3543     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3544   }
3545
3546   if (qtdemux->mss_mode) {
3547     /* mss has no stsd entry */
3548     (*stream)->stsd_sample_description_id = 0;
3549   }
3550
3551   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3552     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3553       goto invalid_track;
3554
3555   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3556     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3557       goto invalid_track;
3558
3559   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3560     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3561       goto invalid_track;
3562
3563   return TRUE;
3564
3565 invalid_track:
3566   {
3567     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3568     return FALSE;
3569   }
3570 unknown_stream:
3571   {
3572     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3573     return TRUE;
3574   }
3575 }
3576
3577 static gboolean
3578 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3579     guint64 * decode_time)
3580 {
3581   guint32 version = 0;
3582
3583   if (!gst_byte_reader_get_uint32_be (br, &version))
3584     return FALSE;
3585
3586   version >>= 24;
3587   if (version == 1) {
3588     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3589       goto failed;
3590   } else {
3591     guint32 dec_time = 0;
3592     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3593       goto failed;
3594     *decode_time = dec_time;
3595   }
3596
3597   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3598       *decode_time);
3599
3600   return TRUE;
3601
3602 failed:
3603   {
3604     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3605     return FALSE;
3606   }
3607 }
3608
3609 /* Returns a pointer to a GstStructure containing the properties of
3610  * the stream sample identified by @sample_index. The caller must unref
3611  * the returned object after use. Returns NULL if unsuccessful. */
3612 static GstStructure *
3613 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3614     QtDemuxStream * stream, guint sample_index)
3615 {
3616   QtDemuxCencSampleSetInfo *info = NULL;
3617
3618   g_return_val_if_fail (stream != NULL, NULL);
3619   g_return_val_if_fail (stream->protected, NULL);
3620   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3621
3622   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3623
3624   /* Currently, cenc properties for groups of samples are not supported, so
3625    * simply return a copy of the default sample properties */
3626   return gst_structure_copy (info->default_properties);
3627 }
3628
3629 /* Parses the sizes of sample auxiliary information contained within a stream,
3630  * as given in a saiz box. Returns array of sample_count guint8 size values,
3631  * or NULL on failure */
3632 static guint8 *
3633 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3634     GstByteReader * br, guint32 * sample_count)
3635 {
3636   guint32 flags = 0;
3637   guint8 *info_sizes;
3638   guint8 default_info_size;
3639
3640   g_return_val_if_fail (qtdemux != NULL, NULL);
3641   g_return_val_if_fail (stream != NULL, NULL);
3642   g_return_val_if_fail (br != NULL, NULL);
3643   g_return_val_if_fail (sample_count != NULL, NULL);
3644
3645   if (!gst_byte_reader_get_uint32_be (br, &flags))
3646     return NULL;
3647
3648   if (flags & 0x1) {
3649     /* aux_info_type and aux_info_type_parameter are ignored */
3650     if (!gst_byte_reader_skip (br, 8))
3651       return NULL;
3652   }
3653
3654   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3655     return NULL;
3656   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3657
3658   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3659     return NULL;
3660   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3661
3662
3663   if (default_info_size == 0) {
3664     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3665       return NULL;
3666     }
3667   } else {
3668     info_sizes = g_new (guint8, *sample_count);
3669     memset (info_sizes, default_info_size, *sample_count);
3670   }
3671
3672   return info_sizes;
3673 }
3674
3675 /* Parses the offset of sample auxiliary information contained within a stream,
3676  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3677 static gboolean
3678 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3679     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3680     guint64 * offset)
3681 {
3682   guint8 version = 0;
3683   guint32 flags = 0;
3684   guint32 aux_info_type = 0;
3685   guint32 aux_info_type_parameter = 0;
3686   guint32 entry_count;
3687   guint32 off_32;
3688   guint64 off_64;
3689   const guint8 *aux_info_type_data = NULL;
3690
3691   g_return_val_if_fail (qtdemux != NULL, FALSE);
3692   g_return_val_if_fail (stream != NULL, FALSE);
3693   g_return_val_if_fail (br != NULL, FALSE);
3694   g_return_val_if_fail (offset != NULL, FALSE);
3695
3696   if (!gst_byte_reader_get_uint8 (br, &version))
3697     return FALSE;
3698
3699   if (!gst_byte_reader_get_uint24_be (br, &flags))
3700     return FALSE;
3701
3702   if (flags & 0x1) {
3703
3704     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3705       return FALSE;
3706     aux_info_type = QT_FOURCC (aux_info_type_data);
3707
3708     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3709       return FALSE;
3710   } else if (stream->protected) {
3711     aux_info_type = stream->protection_scheme_type;
3712   } else {
3713     aux_info_type = CUR_STREAM (stream)->fourcc;
3714   }
3715
3716   if (info_type)
3717     *info_type = aux_info_type;
3718   if (info_type_parameter)
3719     *info_type_parameter = aux_info_type_parameter;
3720
3721   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3722       "aux_info_type_parameter:  %#06x",
3723       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3724
3725   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3726     return FALSE;
3727
3728   if (entry_count != 1) {
3729     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3730     return FALSE;
3731   }
3732
3733   if (version == 0) {
3734     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3735       return FALSE;
3736     *offset = (guint64) off_32;
3737   } else {
3738     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3739       return FALSE;
3740     *offset = off_64;
3741   }
3742
3743   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3744   return TRUE;
3745 }
3746
3747 static void
3748 qtdemux_gst_structure_free (GstStructure * gststructure)
3749 {
3750   if (gststructure) {
3751     gst_structure_free (gststructure);
3752   }
3753 }
3754
3755 /* Parses auxiliary information relating to samples protected using
3756  * Common Encryption (cenc and cbcs); the format of this information
3757  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3758  * otherwise. */
3759 static gboolean
3760 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3761     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3762 {
3763   QtDemuxCencSampleSetInfo *ss_info = NULL;
3764   guint8 size;
3765   gint i;
3766   GPtrArray *old_crypto_info = NULL;
3767   guint old_entries = 0;
3768
3769   g_return_val_if_fail (qtdemux != NULL, FALSE);
3770   g_return_val_if_fail (stream != NULL, FALSE);
3771   g_return_val_if_fail (br != NULL, FALSE);
3772   g_return_val_if_fail (stream->protected, FALSE);
3773   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3774
3775   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3776
3777   if (ss_info->crypto_info) {
3778     old_crypto_info = ss_info->crypto_info;
3779     /* Count number of non-null entries remaining at the tail end */
3780     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3781       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3782         break;
3783       old_entries++;
3784     }
3785   }
3786
3787   ss_info->crypto_info =
3788       g_ptr_array_new_full (sample_count + old_entries,
3789       (GDestroyNotify) qtdemux_gst_structure_free);
3790
3791   /* We preserve old entries because we parse the next moof in advance
3792    * of consuming all samples from the previous moof, and otherwise
3793    * we'd discard the corresponding crypto info for the samples
3794    * from the previous fragment. */
3795   if (old_entries) {
3796     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3797         old_entries);
3798     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3799       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3800               i));
3801       g_ptr_array_index (old_crypto_info, i) = NULL;
3802     }
3803   }
3804
3805   if (old_crypto_info) {
3806     /* Everything now belongs to the new array */
3807     g_ptr_array_free (old_crypto_info, TRUE);
3808   }
3809
3810   for (i = 0; i < sample_count; ++i) {
3811     GstStructure *properties;
3812     guint16 n_subsamples = 0;
3813     guint8 *data;
3814     guint iv_size;
3815     GstBuffer *buf;
3816     gboolean could_read_iv;
3817
3818     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3819     if (properties == NULL) {
3820       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3821       return FALSE;
3822     }
3823     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3824       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3825       gst_structure_free (properties);
3826       return FALSE;
3827     }
3828     could_read_iv =
3829         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3830     if (could_read_iv) {
3831       buf = gst_buffer_new_wrapped (data, iv_size);
3832       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3833       gst_buffer_unref (buf);
3834     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3835       const GValue *constant_iv_size_value =
3836           gst_structure_get_value (properties, "constant_iv_size");
3837       const GValue *constant_iv_value =
3838           gst_structure_get_value (properties, "iv");
3839       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3840         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3841         gst_structure_free (properties);
3842         return FALSE;
3843       }
3844       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3845       gst_structure_remove_field (properties, "constant_iv_size");
3846     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3847       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3848       gst_structure_free (properties);
3849       return FALSE;
3850     }
3851     size = info_sizes[i];
3852     if (size > iv_size) {
3853       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3854           || !(n_subsamples > 0)) {
3855         gst_structure_free (properties);
3856         GST_ERROR_OBJECT (qtdemux,
3857             "failed to get subsample count for sample %u", i);
3858         return FALSE;
3859       }
3860       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3861       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3862         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3863             i);
3864         gst_structure_free (properties);
3865         return FALSE;
3866       }
3867       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3868       if (!buf) {
3869         gst_structure_free (properties);
3870         return FALSE;
3871       }
3872       gst_structure_set (properties,
3873           "subsample_count", G_TYPE_UINT, n_subsamples,
3874           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3875       gst_buffer_unref (buf);
3876     } else {
3877       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3878     }
3879     g_ptr_array_add (ss_info->crypto_info, properties);
3880   }
3881   return TRUE;
3882 }
3883
3884 /* Converts a UUID in raw byte form to a string representation, as defined in
3885  * RFC 4122. The caller takes ownership of the returned string and is
3886  * responsible for freeing it after use. */
3887 static gchar *
3888 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3889 {
3890   const guint8 *uuid = (const guint8 *) uuid_bytes;
3891
3892   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3893       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3894       uuid[0], uuid[1], uuid[2], uuid[3],
3895       uuid[4], uuid[5], uuid[6], uuid[7],
3896       uuid[8], uuid[9], uuid[10], uuid[11],
3897       uuid[12], uuid[13], uuid[14], uuid[15]);
3898 }
3899
3900 /* Parses a Protection System Specific Header box (pssh), as defined in the
3901  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3902  * information needed by a specific content protection system in order to
3903  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3904  * otherwise. */
3905 static gboolean
3906 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3907 {
3908   gchar *sysid_string;
3909   guint32 pssh_size = QT_UINT32 (node->data);
3910   GstBuffer *pssh = NULL;
3911   GstEvent *event = NULL;
3912   guint32 parent_box_type;
3913   gint i;
3914
3915   if (G_UNLIKELY (pssh_size < 32U)) {
3916     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3917     return FALSE;
3918   }
3919
3920   sysid_string =
3921       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3922
3923   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3924
3925   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3926   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3927       gst_buffer_get_size (pssh));
3928
3929   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3930
3931   /* Push an event containing the pssh box onto the queues of all streams. */
3932   event = gst_event_new_protection (sysid_string, pssh,
3933       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3934   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3935     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3936     GST_TRACE_OBJECT (qtdemux,
3937         "adding protection event for stream %s and system %s",
3938         stream->stream_id, sysid_string);
3939     g_queue_push_tail (&stream->protection_scheme_event_queue,
3940         gst_event_ref (event));
3941   }
3942   g_free (sysid_string);
3943   gst_event_unref (event);
3944   gst_buffer_unref (pssh);
3945   return TRUE;
3946 }
3947
3948 static gboolean
3949 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3950     guint64 moof_offset, QtDemuxStream * stream)
3951 {
3952   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3953   GNode *uuid_node;
3954   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3955   GNode *saiz_node, *saio_node, *pssh_node;
3956   GstByteReader saiz_data, saio_data;
3957   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3958   gint64 base_offset, running_offset;
3959   guint32 frag_num;
3960   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3961
3962   /* NOTE @stream ignored */
3963
3964   moof_node = g_node_new ((guint8 *) buffer);
3965   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3966   qtdemux_node_dump (qtdemux, moof_node);
3967
3968   /* Get fragment number from mfhd and check it's valid */
3969   mfhd_node =
3970       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3971   if (mfhd_node == NULL)
3972     goto missing_mfhd;
3973   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3974     goto fail;
3975   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3976
3977   /* unknown base_offset to start with */
3978   base_offset = running_offset = -1;
3979   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3980   while (traf_node) {
3981     guint64 decode_time = 0;
3982
3983     /* Fragment Header node */
3984     tfhd_node =
3985         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3986         &tfhd_data);
3987     if (!tfhd_node)
3988       goto missing_tfhd;
3989     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3990             &ds_size, &ds_flags, &base_offset))
3991       goto missing_tfhd;
3992
3993     /* The following code assumes at most a single set of sample auxiliary
3994      * data in the fragment (consisting of a saiz box and a corresponding saio
3995      * box); in theory, however, there could be multiple sets of sample
3996      * auxiliary data in a fragment. */
3997     saiz_node =
3998         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3999         &saiz_data);
4000     if (saiz_node) {
4001       guint32 info_type = 0;
4002       guint64 offset = 0;
4003       guint32 info_type_parameter = 0;
4004
4005       g_free (qtdemux->cenc_aux_info_sizes);
4006
4007       qtdemux->cenc_aux_info_sizes =
4008           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4009           &qtdemux->cenc_aux_sample_count);
4010       if (qtdemux->cenc_aux_info_sizes == NULL) {
4011         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4012         goto fail;
4013       }
4014       saio_node =
4015           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4016           &saio_data);
4017       if (!saio_node) {
4018         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4019         g_free (qtdemux->cenc_aux_info_sizes);
4020         qtdemux->cenc_aux_info_sizes = NULL;
4021         goto fail;
4022       }
4023
4024       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4025                   &info_type, &info_type_parameter, &offset))) {
4026         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4027         g_free (qtdemux->cenc_aux_info_sizes);
4028         qtdemux->cenc_aux_info_sizes = NULL;
4029         goto fail;
4030       }
4031       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4032         offset += (guint64) (base_offset - qtdemux->moof_offset);
4033       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4034           && info_type_parameter == 0U) {
4035         GstByteReader br;
4036         if (offset > length) {
4037           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4038           qtdemux->cenc_aux_info_offset = offset;
4039         } else {
4040           gst_byte_reader_init (&br, buffer + offset, length - offset);
4041           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4042                   qtdemux->cenc_aux_info_sizes,
4043                   qtdemux->cenc_aux_sample_count)) {
4044             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4045             g_free (qtdemux->cenc_aux_info_sizes);
4046             qtdemux->cenc_aux_info_sizes = NULL;
4047             goto fail;
4048           }
4049         }
4050       }
4051     }
4052
4053     tfdt_node =
4054         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4055         &tfdt_data);
4056     if (tfdt_node) {
4057       /* We'll use decode_time to interpolate timestamps
4058        * in case the input timestamps are missing */
4059       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4060
4061       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4062           " (%" GST_TIME_FORMAT ")", decode_time,
4063           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4064                   decode_time) : GST_CLOCK_TIME_NONE));
4065
4066       /* Discard the fragment buffer timestamp info to avoid using it.
4067        * Rely on tfdt instead as it is more accurate than the timestamp
4068        * that is fetched from a manifest/playlist and is usually
4069        * less accurate. */
4070       qtdemux->fragment_start = -1;
4071     }
4072
4073     if (G_UNLIKELY (!stream)) {
4074       /* we lost track of offset, we'll need to regain it,
4075        * but can delay complaining until later or avoid doing so altogether */
4076       base_offset = -2;
4077       goto next;
4078     }
4079     if (G_UNLIKELY (base_offset < -1))
4080       goto lost_offset;
4081
4082     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4083
4084     if (!qtdemux->pullbased) {
4085       /* Sample tables can grow enough to be problematic if the system memory
4086        * is very low (e.g. embedded devices) and the videos very long
4087        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4088        * Fortunately, we can easily discard them for each new fragment when
4089        * we know qtdemux will not receive seeks outside of the current fragment.
4090        * adaptivedemux honors this assumption.
4091        * This optimization is also useful for applications that use qtdemux as
4092        * a push-based simple demuxer, like Media Source Extensions. */
4093       gst_qtdemux_stream_flush_samples_data (stream);
4094     }
4095
4096     /* initialise moof sample data */
4097     stream->n_samples_moof = 0;
4098     stream->duration_last_moof = stream->duration_moof;
4099     stream->duration_moof = 0;
4100
4101     /* Track Run node */
4102     trun_node =
4103         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4104         &trun_data);
4105     while (trun_node) {
4106       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4107           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4108           &running_offset, decode_time, (tfdt_node != NULL));
4109       /* iterate all siblings */
4110       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4111           &trun_data);
4112     }
4113
4114     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4115     if (uuid_node) {
4116       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4117       guint32 box_length = QT_UINT32 (uuid_buffer);
4118
4119       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4120     }
4121
4122     /* if no new base_offset provided for next traf,
4123      * base is end of current traf */
4124     base_offset = running_offset;
4125     running_offset = -1;
4126
4127     if (stream->n_samples_moof && stream->duration_moof)
4128       stream->new_caps = TRUE;
4129
4130   next:
4131     /* iterate all siblings */
4132     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4133   }
4134
4135   /* parse any protection system info */
4136   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4137   while (pssh_node) {
4138     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4139     qtdemux_parse_pssh (qtdemux, pssh_node);
4140     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4141   }
4142
4143   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4144       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4145       && min_dts != 0) {
4146     /* Unless the user has explicitly requested another seek, perform an
4147      * internal seek to the time specified in the tfdt.
4148      *
4149      * This way if the user opens a file where the first tfdt is 1 hour
4150      * into the presentation, they will not have to wait 1 hour for run
4151      * time to catch up and actual playback to start. */
4152     gint i;
4153
4154     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4155         "performing an internal seek to %" GST_TIME_FORMAT,
4156         GST_TIME_ARGS (min_dts));
4157
4158     qtdemux->segment.start = min_dts;
4159     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4160
4161     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4162       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4163       stream->time_position = min_dts;
4164     }
4165
4166     /* Before this code was run a segment was already sent when the moov was
4167      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4168      * be emitted after a moov, and we can emit a second segment anyway for
4169      * special cases like this. */
4170     qtdemux->need_segment = TRUE;
4171   }
4172
4173   qtdemux->first_moof_already_parsed = TRUE;
4174
4175   g_node_destroy (moof_node);
4176   return TRUE;
4177
4178 missing_tfhd:
4179   {
4180     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4181     goto fail;
4182   }
4183 missing_mfhd:
4184   {
4185     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4186     goto fail;
4187   }
4188 lost_offset:
4189   {
4190     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4191     goto fail;
4192   }
4193 fail:
4194   {
4195     g_node_destroy (moof_node);
4196     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4197         (_("This file is corrupt and cannot be played.")), (NULL));
4198     return FALSE;
4199   }
4200 }
4201
4202 #if 0
4203 /* might be used if some day we actually use mfra & co
4204  * for random access to fragments,
4205  * but that will require quite some modifications and much less relying
4206  * on a sample array */
4207 #endif
4208
4209 static gboolean
4210 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4211 {
4212   QtDemuxStream *stream;
4213   guint32 ver_flags, track_id, len, num_entries, i;
4214   guint value_size, traf_size, trun_size, sample_size;
4215   guint64 time = 0, moof_offset = 0;
4216 #if 0
4217   GstBuffer *buf = NULL;
4218   GstFlowReturn ret;
4219 #endif
4220   GstByteReader tfra;
4221
4222   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4223
4224   if (!gst_byte_reader_skip (&tfra, 8))
4225     return FALSE;
4226
4227   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4228     return FALSE;
4229
4230   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4231       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4232       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4233     return FALSE;
4234
4235   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4236
4237   stream = qtdemux_find_stream (qtdemux, track_id);
4238   if (stream == NULL)
4239     goto unknown_trackid;
4240
4241   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4242   sample_size = (len & 3) + 1;
4243   trun_size = ((len & 12) >> 2) + 1;
4244   traf_size = ((len & 48) >> 4) + 1;
4245
4246   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4247       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4248
4249   if (num_entries == 0)
4250     goto no_samples;
4251
4252   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4253           value_size + value_size + traf_size + trun_size + sample_size))
4254     goto corrupt_file;
4255
4256   g_free (stream->ra_entries);
4257   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4258   stream->n_ra_entries = num_entries;
4259
4260   for (i = 0; i < num_entries; i++) {
4261     qt_atom_parser_get_offset (&tfra, value_size, &time);
4262     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4263     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4264     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4265     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4266
4267     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4268
4269     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4270         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4271
4272     stream->ra_entries[i].ts = time;
4273     stream->ra_entries[i].moof_offset = moof_offset;
4274
4275     /* don't want to go through the entire file and read all moofs at startup */
4276 #if 0
4277     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4278     if (ret != GST_FLOW_OK)
4279       goto corrupt_file;
4280     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4281         moof_offset, stream);
4282     gst_buffer_unref (buf);
4283 #endif
4284   }
4285
4286   check_update_duration (qtdemux, time);
4287
4288   return TRUE;
4289
4290 /* ERRORS */
4291 unknown_trackid:
4292   {
4293     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4294     return FALSE;
4295   }
4296 corrupt_file:
4297   {
4298     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4299     return FALSE;
4300   }
4301 no_samples:
4302   {
4303     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4304     return FALSE;
4305   }
4306 }
4307
4308 static gboolean
4309 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4310 {
4311   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4312   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4313   GstBuffer *mfro = NULL, *mfra = NULL;
4314   GstFlowReturn flow;
4315   gboolean ret = FALSE;
4316   GNode *mfra_node, *tfra_node;
4317   guint64 mfra_offset = 0;
4318   guint32 fourcc, mfra_size;
4319   gint64 len;
4320
4321   /* query upstream size in bytes */
4322   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4323     goto size_query_failed;
4324
4325   /* mfro box should be at the very end of the file */
4326   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4327   if (flow != GST_FLOW_OK)
4328     goto exit;
4329
4330   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4331
4332   fourcc = QT_FOURCC (mfro_map.data + 4);
4333   if (fourcc != FOURCC_mfro)
4334     goto exit;
4335
4336   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4337   if (mfro_map.size < 16)
4338     goto invalid_mfro_size;
4339
4340   mfra_size = QT_UINT32 (mfro_map.data + 12);
4341   if (mfra_size >= len)
4342     goto invalid_mfra_size;
4343
4344   mfra_offset = len - mfra_size;
4345
4346   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4347       mfra_offset, mfra_size);
4348
4349   /* now get and parse mfra box */
4350   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4351   if (flow != GST_FLOW_OK)
4352     goto broken_file;
4353
4354   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4355
4356   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4357   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4358
4359   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4360
4361   while (tfra_node) {
4362     qtdemux_parse_tfra (qtdemux, tfra_node);
4363     /* iterate all siblings */
4364     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4365   }
4366   g_node_destroy (mfra_node);
4367
4368   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4369   ret = TRUE;
4370
4371 exit:
4372
4373   if (mfro) {
4374     if (mfro_map.memory != NULL)
4375       gst_buffer_unmap (mfro, &mfro_map);
4376     gst_buffer_unref (mfro);
4377   }
4378   if (mfra) {
4379     if (mfra_map.memory != NULL)
4380       gst_buffer_unmap (mfra, &mfra_map);
4381     gst_buffer_unref (mfra);
4382   }
4383   return ret;
4384
4385 /* ERRORS */
4386 size_query_failed:
4387   {
4388     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4389     goto exit;
4390   }
4391 invalid_mfro_size:
4392   {
4393     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4394     goto exit;
4395   }
4396 invalid_mfra_size:
4397   {
4398     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4399     goto exit;
4400   }
4401 broken_file:
4402   {
4403     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4404     goto exit;
4405   }
4406 }
4407
4408 static guint64
4409 add_offset (guint64 offset, guint64 advance)
4410 {
4411   /* Avoid 64-bit overflow by clamping */
4412   if (offset > G_MAXUINT64 - advance)
4413     return G_MAXUINT64;
4414   return offset + advance;
4415 }
4416
4417 static GstFlowReturn
4418 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4419 {
4420   guint64 length = 0;
4421   guint32 fourcc = 0;
4422   GstBuffer *buf = NULL;
4423   GstFlowReturn ret = GST_FLOW_OK;
4424   guint64 cur_offset = qtdemux->offset;
4425   GstMapInfo map;
4426
4427   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4428   if (G_UNLIKELY (ret != GST_FLOW_OK))
4429     goto beach;
4430   gst_buffer_map (buf, &map, GST_MAP_READ);
4431   if (G_LIKELY (map.size >= 8))
4432     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4433   gst_buffer_unmap (buf, &map);
4434   gst_buffer_unref (buf);
4435
4436   /* maybe we already got most we needed, so only consider this eof */
4437   if (G_UNLIKELY (length == 0)) {
4438     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4439         (_("Invalid atom size.")),
4440         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4441             GST_FOURCC_ARGS (fourcc)));
4442     ret = GST_FLOW_EOS;
4443     goto beach;
4444   }
4445
4446   switch (fourcc) {
4447     case FOURCC_moof:
4448       /* record for later parsing when needed */
4449       if (!qtdemux->moof_offset) {
4450         qtdemux->moof_offset = qtdemux->offset;
4451       }
4452       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4453         /* FIXME */
4454       } else {
4455         qtdemux->offset += length;      /* skip moof and keep going */
4456       }
4457       if (qtdemux->got_moov) {
4458         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4459         ret = GST_FLOW_EOS;
4460         goto beach;
4461       }
4462       break;
4463     case FOURCC_mdat:
4464     case FOURCC_free:
4465     case FOURCC_skip:
4466     case FOURCC_wide:
4467     case FOURCC_PICT:
4468     case FOURCC_pnot:
4469     {
4470       GST_LOG_OBJECT (qtdemux,
4471           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4472           GST_FOURCC_ARGS (fourcc), cur_offset);
4473       qtdemux->offset = add_offset (qtdemux->offset, length);
4474       break;
4475     }
4476     case FOURCC_moov:
4477     {
4478       GstBuffer *moov = NULL;
4479
4480       if (qtdemux->got_moov) {
4481         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4482         qtdemux->offset = add_offset (qtdemux->offset, length);
4483         goto beach;
4484       }
4485
4486       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4487       if (ret != GST_FLOW_OK)
4488         goto beach;
4489       gst_buffer_map (moov, &map, GST_MAP_READ);
4490
4491       if (length != map.size) {
4492         /* Some files have a 'moov' atom at the end of the file which contains
4493          * a terminal 'free' atom where the body of the atom is missing.
4494          * Check for, and permit, this special case.
4495          */
4496         if (map.size >= 8) {
4497           guint8 *final_data = map.data + (map.size - 8);
4498           guint32 final_length = QT_UINT32 (final_data);
4499           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4500
4501           if (final_fourcc == FOURCC_free
4502               && map.size + final_length - 8 == length) {
4503             /* Ok, we've found that special case. Allocate a new buffer with
4504              * that free atom actually present. */
4505             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4506             gst_buffer_fill (newmoov, 0, map.data, map.size);
4507             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4508             gst_buffer_unmap (moov, &map);
4509             gst_buffer_unref (moov);
4510             moov = newmoov;
4511             gst_buffer_map (moov, &map, GST_MAP_READ);
4512           }
4513         }
4514       }
4515
4516       if (length != map.size) {
4517         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4518             (_("This file is incomplete and cannot be played.")),
4519             ("We got less than expected (received %" G_GSIZE_FORMAT
4520                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4521                 (guint) length, cur_offset));
4522         gst_buffer_unmap (moov, &map);
4523         gst_buffer_unref (moov);
4524         ret = GST_FLOW_ERROR;
4525         goto beach;
4526       }
4527       qtdemux->offset += length;
4528
4529       qtdemux_parse_moov (qtdemux, map.data, length);
4530       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4531
4532       qtdemux_parse_tree (qtdemux);
4533       if (qtdemux->moov_node_compressed) {
4534         g_node_destroy (qtdemux->moov_node_compressed);
4535         g_free (qtdemux->moov_node->data);
4536       }
4537       qtdemux->moov_node_compressed = NULL;
4538       g_node_destroy (qtdemux->moov_node);
4539       qtdemux->moov_node = NULL;
4540       gst_buffer_unmap (moov, &map);
4541       gst_buffer_unref (moov);
4542       qtdemux->got_moov = TRUE;
4543
4544       break;
4545     }
4546     case FOURCC_ftyp:
4547     {
4548       GstBuffer *ftyp = NULL;
4549
4550       /* extract major brand; might come in handy for ISO vs QT issues */
4551       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4552       if (ret != GST_FLOW_OK)
4553         goto beach;
4554       qtdemux->offset += length;
4555       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4556       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4557       gst_buffer_unmap (ftyp, &map);
4558       gst_buffer_unref (ftyp);
4559       break;
4560     }
4561     case FOURCC_uuid:
4562     {
4563       GstBuffer *uuid = NULL;
4564
4565       /* uuid are extension atoms */
4566       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4567       if (ret != GST_FLOW_OK)
4568         goto beach;
4569       qtdemux->offset += length;
4570       gst_buffer_map (uuid, &map, GST_MAP_READ);
4571       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4572       gst_buffer_unmap (uuid, &map);
4573       gst_buffer_unref (uuid);
4574       break;
4575     }
4576     case FOURCC_sidx:
4577     {
4578       GstBuffer *sidx = NULL;
4579       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4580       if (ret != GST_FLOW_OK)
4581         goto beach;
4582       qtdemux->offset += length;
4583       gst_buffer_map (sidx, &map, GST_MAP_READ);
4584       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4585       gst_buffer_unmap (sidx, &map);
4586       gst_buffer_unref (sidx);
4587       break;
4588     }
4589     default:
4590     {
4591       GstBuffer *unknown = NULL;
4592
4593       GST_LOG_OBJECT (qtdemux,
4594           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4595           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4596           cur_offset);
4597       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4598       if (ret != GST_FLOW_OK)
4599         goto beach;
4600       gst_buffer_map (unknown, &map, GST_MAP_READ);
4601       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4602       gst_buffer_unmap (unknown, &map);
4603       gst_buffer_unref (unknown);
4604       qtdemux->offset += length;
4605       break;
4606     }
4607   }
4608
4609 beach:
4610   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4611     /* digested all data, show what we have */
4612     qtdemux_prepare_streams (qtdemux);
4613     QTDEMUX_EXPOSE_LOCK (qtdemux);
4614     ret = qtdemux_expose_streams (qtdemux);
4615     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4616
4617     qtdemux->state = QTDEMUX_STATE_MOVIE;
4618     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4619         qtdemux->state);
4620     return ret;
4621   }
4622   return ret;
4623 }
4624
4625 /* Seeks to the previous keyframe of the indexed stream and
4626  * aligns other streams with respect to the keyframe timestamp
4627  * of indexed stream. Only called in case of Reverse Playback
4628  */
4629 static GstFlowReturn
4630 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4631 {
4632   guint32 seg_idx = 0, k_index = 0;
4633   guint32 ref_seg_idx, ref_k_index;
4634   GstClockTime k_pos = 0, last_stop = 0;
4635   QtDemuxSegment *seg = NULL;
4636   QtDemuxStream *ref_str = NULL;
4637   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4638   guint64 target_ts;
4639   gint i;
4640
4641   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4642    * and finally align all the other streams on that timestamp with their
4643    * respective keyframes */
4644   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4645     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4646
4647     /* No candidate yet, take the first stream */
4648     if (!ref_str) {
4649       ref_str = str;
4650       continue;
4651     }
4652
4653     /* So that stream has a segment, we prefer video streams */
4654     if (str->subtype == FOURCC_vide) {
4655       ref_str = str;
4656       break;
4657     }
4658   }
4659
4660   if (G_UNLIKELY (!ref_str)) {
4661     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4662     goto eos;
4663   }
4664
4665   if (G_UNLIKELY (!ref_str->from_sample)) {
4666     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4667     goto eos;
4668   }
4669
4670   /* So that stream has been playing from from_sample to to_sample. We will
4671    * get the timestamp of the previous sample and search for a keyframe before
4672    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4673   if (ref_str->subtype == FOURCC_vide) {
4674     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4675         ref_str->from_sample - 1, FALSE);
4676   } else {
4677     if (ref_str->from_sample >= 10)
4678       k_index = ref_str->from_sample - 10;
4679     else
4680       k_index = 0;
4681   }
4682
4683   target_ts =
4684       ref_str->samples[k_index].timestamp +
4685       ref_str->samples[k_index].pts_offset;
4686
4687   /* get current segment for that stream */
4688   seg = &ref_str->segments[ref_str->segment_index];
4689   /* Use segment start in original timescale for comparisons */
4690   seg_media_start_mov = seg->trak_media_start;
4691
4692   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4693       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4694       k_index, target_ts, seg_media_start_mov,
4695       GST_TIME_ARGS (seg->media_start));
4696
4697   /* Crawl back through segments to find the one containing this I frame */
4698   while (target_ts < seg_media_start_mov) {
4699     GST_DEBUG_OBJECT (qtdemux,
4700         "keyframe position (sample %u) is out of segment %u " " target %"
4701         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4702         ref_str->segment_index, target_ts, seg_media_start_mov);
4703
4704     if (G_UNLIKELY (!ref_str->segment_index)) {
4705       /* Reached first segment, let's consider it's EOS */
4706       goto eos;
4707     }
4708     ref_str->segment_index--;
4709     seg = &ref_str->segments[ref_str->segment_index];
4710     /* Use segment start in original timescale for comparisons */
4711     seg_media_start_mov = seg->trak_media_start;
4712   }
4713   /* Calculate time position of the keyframe and where we should stop */
4714   k_pos =
4715       QTSTREAMTIME_TO_GSTTIME (ref_str,
4716       target_ts - seg->trak_media_start) + seg->time;
4717   last_stop =
4718       QTSTREAMTIME_TO_GSTTIME (ref_str,
4719       ref_str->samples[ref_str->from_sample].timestamp -
4720       seg->trak_media_start) + seg->time;
4721
4722   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4723       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4724       k_index, GST_TIME_ARGS (k_pos));
4725
4726   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4727   qtdemux->segment.position = last_stop;
4728   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4729       GST_TIME_ARGS (last_stop));
4730
4731   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4732     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4733     goto eos;
4734   }
4735
4736   ref_seg_idx = ref_str->segment_index;
4737   ref_k_index = k_index;
4738
4739   /* Align them all on this */
4740   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4741     guint32 index = 0;
4742     GstClockTime seg_time = 0;
4743     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4744
4745     /* aligning reference stream again might lead to backing up to yet another
4746      * keyframe (due to timestamp rounding issues),
4747      * potentially putting more load on downstream; so let's try to avoid */
4748     if (str == ref_str) {
4749       seg_idx = ref_seg_idx;
4750       seg = &str->segments[seg_idx];
4751       k_index = ref_k_index;
4752       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4753           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4754     } else {
4755       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4756       GST_DEBUG_OBJECT (qtdemux,
4757           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4758           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4759
4760       /* get segment and time in the segment */
4761       seg = &str->segments[seg_idx];
4762       seg_time = k_pos - seg->time;
4763
4764       /* get the media time in the segment.
4765        * No adjustment for empty "filler" segments */
4766       if (seg->media_start != GST_CLOCK_TIME_NONE)
4767         seg_time += seg->media_start;
4768
4769       /* get the index of the sample with media time */
4770       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4771       GST_DEBUG_OBJECT (qtdemux,
4772           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4773           GST_TIME_ARGS (seg_time), index);
4774
4775       /* find previous keyframe */
4776       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4777     }
4778
4779     /* Remember until where we want to go */
4780     str->to_sample = str->from_sample - 1;
4781     /* Define our time position */
4782     target_ts =
4783         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4784     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4785     if (seg->media_start != GST_CLOCK_TIME_NONE)
4786       str->time_position -= seg->media_start;
4787
4788     /* Now seek back in time */
4789     gst_qtdemux_move_stream (qtdemux, str, k_index);
4790     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4791         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4792         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4793   }
4794
4795   return GST_FLOW_OK;
4796
4797 eos:
4798   return GST_FLOW_EOS;
4799 }
4800
4801 /*
4802  * Gets the current qt segment start, stop and position for the
4803  * given time offset. This is used in update_segment()
4804  */
4805 static void
4806 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4807     QtDemuxStream * stream, GstClockTime offset,
4808     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4809 {
4810   GstClockTime seg_time;
4811   GstClockTime start, stop, time;
4812   QtDemuxSegment *segment;
4813
4814   segment = &stream->segments[stream->segment_index];
4815
4816   /* get time in this segment */
4817   seg_time = (offset - segment->time) * segment->rate;
4818
4819   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4820       GST_TIME_ARGS (seg_time));
4821
4822   if (G_UNLIKELY (seg_time > segment->duration)) {
4823     GST_LOG_OBJECT (stream->pad,
4824         "seg_time > segment->duration %" GST_TIME_FORMAT,
4825         GST_TIME_ARGS (segment->duration));
4826     seg_time = segment->duration;
4827   }
4828
4829   /* qtdemux->segment.stop is in outside-time-realm, whereas
4830    * segment->media_stop is in track-time-realm.
4831    *
4832    * In order to compare the two, we need to bring segment.stop
4833    * into the track-time-realm
4834    *
4835    * FIXME - does this comment still hold? Don't see any conversion here */
4836
4837   stop = qtdemux->segment.stop;
4838   if (stop == GST_CLOCK_TIME_NONE)
4839     stop = qtdemux->segment.duration;
4840   if (stop == GST_CLOCK_TIME_NONE)
4841     stop = segment->media_stop;
4842   else
4843     stop =
4844         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4845
4846   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4847     start = segment->time + seg_time;
4848     time = offset;
4849     stop = start - seg_time + segment->duration;
4850   } else if (qtdemux->segment.rate >= 0) {
4851     start = MIN (segment->media_start + seg_time, stop);
4852     time = offset;
4853   } else {
4854     if (segment->media_start >= qtdemux->segment.start) {
4855       time = segment->time;
4856     } else {
4857       time = segment->time + (qtdemux->segment.start - segment->media_start);
4858     }
4859
4860     start = MAX (segment->media_start, qtdemux->segment.start);
4861     stop = MIN (segment->media_start + seg_time, stop);
4862   }
4863
4864   *_start = start;
4865   *_stop = stop;
4866   *_time = time;
4867 }
4868
4869 /*
4870  * Updates the qt segment used for the stream and pushes a new segment event
4871  * downstream on this stream's pad.
4872  */
4873 static gboolean
4874 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4875     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4876     GstClockTime * _stop)
4877 {
4878   QtDemuxSegment *segment;
4879   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4880   gdouble rate;
4881   GstEvent *event;
4882
4883   /* update the current segment */
4884   stream->segment_index = seg_idx;
4885
4886   /* get the segment */
4887   segment = &stream->segments[seg_idx];
4888
4889   if (G_UNLIKELY (offset < segment->time)) {
4890     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4891         GST_TIME_ARGS (segment->time));
4892     return FALSE;
4893   }
4894
4895   /* segment lies beyond total indicated duration */
4896   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4897           segment->time > qtdemux->segment.duration)) {
4898     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4899         " < segment->time %" GST_TIME_FORMAT,
4900         GST_TIME_ARGS (qtdemux->segment.duration),
4901         GST_TIME_ARGS (segment->time));
4902     return FALSE;
4903   }
4904
4905   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4906       &start, &stop, &time);
4907
4908   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4909       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4910       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4911
4912   /* combine global rate with that of the segment */
4913   rate = segment->rate * qtdemux->segment.rate;
4914
4915   /* Copy flags from main segment */
4916   stream->segment.flags = qtdemux->segment.flags;
4917
4918   /* update the segment values used for clipping */
4919   stream->segment.offset = qtdemux->segment.offset;
4920   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4921   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4922   stream->segment.rate = rate;
4923   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4924       stream->cslg_shift);
4925   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4926       stream->cslg_shift);
4927   stream->segment.time = time;
4928   stream->segment.position = stream->segment.start;
4929
4930   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4931       &stream->segment);
4932
4933   /* now prepare and send the segment */
4934   if (stream->pad) {
4935     event = gst_event_new_segment (&stream->segment);
4936     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4937       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4938     }
4939     gst_pad_push_event (stream->pad, event);
4940     /* assume we can send more data now */
4941     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4942     /* clear to send tags on this pad now */
4943     gst_qtdemux_push_tags (qtdemux, stream);
4944   }
4945
4946   if (_start)
4947     *_start = start;
4948   if (_stop)
4949     *_stop = stop;
4950
4951   return TRUE;
4952 }
4953
4954 /* activate the given segment number @seg_idx of @stream at time @offset.
4955  * @offset is an absolute global position over all the segments.
4956  *
4957  * This will push out a NEWSEGMENT event with the right values and
4958  * position the stream index to the first decodable sample before
4959  * @offset.
4960  */
4961 static gboolean
4962 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4963     guint32 seg_idx, GstClockTime offset)
4964 {
4965   QtDemuxSegment *segment;
4966   guint32 index, kf_index;
4967   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4968
4969   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4970       seg_idx, GST_TIME_ARGS (offset));
4971
4972   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4973           &start, &stop))
4974     return FALSE;
4975
4976   segment = &stream->segments[stream->segment_index];
4977
4978   /* in the fragmented case, we pick a fragment that starts before our
4979    * desired position and rely on downstream to wait for a keyframe
4980    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4981    * tfra entries tells us which trun/sample the key unit is in, but we don't
4982    * make use of this additional information at the moment) */
4983   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4984     stream->to_sample = G_MAXUINT32;
4985     return TRUE;
4986   } else {
4987     /* well, it will be taken care of below */
4988     qtdemux->fragmented_seek_pending = FALSE;
4989     /* FIXME ideally the do_fragmented_seek can be done right here,
4990      * rather than at loop level
4991      * (which might even allow handling edit lists in a fragmented file) */
4992   }
4993
4994   /* We don't need to look for a sample in push-based */
4995   if (!qtdemux->pullbased)
4996     return TRUE;
4997
4998   /* and move to the keyframe before the indicated media time of the
4999    * segment */
5000   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5001     if (qtdemux->segment.rate >= 0) {
5002       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5003       stream->to_sample = G_MAXUINT32;
5004       GST_DEBUG_OBJECT (stream->pad,
5005           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5006           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5007           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5008     } else {
5009       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5010       stream->to_sample = index;
5011       GST_DEBUG_OBJECT (stream->pad,
5012           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5013           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5014           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5015     }
5016   } else {
5017     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5018         "this is an empty segment");
5019     return TRUE;
5020   }
5021
5022   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5023    * encountered an error and printed a message so we return appropriately */
5024   if (index == -1)
5025     return FALSE;
5026
5027   /* we're at the right spot */
5028   if (index == stream->sample_index) {
5029     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5030     return TRUE;
5031   }
5032
5033   /* find keyframe of the target index */
5034   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5035
5036   /* go back two frames to provide lead-in for non-raw audio decoders */
5037   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5038     guint32 lead_in = 2;
5039     guint32 old_index = kf_index;
5040     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5041
5042     if (gst_structure_has_name (s, "audio/mpeg")) {
5043       gint mpegversion;
5044       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5045           && mpegversion == 1) {
5046         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5047         lead_in = 30;
5048       }
5049     }
5050
5051     kf_index = MAX (kf_index, lead_in) - lead_in;
5052     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5053       GST_DEBUG_OBJECT (stream->pad,
5054           "Moving backwards %u frames to ensure sufficient sound lead-in",
5055           old_index - kf_index);
5056     } else {
5057       kf_index = old_index;
5058     }
5059   }
5060
5061   /* if we move forwards, we don't have to go back to the previous
5062    * keyframe since we already sent that. We can also just jump to
5063    * the keyframe right before the target index if there is one. */
5064   if (index > stream->sample_index) {
5065     /* moving forwards check if we move past a keyframe */
5066     if (kf_index > stream->sample_index) {
5067       GST_DEBUG_OBJECT (stream->pad,
5068           "moving forwards to keyframe at %u "
5069           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5070           kf_index,
5071           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5072           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5073       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5074     } else {
5075       GST_DEBUG_OBJECT (stream->pad,
5076           "moving forwards, keyframe at %u "
5077           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5078           kf_index,
5079           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5080           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5081     }
5082   } else {
5083     GST_DEBUG_OBJECT (stream->pad,
5084         "moving backwards to %sframe at %u "
5085         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5086         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5087         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5088         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5089     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5090   }
5091
5092   return TRUE;
5093 }
5094
5095 /* prepare to get the current sample of @stream, getting essential values.
5096  *
5097  * This function will also prepare and send the segment when needed.
5098  *
5099  * Return FALSE if the stream is EOS.
5100  *
5101  * PULL-BASED
5102  */
5103 static gboolean
5104 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5105     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5106     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5107     gboolean * keyframe)
5108 {
5109   QtDemuxSample *sample;
5110   GstClockTime time_position;
5111   guint32 seg_idx;
5112
5113   g_return_val_if_fail (stream != NULL, FALSE);
5114
5115   time_position = stream->time_position;
5116   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5117     goto eos;
5118
5119   seg_idx = stream->segment_index;
5120   if (G_UNLIKELY (seg_idx == -1)) {
5121     /* find segment corresponding to time_position if we are looking
5122      * for a segment. */
5123     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5124   }
5125
5126   /* different segment, activate it, sample_index will be set. */
5127   if (G_UNLIKELY (stream->segment_index != seg_idx))
5128     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5129
5130   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5131               segments[stream->segment_index]))) {
5132     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5133
5134     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5135         " prepare empty sample");
5136
5137     *empty = TRUE;
5138     *pts = *dts = time_position;
5139     *duration = seg->duration - (time_position - seg->time);
5140
5141     return TRUE;
5142   }
5143
5144   *empty = FALSE;
5145
5146   if (stream->sample_index == -1)
5147     stream->sample_index = 0;
5148
5149   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5150       stream->sample_index, stream->n_samples);
5151
5152   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5153     if (!qtdemux->fragmented)
5154       goto eos;
5155
5156     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5157     do {
5158       GstFlowReturn flow;
5159
5160       GST_OBJECT_LOCK (qtdemux);
5161       flow = qtdemux_add_fragmented_samples (qtdemux);
5162       GST_OBJECT_UNLOCK (qtdemux);
5163
5164       if (flow != GST_FLOW_OK)
5165         goto eos;
5166     }
5167     while (stream->sample_index >= stream->n_samples);
5168   }
5169
5170   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5171     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5172         stream->sample_index);
5173     return FALSE;
5174   }
5175
5176   /* now get the info for the sample we're at */
5177   sample = &stream->samples[stream->sample_index];
5178
5179   *dts = QTSAMPLE_DTS (stream, sample);
5180   *pts = QTSAMPLE_PTS (stream, sample);
5181   *offset = sample->offset;
5182   *size = sample->size;
5183   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5184   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5185
5186   return TRUE;
5187
5188   /* special cases */
5189 eos:
5190   {
5191     stream->time_position = GST_CLOCK_TIME_NONE;
5192     return FALSE;
5193   }
5194 }
5195
5196 /* move to the next sample in @stream.
5197  *
5198  * Moves to the next segment when needed.
5199  */
5200 static void
5201 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5202 {
5203   QtDemuxSample *sample;
5204   QtDemuxSegment *segment;
5205
5206   /* get current segment */
5207   segment = &stream->segments[stream->segment_index];
5208
5209   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5210     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5211     goto next_segment;
5212   }
5213
5214   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5215     /* Mark the stream as EOS */
5216     GST_DEBUG_OBJECT (qtdemux,
5217         "reached max allowed sample %u, mark EOS", stream->to_sample);
5218     stream->time_position = GST_CLOCK_TIME_NONE;
5219     return;
5220   }
5221
5222   /* move to next sample */
5223   stream->sample_index++;
5224   stream->offset_in_sample = 0;
5225
5226   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5227       stream->n_samples);
5228
5229   /* reached the last sample, we need the next segment */
5230   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5231     goto next_segment;
5232
5233   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5234     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5235         stream->sample_index);
5236     return;
5237   }
5238
5239   /* get next sample */
5240   sample = &stream->samples[stream->sample_index];
5241
5242   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5243       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5244       GST_TIME_ARGS (segment->media_stop));
5245
5246   /* see if we are past the segment */
5247   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5248     goto next_segment;
5249
5250   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5251     /* inside the segment, update time_position, looks very familiar to
5252      * GStreamer segments, doesn't it? */
5253     stream->time_position =
5254         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5255   } else {
5256     /* not yet in segment, time does not yet increment. This means
5257      * that we are still prerolling keyframes to the decoder so it can
5258      * decode the first sample of the segment. */
5259     stream->time_position = segment->time;
5260   }
5261   return;
5262
5263   /* move to the next segment */
5264 next_segment:
5265   {
5266     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5267
5268     if (stream->segment_index == stream->n_segments - 1) {
5269       /* are we at the end of the last segment, we're EOS */
5270       stream->time_position = GST_CLOCK_TIME_NONE;
5271     } else {
5272       /* else we're only at the end of the current segment */
5273       stream->time_position = segment->stop_time;
5274     }
5275     /* make sure we select a new segment */
5276
5277     /* accumulate previous segments */
5278     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5279       stream->accumulated_base +=
5280           (stream->segment.stop -
5281           stream->segment.start) / ABS (stream->segment.rate);
5282
5283     stream->segment_index = -1;
5284   }
5285 }
5286
5287 static void
5288 gst_qtdemux_sync_streams (GstQTDemux * demux)
5289 {
5290   gint i;
5291
5292   if (QTDEMUX_N_STREAMS (demux) <= 1)
5293     return;
5294
5295   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5296     QtDemuxStream *stream;
5297     GstClockTime end_time;
5298
5299     stream = QTDEMUX_NTH_STREAM (demux, i);
5300
5301     if (!stream->pad)
5302       continue;
5303
5304     /* TODO advance time on subtitle streams here, if any some day */
5305
5306     /* some clips/trailers may have unbalanced streams at the end,
5307      * so send EOS on shorter stream to prevent stalling others */
5308
5309     /* do not mess with EOS if SEGMENT seeking */
5310     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5311       continue;
5312
5313     if (demux->pullbased) {
5314       /* loop mode is sample time based */
5315       if (!STREAM_IS_EOS (stream))
5316         continue;
5317     } else {
5318       /* push mode is byte position based */
5319       if (stream->n_samples &&
5320           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5321         continue;
5322     }
5323
5324     if (stream->sent_eos)
5325       continue;
5326
5327     /* only act if some gap */
5328     end_time = stream->segments[stream->n_segments - 1].stop_time;
5329     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5330         ", stream end: %" GST_TIME_FORMAT,
5331         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5332     if (GST_CLOCK_TIME_IS_VALID (end_time)
5333         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5334       GstEvent *event;
5335
5336       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5337           GST_PAD_NAME (stream->pad));
5338       stream->sent_eos = TRUE;
5339       event = gst_event_new_eos ();
5340       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5341         gst_event_set_seqnum (event, demux->segment_seqnum);
5342       gst_pad_push_event (stream->pad, event);
5343     }
5344   }
5345 }
5346
5347 /* EOS and NOT_LINKED need to be combined. This means that we return:
5348  *
5349  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5350  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5351  */
5352 static GstFlowReturn
5353 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5354     GstFlowReturn ret)
5355 {
5356   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5357
5358   if (stream->pad)
5359     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5360         ret);
5361   else
5362     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5363
5364   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5365   return ret;
5366 }
5367
5368 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5369  * completely clipped
5370  *
5371  * Should be used only with raw buffers */
5372 static GstBuffer *
5373 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5374     GstBuffer * buf)
5375 {
5376   guint64 start, stop, cstart, cstop, diff;
5377   GstClockTime pts, duration;
5378   gsize size, osize;
5379   gint num_rate, denom_rate;
5380   gint frame_size;
5381   gboolean clip_data;
5382   guint offset;
5383
5384   osize = size = gst_buffer_get_size (buf);
5385   offset = 0;
5386
5387   /* depending on the type, setup the clip parameters */
5388   if (stream->subtype == FOURCC_soun) {
5389     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5390     num_rate = GST_SECOND;
5391     denom_rate = (gint) CUR_STREAM (stream)->rate;
5392     clip_data = TRUE;
5393   } else if (stream->subtype == FOURCC_vide) {
5394     frame_size = size;
5395     num_rate = CUR_STREAM (stream)->fps_n;
5396     denom_rate = CUR_STREAM (stream)->fps_d;
5397     clip_data = FALSE;
5398   } else
5399     goto wrong_type;
5400
5401   if (frame_size <= 0)
5402     goto bad_frame_size;
5403
5404   /* we can only clip if we have a valid pts */
5405   pts = GST_BUFFER_PTS (buf);
5406   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5407     goto no_pts;
5408
5409   duration = GST_BUFFER_DURATION (buf);
5410
5411   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5412     duration =
5413         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5414   }
5415
5416   start = pts;
5417   stop = start + duration;
5418
5419   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5420               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5421     goto clipped;
5422
5423   /* see if some clipping happened */
5424   diff = cstart - start;
5425   if (diff > 0) {
5426     pts += diff;
5427     duration -= diff;
5428
5429     if (clip_data) {
5430       /* bring clipped time to samples and to bytes */
5431       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5432       diff *= frame_size;
5433
5434       GST_DEBUG_OBJECT (qtdemux,
5435           "clipping start to %" GST_TIME_FORMAT " %"
5436           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5437
5438       offset = diff;
5439       size -= diff;
5440     }
5441   }
5442   diff = stop - cstop;
5443   if (diff > 0) {
5444     duration -= diff;
5445
5446     if (clip_data) {
5447       /* bring clipped time to samples and then to bytes */
5448       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5449       diff *= frame_size;
5450       GST_DEBUG_OBJECT (qtdemux,
5451           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5452           " bytes", GST_TIME_ARGS (cstop), diff);
5453       size -= diff;
5454     }
5455   }
5456
5457   if (offset != 0 || size != osize)
5458     gst_buffer_resize (buf, offset, size);
5459
5460   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5461   GST_BUFFER_PTS (buf) = pts;
5462   GST_BUFFER_DURATION (buf) = duration;
5463
5464   return buf;
5465
5466   /* dropped buffer */
5467 wrong_type:
5468   {
5469     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5470     return buf;
5471   }
5472 bad_frame_size:
5473   {
5474     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5475     return buf;
5476   }
5477 no_pts:
5478   {
5479     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5480     return buf;
5481   }
5482 clipped:
5483   {
5484     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5485     gst_buffer_unref (buf);
5486     return NULL;
5487   }
5488 }
5489
5490 static GstBuffer *
5491 gst_qtdemux_align_buffer (GstQTDemux * demux,
5492     GstBuffer * buffer, gsize alignment)
5493 {
5494   GstMapInfo map;
5495
5496   gst_buffer_map (buffer, &map, GST_MAP_READ);
5497
5498   if (map.size < sizeof (guintptr)) {
5499     gst_buffer_unmap (buffer, &map);
5500     return buffer;
5501   }
5502
5503   if (((guintptr) map.data) & (alignment - 1)) {
5504     GstBuffer *new_buffer;
5505     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5506
5507     new_buffer = gst_buffer_new_allocate (NULL,
5508         gst_buffer_get_size (buffer), &params);
5509
5510     /* Copy data "by hand", so ensure alignment is kept: */
5511     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5512
5513     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5514     GST_DEBUG_OBJECT (demux,
5515         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5516         alignment);
5517
5518     gst_buffer_unmap (buffer, &map);
5519     gst_buffer_unref (buffer);
5520
5521     return new_buffer;
5522   }
5523
5524   gst_buffer_unmap (buffer, &map);
5525   return buffer;
5526 }
5527
5528 static guint8 *
5529 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5530     gsize * res)
5531 {
5532   guint8 *storage;
5533   gsize i;
5534
5535   /* We are converting from pairs to triplets */
5536   *res = ccpair_size / 2 * 3;
5537   storage = g_malloc (*res);
5538   for (i = 0; i * 2 < ccpair_size; i += 1) {
5539     /* FIXME: Use line offset 0 as we simply can't know here */
5540     if (field == 1)
5541       storage[i * 3] = 0x80 | 0x00;
5542     else
5543       storage[i * 3] = 0x00 | 0x00;
5544     storage[i * 3 + 1] = ccpair[i * 2];
5545     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5546   }
5547
5548   return storage;
5549 }
5550
5551 static guint8 *
5552 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5553     gsize * cclen)
5554 {
5555   guint8 *res = NULL;
5556   guint32 atom_length, fourcc;
5557   QtDemuxStreamStsdEntry *stsd_entry;
5558
5559   GST_MEMDUMP ("caption atom", data, size);
5560
5561   /* There might be multiple atoms */
5562
5563   *cclen = 0;
5564   if (size < 8)
5565     goto invalid_cdat;
5566   atom_length = QT_UINT32 (data);
5567   fourcc = QT_FOURCC (data + 4);
5568   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5569     goto invalid_cdat;
5570
5571   GST_DEBUG_OBJECT (stream->pad, "here");
5572
5573   /* Check if we have something compatible */
5574   stsd_entry = CUR_STREAM (stream);
5575   switch (stsd_entry->fourcc) {
5576     case FOURCC_c608:{
5577       guint8 *cdat = NULL, *cdt2 = NULL;
5578       gsize cdat_size = 0, cdt2_size = 0;
5579       /* Should be cdat or cdt2 */
5580       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5581         GST_WARNING_OBJECT (stream->pad,
5582             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5583             GST_FOURCC_ARGS (fourcc));
5584         goto invalid_cdat;
5585       }
5586
5587       /* Convert to S334-1 Annex A byte triplet */
5588       if (fourcc == FOURCC_cdat)
5589         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5590       else
5591         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5592       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5593           size, atom_length);
5594
5595       /* Check for another atom ? */
5596       if (size > atom_length + 8) {
5597         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5598         if (size >= atom_length + new_atom_length) {
5599           fourcc = QT_FOURCC (data + atom_length + 4);
5600           if (fourcc == FOURCC_cdat) {
5601             if (cdat == NULL)
5602               cdat =
5603                   convert_to_s334_1a (data + atom_length + 8,
5604                   new_atom_length - 8, 1, &cdat_size);
5605             else
5606               GST_WARNING_OBJECT (stream->pad,
5607                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5608           } else {
5609             if (cdt2 == NULL)
5610               cdt2 =
5611                   convert_to_s334_1a (data + atom_length + 8,
5612                   new_atom_length - 8, 2, &cdt2_size);
5613             else
5614               GST_WARNING_OBJECT (stream->pad,
5615                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5616           }
5617         }
5618       }
5619
5620       *cclen = cdat_size + cdt2_size;
5621       res = g_malloc (*cclen);
5622       if (cdat_size)
5623         memcpy (res, cdat, cdat_size);
5624       if (cdt2_size)
5625         memcpy (res + cdat_size, cdt2, cdt2_size);
5626       g_free (cdat);
5627       g_free (cdt2);
5628     }
5629       break;
5630     case FOURCC_c708:
5631       if (fourcc != FOURCC_ccdp) {
5632         GST_WARNING_OBJECT (stream->pad,
5633             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5634             GST_FOURCC_ARGS (fourcc));
5635         goto invalid_cdat;
5636       }
5637       *cclen = atom_length - 8;
5638       res = g_memdup2 (data + 8, *cclen);
5639       break;
5640     default:
5641       /* Keep this here in case other closed caption formats are added */
5642       g_assert_not_reached ();
5643       break;
5644   }
5645
5646   GST_MEMDUMP ("Output", res, *cclen);
5647   return res;
5648
5649   /* Errors */
5650 invalid_cdat:
5651   GST_WARNING ("[cdat] atom is too small or invalid");
5652   return NULL;
5653 }
5654
5655 /* the input buffer metadata must be writable,
5656  * but time/duration etc not yet set and need not be preserved */
5657 static GstBuffer *
5658 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5659     GstBuffer * buf)
5660 {
5661   GstMapInfo map;
5662   guint nsize = 0;
5663   gchar *str;
5664
5665   /* not many cases for now */
5666   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5667     /* send a one time dvd clut event */
5668     if (stream->pending_event && stream->pad)
5669       gst_pad_push_event (stream->pad, stream->pending_event);
5670     stream->pending_event = NULL;
5671   }
5672
5673   if (G_UNLIKELY (stream->subtype != FOURCC_text
5674           && stream->subtype != FOURCC_sbtl &&
5675           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5676     return buf;
5677   }
5678
5679   gst_buffer_map (buf, &map, GST_MAP_READ);
5680
5681   /* empty buffer is sent to terminate previous subtitle */
5682   if (map.size <= 2) {
5683     gst_buffer_unmap (buf, &map);
5684     gst_buffer_unref (buf);
5685     return NULL;
5686   }
5687   if (stream->subtype == FOURCC_subp) {
5688     /* That's all the processing needed for subpictures */
5689     gst_buffer_unmap (buf, &map);
5690     return buf;
5691   }
5692
5693   if (stream->subtype == FOURCC_clcp) {
5694     guint8 *cc;
5695     gsize cclen = 0;
5696     /* For closed caption, we need to extract the information from the
5697      * [cdat],[cdt2] or [ccdp] atom */
5698     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5699     gst_buffer_unmap (buf, &map);
5700     gst_buffer_unref (buf);
5701     if (cc) {
5702       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5703     } else {
5704       /* Conversion failed or there's nothing */
5705       buf = NULL;
5706     }
5707     return buf;
5708   }
5709
5710   nsize = GST_READ_UINT16_BE (map.data);
5711   nsize = MIN (nsize, map.size - 2);
5712
5713   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5714       nsize, map.size);
5715
5716   /* takes care of UTF-8 validation or UTF-16 recognition,
5717    * no other encoding expected */
5718   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5719   gst_buffer_unmap (buf, &map);
5720   if (str) {
5721     gst_buffer_unref (buf);
5722     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5723   } else {
5724     /* this should not really happen unless the subtitle is corrupted */
5725     gst_buffer_unref (buf);
5726     buf = NULL;
5727   }
5728
5729   /* FIXME ? convert optional subsequent style info to markup */
5730
5731   return buf;
5732 }
5733
5734 static GstFlowReturn
5735 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5736     GstBuffer * buf)
5737 {
5738   GstFlowReturn ret = GST_FLOW_OK;
5739   GstClockTime pts, duration;
5740
5741   if (stream->need_clip)
5742     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5743
5744   if (G_UNLIKELY (buf == NULL))
5745     goto exit;
5746
5747   if (G_UNLIKELY (stream->discont)) {
5748     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5749     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5750     stream->discont = FALSE;
5751   } else {
5752     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5753   }
5754
5755   GST_LOG_OBJECT (qtdemux,
5756       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5757       ", duration %" GST_TIME_FORMAT " on pad %s",
5758       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5759       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5760       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5761
5762   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5763     GstStructure *crypto_info;
5764     QtDemuxAavdEncryptionInfo *info =
5765         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5766
5767     crypto_info = gst_structure_copy (info->default_properties);
5768     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5769       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5770   }
5771
5772   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5773           || stream->protection_scheme_type == FOURCC_cbcs)) {
5774     GstStructure *crypto_info;
5775     QtDemuxCencSampleSetInfo *info =
5776         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5777     gint index;
5778     GstEvent *event;
5779
5780     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5781       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5782           GST_PTR_FORMAT, event);
5783       gst_pad_push_event (stream->pad, event);
5784     }
5785
5786     if (info->crypto_info == NULL) {
5787       if (stream->protection_scheme_type == FOURCC_cbcs) {
5788         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5789         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5790           GST_ERROR_OBJECT (qtdemux,
5791               "failed to attach cbcs metadata to buffer");
5792           qtdemux_gst_structure_free (crypto_info);
5793         } else {
5794           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5795         }
5796       } else {
5797         GST_DEBUG_OBJECT (qtdemux,
5798             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5799       }
5800     } else {
5801       /* The end of the crypto_info array matches our n_samples position,
5802        * so count backward from there */
5803       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5804       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5805         /* steal structure from array */
5806         crypto_info = g_ptr_array_index (info->crypto_info, index);
5807         g_ptr_array_index (info->crypto_info, index) = NULL;
5808         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5809             info->crypto_info->len);
5810         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5811           GST_ERROR_OBJECT (qtdemux,
5812               "failed to attach cenc metadata to buffer");
5813       } else {
5814         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5815             index, stream->sample_index);
5816       }
5817     }
5818   }
5819
5820   if (stream->alignment > 1)
5821     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5822
5823   pts = GST_BUFFER_PTS (buf);
5824   duration = GST_BUFFER_DURATION (buf);
5825
5826   ret = gst_pad_push (stream->pad, buf);
5827
5828   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5829     /* mark position in stream, we'll need this to know when to send GAP event */
5830     stream->segment.position = pts + duration;
5831   }
5832
5833 exit:
5834
5835   return ret;
5836 }
5837
5838 static GstFlowReturn
5839 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5840     GstBuffer * buf)
5841 {
5842   GstFlowReturn ret = GST_FLOW_OK;
5843
5844   if (stream->subtype == FOURCC_clcp
5845       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5846     GstMapInfo map;
5847     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5848     guint n_triplets, i;
5849     guint field1_off = 0, field2_off = 0;
5850
5851     /* We have to split CEA608 buffers so that each outgoing buffer contains
5852      * one byte pair per field according to the framerate of the video track.
5853      *
5854      * If there is only a single byte pair per field we don't have to do
5855      * anything
5856      */
5857
5858     gst_buffer_map (buf, &map, GST_MAP_READ);
5859
5860     n_triplets = map.size / 3;
5861     for (i = 0; i < n_triplets; i++) {
5862       if (map.data[3 * i] & 0x80)
5863         n_field1++;
5864       else
5865         n_field2++;
5866     }
5867
5868     g_assert (n_field1 || n_field2);
5869
5870     /* If there's more than 1 frame we have to split, otherwise we can just
5871      * pass through */
5872     if (n_field1 > 1 || n_field2 > 1) {
5873       n_output_buffers =
5874           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5875           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5876
5877       for (i = 0; i < n_output_buffers; i++) {
5878         GstBuffer *outbuf =
5879             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5880         GstMapInfo outmap;
5881         guint8 *outptr;
5882
5883         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5884         outptr = outmap.data;
5885
5886         if (n_field1) {
5887           gboolean found = FALSE;
5888
5889           while (map.data + field1_off < map.data + map.size) {
5890             if (map.data[field1_off] & 0x80) {
5891               memcpy (outptr, &map.data[field1_off], 3);
5892               field1_off += 3;
5893               found = TRUE;
5894               break;
5895             }
5896             field1_off += 3;
5897           }
5898
5899           if (!found) {
5900             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5901
5902             memcpy (outptr, empty, 3);
5903           }
5904
5905           outptr += 3;
5906         }
5907
5908         if (n_field2) {
5909           gboolean found = FALSE;
5910
5911           while (map.data + field2_off < map.data + map.size) {
5912             if ((map.data[field2_off] & 0x80) == 0) {
5913               memcpy (outptr, &map.data[field2_off], 3);
5914               field2_off += 3;
5915               found = TRUE;
5916               break;
5917             }
5918             field2_off += 3;
5919           }
5920
5921           if (!found) {
5922             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5923
5924             memcpy (outptr, empty, 3);
5925           }
5926
5927           outptr += 3;
5928         }
5929
5930         gst_buffer_unmap (outbuf, &outmap);
5931
5932         GST_BUFFER_PTS (outbuf) =
5933             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5934             GST_SECOND * CUR_STREAM (stream)->fps_d,
5935             CUR_STREAM (stream)->fps_n);
5936         GST_BUFFER_DURATION (outbuf) =
5937             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5938             CUR_STREAM (stream)->fps_n);
5939         GST_BUFFER_OFFSET (outbuf) = -1;
5940         GST_BUFFER_OFFSET_END (outbuf) = -1;
5941
5942         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
5943
5944         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
5945           break;
5946       }
5947       gst_buffer_unmap (buf, &map);
5948       gst_buffer_unref (buf);
5949     } else {
5950       gst_buffer_unmap (buf, &map);
5951       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5952     }
5953   } else {
5954     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5955   }
5956
5957   return ret;
5958 }
5959
5960 /* Sets a buffer's attributes properly and pushes it downstream.
5961  * Also checks for additional actions and custom processing that may
5962  * need to be done first.
5963  */
5964 static GstFlowReturn
5965 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5966     QtDemuxStream * stream, GstBuffer * buf,
5967     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5968     gboolean keyframe, GstClockTime position, guint64 byte_position)
5969 {
5970   GstFlowReturn ret = GST_FLOW_OK;
5971
5972   /* offset the timestamps according to the edit list */
5973
5974   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5975     gchar *url;
5976     GstMapInfo map;
5977
5978     gst_buffer_map (buf, &map, GST_MAP_READ);
5979     url = g_strndup ((gchar *) map.data, map.size);
5980     gst_buffer_unmap (buf, &map);
5981     if (url != NULL && strlen (url) != 0) {
5982       /* we have RTSP redirect now */
5983       g_free (qtdemux->redirect_location);
5984       qtdemux->redirect_location = g_strdup (url);
5985       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5986           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5987               gst_structure_new ("redirect",
5988                   "new-location", G_TYPE_STRING, url, NULL)));
5989     } else {
5990       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5991           "posting");
5992     }
5993     g_free (url);
5994   }
5995
5996   /* position reporting */
5997   if (qtdemux->segment.rate >= 0) {
5998     qtdemux->segment.position = position;
5999     gst_qtdemux_sync_streams (qtdemux);
6000   }
6001
6002   if (G_UNLIKELY (!stream->pad)) {
6003     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6004     gst_buffer_unref (buf);
6005     goto exit;
6006   }
6007
6008   /* send out pending buffers */
6009   while (stream->buffers) {
6010     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6011
6012     if (G_UNLIKELY (stream->discont)) {
6013       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6014       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6015       stream->discont = FALSE;
6016     } else {
6017       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6018     }
6019
6020     if (stream->alignment > 1)
6021       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6022     gst_pad_push (stream->pad, buffer);
6023
6024     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6025   }
6026
6027   /* we're going to modify the metadata */
6028   buf = gst_buffer_make_writable (buf);
6029
6030   if (G_UNLIKELY (stream->need_process))
6031     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
6032
6033   if (!buf) {
6034     goto exit;
6035   }
6036
6037   GST_BUFFER_DTS (buf) = dts;
6038   GST_BUFFER_PTS (buf) = pts;
6039   GST_BUFFER_DURATION (buf) = duration;
6040   GST_BUFFER_OFFSET (buf) = -1;
6041   GST_BUFFER_OFFSET_END (buf) = -1;
6042
6043   if (!keyframe) {
6044     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6045     stream->on_keyframe = FALSE;
6046   } else {
6047     stream->on_keyframe = TRUE;
6048   }
6049
6050   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6051     gst_buffer_append_memory (buf,
6052         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6053
6054   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6055     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6056   }
6057 #if 0
6058   if (G_UNLIKELY (qtdemux->element_index)) {
6059     GstClockTime stream_time;
6060
6061     stream_time =
6062         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6063         timestamp);
6064     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6065       GST_LOG_OBJECT (qtdemux,
6066           "adding association %" GST_TIME_FORMAT "-> %"
6067           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6068       gst_index_add_association (qtdemux->element_index,
6069           qtdemux->index_id,
6070           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6071           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6072           GST_FORMAT_BYTES, byte_position, NULL);
6073     }
6074   }
6075 #endif
6076
6077   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6078
6079 exit:
6080   return ret;
6081 }
6082
6083 static const QtDemuxRandomAccessEntry *
6084 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6085     GstClockTime pos, gboolean after)
6086 {
6087   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6088   guint n_entries = stream->n_ra_entries;
6089   guint i;
6090
6091   /* we assume the table is sorted */
6092   for (i = 0; i < n_entries; ++i) {
6093     if (entries[i].ts > pos)
6094       break;
6095   }
6096
6097   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6098    * probably okay to assume that the index lists the very first fragment */
6099   if (i == 0)
6100     return &entries[0];
6101
6102   if (after)
6103     return &entries[i];
6104   else
6105     return &entries[i - 1];
6106 }
6107
6108 static gboolean
6109 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6110 {
6111   const QtDemuxRandomAccessEntry *best_entry = NULL;
6112   gint i;
6113
6114   GST_OBJECT_LOCK (qtdemux);
6115
6116   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6117
6118   /* first see if we can determine where to go to using mfra,
6119    * before we start clearing things */
6120   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6121     const QtDemuxRandomAccessEntry *entry;
6122     QtDemuxStream *stream;
6123     gboolean is_audio_or_video;
6124
6125     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6126
6127     if (stream->ra_entries == NULL)
6128       continue;
6129
6130     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6131       is_audio_or_video = TRUE;
6132     else
6133       is_audio_or_video = FALSE;
6134
6135     entry =
6136         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6137         stream->time_position, !is_audio_or_video);
6138
6139     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6140         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6141
6142     stream->pending_seek = entry;
6143
6144     /* decide position to jump to just based on audio/video tracks, not subs */
6145     if (!is_audio_or_video)
6146       continue;
6147
6148     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6149       best_entry = entry;
6150   }
6151
6152   /* no luck, will handle seek otherwise */
6153   if (best_entry == NULL) {
6154     GST_OBJECT_UNLOCK (qtdemux);
6155     return FALSE;
6156   }
6157
6158   /* ok, now we can prepare for processing as of located moof */
6159   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6160     QtDemuxStream *stream;
6161
6162     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6163
6164     g_free (stream->samples);
6165     stream->samples = NULL;
6166     stream->n_samples = 0;
6167     stream->stbl_index = -1;    /* no samples have yet been parsed */
6168     stream->sample_index = -1;
6169
6170     if (stream->protection_scheme_info) {
6171       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6172       if (stream->protection_scheme_type == FOURCC_cenc
6173           || stream->protection_scheme_type == FOURCC_cbcs) {
6174         QtDemuxCencSampleSetInfo *info =
6175             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6176         if (info->crypto_info) {
6177           g_ptr_array_free (info->crypto_info, TRUE);
6178           info->crypto_info = NULL;
6179         }
6180       }
6181     }
6182   }
6183
6184   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6185       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6186       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6187       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6188
6189   qtdemux->moof_offset = best_entry->moof_offset;
6190
6191   qtdemux_add_fragmented_samples (qtdemux);
6192
6193   GST_OBJECT_UNLOCK (qtdemux);
6194   return TRUE;
6195 }
6196
6197 static GstFlowReturn
6198 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6199 {
6200   GstFlowReturn ret = GST_FLOW_OK;
6201   GstBuffer *buf = NULL;
6202   QtDemuxStream *stream, *target_stream = NULL;
6203   GstClockTime min_time;
6204   guint64 offset = 0;
6205   GstClockTime dts = GST_CLOCK_TIME_NONE;
6206   GstClockTime pts = GST_CLOCK_TIME_NONE;
6207   GstClockTime duration = 0;
6208   gboolean keyframe = FALSE;
6209   guint sample_size = 0;
6210   guint num_samples = 1;
6211   gboolean empty = 0;
6212   guint size;
6213   gint i;
6214
6215   if (qtdemux->fragmented_seek_pending) {
6216     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6217     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6218       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6219       qtdemux->fragmented_seek_pending = FALSE;
6220     } else {
6221       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6222     }
6223   }
6224
6225   /* Figure out the next stream sample to output, min_time is expressed in
6226    * global time and runs over the edit list segments. */
6227   min_time = G_MAXUINT64;
6228   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6229     GstClockTime position;
6230
6231     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6232     position = stream->time_position;
6233
6234     if (!GST_CLOCK_TIME_IS_VALID (position))
6235       continue;
6236
6237     if (stream->segment_index != -1) {
6238       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6239       position += segment->media_start;
6240     }
6241
6242     /* position of -1 is EOS */
6243     if (position < min_time) {
6244       min_time = position;
6245       target_stream = stream;
6246     }
6247   }
6248   /* all are EOS */
6249   if (G_UNLIKELY (target_stream == NULL)) {
6250     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6251     goto eos;
6252   }
6253
6254   /* check for segment end */
6255   if (G_UNLIKELY (qtdemux->segment.stop != -1
6256           && qtdemux->segment.rate >= 0
6257           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6258     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6259     target_stream->time_position = GST_CLOCK_TIME_NONE;
6260     goto eos_stream;
6261   }
6262
6263   /* gap events for subtitle streams */
6264   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6265     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6266     if (stream->pad) {
6267       GstClockTime gap_threshold;
6268
6269       /* Only send gap events on non-subtitle streams if lagging way behind. */
6270       if (stream->subtype == FOURCC_subp
6271           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)
6272         gap_threshold = 1 * GST_SECOND;
6273       else
6274         gap_threshold = 3 * GST_SECOND;
6275
6276       /* send gap events until the stream catches up */
6277       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6278       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6279           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6280           stream->segment.position + gap_threshold < min_time) {
6281         GstEvent *gap =
6282             gst_event_new_gap (stream->segment.position, gap_threshold);
6283         gst_pad_push_event (stream->pad, gap);
6284         stream->segment.position += gap_threshold;
6285       }
6286     }
6287   }
6288
6289   stream = target_stream;
6290   /* fetch info for the current sample of this stream */
6291   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6292               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6293     goto eos_stream;
6294
6295   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6296   if (stream->new_caps) {
6297     gst_qtdemux_configure_stream (qtdemux, stream);
6298     qtdemux_do_allocation (stream, qtdemux);
6299   }
6300
6301   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6302   if (G_UNLIKELY (qtdemux->segment.
6303           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6304     if (stream->subtype == FOURCC_vide) {
6305       if (!keyframe) {
6306         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6307             stream->track_id);
6308         goto next;
6309       } else if (qtdemux->trickmode_interval > 0) {
6310         GstClockTimeDiff interval;
6311
6312         if (qtdemux->segment.rate > 0)
6313           interval = stream->time_position - stream->last_keyframe_dts;
6314         else
6315           interval = stream->last_keyframe_dts - stream->time_position;
6316
6317         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6318             && interval < qtdemux->trickmode_interval) {
6319           GST_LOG_OBJECT (qtdemux,
6320               "Skipping keyframe within interval on track-id %u",
6321               stream->track_id);
6322           goto next;
6323         } else {
6324           stream->last_keyframe_dts = stream->time_position;
6325         }
6326       }
6327     }
6328   }
6329
6330   GST_DEBUG_OBJECT (qtdemux,
6331       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6332       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6333       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6334       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6335       GST_TIME_ARGS (duration));
6336
6337   if (G_UNLIKELY (empty)) {
6338     /* empty segment, push a gap if there's a second or more
6339      * difference and move to the next one */
6340     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6341       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6342     stream->segment.position = pts + duration;
6343     goto next;
6344   }
6345
6346   /* hmm, empty sample, skip and move to next sample */
6347   if (G_UNLIKELY (sample_size <= 0))
6348     goto next;
6349
6350   /* last pushed sample was out of boundary, goto next sample */
6351   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6352     goto next;
6353
6354   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6355     GST_DEBUG_OBJECT (qtdemux,
6356         "size %d larger than stream max_buffer_size %d, trimming",
6357         sample_size, stream->max_buffer_size);
6358     size =
6359         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6360   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6361       && sample_size < stream->min_buffer_size) {
6362     guint start_sample_index = stream->sample_index;
6363     guint accumulated_size = sample_size;
6364     guint64 expected_next_offset = offset + sample_size;
6365
6366     GST_DEBUG_OBJECT (qtdemux,
6367         "size %d smaller than stream min_buffer_size %d, combining with the next",
6368         sample_size, stream->min_buffer_size);
6369
6370     while (stream->sample_index < stream->to_sample
6371         && stream->sample_index + 1 < stream->n_samples) {
6372       const QtDemuxSample *next_sample;
6373
6374       /* Increment temporarily */
6375       stream->sample_index++;
6376
6377       /* Failed to parse sample so let's go back to the previous one that was
6378        * still successful */
6379       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6380         stream->sample_index--;
6381         break;
6382       }
6383
6384       next_sample = &stream->samples[stream->sample_index];
6385
6386       /* Not contiguous with the previous sample so let's go back to the
6387        * previous one that was still successful */
6388       if (next_sample->offset != expected_next_offset) {
6389         stream->sample_index--;
6390         break;
6391       }
6392
6393       accumulated_size += next_sample->size;
6394       expected_next_offset += next_sample->size;
6395       if (accumulated_size >= stream->min_buffer_size)
6396         break;
6397     }
6398
6399     num_samples = stream->sample_index + 1 - start_sample_index;
6400     stream->sample_index = start_sample_index;
6401     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6402         num_samples, accumulated_size);
6403     size = accumulated_size;
6404   } else {
6405     size = sample_size;
6406   }
6407
6408   if (qtdemux->cenc_aux_info_offset > 0) {
6409     GstMapInfo map;
6410     GstByteReader br;
6411     GstBuffer *aux_info = NULL;
6412
6413     /* pull the data stored before the sample */
6414     ret =
6415         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6416         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6417     if (G_UNLIKELY (ret != GST_FLOW_OK))
6418       goto beach;
6419     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6420     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6421     gst_byte_reader_init (&br, map.data + 8, map.size);
6422     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6423             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6424       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6425       gst_buffer_unmap (aux_info, &map);
6426       gst_buffer_unref (aux_info);
6427       ret = GST_FLOW_ERROR;
6428       goto beach;
6429     }
6430     gst_buffer_unmap (aux_info, &map);
6431     gst_buffer_unref (aux_info);
6432   }
6433
6434   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6435       offset);
6436
6437   if (stream->use_allocator) {
6438     /* if we have a per-stream allocator, use it */
6439     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6440   }
6441
6442   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6443       size, &buf);
6444   if (G_UNLIKELY (ret != GST_FLOW_OK))
6445     goto beach;
6446
6447   /* Update for both splitting and combining of samples */
6448   if (size != sample_size) {
6449     pts += gst_util_uint64_scale_int (GST_SECOND,
6450         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6451         stream->timescale);
6452     dts +=
6453         gst_util_uint64_scale_int (GST_SECOND,
6454         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6455         stream->timescale);
6456     duration =
6457         gst_util_uint64_scale_int (GST_SECOND,
6458         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6459   }
6460
6461   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6462       dts, pts, duration, keyframe, min_time, offset);
6463
6464   if (size < sample_size) {
6465     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6466     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6467
6468     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6469         sample->timestamp +
6470         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6471     if (time_position >= segment->media_start) {
6472       /* inside the segment, update time_position, looks very familiar to
6473        * GStreamer segments, doesn't it? */
6474       stream->time_position = (time_position - segment->media_start) +
6475           segment->time;
6476     } else {
6477       /* not yet in segment, time does not yet increment. This means
6478        * that we are still prerolling keyframes to the decoder so it can
6479        * decode the first sample of the segment. */
6480       stream->time_position = segment->time;
6481     }
6482   } else if (size > sample_size) {
6483     /* Increase to the last sample we already pulled so that advancing
6484      * below brings us to the next sample we need to pull */
6485     stream->sample_index += num_samples - 1;
6486   }
6487
6488   /* combine flows */
6489   GST_OBJECT_LOCK (qtdemux);
6490   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6491   GST_OBJECT_UNLOCK (qtdemux);
6492   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6493    * we have no more data for the pad to push */
6494   if (ret == GST_FLOW_EOS)
6495     ret = GST_FLOW_OK;
6496
6497   stream->offset_in_sample += size;
6498   if (stream->offset_in_sample >= sample_size) {
6499     gst_qtdemux_advance_sample (qtdemux, stream);
6500   }
6501   goto beach;
6502
6503 next:
6504   gst_qtdemux_advance_sample (qtdemux, stream);
6505
6506 beach:
6507   return ret;
6508
6509   /* special cases */
6510 eos:
6511   {
6512     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6513     ret = GST_FLOW_EOS;
6514     goto beach;
6515   }
6516 eos_stream:
6517   {
6518     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6519     /* EOS will be raised if all are EOS */
6520     ret = GST_FLOW_OK;
6521     goto beach;
6522   }
6523 }
6524
6525 static void
6526 gst_qtdemux_loop (GstPad * pad)
6527 {
6528   GstQTDemux *qtdemux;
6529   guint64 cur_offset;
6530   GstFlowReturn ret;
6531
6532   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6533
6534   cur_offset = qtdemux->offset;
6535   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6536       cur_offset, qt_demux_state_string (qtdemux->state));
6537
6538   switch (qtdemux->state) {
6539     case QTDEMUX_STATE_INITIAL:
6540     case QTDEMUX_STATE_HEADER:
6541       ret = gst_qtdemux_loop_state_header (qtdemux);
6542       break;
6543     case QTDEMUX_STATE_MOVIE:
6544       ret = gst_qtdemux_loop_state_movie (qtdemux);
6545       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6546         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6547       }
6548       break;
6549     default:
6550       /* ouch */
6551       goto invalid_state;
6552   }
6553
6554   /* if something went wrong, pause */
6555   if (ret != GST_FLOW_OK)
6556     goto pause;
6557
6558 done:
6559   gst_object_unref (qtdemux);
6560   return;
6561
6562   /* ERRORS */
6563 invalid_state:
6564   {
6565     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6566         (NULL), ("streaming stopped, invalid state"));
6567     gst_pad_pause_task (pad);
6568     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6569     goto done;
6570   }
6571 pause:
6572   {
6573     const gchar *reason = gst_flow_get_name (ret);
6574
6575     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6576
6577     gst_pad_pause_task (pad);
6578
6579     /* fatal errors need special actions */
6580     /* check EOS */
6581     if (ret == GST_FLOW_EOS) {
6582       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6583         /* we have no streams, post an error */
6584         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6585       }
6586       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6587         gint64 stop;
6588
6589         if ((stop = qtdemux->segment.stop) == -1)
6590           stop = qtdemux->segment.duration;
6591
6592         if (qtdemux->segment.rate >= 0) {
6593           GstMessage *message;
6594           GstEvent *event;
6595
6596           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6597           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6598               GST_FORMAT_TIME, stop);
6599           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6600           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6601             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6602             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6603           }
6604           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6605           gst_qtdemux_push_event (qtdemux, event);
6606         } else {
6607           GstMessage *message;
6608           GstEvent *event;
6609
6610           /*  For Reverse Playback */
6611           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6612           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6613               GST_FORMAT_TIME, qtdemux->segment.start);
6614           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6615               qtdemux->segment.start);
6616           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6617             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6618             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6619           }
6620           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6621           gst_qtdemux_push_event (qtdemux, event);
6622         }
6623       } else {
6624         GstEvent *event;
6625
6626         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6627         event = gst_event_new_eos ();
6628         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6629           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6630         gst_qtdemux_push_event (qtdemux, event);
6631       }
6632     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6633       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6634       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6635     }
6636     goto done;
6637   }
6638 }
6639
6640 /*
6641  * has_next_entry
6642  *
6643  * Returns if there are samples to be played.
6644  */
6645 static gboolean
6646 has_next_entry (GstQTDemux * demux)
6647 {
6648   QtDemuxStream *stream;
6649   gint i;
6650
6651   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6652
6653   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6654     stream = QTDEMUX_NTH_STREAM (demux, i);
6655
6656     if (stream->sample_index == -1) {
6657       stream->sample_index = 0;
6658       stream->offset_in_sample = 0;
6659     }
6660
6661     if (stream->sample_index >= stream->n_samples) {
6662       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6663       continue;
6664     }
6665     GST_DEBUG_OBJECT (demux, "Found a sample");
6666     return TRUE;
6667   }
6668
6669   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6670   return FALSE;
6671 }
6672
6673 /*
6674  * next_entry_size
6675  *
6676  * Returns the size of the first entry at the current offset.
6677  * If -1, there are none (which means EOS or empty file).
6678  */
6679 static guint64
6680 next_entry_size (GstQTDemux * demux)
6681 {
6682   QtDemuxStream *stream, *target_stream = NULL;
6683   guint64 smalloffs = (guint64) - 1;
6684   QtDemuxSample *sample;
6685   gint i;
6686
6687   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6688       demux->offset);
6689
6690   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6691     stream = QTDEMUX_NTH_STREAM (demux, i);
6692
6693     if (stream->sample_index == -1) {
6694       stream->sample_index = 0;
6695       stream->offset_in_sample = 0;
6696     }
6697
6698     if (stream->sample_index >= stream->n_samples) {
6699       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6700       continue;
6701     }
6702
6703     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6704       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6705           stream->sample_index);
6706       return -1;
6707     }
6708
6709     sample = &stream->samples[stream->sample_index];
6710
6711     GST_LOG_OBJECT (demux,
6712         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6713         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6714         stream->sample_index, sample->offset, sample->size);
6715
6716     if (((smalloffs == -1)
6717             || (sample->offset < smalloffs)) && (sample->size)) {
6718       smalloffs = sample->offset;
6719       target_stream = stream;
6720     }
6721   }
6722
6723   if (!target_stream)
6724     return -1;
6725
6726   GST_LOG_OBJECT (demux,
6727       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6728       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6729
6730   stream = target_stream;
6731   sample = &stream->samples[stream->sample_index];
6732
6733   if (sample->offset >= demux->offset) {
6734     demux->todrop = sample->offset - demux->offset;
6735     return sample->size + demux->todrop;
6736   }
6737
6738   GST_DEBUG_OBJECT (demux,
6739       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6740   return -1;
6741 }
6742
6743 static void
6744 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6745 {
6746   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6747
6748   gst_element_post_message (GST_ELEMENT_CAST (demux),
6749       gst_message_new_element (GST_OBJECT_CAST (demux),
6750           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6751 }
6752
6753 static gboolean
6754 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6755 {
6756   GstEvent *event;
6757   gboolean res = 0;
6758
6759   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6760
6761   event =
6762       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6763       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6764       GST_SEEK_TYPE_NONE, -1);
6765
6766   /* store seqnum to drop flush events, they don't need to reach downstream */
6767   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6768   res = gst_pad_push_event (demux->sinkpad, event);
6769   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6770
6771   return res;
6772 }
6773
6774 /* check for seekable upstream, above and beyond a mere query */
6775 static void
6776 gst_qtdemux_check_seekability (GstQTDemux * demux)
6777 {
6778   GstQuery *query;
6779   gboolean seekable = FALSE;
6780   gint64 start = -1, stop = -1;
6781
6782   if (demux->upstream_size)
6783     return;
6784
6785   if (demux->upstream_format_is_time)
6786     return;
6787
6788   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6789   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6790     GST_DEBUG_OBJECT (demux, "seeking query failed");
6791     goto done;
6792   }
6793
6794   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6795
6796   /* try harder to query upstream size if we didn't get it the first time */
6797   if (seekable && stop == -1) {
6798     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6799     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6800   }
6801
6802   /* if upstream doesn't know the size, it's likely that it's not seekable in
6803    * practice even if it technically may be seekable */
6804   if (seekable && (start != 0 || stop <= start)) {
6805     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6806     seekable = FALSE;
6807   }
6808
6809 done:
6810   gst_query_unref (query);
6811
6812   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6813       G_GUINT64_FORMAT ")", seekable, start, stop);
6814   demux->upstream_seekable = seekable;
6815   demux->upstream_size = seekable ? stop : -1;
6816 }
6817
6818 static void
6819 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6820 {
6821   g_return_if_fail (bytes <= demux->todrop);
6822
6823   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6824   gst_adapter_flush (demux->adapter, bytes);
6825   demux->neededbytes -= bytes;
6826   demux->offset += bytes;
6827   demux->todrop -= bytes;
6828 }
6829
6830 /* PUSH-MODE only: Send a segment, if not done already. */
6831 static void
6832 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6833 {
6834   if (G_UNLIKELY (demux->need_segment)) {
6835     gint i;
6836
6837     if (!demux->upstream_format_is_time) {
6838       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6839     } else {
6840       GstEvent *segment_event;
6841       segment_event = gst_event_new_segment (&demux->segment);
6842       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6843         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6844       gst_qtdemux_push_event (demux, segment_event);
6845     }
6846
6847     demux->need_segment = FALSE;
6848
6849     /* clear to send tags on all streams */
6850     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6851       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6852       gst_qtdemux_push_tags (demux, stream);
6853       if (CUR_STREAM (stream)->sparse) {
6854         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6855         gst_pad_push_event (stream->pad,
6856             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6857       }
6858     }
6859   }
6860 }
6861
6862 /* Used for push mode only. */
6863 static void
6864 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6865     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6866 {
6867   GstClockTime ts, dur;
6868
6869   ts = pos;
6870   dur =
6871       stream->segments[segment_index].duration - (pos -
6872       stream->segments[segment_index].time);
6873   stream->time_position += dur;
6874
6875   /* Only gaps with a duration of at least one second are propagated.
6876    * Same workaround as in pull mode.
6877    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6878   if (dur >= GST_SECOND) {
6879     GstEvent *gap;
6880     gap = gst_event_new_gap (ts, dur);
6881
6882     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6883         "segment: %" GST_PTR_FORMAT, gap);
6884     gst_pad_push_event (stream->pad, gap);
6885   }
6886 }
6887
6888 static GstFlowReturn
6889 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6890 {
6891   GstQTDemux *demux;
6892
6893   demux = GST_QTDEMUX (parent);
6894
6895   GST_DEBUG_OBJECT (demux,
6896       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6897       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6898       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6899       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6900       gst_buffer_get_size (inbuf), demux->offset);
6901
6902   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6903     gboolean is_gap_input = FALSE;
6904     gint i;
6905
6906     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6907
6908     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6909       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6910     }
6911
6912     /* Check if we can land back on our feet in the case where upstream is
6913      * handling the seeking/pushing of samples with gaps in between (like
6914      * in the case of trick-mode DASH for example) */
6915     if (demux->upstream_format_is_time
6916         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6917       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6918         guint32 res;
6919         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6920         GST_LOG_OBJECT (demux,
6921             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6922             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6923         res =
6924             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6925             stream, GST_BUFFER_OFFSET (inbuf));
6926         if (res != -1) {
6927           QtDemuxSample *sample = &stream->samples[res];
6928           GST_LOG_OBJECT (demux,
6929               "Checking if sample %d from track-id %u is valid (offset:%"
6930               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6931               stream->track_id, sample->offset, sample->size);
6932           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6933             GST_LOG_OBJECT (demux,
6934                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6935                 res);
6936             is_gap_input = TRUE;
6937             /* We can go back to standard playback mode */
6938             demux->state = QTDEMUX_STATE_MOVIE;
6939             /* Remember which sample this stream is at */
6940             stream->sample_index = res;
6941             /* Finally update all push-based values to the expected values */
6942             demux->neededbytes = stream->samples[res].size;
6943             demux->offset = GST_BUFFER_OFFSET (inbuf);
6944             demux->mdatleft =
6945                 demux->mdatsize - demux->offset + demux->mdatoffset;
6946             demux->todrop = 0;
6947           }
6948         }
6949       }
6950       if (!is_gap_input) {
6951         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6952         /* Reset state if it's a real discont */
6953         demux->neededbytes = 16;
6954         demux->state = QTDEMUX_STATE_INITIAL;
6955         demux->offset = GST_BUFFER_OFFSET (inbuf);
6956         gst_adapter_clear (demux->adapter);
6957       }
6958     }
6959     /* Reverse fragmented playback, need to flush all we have before
6960      * consuming a new fragment.
6961      * The samples array have the timestamps calculated by accumulating the
6962      * durations but this won't work for reverse playback of fragments as
6963      * the timestamps of a subsequent fragment should be smaller than the
6964      * previously received one. */
6965     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6966       gst_qtdemux_process_adapter (demux, TRUE);
6967       g_ptr_array_foreach (demux->active_streams,
6968           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6969     }
6970   }
6971
6972   gst_adapter_push (demux->adapter, inbuf);
6973
6974   GST_DEBUG_OBJECT (demux,
6975       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6976       demux->neededbytes, gst_adapter_available (demux->adapter));
6977
6978   return gst_qtdemux_process_adapter (demux, FALSE);
6979 }
6980
6981 static GstFlowReturn
6982 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6983 {
6984   GstFlowReturn ret = GST_FLOW_OK;
6985
6986   /* we never really mean to buffer that much */
6987   if (demux->neededbytes == -1) {
6988     goto eos;
6989   }
6990
6991   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6992       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6993
6994 #ifndef GST_DISABLE_GST_DEBUG
6995     {
6996       guint64 discont_offset, distance_from_discont;
6997
6998       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6999       distance_from_discont =
7000           gst_adapter_distance_from_discont (demux->adapter);
7001
7002       GST_DEBUG_OBJECT (demux,
7003           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7004           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7005           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7006           demux->offset, discont_offset, distance_from_discont);
7007     }
7008 #endif
7009
7010     switch (demux->state) {
7011       case QTDEMUX_STATE_INITIAL:{
7012         const guint8 *data;
7013         guint32 fourcc;
7014         guint64 size;
7015
7016         gst_qtdemux_check_seekability (demux);
7017
7018         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7019
7020         /* get fourcc/length, set neededbytes */
7021         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7022             &size, &fourcc);
7023         gst_adapter_unmap (demux->adapter);
7024         data = NULL;
7025         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7026             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7027         if (size == 0) {
7028           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7029               (_("This file is invalid and cannot be played.")),
7030               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7031                   GST_FOURCC_ARGS (fourcc)));
7032           ret = GST_FLOW_ERROR;
7033           break;
7034         }
7035         if (fourcc == FOURCC_mdat) {
7036           gint next_entry = next_entry_size (demux);
7037           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7038                   || !demux->fragmented)) {
7039             /* we have the headers, start playback */
7040             demux->state = QTDEMUX_STATE_MOVIE;
7041             demux->neededbytes = next_entry;
7042             demux->mdatleft = size;
7043             demux->mdatsize = demux->mdatleft;
7044           } else {
7045             /* no headers yet, try to get them */
7046             guint bs;
7047             gboolean res;
7048             guint64 old, target;
7049
7050           buffer_data:
7051             old = demux->offset;
7052             target = old + size;
7053
7054             /* try to jump over the atom with a seek */
7055             /* only bother if it seems worth doing so,
7056              * and avoids possible upstream/server problems */
7057             if (demux->upstream_seekable &&
7058                 demux->upstream_size > 4 * (1 << 20)) {
7059               res = qtdemux_seek_offset (demux, target);
7060             } else {
7061               GST_DEBUG_OBJECT (demux, "skipping seek");
7062               res = FALSE;
7063             }
7064
7065             if (res) {
7066               GST_DEBUG_OBJECT (demux, "seek success");
7067               /* remember the offset fo the first mdat so we can seek back to it
7068                * after we have the headers */
7069               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7070                 demux->first_mdat = old;
7071                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7072                     demux->first_mdat);
7073               }
7074               /* seek worked, continue reading */
7075               demux->offset = target;
7076               demux->neededbytes = 16;
7077               demux->state = QTDEMUX_STATE_INITIAL;
7078             } else {
7079               /* seek failed, need to buffer */
7080               demux->offset = old;
7081               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7082               /* there may be multiple mdat (or alike) buffers */
7083               /* sanity check */
7084               if (demux->mdatbuffer)
7085                 bs = gst_buffer_get_size (demux->mdatbuffer);
7086               else
7087                 bs = 0;
7088               if (size + bs > 10 * (1 << 20))
7089                 goto no_moov;
7090               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7091               demux->neededbytes = size;
7092               if (!demux->mdatbuffer)
7093                 demux->mdatoffset = demux->offset;
7094             }
7095           }
7096         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7097           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7098               (_("This file is invalid and cannot be played.")),
7099               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7100                   GST_FOURCC_ARGS (fourcc), size));
7101           ret = GST_FLOW_ERROR;
7102           break;
7103         } else {
7104           /* this means we already started buffering and still no moov header,
7105            * let's continue buffering everything till we get moov */
7106           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7107                   || fourcc == FOURCC_moof))
7108             goto buffer_data;
7109           demux->neededbytes = size;
7110           demux->state = QTDEMUX_STATE_HEADER;
7111         }
7112         break;
7113       }
7114       case QTDEMUX_STATE_HEADER:{
7115         const guint8 *data;
7116         guint32 fourcc;
7117
7118         GST_DEBUG_OBJECT (demux, "In header");
7119
7120         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7121
7122         /* parse the header */
7123         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7124             &fourcc);
7125         if (fourcc == FOURCC_moov) {
7126           /* in usual fragmented setup we could try to scan for more
7127            * and end up at the the moov (after mdat) again */
7128           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7129               (!demux->fragmented
7130                   || demux->last_moov_offset == demux->offset)) {
7131             GST_DEBUG_OBJECT (demux,
7132                 "Skipping moov atom as we have (this) one already");
7133           } else {
7134             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7135
7136             if (demux->got_moov && demux->fragmented) {
7137               GST_DEBUG_OBJECT (demux,
7138                   "Got a second moov, clean up data from old one");
7139               if (demux->moov_node_compressed) {
7140                 g_node_destroy (demux->moov_node_compressed);
7141                 if (demux->moov_node)
7142                   g_free (demux->moov_node->data);
7143               }
7144               demux->moov_node_compressed = NULL;
7145               if (demux->moov_node)
7146                 g_node_destroy (demux->moov_node);
7147               demux->moov_node = NULL;
7148             }
7149
7150             demux->last_moov_offset = demux->offset;
7151
7152             /* Update streams with new moov */
7153             gst_qtdemux_stream_concat (demux,
7154                 demux->old_streams, demux->active_streams);
7155
7156             qtdemux_parse_moov (demux, data, demux->neededbytes);
7157             qtdemux_node_dump (demux, demux->moov_node);
7158             qtdemux_parse_tree (demux);
7159             qtdemux_prepare_streams (demux);
7160             QTDEMUX_EXPOSE_LOCK (demux);
7161             qtdemux_expose_streams (demux);
7162             QTDEMUX_EXPOSE_UNLOCK (demux);
7163
7164             demux->got_moov = TRUE;
7165
7166             gst_qtdemux_check_send_pending_segment (demux);
7167
7168             if (demux->moov_node_compressed) {
7169               g_node_destroy (demux->moov_node_compressed);
7170               g_free (demux->moov_node->data);
7171             }
7172             demux->moov_node_compressed = NULL;
7173             g_node_destroy (demux->moov_node);
7174             demux->moov_node = NULL;
7175             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7176           }
7177         } else if (fourcc == FOURCC_moof) {
7178           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7179             guint64 dist = 0;
7180             GstClockTime prev_pts;
7181             guint64 prev_offset;
7182             guint64 adapter_discont_offset, adapter_discont_dist;
7183
7184             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7185
7186             /*
7187              * The timestamp of the moof buffer is relevant as some scenarios
7188              * won't have the initial timestamp in the atoms. Whenever a new
7189              * buffer has started, we get that buffer's PTS and use it as a base
7190              * timestamp for the trun entries.
7191              *
7192              * To keep track of the current buffer timestamp and starting point
7193              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7194              * from the beginning of the buffer, with the distance and demux->offset
7195              * we know if it is still the same buffer or not.
7196              */
7197             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7198             prev_offset = demux->offset - dist;
7199             if (demux->fragment_start_offset == -1
7200                 || prev_offset > demux->fragment_start_offset) {
7201               demux->fragment_start_offset = prev_offset;
7202               demux->fragment_start = prev_pts;
7203               GST_DEBUG_OBJECT (demux,
7204                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7205                   GST_TIME_FORMAT, demux->fragment_start_offset,
7206                   GST_TIME_ARGS (demux->fragment_start));
7207             }
7208
7209             /* We can't use prev_offset() here because this would require
7210              * upstream to set consistent and correct offsets on all buffers
7211              * since the discont. Nothing ever did that in the past and we
7212              * would break backwards compatibility here then.
7213              * Instead take the offset we had at the last discont and count
7214              * the bytes from there. This works with old code as there would
7215              * be no discont between moov and moof, and also works with
7216              * adaptivedemux which correctly sets offset and will set the
7217              * DISCONT flag accordingly when needed.
7218              *
7219              * We also only do this for upstream TIME segments as otherwise
7220              * there are potential backwards compatibility problems with
7221              * seeking in PUSH mode and upstream providing inconsistent
7222              * timestamps. */
7223             adapter_discont_offset =
7224                 gst_adapter_offset_at_discont (demux->adapter);
7225             adapter_discont_dist =
7226                 gst_adapter_distance_from_discont (demux->adapter);
7227
7228             GST_DEBUG_OBJECT (demux,
7229                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7230                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7231                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7232
7233             if (demux->upstream_format_is_time) {
7234               demux->moof_offset = adapter_discont_offset;
7235               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7236                 demux->moof_offset += adapter_discont_dist;
7237               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7238                 demux->moof_offset = demux->offset;
7239             } else {
7240               demux->moof_offset = demux->offset;
7241             }
7242
7243             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7244                     demux->moof_offset, NULL)) {
7245               gst_adapter_unmap (demux->adapter);
7246               ret = GST_FLOW_ERROR;
7247               goto done;
7248             }
7249
7250             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7251             if (demux->mss_mode && !demux->exposed) {
7252               QTDEMUX_EXPOSE_LOCK (demux);
7253               qtdemux_expose_streams (demux);
7254               QTDEMUX_EXPOSE_UNLOCK (demux);
7255             }
7256
7257             gst_qtdemux_check_send_pending_segment (demux);
7258           } else {
7259             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7260           }
7261         } else if (fourcc == FOURCC_ftyp) {
7262           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7263           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7264         } else if (fourcc == FOURCC_uuid) {
7265           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7266           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7267         } else if (fourcc == FOURCC_sidx) {
7268           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7269           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7270         } else {
7271           switch (fourcc) {
7272             case FOURCC_styp:
7273               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7274                * FALLTHROUGH */
7275             case FOURCC_skip:
7276             case FOURCC_free:
7277               /* [free] and [skip] are padding atoms */
7278               GST_DEBUG_OBJECT (demux,
7279                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7280                   GST_FOURCC_ARGS (fourcc));
7281               break;
7282             default:
7283               GST_WARNING_OBJECT (demux,
7284                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7285                   GST_FOURCC_ARGS (fourcc));
7286               /* Let's jump that one and go back to initial state */
7287               break;
7288           }
7289         }
7290         gst_adapter_unmap (demux->adapter);
7291         data = NULL;
7292
7293         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7294           gsize remaining_data_size = 0;
7295
7296           /* the mdat was before the header */
7297           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7298               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7299           /* restore our adapter/offset view of things with upstream;
7300            * put preceding buffered data ahead of current moov data.
7301            * This should also handle evil mdat, moov, mdat cases and alike */
7302           gst_adapter_flush (demux->adapter, demux->neededbytes);
7303
7304           /* Store any remaining data after the mdat for later usage */
7305           remaining_data_size = gst_adapter_available (demux->adapter);
7306           if (remaining_data_size > 0) {
7307             g_assert (demux->restoredata_buffer == NULL);
7308             demux->restoredata_buffer =
7309                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7310             demux->restoredata_offset = demux->offset + demux->neededbytes;
7311             GST_DEBUG_OBJECT (demux,
7312                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7313                 G_GUINT64_FORMAT, remaining_data_size,
7314                 demux->restoredata_offset);
7315           }
7316
7317           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7318           demux->mdatbuffer = NULL;
7319           demux->offset = demux->mdatoffset;
7320           demux->neededbytes = next_entry_size (demux);
7321           demux->state = QTDEMUX_STATE_MOVIE;
7322           demux->mdatleft = gst_adapter_available (demux->adapter);
7323           demux->mdatsize = demux->mdatleft;
7324         } else {
7325           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7326           gst_adapter_flush (demux->adapter, demux->neededbytes);
7327
7328           /* only go back to the mdat if there are samples to play */
7329           if (demux->got_moov && demux->first_mdat != -1
7330               && has_next_entry (demux)) {
7331             gboolean res;
7332
7333             /* we need to seek back */
7334             res = qtdemux_seek_offset (demux, demux->first_mdat);
7335             if (res) {
7336               demux->offset = demux->first_mdat;
7337             } else {
7338               GST_DEBUG_OBJECT (demux, "Seek back failed");
7339             }
7340           } else {
7341             demux->offset += demux->neededbytes;
7342           }
7343           demux->neededbytes = 16;
7344           demux->state = QTDEMUX_STATE_INITIAL;
7345         }
7346
7347         break;
7348       }
7349       case QTDEMUX_STATE_BUFFER_MDAT:{
7350         GstBuffer *buf;
7351         guint8 fourcc[4];
7352
7353         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7354             demux->offset);
7355         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7356         gst_buffer_extract (buf, 0, fourcc, 4);
7357         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7358             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7359         if (demux->mdatbuffer)
7360           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7361         else
7362           demux->mdatbuffer = buf;
7363         demux->offset += demux->neededbytes;
7364         demux->neededbytes = 16;
7365         demux->state = QTDEMUX_STATE_INITIAL;
7366         gst_qtdemux_post_progress (demux, 1, 1);
7367
7368         break;
7369       }
7370       case QTDEMUX_STATE_MOVIE:{
7371         QtDemuxStream *stream = NULL;
7372         QtDemuxSample *sample;
7373         GstClockTime dts, pts, duration;
7374         gboolean keyframe;
7375         gint i;
7376
7377         GST_DEBUG_OBJECT (demux,
7378             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7379
7380         if (demux->fragmented) {
7381           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7382               demux->mdatleft);
7383           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7384             /* if needed data starts within this atom,
7385              * then it should not exceed this atom */
7386             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7387               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7388                   (_("This file is invalid and cannot be played.")),
7389                   ("sample data crosses atom boundary"));
7390               ret = GST_FLOW_ERROR;
7391               break;
7392             }
7393             demux->mdatleft -= demux->neededbytes;
7394           } else {
7395             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7396             /* so we are dropping more than left in this atom */
7397             gst_qtdemux_drop_data (demux, demux->mdatleft);
7398             demux->mdatleft = 0;
7399
7400             /* need to resume atom parsing so we do not miss any other pieces */
7401             demux->state = QTDEMUX_STATE_INITIAL;
7402             demux->neededbytes = 16;
7403
7404             /* check if there was any stored post mdat data from previous buffers */
7405             if (demux->restoredata_buffer) {
7406               g_assert (gst_adapter_available (demux->adapter) == 0);
7407
7408               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7409               demux->restoredata_buffer = NULL;
7410               demux->offset = demux->restoredata_offset;
7411             }
7412
7413             break;
7414           }
7415         }
7416
7417         if (demux->todrop) {
7418           if (demux->cenc_aux_info_offset > 0) {
7419             GstByteReader br;
7420             const guint8 *data;
7421
7422             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7423             data = gst_adapter_map (demux->adapter, demux->todrop);
7424             gst_byte_reader_init (&br, data + 8, demux->todrop);
7425             if (!qtdemux_parse_cenc_aux_info (demux,
7426                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7427                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7428               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7429               ret = GST_FLOW_ERROR;
7430               gst_adapter_unmap (demux->adapter);
7431               g_free (demux->cenc_aux_info_sizes);
7432               demux->cenc_aux_info_sizes = NULL;
7433               goto done;
7434             }
7435             demux->cenc_aux_info_offset = 0;
7436             g_free (demux->cenc_aux_info_sizes);
7437             demux->cenc_aux_info_sizes = NULL;
7438             gst_adapter_unmap (demux->adapter);
7439           }
7440           gst_qtdemux_drop_data (demux, demux->todrop);
7441         }
7442
7443         /* first buffer? */
7444         /* initial newsegment sent here after having added pads,
7445          * possible others in sink_event */
7446         gst_qtdemux_check_send_pending_segment (demux);
7447
7448         /* Figure out which stream this packet belongs to */
7449         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7450           stream = QTDEMUX_NTH_STREAM (demux, i);
7451           if (stream->sample_index >= stream->n_samples) {
7452             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7453             stream = NULL;
7454             continue;
7455           }
7456           GST_LOG_OBJECT (demux,
7457               "Checking track-id %u (sample_index:%d / offset:%"
7458               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7459               stream->sample_index,
7460               stream->samples[stream->sample_index].offset,
7461               stream->samples[stream->sample_index].size);
7462
7463           if (stream->samples[stream->sample_index].offset == demux->offset)
7464             break;
7465         }
7466
7467         if (G_UNLIKELY (stream == NULL))
7468           goto unknown_stream;
7469
7470         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7471
7472         if (stream->new_caps) {
7473           gst_qtdemux_configure_stream (demux, stream);
7474         }
7475
7476         /* Put data in a buffer, set timestamps, caps, ... */
7477         sample = &stream->samples[stream->sample_index];
7478
7479         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7480           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7481               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7482
7483           dts = QTSAMPLE_DTS (stream, sample);
7484           pts = QTSAMPLE_PTS (stream, sample);
7485           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7486           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7487
7488           /* check for segment end */
7489           if (G_UNLIKELY (demux->segment.stop != -1
7490                   && demux->segment.stop <= pts && stream->on_keyframe)
7491               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7492             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7493             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7494
7495             /* skip this data, stream is EOS */
7496             gst_adapter_flush (demux->adapter, demux->neededbytes);
7497             demux->offset += demux->neededbytes;
7498
7499             /* check if all streams are eos */
7500             ret = GST_FLOW_EOS;
7501             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7502               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7503                 ret = GST_FLOW_OK;
7504                 break;
7505               }
7506             }
7507           } else {
7508             GstBuffer *outbuf;
7509
7510             outbuf =
7511                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7512
7513             /* FIXME: should either be an assert or a plain check */
7514             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7515
7516             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7517                 dts, pts, duration, keyframe, dts, demux->offset);
7518           }
7519
7520           /* combine flows */
7521           GST_OBJECT_LOCK (demux);
7522           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7523           GST_OBJECT_UNLOCK (demux);
7524         } else {
7525           /* skip this data, stream is EOS */
7526           gst_adapter_flush (demux->adapter, demux->neededbytes);
7527         }
7528
7529         stream->sample_index++;
7530         stream->offset_in_sample = 0;
7531
7532         /* update current offset and figure out size of next buffer */
7533         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7534             demux->offset, demux->neededbytes);
7535         demux->offset += demux->neededbytes;
7536         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7537             demux->offset);
7538
7539
7540         if (ret == GST_FLOW_EOS) {
7541           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7542           demux->neededbytes = -1;
7543           goto eos;
7544         }
7545
7546         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7547           if (demux->fragmented) {
7548             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7549             /* there may be more to follow, only finish this atom */
7550             demux->todrop = demux->mdatleft;
7551             demux->neededbytes = demux->todrop;
7552             break;
7553           }
7554           goto eos;
7555         }
7556         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7557           goto non_ok_unlinked_flow;
7558         }
7559         break;
7560       }
7561       default:
7562         goto invalid_state;
7563     }
7564   }
7565
7566   /* when buffering movie data, at least show user something is happening */
7567   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7568       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7569     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7570         demux->neededbytes);
7571   }
7572 done:
7573
7574   return ret;
7575
7576   /* ERRORS */
7577 non_ok_unlinked_flow:
7578   {
7579     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7580         gst_flow_get_name (ret));
7581     return ret;
7582   }
7583 unknown_stream:
7584   {
7585     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7586     ret = GST_FLOW_ERROR;
7587     goto done;
7588   }
7589 eos:
7590   {
7591     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7592     ret = GST_FLOW_EOS;
7593     goto done;
7594   }
7595 invalid_state:
7596   {
7597     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7598         (NULL), ("qtdemuxer invalid state %d", demux->state));
7599     ret = GST_FLOW_ERROR;
7600     goto done;
7601   }
7602 no_moov:
7603   {
7604     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7605         (NULL), ("no 'moov' atom within the first 10 MB"));
7606     ret = GST_FLOW_ERROR;
7607     goto done;
7608   }
7609 }
7610
7611 static gboolean
7612 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7613 {
7614   GstQuery *query;
7615   gboolean pull_mode;
7616
7617   query = gst_query_new_scheduling ();
7618
7619   if (!gst_pad_peer_query (sinkpad, query)) {
7620     gst_query_unref (query);
7621     goto activate_push;
7622   }
7623
7624   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7625       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7626   gst_query_unref (query);
7627
7628   if (!pull_mode)
7629     goto activate_push;
7630
7631   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7632   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7633
7634 activate_push:
7635   {
7636     GST_DEBUG_OBJECT (sinkpad, "activating push");
7637     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7638   }
7639 }
7640
7641 static gboolean
7642 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7643     GstPadMode mode, gboolean active)
7644 {
7645   gboolean res;
7646   GstQTDemux *demux = GST_QTDEMUX (parent);
7647
7648   switch (mode) {
7649     case GST_PAD_MODE_PUSH:
7650       demux->pullbased = FALSE;
7651       res = TRUE;
7652       break;
7653     case GST_PAD_MODE_PULL:
7654       if (active) {
7655         demux->pullbased = TRUE;
7656         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7657             sinkpad, NULL);
7658       } else {
7659         res = gst_pad_stop_task (sinkpad);
7660       }
7661       break;
7662     default:
7663       res = FALSE;
7664       break;
7665   }
7666   return res;
7667 }
7668
7669 #ifdef HAVE_ZLIB
7670 static void *
7671 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7672 {
7673   guint8 *buffer;
7674   z_stream z;
7675   int ret;
7676
7677   memset (&z, 0, sizeof (z));
7678   z.zalloc = NULL;
7679   z.zfree = NULL;
7680   z.opaque = NULL;
7681
7682   if ((ret = inflateInit (&z)) != Z_OK) {
7683     GST_ERROR ("inflateInit() returned %d", ret);
7684     return NULL;
7685   }
7686
7687   z.next_in = z_buffer;
7688   z.avail_in = z_length;
7689
7690   buffer = (guint8 *) g_malloc (*length);
7691   z.avail_out = *length;
7692   z.next_out = (Bytef *) buffer;
7693   do {
7694     ret = inflate (&z, Z_NO_FLUSH);
7695     if (ret == Z_STREAM_END) {
7696       break;
7697     } else if (ret != Z_OK) {
7698       GST_WARNING ("inflate() returned %d", ret);
7699       break;
7700     }
7701
7702     *length += 4096;
7703     buffer = (guint8 *) g_realloc (buffer, *length);
7704     z.next_out = (Bytef *) (buffer + z.total_out);
7705     z.avail_out += 4096;
7706   } while (z.avail_in > 0);
7707
7708   if (ret != Z_STREAM_END) {
7709     g_free (buffer);
7710     buffer = NULL;
7711     *length = 0;
7712   } else {
7713     *length = z.total_out;
7714   }
7715
7716   inflateEnd (&z);
7717
7718   return buffer;
7719 }
7720 #endif /* HAVE_ZLIB */
7721
7722 static gboolean
7723 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7724 {
7725   GNode *cmov;
7726
7727   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7728
7729   /* counts as header data */
7730   qtdemux->header_size += length;
7731
7732   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7733   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7734
7735   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7736   if (cmov) {
7737     guint32 method;
7738     GNode *dcom;
7739     GNode *cmvd;
7740     guint32 dcom_len;
7741
7742     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7743     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7744     if (dcom == NULL || cmvd == NULL)
7745       goto invalid_compression;
7746
7747     dcom_len = QT_UINT32 (dcom->data);
7748     if (dcom_len < 12)
7749       goto invalid_compression;
7750
7751     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7752     switch (method) {
7753 #ifdef HAVE_ZLIB
7754       case FOURCC_zlib:{
7755         guint uncompressed_length;
7756         guint compressed_length;
7757         guint8 *buf;
7758         guint32 cmvd_len;
7759
7760         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7761         if (cmvd_len < 12)
7762           goto invalid_compression;
7763
7764         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7765         compressed_length = cmvd_len - 12;
7766         GST_LOG ("length = %u", uncompressed_length);
7767
7768         buf =
7769             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7770             compressed_length, &uncompressed_length);
7771
7772         if (buf) {
7773           qtdemux->moov_node_compressed = qtdemux->moov_node;
7774           qtdemux->moov_node = g_node_new (buf);
7775
7776           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7777               uncompressed_length);
7778         }
7779         break;
7780       }
7781 #endif /* HAVE_ZLIB */
7782       default:
7783         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7784             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7785         break;
7786     }
7787   }
7788   return TRUE;
7789
7790   /* ERRORS */
7791 invalid_compression:
7792   {
7793     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7794     return FALSE;
7795   }
7796 }
7797
7798 static gboolean
7799 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7800     const guint8 * end)
7801 {
7802   while (G_UNLIKELY (buf < end)) {
7803     GNode *child;
7804     guint32 len;
7805
7806     if (G_UNLIKELY (buf + 4 > end)) {
7807       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7808       break;
7809     }
7810     len = QT_UINT32 (buf);
7811     if (G_UNLIKELY (len == 0)) {
7812       GST_LOG_OBJECT (qtdemux, "empty container");
7813       break;
7814     }
7815     if (G_UNLIKELY (len < 8)) {
7816       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7817       break;
7818     }
7819     if (G_UNLIKELY (len > (end - buf))) {
7820       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7821           (gint) (end - buf));
7822       break;
7823     }
7824
7825     child = g_node_new ((guint8 *) buf);
7826     g_node_append (node, child);
7827     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7828     qtdemux_parse_node (qtdemux, child, buf, len);
7829
7830     buf += len;
7831   }
7832   return TRUE;
7833 }
7834
7835 static gboolean
7836 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7837     GNode * xdxt)
7838 {
7839   int len = QT_UINT32 (xdxt->data);
7840   guint8 *buf = xdxt->data;
7841   guint8 *end = buf + len;
7842   GstBuffer *buffer;
7843
7844   /* skip size and type */
7845   buf += 8;
7846   end -= 8;
7847
7848   while (buf < end) {
7849     gint size;
7850     guint32 type;
7851
7852     size = QT_UINT32 (buf);
7853     type = QT_FOURCC (buf + 4);
7854
7855     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7856
7857     if (buf + size > end || size <= 0)
7858       break;
7859
7860     buf += 8;
7861     size -= 8;
7862
7863     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7864         GST_FOURCC_ARGS (type));
7865
7866     switch (type) {
7867       case FOURCC_tCtH:
7868         buffer = gst_buffer_new_and_alloc (size);
7869         gst_buffer_fill (buffer, 0, buf, size);
7870         stream->buffers = g_slist_append (stream->buffers, buffer);
7871         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7872         break;
7873       case FOURCC_tCt_:
7874         buffer = gst_buffer_new_and_alloc (size);
7875         gst_buffer_fill (buffer, 0, buf, size);
7876         stream->buffers = g_slist_append (stream->buffers, buffer);
7877         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7878         break;
7879       case FOURCC_tCtC:
7880         buffer = gst_buffer_new_and_alloc (size);
7881         gst_buffer_fill (buffer, 0, buf, size);
7882         stream->buffers = g_slist_append (stream->buffers, buffer);
7883         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7884         break;
7885       default:
7886         GST_WARNING_OBJECT (qtdemux,
7887             "unknown theora cookie %" GST_FOURCC_FORMAT,
7888             GST_FOURCC_ARGS (type));
7889         break;
7890     }
7891     buf += size;
7892   }
7893   return TRUE;
7894 }
7895
7896 static gboolean
7897 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7898     guint length)
7899 {
7900   guint32 fourcc = 0;
7901   guint32 node_length = 0;
7902   const QtNodeType *type;
7903   const guint8 *end;
7904
7905   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7906
7907   if (G_UNLIKELY (length < 8))
7908     goto not_enough_data;
7909
7910   node_length = QT_UINT32 (buffer);
7911   fourcc = QT_FOURCC (buffer + 4);
7912
7913   /* ignore empty nodes */
7914   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7915     return TRUE;
7916
7917   type = qtdemux_type_get (fourcc);
7918
7919   end = buffer + length;
7920
7921   GST_LOG_OBJECT (qtdemux,
7922       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7923       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7924
7925   if (node_length > length)
7926     goto broken_atom_size;
7927
7928   if (type->flags & QT_FLAG_CONTAINER) {
7929     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7930   } else {
7931     switch (fourcc) {
7932       case FOURCC_stsd:
7933       {
7934         if (node_length < 20) {
7935           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7936           break;
7937         }
7938         GST_DEBUG_OBJECT (qtdemux,
7939             "parsing stsd (sample table, sample description) atom");
7940         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7941         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7942         break;
7943       }
7944       case FOURCC_mp4a:
7945       case FOURCC_alac:
7946       case FOURCC_fLaC:
7947       case FOURCC_aavd:
7948       {
7949         guint32 version;
7950         guint32 offset;
7951         guint min_size;
7952
7953         /* also read alac (or whatever) in stead of mp4a in the following,
7954          * since a similar layout is used in other cases as well */
7955         if (fourcc == FOURCC_mp4a)
7956           min_size = 20;
7957         else if (fourcc == FOURCC_fLaC)
7958           min_size = 86;
7959         else
7960           min_size = 40;
7961
7962         /* There are two things we might encounter here: a true mp4a atom, and
7963            an mp4a entry in an stsd atom. The latter is what we're interested
7964            in, and it looks like an atom, but isn't really one. The true mp4a
7965            atom is short, so we detect it based on length here. */
7966         if (length < min_size) {
7967           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7968               GST_FOURCC_ARGS (fourcc));
7969           break;
7970         }
7971
7972         /* 'version' here is the sound sample description version. Types 0 and
7973            1 are documented in the QTFF reference, but type 2 is not: it's
7974            described in Apple header files instead (struct SoundDescriptionV2
7975            in Movies.h) */
7976         version = QT_UINT16 (buffer + 16);
7977
7978         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7979             GST_FOURCC_ARGS (fourcc), version);
7980
7981         /* parse any esds descriptors */
7982         switch (version) {
7983           case 0:
7984             offset = 0x24;
7985             break;
7986           case 1:
7987             offset = 0x34;
7988             break;
7989           case 2:
7990             offset = 0x48;
7991             break;
7992           default:
7993             GST_WARNING_OBJECT (qtdemux,
7994                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7995                 GST_FOURCC_ARGS (fourcc), version);
7996             offset = 0;
7997             break;
7998         }
7999         if (offset)
8000           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8001         break;
8002       }
8003       case FOURCC_mp4v:
8004       case FOURCC_MP4V:
8005       case FOURCC_fmp4:
8006       case FOURCC_FMP4:
8007       case FOURCC_apcs:
8008       case FOURCC_apch:
8009       case FOURCC_apcn:
8010       case FOURCC_apco:
8011       case FOURCC_ap4h:
8012       case FOURCC_xvid:
8013       case FOURCC_XVID:
8014       case FOURCC_H264:
8015       case FOURCC_avc1:
8016       case FOURCC_avc3:
8017       case FOURCC_H265:
8018       case FOURCC_hvc1:
8019       case FOURCC_hev1:
8020       case FOURCC_dvh1:
8021       case FOURCC_dvhe:
8022       case FOURCC_mjp2:
8023       case FOURCC_encv:
8024       {
8025         guint32 version;
8026         guint32 str_len;
8027
8028         /* codec_data is contained inside these atoms, which all have
8029          * the same format. */
8030         /* video sample description size is 86 bytes without extension.
8031          * node_length have to be bigger than 86 bytes because video sample
8032          * description can include extensions such as esds, fiel, glbl, etc. */
8033         if (node_length < 86) {
8034           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8035               " sample description length too short (%u < 86)",
8036               GST_FOURCC_ARGS (fourcc), node_length);
8037           break;
8038         }
8039
8040         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8041             GST_FOURCC_ARGS (fourcc));
8042
8043         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8044          *              its data format.
8045          * revision level (2 bytes) : must be set to 0. */
8046         version = QT_UINT32 (buffer + 16);
8047         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8048
8049         /* compressor name : PASCAL string and informative purposes
8050          * first byte : the number of bytes to be displayed.
8051          *              it has to be less than 32 because it is reserved
8052          *              space of 32 bytes total including itself. */
8053         str_len = QT_UINT8 (buffer + 50);
8054         if (str_len < 32)
8055           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8056               (char *) buffer + 51);
8057         else
8058           GST_WARNING_OBJECT (qtdemux,
8059               "compressorname length too big (%u > 31)", str_len);
8060
8061         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8062             end - buffer);
8063         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8064         break;
8065       }
8066       case FOURCC_meta:
8067       {
8068         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8069
8070         /* You are reading this correctly. QTFF specifies that the
8071          * metadata atom is a short atom, whereas ISO BMFF specifies
8072          * it's a full atom. But since so many people are doing things
8073          * differently, we actually peek into the atom to see which
8074          * variant it is */
8075         if (length < 16) {
8076           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8077               GST_FOURCC_ARGS (fourcc));
8078           break;
8079         }
8080         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8081           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8082            * starts with a 'hdlr' atom */
8083           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8084         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8085           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8086            * with version/flags both set to zero */
8087           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8088         } else
8089           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8090         break;
8091       }
8092       case FOURCC_mp4s:
8093       {
8094         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8095         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8096         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8097         break;
8098       }
8099       case FOURCC_XiTh:
8100       {
8101         guint32 version;
8102         guint32 offset;
8103
8104         if (length < 16) {
8105           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8106               GST_FOURCC_ARGS (fourcc));
8107           break;
8108         }
8109
8110         version = QT_UINT32 (buffer + 12);
8111         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8112
8113         switch (version) {
8114           case 0x00000001:
8115             offset = 0x62;
8116             break;
8117           default:
8118             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8119             offset = 0;
8120             break;
8121         }
8122         if (offset) {
8123           if (length < offset) {
8124             GST_WARNING_OBJECT (qtdemux,
8125                 "skipping too small %" GST_FOURCC_FORMAT " box",
8126                 GST_FOURCC_ARGS (fourcc));
8127             break;
8128           }
8129           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8130         }
8131         break;
8132       }
8133       case FOURCC_in24:
8134       {
8135         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8136         break;
8137       }
8138       case FOURCC_uuid:
8139       {
8140         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8141         break;
8142       }
8143       case FOURCC_enca:
8144       {
8145         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8146         break;
8147       }
8148       default:
8149         if (!strcmp (type->name, "unknown"))
8150           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8151         break;
8152     }
8153   }
8154   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8155       GST_FOURCC_ARGS (fourcc));
8156   return TRUE;
8157
8158 /* ERRORS */
8159 not_enough_data:
8160   {
8161     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8162         (_("This file is corrupt and cannot be played.")),
8163         ("Not enough data for an atom header, got only %u bytes", length));
8164     return FALSE;
8165   }
8166 broken_atom_size:
8167   {
8168     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8169         (_("This file is corrupt and cannot be played.")),
8170         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8171             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8172             length));
8173     return FALSE;
8174   }
8175 }
8176
8177 static void
8178 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8179 {
8180 /* FIXME: This can only reliably work if demuxers have a
8181  * separate streaming thread per srcpad. This should be
8182  * done in a demuxer base class, which integrates parts
8183  * of multiqueue
8184  *
8185  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8186  */
8187 #if 0
8188   GstQuery *query;
8189
8190   query = gst_query_new_allocation (stream->caps, FALSE);
8191
8192   if (!gst_pad_peer_query (stream->pad, query)) {
8193     /* not a problem, just debug a little */
8194     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8195   }
8196
8197   if (stream->allocator)
8198     gst_object_unref (stream->allocator);
8199
8200   if (gst_query_get_n_allocation_params (query) > 0) {
8201     /* try the allocator */
8202     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8203         &stream->params);
8204     stream->use_allocator = TRUE;
8205   } else {
8206     stream->allocator = NULL;
8207     gst_allocation_params_init (&stream->params);
8208     stream->use_allocator = FALSE;
8209   }
8210   gst_query_unref (query);
8211 #endif
8212 }
8213
8214 static gboolean
8215 pad_query (const GValue * item, GValue * value, gpointer user_data)
8216 {
8217   GstPad *pad = g_value_get_object (item);
8218   GstQuery *query = user_data;
8219   gboolean res;
8220
8221   res = gst_pad_peer_query (pad, query);
8222
8223   if (res) {
8224     g_value_set_boolean (value, TRUE);
8225     return FALSE;
8226   }
8227
8228   GST_INFO_OBJECT (pad, "pad peer query failed");
8229   return TRUE;
8230 }
8231
8232 static gboolean
8233 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8234     GstPadDirection direction)
8235 {
8236   GstIterator *it;
8237   GstIteratorFoldFunction func = pad_query;
8238   GValue res = { 0, };
8239
8240   g_value_init (&res, G_TYPE_BOOLEAN);
8241   g_value_set_boolean (&res, FALSE);
8242
8243   /* Ask neighbor */
8244   if (direction == GST_PAD_SRC)
8245     it = gst_element_iterate_src_pads (element);
8246   else
8247     it = gst_element_iterate_sink_pads (element);
8248
8249   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8250     gst_iterator_resync (it);
8251
8252   gst_iterator_free (it);
8253
8254   return g_value_get_boolean (&res);
8255 }
8256
8257 static void
8258 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8259     QtDemuxStream * stream)
8260 {
8261   GstQuery *query;
8262   GstContext *ctxt;
8263   GstElement *element = GST_ELEMENT (qtdemux);
8264   GstStructure *st;
8265   gchar **filtered_sys_ids;
8266   GValue event_list = G_VALUE_INIT;
8267   GList *walk;
8268
8269   /* 1. Check if we already have the context. */
8270   if (qtdemux->preferred_protection_system_id != NULL) {
8271     GST_LOG_OBJECT (element,
8272         "already have the protection context, no need to request it again");
8273     return;
8274   }
8275
8276   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8277   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8278       (const gchar **) qtdemux->protection_system_ids->pdata);
8279
8280   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8281       qtdemux->protection_system_ids->len - 1);
8282   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8283       "decryptors for %u of them, running context request",
8284       qtdemux->protection_system_ids->len,
8285       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8286
8287
8288   if (stream->protection_scheme_event_queue.length) {
8289     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8290         stream->protection_scheme_event_queue.length);
8291     walk = stream->protection_scheme_event_queue.tail;
8292   } else {
8293     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8294         qtdemux->protection_event_queue.length);
8295     walk = qtdemux->protection_event_queue.tail;
8296   }
8297
8298   g_value_init (&event_list, GST_TYPE_LIST);
8299   for (; walk; walk = g_list_previous (walk)) {
8300     GValue *event_value = g_new0 (GValue, 1);
8301     g_value_init (event_value, GST_TYPE_EVENT);
8302     g_value_set_boxed (event_value, walk->data);
8303     gst_value_list_append_and_take_value (&event_list, event_value);
8304   }
8305
8306   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8307    *      check if downstream already has a context of the specific type
8308    *  2b) Query upstream as above.
8309    */
8310   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8311   st = gst_query_writable_structure (query);
8312   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8313       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8314       NULL);
8315   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8316   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8317     gst_query_parse_context (query, &ctxt);
8318     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8319     gst_element_set_context (element, ctxt);
8320   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8321     gst_query_parse_context (query, &ctxt);
8322     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8323     gst_element_set_context (element, ctxt);
8324   } else {
8325     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8326      *    the required context type and afterwards check if a
8327      *    usable context was set now as in 1). The message could
8328      *    be handled by the parent bins of the element and the
8329      *    application.
8330      */
8331     GstMessage *msg;
8332
8333     GST_INFO_OBJECT (element, "posting need context message");
8334     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8335         "drm-preferred-decryption-system-id");
8336     st = (GstStructure *) gst_message_get_structure (msg);
8337     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8338         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8339         NULL);
8340
8341     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8342     gst_element_post_message (element, msg);
8343   }
8344
8345   g_strfreev (filtered_sys_ids);
8346   g_value_unset (&event_list);
8347   gst_query_unref (query);
8348 }
8349
8350 static gboolean
8351 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8352     QtDemuxStream * stream)
8353 {
8354   GstStructure *s;
8355   const gchar *selected_system = NULL;
8356
8357   g_return_val_if_fail (qtdemux != NULL, FALSE);
8358   g_return_val_if_fail (stream != NULL, FALSE);
8359   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8360       FALSE);
8361
8362   if (stream->protection_scheme_type == FOURCC_aavd) {
8363     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8364     if (!gst_structure_has_name (s, "application/x-aavd")) {
8365       gst_structure_set (s,
8366           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8367           NULL);
8368       gst_structure_set_name (s, "application/x-aavd");
8369     }
8370     return TRUE;
8371   }
8372
8373   if (stream->protection_scheme_type != FOURCC_cenc
8374       && stream->protection_scheme_type != FOURCC_cbcs) {
8375     GST_ERROR_OBJECT (qtdemux,
8376         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8377         GST_FOURCC_ARGS (stream->protection_scheme_type));
8378     return FALSE;
8379   }
8380
8381   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8382   if (!gst_structure_has_name (s, "application/x-cenc")
8383       && !gst_structure_has_name (s, "application/x-cbcs")) {
8384     gst_structure_set (s,
8385         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8386     gst_structure_set_name (s,
8387         stream->protection_scheme_type ==
8388         FOURCC_cbcs ? "application/x-cbcs" : "application/x-cenc");
8389   }
8390
8391   if (qtdemux->protection_system_ids == NULL) {
8392     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8393         "cenc protection system information has been found, not setting a "
8394         "protection system UUID");
8395     return TRUE;
8396   }
8397
8398   gst_qtdemux_request_protection_context (qtdemux, stream);
8399   if (qtdemux->preferred_protection_system_id != NULL) {
8400     const gchar *preferred_system_array[] =
8401         { qtdemux->preferred_protection_system_id, NULL };
8402
8403     selected_system = gst_protection_select_system (preferred_system_array);
8404
8405     if (selected_system) {
8406       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8407           qtdemux->preferred_protection_system_id);
8408     } else {
8409       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8410           "because there is no available decryptor",
8411           qtdemux->preferred_protection_system_id);
8412     }
8413   }
8414
8415   if (!selected_system) {
8416     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8417     selected_system = gst_protection_select_system ((const gchar **)
8418         qtdemux->protection_system_ids->pdata);
8419     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8420         qtdemux->protection_system_ids->len - 1);
8421   }
8422
8423   if (!selected_system) {
8424     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8425         "suitable decryptor element has been found");
8426     return FALSE;
8427   }
8428
8429   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8430       selected_system);
8431
8432   gst_structure_set (s,
8433       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8434       NULL);
8435
8436   return TRUE;
8437 }
8438
8439 static gboolean
8440 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8441 {
8442   /* fps is calculated base on the duration of the average framerate since
8443    * qt does not have a fixed framerate. */
8444   gboolean fps_available = TRUE;
8445   guint32 first_duration = 0;
8446
8447   if (stream->n_samples > 0)
8448     first_duration = stream->samples[0].duration;
8449
8450   if ((stream->n_samples == 1 && first_duration == 0)
8451       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8452     /* still frame */
8453     CUR_STREAM (stream)->fps_n = 0;
8454     CUR_STREAM (stream)->fps_d = 1;
8455   } else {
8456     if (stream->duration == 0 || stream->n_samples < 2) {
8457       CUR_STREAM (stream)->fps_n = stream->timescale;
8458       CUR_STREAM (stream)->fps_d = 1;
8459       fps_available = FALSE;
8460     } else {
8461       GstClockTime avg_duration;
8462       guint64 duration;
8463       guint32 n_samples;
8464
8465       /* duration and n_samples can be updated for fragmented format
8466        * so, framerate of fragmented format is calculated using data in a moof */
8467       if (qtdemux->fragmented && stream->n_samples_moof > 0
8468           && stream->duration_moof > 0) {
8469         n_samples = stream->n_samples_moof;
8470         duration = stream->duration_moof;
8471       } else {
8472         n_samples = stream->n_samples;
8473         duration = stream->duration;
8474       }
8475
8476       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8477       /* stream->duration is guint64, timescale, n_samples are guint32 */
8478       avg_duration =
8479           gst_util_uint64_scale_round (duration -
8480           first_duration, GST_SECOND,
8481           (guint64) (stream->timescale) * (n_samples - 1));
8482
8483       GST_LOG_OBJECT (qtdemux,
8484           "Calculating avg sample duration based on stream (or moof) duration %"
8485           G_GUINT64_FORMAT
8486           " minus first sample %u, leaving %d samples gives %"
8487           GST_TIME_FORMAT, duration, first_duration,
8488           n_samples - 1, GST_TIME_ARGS (avg_duration));
8489
8490       fps_available =
8491           gst_video_guess_framerate (avg_duration,
8492           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8493
8494       GST_DEBUG_OBJECT (qtdemux,
8495           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8496           stream->timescale, CUR_STREAM (stream)->fps_n,
8497           CUR_STREAM (stream)->fps_d);
8498     }
8499   }
8500
8501   return fps_available;
8502 }
8503
8504 static gboolean
8505 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8506 {
8507   if (stream->subtype == FOURCC_vide) {
8508     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8509
8510     if (CUR_STREAM (stream)->caps) {
8511       CUR_STREAM (stream)->caps =
8512           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8513
8514       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8515         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8516             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8517             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8518
8519       /* set framerate if calculated framerate is reliable */
8520       if (fps_available) {
8521         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8522             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8523             CUR_STREAM (stream)->fps_d, NULL);
8524       }
8525
8526       /* calculate pixel-aspect-ratio using display width and height */
8527       GST_DEBUG_OBJECT (qtdemux,
8528           "video size %dx%d, target display size %dx%d",
8529           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8530           stream->display_width, stream->display_height);
8531       /* qt file might have pasp atom */
8532       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8533         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8534             CUR_STREAM (stream)->par_h);
8535         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8536             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8537             CUR_STREAM (stream)->par_h, NULL);
8538       } else if (stream->display_width > 0 && stream->display_height > 0
8539           && CUR_STREAM (stream)->width > 0
8540           && CUR_STREAM (stream)->height > 0) {
8541         gint n, d;
8542
8543         /* calculate the pixel aspect ratio using the display and pixel w/h */
8544         n = stream->display_width * CUR_STREAM (stream)->height;
8545         d = stream->display_height * CUR_STREAM (stream)->width;
8546         if (n == d)
8547           n = d = 1;
8548         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8549         CUR_STREAM (stream)->par_w = n;
8550         CUR_STREAM (stream)->par_h = d;
8551         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8552             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8553             CUR_STREAM (stream)->par_h, NULL);
8554       }
8555
8556       if (CUR_STREAM (stream)->interlace_mode > 0) {
8557         if (CUR_STREAM (stream)->interlace_mode == 1) {
8558           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8559               G_TYPE_STRING, "progressive", NULL);
8560         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8561           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8562               G_TYPE_STRING, "interleaved", NULL);
8563           if (CUR_STREAM (stream)->field_order == 9) {
8564             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8565                 G_TYPE_STRING, "top-field-first", NULL);
8566           } else if (CUR_STREAM (stream)->field_order == 14) {
8567             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8568                 G_TYPE_STRING, "bottom-field-first", NULL);
8569           }
8570         }
8571       }
8572
8573       /* Create incomplete colorimetry here if needed */
8574       if (CUR_STREAM (stream)->colorimetry.range ||
8575           CUR_STREAM (stream)->colorimetry.matrix ||
8576           CUR_STREAM (stream)->colorimetry.transfer
8577           || CUR_STREAM (stream)->colorimetry.primaries) {
8578         gchar *colorimetry =
8579             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8580         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8581             G_TYPE_STRING, colorimetry, NULL);
8582         g_free (colorimetry);
8583       }
8584
8585       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8586         guint par_w = 1, par_h = 1;
8587
8588         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8589           par_w = CUR_STREAM (stream)->par_w;
8590           par_h = CUR_STREAM (stream)->par_h;
8591         }
8592
8593         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8594                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8595                 par_h)) {
8596           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8597         }
8598
8599         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8600             "multiview-mode", G_TYPE_STRING,
8601             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8602             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8603             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8604       }
8605     }
8606   }
8607
8608   else if (stream->subtype == FOURCC_soun) {
8609     if (CUR_STREAM (stream)->caps) {
8610       CUR_STREAM (stream)->caps =
8611           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8612       if (CUR_STREAM (stream)->rate > 0)
8613         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8614             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8615       if (CUR_STREAM (stream)->n_channels > 0)
8616         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8617             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8618       if (CUR_STREAM (stream)->n_channels > 2) {
8619         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8620          * correctly; this is just the minimum we can do - assume
8621          * we don't actually have any channel positions. */
8622         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8623             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8624       }
8625     }
8626   }
8627
8628   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8629     const GstStructure *s;
8630     QtDemuxStream *fps_stream = NULL;
8631     gboolean fps_available = FALSE;
8632
8633     /* CEA608 closed caption tracks are a bit special in that each sample
8634      * can contain CCs for multiple frames, and CCs can be omitted and have to
8635      * be inferred from the duration of the sample then.
8636      *
8637      * As such we take the framerate from the (first) video track here for
8638      * CEA608 as there must be one CC byte pair for every video frame
8639      * according to the spec.
8640      *
8641      * For CEA708 all is fine and there is one sample per frame.
8642      */
8643
8644     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8645     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8646       gint i;
8647
8648       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8649         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8650
8651         if (tmp->subtype == FOURCC_vide) {
8652           fps_stream = tmp;
8653           break;
8654         }
8655       }
8656
8657       if (fps_stream) {
8658         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8659         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8660         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8661       }
8662     } else {
8663       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8664       fps_stream = stream;
8665     }
8666
8667     CUR_STREAM (stream)->caps =
8668         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8669
8670     /* set framerate if calculated framerate is reliable */
8671     if (fps_available) {
8672       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8673           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8674           CUR_STREAM (stream)->fps_d, NULL);
8675     }
8676   }
8677
8678   if (stream->pad) {
8679     GstCaps *prev_caps = NULL;
8680
8681     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8682     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8683     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8684     gst_pad_set_active (stream->pad, TRUE);
8685
8686     gst_pad_use_fixed_caps (stream->pad);
8687
8688     if (stream->protected) {
8689       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8690         GST_ERROR_OBJECT (qtdemux,
8691             "Failed to configure protected stream caps.");
8692         return FALSE;
8693       }
8694     }
8695
8696     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8697         CUR_STREAM (stream)->caps);
8698     if (stream->new_stream) {
8699       GstEvent *event;
8700       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8701
8702       event =
8703           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8704           0);
8705       if (event) {
8706         gst_event_parse_stream_flags (event, &stream_flags);
8707         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8708           qtdemux->have_group_id = TRUE;
8709         else
8710           qtdemux->have_group_id = FALSE;
8711         gst_event_unref (event);
8712       } else if (!qtdemux->have_group_id) {
8713         qtdemux->have_group_id = TRUE;
8714         qtdemux->group_id = gst_util_group_id_next ();
8715       }
8716
8717       stream->new_stream = FALSE;
8718       event = gst_event_new_stream_start (stream->stream_id);
8719       if (qtdemux->have_group_id)
8720         gst_event_set_group_id (event, qtdemux->group_id);
8721       if (stream->disabled)
8722         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8723       if (CUR_STREAM (stream)->sparse) {
8724         stream_flags |= GST_STREAM_FLAG_SPARSE;
8725       } else {
8726         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8727       }
8728       gst_event_set_stream_flags (event, stream_flags);
8729       gst_pad_push_event (stream->pad, event);
8730     }
8731
8732     prev_caps = gst_pad_get_current_caps (stream->pad);
8733
8734     if (CUR_STREAM (stream)->caps) {
8735       if (!prev_caps
8736           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8737         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8738             CUR_STREAM (stream)->caps);
8739         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8740       } else {
8741         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8742       }
8743     } else {
8744       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8745     }
8746
8747     if (prev_caps)
8748       gst_caps_unref (prev_caps);
8749     stream->new_caps = FALSE;
8750   }
8751   return TRUE;
8752 }
8753
8754 static void
8755 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8756     QtDemuxStream * stream)
8757 {
8758   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8759     return;
8760
8761   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8762       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8763   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8764           stream->stsd_entries_length)) {
8765     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8766         (_("This file is invalid and cannot be played.")),
8767         ("New sample description id is out of bounds (%d >= %d)",
8768             stream->stsd_sample_description_id, stream->stsd_entries_length));
8769   } else {
8770     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8771     stream->new_caps = TRUE;
8772   }
8773 }
8774
8775 static gboolean
8776 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8777     QtDemuxStream * stream, GstTagList * list)
8778 {
8779   gboolean ret = TRUE;
8780
8781   if (stream->subtype == FOURCC_vide) {
8782     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8783
8784     stream->pad =
8785         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8786     g_free (name);
8787
8788     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8789       gst_object_unref (stream->pad);
8790       stream->pad = NULL;
8791       ret = FALSE;
8792       goto done;
8793     }
8794
8795     qtdemux->n_video_streams++;
8796   } else if (stream->subtype == FOURCC_soun) {
8797     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8798
8799     stream->pad =
8800         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8801     g_free (name);
8802     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8803       gst_object_unref (stream->pad);
8804       stream->pad = NULL;
8805       ret = FALSE;
8806       goto done;
8807     }
8808     qtdemux->n_audio_streams++;
8809   } else if (stream->subtype == FOURCC_strm) {
8810     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8811   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8812       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8813       || stream->subtype == FOURCC_clcp) {
8814     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8815
8816     stream->pad =
8817         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8818     g_free (name);
8819     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8820       gst_object_unref (stream->pad);
8821       stream->pad = NULL;
8822       ret = FALSE;
8823       goto done;
8824     }
8825     qtdemux->n_sub_streams++;
8826   } else if (CUR_STREAM (stream)->caps) {
8827     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8828
8829     stream->pad =
8830         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8831     g_free (name);
8832     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8833       gst_object_unref (stream->pad);
8834       stream->pad = NULL;
8835       ret = FALSE;
8836       goto done;
8837     }
8838     qtdemux->n_video_streams++;
8839   } else {
8840     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8841     goto done;
8842   }
8843
8844   if (stream->pad) {
8845     GList *l;
8846
8847     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8848         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8849     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8850     GST_OBJECT_LOCK (qtdemux);
8851     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8852     GST_OBJECT_UNLOCK (qtdemux);
8853
8854     if (stream->stream_tags)
8855       gst_tag_list_unref (stream->stream_tags);
8856     stream->stream_tags = list;
8857     list = NULL;
8858     /* global tags go on each pad anyway */
8859     stream->send_global_tags = TRUE;
8860     /* send upstream GST_EVENT_PROTECTION events that were received before
8861        this source pad was created */
8862     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8863       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8864   }
8865 done:
8866   if (list)
8867     gst_tag_list_unref (list);
8868   return ret;
8869 }
8870
8871 /* find next atom with @fourcc starting at @offset */
8872 static GstFlowReturn
8873 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8874     guint64 * length, guint32 fourcc)
8875 {
8876   GstFlowReturn ret;
8877   guint32 lfourcc;
8878   GstBuffer *buf;
8879
8880   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8881       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8882
8883   while (TRUE) {
8884     GstMapInfo map;
8885
8886     buf = NULL;
8887     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8888     if (G_UNLIKELY (ret != GST_FLOW_OK))
8889       goto locate_failed;
8890     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8891       /* likely EOF */
8892       ret = GST_FLOW_EOS;
8893       gst_buffer_unref (buf);
8894       goto locate_failed;
8895     }
8896     gst_buffer_map (buf, &map, GST_MAP_READ);
8897     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8898     gst_buffer_unmap (buf, &map);
8899     gst_buffer_unref (buf);
8900
8901     if (G_UNLIKELY (*length == 0)) {
8902       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8903       ret = GST_FLOW_ERROR;
8904       goto locate_failed;
8905     }
8906
8907     if (lfourcc == fourcc) {
8908       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
8909           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8910       break;
8911     } else {
8912       GST_LOG_OBJECT (qtdemux,
8913           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8914           GST_FOURCC_ARGS (lfourcc), *offset);
8915       if (*offset == G_MAXUINT64)
8916         goto locate_failed;
8917       *offset += *length;
8918     }
8919   }
8920
8921   return GST_FLOW_OK;
8922
8923 locate_failed:
8924   {
8925     /* might simply have had last one */
8926     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8927     return ret;
8928   }
8929 }
8930
8931 /* should only do something in pull mode */
8932 /* call with OBJECT lock */
8933 static GstFlowReturn
8934 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8935 {
8936   guint64 length, offset;
8937   GstBuffer *buf = NULL;
8938   GstFlowReturn ret = GST_FLOW_OK;
8939   GstFlowReturn res = GST_FLOW_OK;
8940   GstMapInfo map;
8941
8942   offset = qtdemux->moof_offset;
8943   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8944
8945   if (!offset) {
8946     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8947     return GST_FLOW_EOS;
8948   }
8949
8950   /* best not do pull etc with lock held */
8951   GST_OBJECT_UNLOCK (qtdemux);
8952
8953   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8954   if (ret != GST_FLOW_OK)
8955     goto flow_failed;
8956
8957   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8958   if (G_UNLIKELY (ret != GST_FLOW_OK))
8959     goto flow_failed;
8960   gst_buffer_map (buf, &map, GST_MAP_READ);
8961   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8962     gst_buffer_unmap (buf, &map);
8963     gst_buffer_unref (buf);
8964     buf = NULL;
8965     goto parse_failed;
8966   }
8967
8968   gst_buffer_unmap (buf, &map);
8969   gst_buffer_unref (buf);
8970   buf = NULL;
8971
8972   offset += length;
8973   /* look for next moof */
8974   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8975   if (G_UNLIKELY (ret != GST_FLOW_OK))
8976     goto flow_failed;
8977
8978 exit:
8979   GST_OBJECT_LOCK (qtdemux);
8980
8981   qtdemux->moof_offset = offset;
8982
8983   return res;
8984
8985 parse_failed:
8986   {
8987     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8988     offset = 0;
8989     res = GST_FLOW_ERROR;
8990     goto exit;
8991   }
8992 flow_failed:
8993   {
8994     /* maybe upstream temporarily flushing */
8995     if (ret != GST_FLOW_FLUSHING) {
8996       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8997       offset = 0;
8998     } else {
8999       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9000       /* resume at current position next time */
9001     }
9002     res = ret;
9003     goto exit;
9004   }
9005 }
9006
9007 static void
9008 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9009 {
9010   guint i;
9011   guint32 num_chunks;
9012   gint32 stts_duration;
9013   GstByteWriter stsc, stts, stsz;
9014
9015   /* Each sample has a different size, which we don't support for merging */
9016   if (stream->sample_size == 0) {
9017     GST_DEBUG_OBJECT (qtdemux,
9018         "Not all samples have the same size, not merging");
9019     return;
9020   }
9021
9022   /* The stream has a ctts table, we don't support that */
9023   if (stream->ctts_present) {
9024     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9025     return;
9026   }
9027
9028   /* If there's a sync sample table also ignore this stream */
9029   if (stream->stps_present || stream->stss_present) {
9030     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9031     return;
9032   }
9033
9034   /* If chunks are considered samples already ignore this stream */
9035   if (stream->chunks_are_samples) {
9036     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9037     return;
9038   }
9039
9040   /* Require that all samples have the same duration */
9041   if (stream->n_sample_times > 1) {
9042     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9043     return;
9044   }
9045
9046   /* Parse the stts to get the sample duration and number of samples */
9047   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9048   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9049
9050   /* Parse the number of chunks from the stco manually because the
9051    * reader is already behind that */
9052   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9053
9054   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9055       num_chunks);
9056
9057   /* Now parse stsc, convert chunks into single samples and generate a
9058    * new stsc, stts and stsz from this information */
9059   gst_byte_writer_init (&stsc);
9060   gst_byte_writer_init (&stts);
9061   gst_byte_writer_init (&stsz);
9062
9063   /* Note: we skip fourccs, size, version, flags and other fields of the new
9064    * atoms as the byte readers with them are already behind that position
9065    * anyway and only update the values of those inside the stream directly.
9066    */
9067   stream->n_sample_times = 0;
9068   stream->n_samples = 0;
9069   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9070     guint j;
9071     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9072
9073     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9074     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9075     sample_description_id =
9076         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9077
9078     if (i == stream->n_samples_per_chunk - 1) {
9079       /* +1 because first_chunk is 1-based */
9080       last_chunk = num_chunks + 1;
9081     } else {
9082       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9083     }
9084
9085     GST_DEBUG_OBJECT (qtdemux,
9086         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9087         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9088
9089     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9090     /* One sample in this chunk */
9091     gst_byte_writer_put_uint32_be (&stsc, 1);
9092     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9093
9094     /* For each chunk write a stts and stsz entry now */
9095     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9096     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9097     for (j = first_chunk; j < last_chunk; j++) {
9098       gst_byte_writer_put_uint32_be (&stsz,
9099           stream->sample_size * samples_per_chunk);
9100     }
9101
9102     stream->n_sample_times += 1;
9103     stream->n_samples += last_chunk - first_chunk;
9104   }
9105
9106   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9107
9108   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9109       stream->n_samples, stream->n_sample_times);
9110
9111   /* We don't have a fixed sample size anymore */
9112   stream->sample_size = 0;
9113
9114   /* Free old data for the atoms */
9115   g_free ((gpointer) stream->stsz.data);
9116   stream->stsz.data = NULL;
9117   g_free ((gpointer) stream->stsc.data);
9118   stream->stsc.data = NULL;
9119   g_free ((gpointer) stream->stts.data);
9120   stream->stts.data = NULL;
9121
9122   /* Store new data and replace byte readers */
9123   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9124   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9125   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9126   stream->stts.size = gst_byte_writer_get_size (&stts);
9127   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9128   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9129   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9130   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9131   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9132 }
9133
9134 /* initialise bytereaders for stbl sub-atoms */
9135 static gboolean
9136 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9137 {
9138   stream->stbl_index = -1;      /* no samples have yet been parsed */
9139   stream->sample_index = -1;
9140
9141   /* time-to-sample atom */
9142   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9143     goto corrupt_file;
9144
9145   /* copy atom data into a new buffer for later use */
9146   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9147
9148   /* skip version + flags */
9149   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9150       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9151     goto corrupt_file;
9152   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9153
9154   /* make sure there's enough data */
9155   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9156     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9157     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9158         stream->n_sample_times);
9159     if (!stream->n_sample_times)
9160       goto corrupt_file;
9161   }
9162
9163   /* sync sample atom */
9164   stream->stps_present = FALSE;
9165   if ((stream->stss_present =
9166           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9167               &stream->stss) ? TRUE : FALSE) == TRUE) {
9168     /* copy atom data into a new buffer for later use */
9169     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9170
9171     /* skip version + flags */
9172     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9173         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9174       goto corrupt_file;
9175
9176     if (stream->n_sample_syncs) {
9177       /* make sure there's enough data */
9178       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9179         goto corrupt_file;
9180     }
9181
9182     /* partial sync sample atom */
9183     if ((stream->stps_present =
9184             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9185                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9186       /* copy atom data into a new buffer for later use */
9187       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9188
9189       /* skip version + flags */
9190       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9191           !gst_byte_reader_get_uint32_be (&stream->stps,
9192               &stream->n_sample_partial_syncs))
9193         goto corrupt_file;
9194
9195       /* if there are no entries, the stss table contains the real
9196        * sync samples */
9197       if (stream->n_sample_partial_syncs) {
9198         /* make sure there's enough data */
9199         if (!qt_atom_parser_has_chunks (&stream->stps,
9200                 stream->n_sample_partial_syncs, 4))
9201           goto corrupt_file;
9202       }
9203     }
9204   }
9205
9206   /* sample size */
9207   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9208     goto no_samples;
9209
9210   /* copy atom data into a new buffer for later use */
9211   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9212
9213   /* skip version + flags */
9214   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9215       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9216     goto corrupt_file;
9217
9218   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9219     goto corrupt_file;
9220
9221   if (!stream->n_samples)
9222     goto no_samples;
9223
9224   /* sample-to-chunk atom */
9225   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9226     goto corrupt_file;
9227
9228   /* copy atom data into a new buffer for later use */
9229   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9230
9231   /* skip version + flags */
9232   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9233       !gst_byte_reader_get_uint32_be (&stream->stsc,
9234           &stream->n_samples_per_chunk))
9235     goto corrupt_file;
9236
9237   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9238       stream->n_samples_per_chunk);
9239
9240   /* make sure there's enough data */
9241   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9242           12))
9243     goto corrupt_file;
9244
9245
9246   /* chunk offset */
9247   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9248     stream->co_size = sizeof (guint32);
9249   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9250           &stream->stco))
9251     stream->co_size = sizeof (guint64);
9252   else
9253     goto corrupt_file;
9254
9255   /* copy atom data into a new buffer for later use */
9256   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9257
9258   /* skip version + flags */
9259   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9260     goto corrupt_file;
9261
9262   /* chunks_are_samples == TRUE means treat chunks as samples */
9263   stream->chunks_are_samples = stream->sample_size
9264       && !CUR_STREAM (stream)->sampled;
9265   if (stream->chunks_are_samples) {
9266     /* treat chunks as samples */
9267     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9268       goto corrupt_file;
9269   } else {
9270     /* skip number of entries */
9271     if (!gst_byte_reader_skip (&stream->stco, 4))
9272       goto corrupt_file;
9273
9274     /* make sure there are enough data in the stsz atom */
9275     if (!stream->sample_size) {
9276       /* different sizes for each sample */
9277       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9278         goto corrupt_file;
9279     }
9280   }
9281
9282   /* composition time-to-sample */
9283   if ((stream->ctts_present =
9284           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9285               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9286     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9287
9288     /* copy atom data into a new buffer for later use */
9289     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9290
9291     /* skip version + flags */
9292     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9293         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9294             &stream->n_composition_times))
9295       goto corrupt_file;
9296
9297     /* make sure there's enough data */
9298     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9299             4 + 4))
9300       goto corrupt_file;
9301
9302     /* This is optional, if missing we iterate the ctts */
9303     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9304       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9305           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9306         g_free ((gpointer) cslg.data);
9307         goto corrupt_file;
9308       }
9309     } else {
9310       gint32 cslg_least = 0;
9311       guint num_entries, pos;
9312       gint i;
9313
9314       pos = gst_byte_reader_get_pos (&stream->ctts);
9315       num_entries = stream->n_composition_times;
9316
9317       stream->cslg_shift = 0;
9318
9319       for (i = 0; i < num_entries; i++) {
9320         gint32 offset;
9321
9322         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9323         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9324         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9325          * slightly inaccurate PTS could be more usable than corrupted one */
9326         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9327           GST_WARNING_OBJECT (qtdemux,
9328               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9329               " larger than duration %" G_GUINT64_FORMAT,
9330               offset, stream->duration);
9331
9332           stream->cslg_shift = 0;
9333           stream->ctts_present = FALSE;
9334           goto done;
9335         }
9336
9337         if (offset < cslg_least)
9338           cslg_least = offset;
9339       }
9340
9341       if (cslg_least < 0)
9342         stream->cslg_shift = ABS (cslg_least);
9343       else
9344         stream->cslg_shift = 0;
9345
9346       /* reset the reader so we can generate sample table */
9347       gst_byte_reader_set_pos (&stream->ctts, pos);
9348     }
9349   } else {
9350     /* Ensure the cslg_shift value is consistent so we can use it
9351      * unconditionally to produce TS and Segment */
9352     stream->cslg_shift = 0;
9353   }
9354
9355   /* For raw audio streams especially we might want to merge the samples
9356    * to not output one audio sample per buffer. We're doing this here
9357    * before allocating the sample tables so that from this point onwards
9358    * the number of container samples are static */
9359   if (stream->min_buffer_size > 0) {
9360     qtdemux_merge_sample_table (qtdemux, stream);
9361   }
9362
9363 done:
9364   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9365       stream->n_samples, (guint) sizeof (QtDemuxSample),
9366       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9367
9368   if (stream->n_samples >=
9369       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9370     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9371         "be larger than %uMB (broken file?)", stream->n_samples,
9372         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9373     return FALSE;
9374   }
9375
9376   g_assert (stream->samples == NULL);
9377   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9378   if (!stream->samples) {
9379     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9380         stream->n_samples);
9381     return FALSE;
9382   }
9383
9384   return TRUE;
9385
9386 corrupt_file:
9387   {
9388     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9389         (_("This file is corrupt and cannot be played.")), (NULL));
9390     return FALSE;
9391   }
9392 no_samples:
9393   {
9394     gst_qtdemux_stbl_free (stream);
9395     if (!qtdemux->fragmented) {
9396       /* not quite good */
9397       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9398       return FALSE;
9399     } else {
9400       /* may pick up samples elsewhere */
9401       return TRUE;
9402     }
9403   }
9404 }
9405
9406 /* collect samples from the next sample to be parsed up to sample @n for @stream
9407  * by reading the info from @stbl
9408  *
9409  * This code can be executed from both the streaming thread and the seeking
9410  * thread so it takes the object lock to protect itself
9411  */
9412 static gboolean
9413 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9414 {
9415   gint i, j, k;
9416   QtDemuxSample *samples, *first, *cur, *last;
9417   guint32 n_samples_per_chunk;
9418   guint32 n_samples;
9419
9420   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9421       GST_FOURCC_FORMAT ", pad %s",
9422       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9423       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9424
9425   n_samples = stream->n_samples;
9426
9427   if (n >= n_samples)
9428     goto out_of_samples;
9429
9430   GST_OBJECT_LOCK (qtdemux);
9431   if (n <= stream->stbl_index)
9432     goto already_parsed;
9433
9434   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9435
9436   if (!stream->stsz.data) {
9437     /* so we already parsed and passed all the moov samples;
9438      * onto fragmented ones */
9439     g_assert (qtdemux->fragmented);
9440     goto done;
9441   }
9442
9443   /* pointer to the sample table */
9444   samples = stream->samples;
9445
9446   /* starts from -1, moves to the next sample index to parse */
9447   stream->stbl_index++;
9448
9449   /* keep track of the first and last sample to fill */
9450   first = &samples[stream->stbl_index];
9451   last = &samples[n];
9452
9453   if (!stream->chunks_are_samples) {
9454     /* set the sample sizes */
9455     if (stream->sample_size == 0) {
9456       /* different sizes for each sample */
9457       for (cur = first; cur <= last; cur++) {
9458         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9459         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9460             (guint) (cur - samples), cur->size);
9461       }
9462     } else {
9463       /* samples have the same size */
9464       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9465       for (cur = first; cur <= last; cur++)
9466         cur->size = stream->sample_size;
9467     }
9468   }
9469
9470   n_samples_per_chunk = stream->n_samples_per_chunk;
9471   cur = first;
9472
9473   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9474     guint32 last_chunk;
9475
9476     if (stream->stsc_chunk_index >= stream->last_chunk
9477         || stream->stsc_chunk_index < stream->first_chunk) {
9478       stream->first_chunk =
9479           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9480       stream->samples_per_chunk =
9481           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9482       /* starts from 1 */
9483       stream->stsd_sample_description_id =
9484           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9485
9486       /* chunk numbers are counted from 1 it seems */
9487       if (G_UNLIKELY (stream->first_chunk == 0))
9488         goto corrupt_file;
9489
9490       --stream->first_chunk;
9491
9492       /* the last chunk of each entry is calculated by taking the first chunk
9493        * of the next entry; except if there is no next, where we fake it with
9494        * INT_MAX */
9495       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9496         stream->last_chunk = G_MAXUINT32;
9497       } else {
9498         stream->last_chunk =
9499             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9500         if (G_UNLIKELY (stream->last_chunk == 0))
9501           goto corrupt_file;
9502
9503         --stream->last_chunk;
9504       }
9505
9506       GST_LOG_OBJECT (qtdemux,
9507           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9508           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9509           stream->samples_per_chunk, stream->stsd_sample_description_id);
9510
9511       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9512         goto corrupt_file;
9513
9514       if (stream->last_chunk != G_MAXUINT32) {
9515         if (!qt_atom_parser_peek_sub (&stream->stco,
9516                 stream->first_chunk * stream->co_size,
9517                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9518                 &stream->co_chunk))
9519           goto corrupt_file;
9520
9521       } else {
9522         stream->co_chunk = stream->stco;
9523         if (!gst_byte_reader_skip (&stream->co_chunk,
9524                 stream->first_chunk * stream->co_size))
9525           goto corrupt_file;
9526       }
9527
9528       stream->stsc_chunk_index = stream->first_chunk;
9529     }
9530
9531     last_chunk = stream->last_chunk;
9532
9533     if (stream->chunks_are_samples) {
9534       cur = &samples[stream->stsc_chunk_index];
9535
9536       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9537         if (j > n) {
9538           /* save state */
9539           stream->stsc_chunk_index = j;
9540           goto done;
9541         }
9542
9543         cur->offset =
9544             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9545             stream->co_size);
9546
9547         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9548             "%" G_GUINT64_FORMAT, j, cur->offset);
9549
9550         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9551             CUR_STREAM (stream)->bytes_per_frame > 0) {
9552           cur->size =
9553               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9554               CUR_STREAM (stream)->samples_per_frame *
9555               CUR_STREAM (stream)->bytes_per_frame;
9556         } else {
9557           cur->size = stream->samples_per_chunk;
9558         }
9559
9560         GST_DEBUG_OBJECT (qtdemux,
9561             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9562             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9563                     stream->stco_sample_index)), cur->size);
9564
9565         cur->timestamp = stream->stco_sample_index;
9566         cur->duration = stream->samples_per_chunk;
9567         cur->keyframe = TRUE;
9568         cur++;
9569
9570         stream->stco_sample_index += stream->samples_per_chunk;
9571       }
9572       stream->stsc_chunk_index = j;
9573     } else {
9574       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9575         guint32 samples_per_chunk;
9576         guint64 chunk_offset;
9577
9578         if (!stream->stsc_sample_index
9579             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9580                 &stream->chunk_offset))
9581           goto corrupt_file;
9582
9583         samples_per_chunk = stream->samples_per_chunk;
9584         chunk_offset = stream->chunk_offset;
9585
9586         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9587           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9588               G_GUINT64_FORMAT " and size %d",
9589               (guint) (cur - samples), chunk_offset, cur->size);
9590
9591           cur->offset = chunk_offset;
9592           chunk_offset += cur->size;
9593           cur++;
9594
9595           if (G_UNLIKELY (cur > last)) {
9596             /* save state */
9597             stream->stsc_sample_index = k + 1;
9598             stream->chunk_offset = chunk_offset;
9599             stream->stsc_chunk_index = j;
9600             goto done2;
9601           }
9602         }
9603         stream->stsc_sample_index = 0;
9604       }
9605       stream->stsc_chunk_index = j;
9606     }
9607     stream->stsc_index++;
9608   }
9609
9610   if (stream->chunks_are_samples)
9611     goto ctts;
9612 done2:
9613   {
9614     guint32 n_sample_times;
9615
9616     n_sample_times = stream->n_sample_times;
9617     cur = first;
9618
9619     for (i = stream->stts_index; i < n_sample_times; i++) {
9620       guint32 stts_samples;
9621       gint32 stts_duration;
9622       gint64 stts_time;
9623
9624       if (stream->stts_sample_index >= stream->stts_samples
9625           || !stream->stts_sample_index) {
9626
9627         stream->stts_samples =
9628             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9629         stream->stts_duration =
9630             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9631
9632         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9633             i, stream->stts_samples, stream->stts_duration);
9634
9635         stream->stts_sample_index = 0;
9636       }
9637
9638       stts_samples = stream->stts_samples;
9639       stts_duration = stream->stts_duration;
9640       stts_time = stream->stts_time;
9641
9642       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9643         GST_DEBUG_OBJECT (qtdemux,
9644             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9645             (guint) (cur - samples), j,
9646             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9647
9648         cur->timestamp = stts_time;
9649         cur->duration = stts_duration;
9650
9651         /* avoid 32-bit wrap-around,
9652          * but still mind possible 'negative' duration */
9653         stts_time += (gint64) stts_duration;
9654         cur++;
9655
9656         if (G_UNLIKELY (cur > last)) {
9657           /* save values */
9658           stream->stts_time = stts_time;
9659           stream->stts_sample_index = j + 1;
9660           if (stream->stts_sample_index >= stream->stts_samples)
9661             stream->stts_index++;
9662           goto done3;
9663         }
9664       }
9665       stream->stts_sample_index = 0;
9666       stream->stts_time = stts_time;
9667       stream->stts_index++;
9668     }
9669     /* fill up empty timestamps with the last timestamp, this can happen when
9670      * the last samples do not decode and so we don't have timestamps for them.
9671      * We however look at the last timestamp to estimate the track length so we
9672      * need something in here. */
9673     for (; cur < last; cur++) {
9674       GST_DEBUG_OBJECT (qtdemux,
9675           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9676           (guint) (cur - samples),
9677           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9678       cur->timestamp = stream->stts_time;
9679       cur->duration = -1;
9680     }
9681   }
9682 done3:
9683   {
9684     /* sample sync, can be NULL */
9685     if (stream->stss_present == TRUE) {
9686       guint32 n_sample_syncs;
9687
9688       n_sample_syncs = stream->n_sample_syncs;
9689
9690       if (!n_sample_syncs) {
9691         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9692         stream->all_keyframe = TRUE;
9693       } else {
9694         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9695           /* note that the first sample is index 1, not 0 */
9696           guint32 index;
9697
9698           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9699
9700           if (G_LIKELY (index > 0 && index <= n_samples)) {
9701             index -= 1;
9702             samples[index].keyframe = TRUE;
9703             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9704             /* and exit if we have enough samples */
9705             if (G_UNLIKELY (index >= n)) {
9706               i++;
9707               break;
9708             }
9709           }
9710         }
9711         /* save state */
9712         stream->stss_index = i;
9713       }
9714
9715       /* stps marks partial sync frames like open GOP I-Frames */
9716       if (stream->stps_present == TRUE) {
9717         guint32 n_sample_partial_syncs;
9718
9719         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9720
9721         /* if there are no entries, the stss table contains the real
9722          * sync samples */
9723         if (n_sample_partial_syncs) {
9724           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9725             /* note that the first sample is index 1, not 0 */
9726             guint32 index;
9727
9728             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9729
9730             if (G_LIKELY (index > 0 && index <= n_samples)) {
9731               index -= 1;
9732               samples[index].keyframe = TRUE;
9733               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9734               /* and exit if we have enough samples */
9735               if (G_UNLIKELY (index >= n)) {
9736                 i++;
9737                 break;
9738               }
9739             }
9740           }
9741           /* save state */
9742           stream->stps_index = i;
9743         }
9744       }
9745     } else {
9746       /* no stss, all samples are keyframes */
9747       stream->all_keyframe = TRUE;
9748       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9749     }
9750   }
9751
9752 ctts:
9753   /* composition time to sample */
9754   if (stream->ctts_present == TRUE) {
9755     guint32 n_composition_times;
9756     guint32 ctts_count;
9757     gint32 ctts_soffset;
9758
9759     /* Fill in the pts_offsets */
9760     cur = first;
9761     n_composition_times = stream->n_composition_times;
9762
9763     for (i = stream->ctts_index; i < n_composition_times; i++) {
9764       if (stream->ctts_sample_index >= stream->ctts_count
9765           || !stream->ctts_sample_index) {
9766         stream->ctts_count =
9767             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9768         stream->ctts_soffset =
9769             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9770         stream->ctts_sample_index = 0;
9771       }
9772
9773       ctts_count = stream->ctts_count;
9774       ctts_soffset = stream->ctts_soffset;
9775
9776       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9777         cur->pts_offset = ctts_soffset;
9778         cur++;
9779
9780         if (G_UNLIKELY (cur > last)) {
9781           /* save state */
9782           stream->ctts_sample_index = j + 1;
9783           goto done;
9784         }
9785       }
9786       stream->ctts_sample_index = 0;
9787       stream->ctts_index++;
9788     }
9789   }
9790 done:
9791   stream->stbl_index = n;
9792   /* if index has been completely parsed, free data that is no-longer needed */
9793   if (n + 1 == stream->n_samples) {
9794     gst_qtdemux_stbl_free (stream);
9795     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9796     if (qtdemux->pullbased) {
9797       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9798       while (n + 1 == stream->n_samples)
9799         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9800           break;
9801     }
9802   }
9803   GST_OBJECT_UNLOCK (qtdemux);
9804
9805   return TRUE;
9806
9807   /* SUCCESS */
9808 already_parsed:
9809   {
9810     GST_LOG_OBJECT (qtdemux,
9811         "Tried to parse up to sample %u but this sample has already been parsed",
9812         n);
9813     /* if fragmented, there may be more */
9814     if (qtdemux->fragmented && n == stream->stbl_index)
9815       goto done;
9816     GST_OBJECT_UNLOCK (qtdemux);
9817     return TRUE;
9818   }
9819   /* ERRORS */
9820 out_of_samples:
9821   {
9822     GST_LOG_OBJECT (qtdemux,
9823         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9824         stream->n_samples);
9825     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9826         (_("This file is corrupt and cannot be played.")), (NULL));
9827     return FALSE;
9828   }
9829 corrupt_file:
9830   {
9831     GST_OBJECT_UNLOCK (qtdemux);
9832     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9833         (_("This file is corrupt and cannot be played.")), (NULL));
9834     return FALSE;
9835   }
9836 }
9837
9838 /* collect all segment info for @stream.
9839  */
9840 static gboolean
9841 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9842     GNode * trak)
9843 {
9844   GNode *edts;
9845   /* accept edts if they contain gaps at start and there is only
9846    * one media segment */
9847   gboolean allow_pushbased_edts = TRUE;
9848   gint media_segments_count = 0;
9849
9850   /* parse and prepare segment info from the edit list */
9851   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9852   stream->n_segments = 0;
9853   stream->segments = NULL;
9854   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9855     GNode *elst;
9856     gint n_segments;
9857     gint segment_number, entry_size;
9858     guint64 time;
9859     GstClockTime stime;
9860     const guint8 *buffer;
9861     guint8 version;
9862     guint32 size;
9863
9864     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9865     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9866       goto done;
9867
9868     buffer = elst->data;
9869
9870     size = QT_UINT32 (buffer);
9871     /* version, flags, n_segments */
9872     if (size < 16) {
9873       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9874       goto done;
9875     }
9876     version = QT_UINT8 (buffer + 8);
9877     entry_size = (version == 1) ? 20 : 12;
9878
9879     n_segments = QT_UINT32 (buffer + 12);
9880
9881     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9882       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9883       goto done;
9884     }
9885
9886     /* we might allocate a bit too much, at least allocate 1 segment */
9887     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9888
9889     /* segments always start from 0 */
9890     time = 0;
9891     stime = 0;
9892     buffer += 16;
9893     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9894       guint64 duration;
9895       guint64 media_time;
9896       gboolean empty_edit = FALSE;
9897       QtDemuxSegment *segment;
9898       guint32 rate_int;
9899       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9900
9901       if (version == 1) {
9902         media_time = QT_UINT64 (buffer + 8);
9903         duration = QT_UINT64 (buffer);
9904         if (media_time == G_MAXUINT64)
9905           empty_edit = TRUE;
9906       } else {
9907         media_time = QT_UINT32 (buffer + 4);
9908         duration = QT_UINT32 (buffer);
9909         if (media_time == G_MAXUINT32)
9910           empty_edit = TRUE;
9911       }
9912
9913       if (!empty_edit)
9914         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9915
9916       segment = &stream->segments[segment_number];
9917
9918       /* time and duration expressed in global timescale */
9919       segment->time = stime;
9920       if (duration != 0 || empty_edit) {
9921         /* edge case: empty edits with duration=zero are treated here.
9922          * (files should not have these anyway). */
9923
9924         /* add non scaled values so we don't cause roundoff errors */
9925         time += duration;
9926         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9927         segment->duration = stime - segment->time;
9928       } else {
9929         /* zero duration does not imply media_start == media_stop
9930          * but, only specify media_start. The edit ends with the track. */
9931         stime = segment->duration = GST_CLOCK_TIME_NONE;
9932         /* Don't allow more edits after this one. */
9933         n_segments = segment_number + 1;
9934       }
9935       segment->stop_time = stime;
9936
9937       segment->trak_media_start = media_time;
9938       /* media_time expressed in stream timescale */
9939       if (!empty_edit) {
9940         segment->media_start = media_start;
9941         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9942             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9943         media_segments_count++;
9944       } else {
9945         segment->media_start = GST_CLOCK_TIME_NONE;
9946         segment->media_stop = GST_CLOCK_TIME_NONE;
9947       }
9948       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9949
9950       if (rate_int <= 1) {
9951         /* 0 is not allowed, some programs write 1 instead of the floating point
9952          * value */
9953         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9954             rate_int);
9955         segment->rate = 1;
9956       } else {
9957         segment->rate = rate_int / 65536.0;
9958       }
9959
9960       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9961           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9962           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9963           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9964           segment_number, GST_TIME_ARGS (segment->time),
9965           GST_TIME_ARGS (segment->duration),
9966           GST_TIME_ARGS (segment->media_start), media_time,
9967           GST_TIME_ARGS (segment->media_stop),
9968           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9969           stream->timescale);
9970       if (segment->stop_time > qtdemux->segment.stop &&
9971           !qtdemux->upstream_format_is_time) {
9972         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9973             " extends to %" GST_TIME_FORMAT
9974             " past the end of the declared movie duration %" GST_TIME_FORMAT
9975             " movie segment will be extended", segment_number,
9976             GST_TIME_ARGS (segment->stop_time),
9977             GST_TIME_ARGS (qtdemux->segment.stop));
9978         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9979       }
9980
9981       buffer += entry_size;
9982     }
9983     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9984     stream->n_segments = n_segments;
9985     if (media_segments_count != 1)
9986       allow_pushbased_edts = FALSE;
9987   }
9988 done:
9989
9990   /* push based does not handle segments, so act accordingly here,
9991    * and warn if applicable */
9992   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9993     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9994     /* remove and use default one below, we stream like it anyway */
9995     g_free (stream->segments);
9996     stream->segments = NULL;
9997     stream->n_segments = 0;
9998   }
9999
10000   /* no segments, create one to play the complete trak */
10001   if (stream->n_segments == 0) {
10002     GstClockTime stream_duration =
10003         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10004
10005     if (stream->segments == NULL)
10006       stream->segments = g_new (QtDemuxSegment, 1);
10007
10008     /* represent unknown our way */
10009     if (stream_duration == 0)
10010       stream_duration = GST_CLOCK_TIME_NONE;
10011
10012     stream->segments[0].time = 0;
10013     stream->segments[0].stop_time = stream_duration;
10014     stream->segments[0].duration = stream_duration;
10015     stream->segments[0].media_start = 0;
10016     stream->segments[0].media_stop = stream_duration;
10017     stream->segments[0].rate = 1.0;
10018     stream->segments[0].trak_media_start = 0;
10019
10020     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10021         GST_TIME_ARGS (stream_duration));
10022     stream->n_segments = 1;
10023     stream->dummy_segment = TRUE;
10024   }
10025   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10026
10027   return TRUE;
10028 }
10029
10030 /*
10031  * Parses the stsd atom of a svq3 trak looking for
10032  * the SMI and gama atoms.
10033  */
10034 static void
10035 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10036     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10037 {
10038   const guint8 *_gamma = NULL;
10039   GstBuffer *_seqh = NULL;
10040   const guint8 *stsd_data = stsd_entry_data;
10041   guint32 length = QT_UINT32 (stsd_data);
10042   guint16 version;
10043
10044   if (length < 32) {
10045     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10046     goto end;
10047   }
10048
10049   stsd_data += 16;
10050   length -= 16;
10051   version = QT_UINT16 (stsd_data);
10052   if (version == 3) {
10053     if (length >= 70) {
10054       length -= 70;
10055       stsd_data += 70;
10056       while (length > 8) {
10057         guint32 fourcc, size;
10058         const guint8 *data;
10059         size = QT_UINT32 (stsd_data);
10060         fourcc = QT_FOURCC (stsd_data + 4);
10061         data = stsd_data + 8;
10062
10063         if (size == 0) {
10064           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10065               "svq3 atom parsing");
10066           goto end;
10067         }
10068
10069         switch (fourcc) {
10070           case FOURCC_gama:{
10071             if (size == 12) {
10072               _gamma = data;
10073             } else {
10074               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10075                   " for gama atom, expected 12", size);
10076             }
10077             break;
10078           }
10079           case FOURCC_SMI_:{
10080             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10081               guint32 seqh_size;
10082               if (_seqh != NULL) {
10083                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10084                     " found, ignoring");
10085               } else {
10086                 seqh_size = QT_UINT32 (data + 4);
10087                 if (seqh_size > 0) {
10088                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10089                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10090                 }
10091               }
10092             }
10093             break;
10094           }
10095           default:{
10096             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10097                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10098           }
10099         }
10100
10101         if (size <= length) {
10102           length -= size;
10103           stsd_data += size;
10104         }
10105       }
10106     } else {
10107       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10108     }
10109   } else {
10110     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10111         G_GUINT16_FORMAT, version);
10112     goto end;
10113   }
10114
10115 end:
10116   if (gamma) {
10117     *gamma = _gamma;
10118   }
10119   if (seqh) {
10120     *seqh = _seqh;
10121   } else if (_seqh) {
10122     gst_buffer_unref (_seqh);
10123   }
10124 }
10125
10126 static gchar *
10127 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10128 {
10129   GNode *dinf;
10130   GstByteReader dref;
10131   gchar *uri = NULL;
10132
10133   /*
10134    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10135    * atom that might contain a 'data' atom with the rtsp uri.
10136    * This case was reported in bug #597497, some info about
10137    * the hndl atom can be found in TN1195
10138    */
10139   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10140   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10141
10142   if (dinf) {
10143     guint32 dref_num_entries = 0;
10144     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10145         gst_byte_reader_skip (&dref, 4) &&
10146         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10147       gint i;
10148
10149       /* search dref entries for hndl atom */
10150       for (i = 0; i < dref_num_entries; i++) {
10151         guint32 size = 0, type;
10152         guint8 string_len = 0;
10153         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10154             qt_atom_parser_get_fourcc (&dref, &type)) {
10155           if (type == FOURCC_hndl) {
10156             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10157
10158             /* skip data reference handle bytes and the
10159              * following pascal string and some extra 4
10160              * bytes I have no idea what are */
10161             if (!gst_byte_reader_skip (&dref, 4) ||
10162                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10163                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10164               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10165               break;
10166             }
10167
10168             /* iterate over the atoms to find the data atom */
10169             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10170               guint32 atom_size;
10171               guint32 atom_type;
10172
10173               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10174                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10175                 if (atom_type == FOURCC_data) {
10176                   const guint8 *uri_aux = NULL;
10177
10178                   /* found the data atom that might contain the rtsp uri */
10179                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10180                       "hndl atom, interpreting it as an URI");
10181                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10182                           &uri_aux)) {
10183                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10184                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10185                     else
10186                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10187                           "didn't contain a rtsp address");
10188                   } else {
10189                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10190                         "atom contents");
10191                   }
10192                   break;
10193                 }
10194                 /* skipping to the next entry */
10195                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10196                   break;
10197               } else {
10198                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10199                     "atom header");
10200                 break;
10201               }
10202             }
10203             break;
10204           }
10205           /* skip to the next entry */
10206           if (!gst_byte_reader_skip (&dref, size - 8))
10207             break;
10208         } else {
10209           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10210         }
10211       }
10212       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10213     }
10214   }
10215   return uri;
10216 }
10217
10218 #define AMR_NB_ALL_MODES        0x81ff
10219 #define AMR_WB_ALL_MODES        0x83ff
10220 static guint
10221 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10222 {
10223   /* The 'damr' atom is of the form:
10224    *
10225    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10226    *    32 b       8 b          16 b           8 b                 8 b
10227    *
10228    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10229    * represents the highest mode used in the stream (and thus the maximum
10230    * bitrate), with a couple of special cases as seen below.
10231    */
10232
10233   /* Map of frame type ID -> bitrate */
10234   static const guint nb_bitrates[] = {
10235     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10236   };
10237   static const guint wb_bitrates[] = {
10238     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10239   };
10240   GstMapInfo map;
10241   gsize max_mode;
10242   guint16 mode_set;
10243
10244   gst_buffer_map (buf, &map, GST_MAP_READ);
10245
10246   if (map.size != 0x11) {
10247     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10248     goto bad_data;
10249   }
10250
10251   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10252     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10253         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10254     goto bad_data;
10255   }
10256
10257   mode_set = QT_UINT16 (map.data + 13);
10258
10259   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10260     max_mode = 7 + (wb ? 1 : 0);
10261   else
10262     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10263     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10264
10265   if (max_mode == -1) {
10266     GST_DEBUG ("No mode indication was found (mode set) = %x",
10267         (guint) mode_set);
10268     goto bad_data;
10269   }
10270
10271   gst_buffer_unmap (buf, &map);
10272   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10273
10274 bad_data:
10275   gst_buffer_unmap (buf, &map);
10276   return 0;
10277 }
10278
10279 static gboolean
10280 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10281     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10282 {
10283   /*
10284    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10285    * [0 1 2]
10286    * [3 4 5]
10287    * [6 7 8]
10288    */
10289
10290   if (gst_byte_reader_get_remaining (reader) < 36)
10291     return FALSE;
10292
10293   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10294   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10295   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10296   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10297   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10298   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10299   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10300   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10301   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10302
10303   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10304   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10305       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10306       matrix[2] & 0xFF);
10307   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10308       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10309       matrix[5] & 0xFF);
10310   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10311       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10312       matrix[8] & 0xFF);
10313
10314   return TRUE;
10315 }
10316
10317 static void
10318 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10319     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10320 {
10321
10322 /* [a b c]
10323  * [d e f]
10324  * [g h i]
10325  *
10326  * This macro will only compare value abdegh, it expects cfi to have already
10327  * been checked
10328  */
10329 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10330                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10331
10332   /* only handle the cases where the last column has standard values */
10333   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10334     const gchar *rotation_tag = NULL;
10335
10336     /* no rotation needed */
10337     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10338       /* NOP */
10339     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10340       rotation_tag = "rotate-90";
10341     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10342       rotation_tag = "rotate-180";
10343     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10344       rotation_tag = "rotate-270";
10345     } else {
10346       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10347     }
10348
10349     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10350         GST_STR_NULL (rotation_tag));
10351     if (rotation_tag != NULL) {
10352       if (*taglist == NULL)
10353         *taglist = gst_tag_list_new_empty ();
10354       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10355           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10356     }
10357   } else {
10358     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10359   }
10360 }
10361
10362 static gboolean
10363 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10364     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10365 {
10366   GNode *adrm;
10367   guint32 adrm_size;
10368   GstBuffer *adrm_buf = NULL;
10369   QtDemuxAavdEncryptionInfo *info;
10370
10371   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10372   if (G_UNLIKELY (!adrm)) {
10373     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10374     return FALSE;
10375   }
10376   adrm_size = QT_UINT32 (adrm->data);
10377   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10378
10379   stream->protection_scheme_type = FOURCC_aavd;
10380
10381   if (!stream->protection_scheme_info)
10382     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10383
10384   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10385
10386   if (info->default_properties)
10387     gst_structure_free (info->default_properties);
10388   info->default_properties = gst_structure_new ("application/x-aavd",
10389       "encrypted", G_TYPE_BOOLEAN, TRUE,
10390       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10391   gst_buffer_unref (adrm_buf);
10392
10393   *original_fmt = FOURCC_mp4a;
10394   return TRUE;
10395 }
10396
10397 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10398  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10399  * Common Encryption (cenc), the function will also parse the tenc box (defined
10400  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10401  * (typically an enc[v|a|t|s] sample entry); the function will set
10402  * @original_fmt to the fourcc of the original unencrypted stream format.
10403  * Returns TRUE if successful; FALSE otherwise. */
10404 static gboolean
10405 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10406     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10407 {
10408   GNode *sinf;
10409   GNode *frma;
10410   GNode *schm;
10411   GNode *schi;
10412   QtDemuxCencSampleSetInfo *info;
10413   GNode *tenc;
10414   const guint8 *tenc_data;
10415
10416   g_return_val_if_fail (qtdemux != NULL, FALSE);
10417   g_return_val_if_fail (stream != NULL, FALSE);
10418   g_return_val_if_fail (container != NULL, FALSE);
10419   g_return_val_if_fail (original_fmt != NULL, FALSE);
10420
10421   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10422   if (G_UNLIKELY (!sinf)) {
10423     if (stream->protection_scheme_type == FOURCC_cenc
10424         || stream->protection_scheme_type == FOURCC_cbcs) {
10425       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10426           "mandatory for Common Encryption");
10427       return FALSE;
10428     }
10429     return TRUE;
10430   }
10431
10432   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10433   if (G_UNLIKELY (!frma)) {
10434     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10435     return FALSE;
10436   }
10437
10438   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10439   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10440       GST_FOURCC_ARGS (*original_fmt));
10441
10442   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10443   if (!schm) {
10444     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10445     return FALSE;
10446   }
10447   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10448   stream->protection_scheme_version =
10449       QT_UINT32 ((const guint8 *) schm->data + 16);
10450
10451   GST_DEBUG_OBJECT (qtdemux,
10452       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10453       "protection_scheme_version: %#010x",
10454       GST_FOURCC_ARGS (stream->protection_scheme_type),
10455       stream->protection_scheme_version);
10456
10457   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10458   if (!schi) {
10459     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10460     return FALSE;
10461   }
10462   if (stream->protection_scheme_type != FOURCC_cenc &&
10463       stream->protection_scheme_type != FOURCC_piff &&
10464       stream->protection_scheme_type != FOURCC_cbcs) {
10465     GST_ERROR_OBJECT (qtdemux,
10466         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10467         GST_FOURCC_ARGS (stream->protection_scheme_type));
10468     return FALSE;
10469   }
10470
10471   if (G_UNLIKELY (!stream->protection_scheme_info))
10472     stream->protection_scheme_info =
10473         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10474
10475   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10476
10477   if (stream->protection_scheme_type == FOURCC_cenc
10478       || stream->protection_scheme_type == FOURCC_cbcs) {
10479     guint8 is_encrypted;
10480     guint8 iv_size;
10481     guint8 constant_iv_size = 0;
10482     const guint8 *default_kid;
10483     guint8 crypt_byte_block = 0;
10484     guint8 skip_byte_block = 0;
10485     const guint8 *constant_iv = NULL;
10486
10487     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10488     if (!tenc) {
10489       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10490           "which is mandatory for Common Encryption");
10491       return FALSE;
10492     }
10493     tenc_data = (const guint8 *) tenc->data + 12;
10494     is_encrypted = QT_UINT8 (tenc_data + 2);
10495     iv_size = QT_UINT8 (tenc_data + 3);
10496     default_kid = (tenc_data + 4);
10497     if (stream->protection_scheme_type == FOURCC_cbcs) {
10498       guint8 possible_pattern_info;
10499       if (iv_size == 0) {
10500         constant_iv_size = QT_UINT8 (tenc_data + 20);
10501         if (constant_iv_size != 8 && constant_iv_size != 16) {
10502           GST_ERROR_OBJECT (qtdemux,
10503               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10504           return FALSE;
10505         }
10506         constant_iv = (tenc_data + 21);
10507       }
10508       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10509       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10510       skip_byte_block = possible_pattern_info & 0x0f;
10511     }
10512     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10513         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10514         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10515   } else if (stream->protection_scheme_type == FOURCC_piff) {
10516     GstByteReader br;
10517     static const guint8 piff_track_encryption_uuid[] = {
10518       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10519       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10520     };
10521
10522     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10523     if (!tenc) {
10524       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10525           "which is mandatory for Common Encryption");
10526       return FALSE;
10527     }
10528
10529     tenc_data = (const guint8 *) tenc->data + 8;
10530     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10531       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10532       GST_ERROR_OBJECT (qtdemux,
10533           "Unsupported track encryption box with uuid: %s", box_uuid);
10534       g_free (box_uuid);
10535       return FALSE;
10536     }
10537     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10538     gst_byte_reader_init (&br, tenc_data, 20);
10539     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10540       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10541       return FALSE;
10542     }
10543     stream->protection_scheme_type = FOURCC_cenc;
10544   }
10545
10546   return TRUE;
10547 }
10548
10549 static gint
10550 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10551     QtDemuxStream ** stream2)
10552 {
10553   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10554 }
10555
10556 static gboolean
10557 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10558     GNode * stbl)
10559 {
10560   GNode *svmi;
10561
10562   /*parse svmi header if existing */
10563   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10564   if (svmi) {
10565     guint len = QT_UINT32 ((guint8 *) svmi->data);
10566     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10567     if (!version) {
10568       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10569       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10570       guint8 frame_type, frame_layout;
10571       guint32 stereo_mono_change_count;
10572
10573       if (len < 18)
10574         return FALSE;
10575
10576       /* MPEG-A stereo video */
10577       if (qtdemux->major_brand == FOURCC_ss02)
10578         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10579
10580       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10581       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10582       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10583
10584       switch (frame_type) {
10585         case 0:
10586           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10587           break;
10588         case 1:
10589           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10590           break;
10591         case 2:
10592           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10593           break;
10594         case 3:
10595           /* mode 3 is primary/secondary view sequence, ie
10596            * left/right views in separate tracks. See section 7.2
10597            * of ISO/IEC 23000-11:2009 */
10598           /* In the future this might be supported using related
10599            * streams, like an enhancement track - if files like this
10600            * ever exist */
10601           GST_FIXME_OBJECT (qtdemux,
10602               "Implement stereo video in separate streams");
10603       }
10604
10605       if ((frame_layout & 0x1) == 0)
10606         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10607
10608       GST_LOG_OBJECT (qtdemux,
10609           "StereoVideo: composition type: %u, is_left_first: %u",
10610           frame_type, frame_layout);
10611
10612       if (stereo_mono_change_count > 1) {
10613         GST_FIXME_OBJECT (qtdemux,
10614             "Mixed-mono flags are not yet supported in qtdemux.");
10615       }
10616
10617       stream->multiview_mode = mode;
10618       stream->multiview_flags = flags;
10619     }
10620   }
10621
10622   return TRUE;
10623 }
10624
10625 /* parse the traks.
10626  * With each track we associate a new QtDemuxStream that contains all the info
10627  * about the trak.
10628  * traks that do not decode to something (like strm traks) will not have a pad.
10629  */
10630 static gboolean
10631 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10632 {
10633   GstByteReader tkhd;
10634   int offset;
10635   GNode *mdia;
10636   GNode *mdhd;
10637   GNode *hdlr;
10638   GNode *minf;
10639   GNode *stbl;
10640   GNode *stsd;
10641   GNode *mp4a;
10642   GNode *mp4v;
10643   GNode *esds;
10644   GNode *tref;
10645   GNode *udta;
10646
10647   QtDemuxStream *stream = NULL;
10648   const guint8 *stsd_data;
10649   const guint8 *stsd_entry_data;
10650   guint remaining_stsd_len;
10651   guint stsd_entry_count;
10652   guint stsd_index;
10653   guint16 lang_code;            /* quicktime lang code or packed iso code */
10654   guint32 version;
10655   guint32 tkhd_flags = 0;
10656   guint8 tkhd_version = 0;
10657   guint32 w = 0, h = 0;
10658   guint value_size, stsd_len, len;
10659   guint32 track_id;
10660   guint32 dummy;
10661
10662   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10663
10664   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10665       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10666       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10667     goto corrupt_file;
10668
10669   /* pick between 64 or 32 bits */
10670   value_size = tkhd_version == 1 ? 8 : 4;
10671   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10672       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10673     goto corrupt_file;
10674
10675   /* Check if current moov has duplicated track_id */
10676   if (qtdemux_find_stream (qtdemux, track_id))
10677     goto existing_stream;
10678
10679   stream = _create_stream (qtdemux, track_id);
10680   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10681
10682   /* need defaults for fragments */
10683   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10684
10685   if ((tkhd_flags & 1) == 0)
10686     stream->disabled = TRUE;
10687
10688   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10689       tkhd_version, tkhd_flags, stream->track_id);
10690
10691   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10692     goto corrupt_file;
10693
10694   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10695     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10696     if (qtdemux->major_brand != FOURCC_mjp2 ||
10697         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10698       goto corrupt_file;
10699   }
10700
10701   len = QT_UINT32 ((guint8 *) mdhd->data);
10702   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10703   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10704   if (version == 0x01000000) {
10705     if (len < 42)
10706       goto corrupt_file;
10707     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10708     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10709     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10710   } else {
10711     if (len < 30)
10712       goto corrupt_file;
10713     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10714     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10715     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10716   }
10717
10718   if (lang_code < 0x400) {
10719     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10720   } else if (lang_code == 0x7fff) {
10721     stream->lang_id[0] = 0;     /* unspecified */
10722   } else {
10723     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10724     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10725     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10726     stream->lang_id[3] = 0;
10727   }
10728
10729   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10730       stream->timescale);
10731   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10732       stream->duration);
10733   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10734       lang_code, stream->lang_id);
10735
10736   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10737     goto corrupt_file;
10738
10739   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10740     /* chapters track reference */
10741     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10742     if (chap) {
10743       gsize length = GST_READ_UINT32_BE (chap->data);
10744       if (qtdemux->chapters_track_id)
10745         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10746
10747       if (length >= 12) {
10748         qtdemux->chapters_track_id =
10749             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10750       }
10751     }
10752   }
10753
10754   /* fragmented files may have bogus duration in moov */
10755   if (!qtdemux->fragmented &&
10756       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10757     guint64 tdur1, tdur2;
10758
10759     /* don't overflow */
10760     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10761     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10762
10763     /* HACK:
10764      * some of those trailers, nowadays, have prologue images that are
10765      * themselves video tracks as well. I haven't really found a way to
10766      * identify those yet, except for just looking at their duration. */
10767     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10768       GST_WARNING_OBJECT (qtdemux,
10769           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10770           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10771           "found, assuming preview image or something; skipping track",
10772           stream->duration, stream->timescale, qtdemux->duration,
10773           qtdemux->timescale);
10774       gst_qtdemux_stream_unref (stream);
10775       return TRUE;
10776     }
10777   }
10778
10779   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10780     goto corrupt_file;
10781
10782   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10783       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10784
10785   len = QT_UINT32 ((guint8 *) hdlr->data);
10786   if (len >= 20)
10787     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10788   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10789       GST_FOURCC_ARGS (stream->subtype));
10790
10791   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10792     goto corrupt_file;
10793
10794   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10795     goto corrupt_file;
10796
10797   /* Parse out svmi (and later st3d/sv3d) atoms */
10798   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10799     goto corrupt_file;
10800
10801   /* parse rest of tkhd */
10802   if (stream->subtype == FOURCC_vide) {
10803     guint32 matrix[9];
10804
10805     /* version 1 uses some 64-bit ints */
10806     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10807       goto corrupt_file;
10808
10809     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10810       goto corrupt_file;
10811
10812     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10813         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10814       goto corrupt_file;
10815
10816     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10817         &stream->stream_tags);
10818   }
10819
10820   /* parse stsd */
10821   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10822     goto corrupt_file;
10823   stsd_data = (const guint8 *) stsd->data;
10824
10825   /* stsd should at least have one entry */
10826   stsd_len = QT_UINT32 (stsd_data);
10827   if (stsd_len < 24) {
10828     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10829     if (stream->subtype == FOURCC_vivo) {
10830       gst_qtdemux_stream_unref (stream);
10831       return TRUE;
10832     } else {
10833       goto corrupt_file;
10834     }
10835   }
10836
10837   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10838   /* each stsd entry must contain at least 8 bytes */
10839   if (stream->stsd_entries_length == 0
10840       || stream->stsd_entries_length > stsd_len / 8) {
10841     stream->stsd_entries_length = 0;
10842     goto corrupt_file;
10843   }
10844   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10845   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10846   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10847
10848   stsd_entry_data = stsd_data + 16;
10849   remaining_stsd_len = stsd_len - 16;
10850   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10851     guint32 fourcc;
10852     gchar *codec = NULL;
10853     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10854
10855     /* and that entry should fit within stsd */
10856     len = QT_UINT32 (stsd_entry_data);
10857     if (len > remaining_stsd_len)
10858       goto corrupt_file;
10859
10860     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10861     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10862         GST_FOURCC_ARGS (entry->fourcc));
10863     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10864
10865     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10866       goto error_encrypted;
10867
10868     if (fourcc == FOURCC_aavd) {
10869       if (stream->subtype != FOURCC_soun) {
10870         GST_ERROR_OBJECT (qtdemux,
10871             "Unexpeced stsd type 'aavd' outside 'soun' track");
10872       } else {
10873         /* encrypted audio with sound sample description v0 */
10874         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10875         stream->protected = TRUE;
10876         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
10877           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10878       }
10879     }
10880
10881     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10882       /* FIXME this looks wrong, there might be multiple children
10883        * with the same type */
10884       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10885       stream->protected = TRUE;
10886       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10887         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10888     }
10889
10890     if (stream->subtype == FOURCC_vide) {
10891       GNode *colr;
10892       GNode *fiel;
10893       GNode *pasp;
10894       gboolean gray;
10895       gint depth, palette_size, palette_count;
10896       guint32 *palette_data = NULL;
10897
10898       entry->sampled = TRUE;
10899
10900       stream->display_width = w >> 16;
10901       stream->display_height = h >> 16;
10902
10903       offset = 16;
10904       if (len < 86)             /* TODO verify */
10905         goto corrupt_file;
10906
10907       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10908       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10909       entry->fps_n = 0;         /* this is filled in later */
10910       entry->fps_d = 0;         /* this is filled in later */
10911       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10912       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10913
10914       /* if color_table_id is 0, ctab atom must follow; however some files
10915        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10916        * if color table is not present we'll correct the value */
10917       if (entry->color_table_id == 0 &&
10918           (len < 90
10919               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10920         entry->color_table_id = -1;
10921       }
10922
10923       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10924           entry->width, entry->height, entry->bits_per_sample,
10925           entry->color_table_id);
10926
10927       depth = entry->bits_per_sample;
10928
10929       /* more than 32 bits means grayscale */
10930       gray = (depth > 32);
10931       /* low 32 bits specify the depth  */
10932       depth &= 0x1F;
10933
10934       /* different number of palette entries is determined by depth. */
10935       palette_count = 0;
10936       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10937         palette_count = (1 << depth);
10938       palette_size = palette_count * 4;
10939
10940       if (entry->color_table_id) {
10941         switch (palette_count) {
10942           case 0:
10943             break;
10944           case 2:
10945             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
10946             break;
10947           case 4:
10948             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
10949             break;
10950           case 16:
10951             if (gray)
10952               palette_data =
10953                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
10954             else
10955               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
10956             break;
10957           case 256:
10958             if (gray)
10959               palette_data =
10960                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
10961             else
10962               palette_data =
10963                   g_memdup2 (ff_qt_default_palette_256, palette_size);
10964             break;
10965           default:
10966             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10967                 (_("The video in this file might not play correctly.")),
10968                 ("unsupported palette depth %d", depth));
10969             break;
10970         }
10971       } else {
10972         gint i, j, start, end;
10973
10974         if (len < 94)
10975           goto corrupt_file;
10976
10977         /* read table */
10978         start = QT_UINT32 (stsd_entry_data + offset + 70);
10979         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10980         end = QT_UINT16 (stsd_entry_data + offset + 76);
10981
10982         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10983             start, end, palette_count);
10984
10985         if (end > 255)
10986           end = 255;
10987         if (start > end)
10988           start = end;
10989
10990         if (len < 94 + (end - start) * 8)
10991           goto corrupt_file;
10992
10993         /* palette is always the same size */
10994         palette_data = g_malloc0 (256 * 4);
10995         palette_size = 256 * 4;
10996
10997         for (j = 0, i = start; i <= end; j++, i++) {
10998           guint32 a, r, g, b;
10999
11000           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11001           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11002           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11003           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11004
11005           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11006               (g & 0xff00) | (b >> 8);
11007         }
11008       }
11009
11010       if (entry->caps)
11011         gst_caps_unref (entry->caps);
11012
11013       entry->caps =
11014           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11015           &codec);
11016       if (G_UNLIKELY (!entry->caps)) {
11017         g_free (palette_data);
11018         goto unknown_stream;
11019       }
11020
11021       if (codec) {
11022         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11023             GST_TAG_VIDEO_CODEC, codec, NULL);
11024         g_free (codec);
11025         codec = NULL;
11026       }
11027
11028       if (palette_data) {
11029         GstStructure *s;
11030
11031         if (entry->rgb8_palette)
11032           gst_memory_unref (entry->rgb8_palette);
11033         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11034             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11035
11036         s = gst_caps_get_structure (entry->caps, 0);
11037
11038         /* non-raw video has a palette_data property. raw video has the palette as
11039          * an extra plane that we append to the output buffers before we push
11040          * them*/
11041         if (!gst_structure_has_name (s, "video/x-raw")) {
11042           GstBuffer *palette;
11043
11044           palette = gst_buffer_new ();
11045           gst_buffer_append_memory (palette, entry->rgb8_palette);
11046           entry->rgb8_palette = NULL;
11047
11048           gst_caps_set_simple (entry->caps, "palette_data",
11049               GST_TYPE_BUFFER, palette, NULL);
11050           gst_buffer_unref (palette);
11051         }
11052       } else if (palette_count != 0) {
11053         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11054             (NULL), ("Unsupported palette depth %d", depth));
11055       }
11056
11057       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11058           QT_UINT16 (stsd_entry_data + offset + 32));
11059
11060       esds = NULL;
11061       pasp = NULL;
11062       colr = NULL;
11063       fiel = NULL;
11064       /* pick 'the' stsd child */
11065       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11066       // We should skip parsing the stsd for non-protected streams if
11067       // the entry doesn't match the fourcc, since they don't change
11068       // format. However, for protected streams we can have partial
11069       // encryption, where parts of the stream are encrypted and parts
11070       // not. For both parts of such streams, we should ensure the
11071       // esds overrides are parsed for both from the stsd.
11072       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11073         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11074           mp4v = NULL;
11075         else if (!stream->protected)
11076           mp4v = NULL;
11077       }
11078
11079       if (mp4v) {
11080         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11081         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11082         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11083         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11084       }
11085
11086       if (pasp) {
11087         const guint8 *pasp_data = (const guint8 *) pasp->data;
11088         gint len = QT_UINT32 (pasp_data);
11089
11090         if (len == 16) {
11091           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11092           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11093         } else {
11094           CUR_STREAM (stream)->par_w = 0;
11095           CUR_STREAM (stream)->par_h = 0;
11096         }
11097       } else {
11098         CUR_STREAM (stream)->par_w = 0;
11099         CUR_STREAM (stream)->par_h = 0;
11100       }
11101
11102       if (fiel) {
11103         const guint8 *fiel_data = (const guint8 *) fiel->data;
11104         gint len = QT_UINT32 (fiel_data);
11105
11106         if (len == 10) {
11107           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11108           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11109         }
11110       }
11111
11112       if (colr) {
11113         const guint8 *colr_data = (const guint8 *) colr->data;
11114         gint len = QT_UINT32 (colr_data);
11115
11116         if (len == 19 || len == 18) {
11117           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11118
11119           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11120             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11121             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11122             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11123             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11124
11125             CUR_STREAM (stream)->colorimetry.primaries =
11126                 gst_video_color_primaries_from_iso (primaries);
11127             CUR_STREAM (stream)->colorimetry.transfer =
11128                 gst_video_transfer_function_from_iso (transfer_function);
11129             CUR_STREAM (stream)->colorimetry.matrix =
11130                 gst_video_color_matrix_from_iso (matrix);
11131             CUR_STREAM (stream)->colorimetry.range =
11132                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11133                 GST_VIDEO_COLOR_RANGE_16_235;
11134           } else {
11135             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11136           }
11137         } else {
11138           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11139         }
11140       }
11141
11142       if (esds) {
11143         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11144             stream->stream_tags);
11145       } else {
11146         switch (fourcc) {
11147           case FOURCC_H264:
11148           case FOURCC_avc1:
11149           case FOURCC_avc3:
11150           {
11151             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11152             const guint8 *avc_data = stsd_entry_data + 0x56;
11153
11154             /* find avcC */
11155             while (len >= 0x8) {
11156               gint size;
11157
11158               if (QT_UINT32 (avc_data) <= len)
11159                 size = QT_UINT32 (avc_data) - 0x8;
11160               else
11161                 size = len - 0x8;
11162
11163               if (size < 1)
11164                 /* No real data, so break out */
11165                 break;
11166
11167               switch (QT_FOURCC (avc_data + 0x4)) {
11168                 case FOURCC_avcC:
11169                 {
11170                   /* parse, if found */
11171                   GstBuffer *buf;
11172
11173                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11174
11175                   /* First 4 bytes are the length of the atom, the next 4 bytes
11176                    * are the fourcc, the next 1 byte is the version, and the
11177                    * subsequent bytes are profile_tier_level structure like data. */
11178                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11179                       avc_data + 8 + 1, size - 1);
11180                   buf = gst_buffer_new_and_alloc (size);
11181                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11182                   gst_caps_set_simple (entry->caps,
11183                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11184                   gst_buffer_unref (buf);
11185
11186                   break;
11187                 }
11188                 case FOURCC_strf:
11189                 {
11190                   GstBuffer *buf;
11191
11192                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11193
11194                   /* First 4 bytes are the length of the atom, the next 4 bytes
11195                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11196                    * next 1 byte is the version, and the
11197                    * subsequent bytes are sequence parameter set like data. */
11198
11199                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11200                   if (size > 1) {
11201                     gst_codec_utils_h264_caps_set_level_and_profile
11202                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11203
11204                     buf = gst_buffer_new_and_alloc (size);
11205                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11206                     gst_caps_set_simple (entry->caps,
11207                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11208                     gst_buffer_unref (buf);
11209                   }
11210                   break;
11211                 }
11212                 case FOURCC_btrt:
11213                 {
11214                   guint avg_bitrate, max_bitrate;
11215
11216                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11217                   if (size < 12)
11218                     break;
11219
11220                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11221                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11222
11223                   if (!max_bitrate && !avg_bitrate)
11224                     break;
11225
11226                   /* Some muxers seem to swap the average and maximum bitrates
11227                    * (I'm looking at you, YouTube), so we swap for sanity. */
11228                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11229                     guint temp = avg_bitrate;
11230
11231                     avg_bitrate = max_bitrate;
11232                     max_bitrate = temp;
11233                   }
11234
11235                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11236                     gst_tag_list_add (stream->stream_tags,
11237                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11238                         max_bitrate, NULL);
11239                   }
11240                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11241                     gst_tag_list_add (stream->stream_tags,
11242                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11243                         NULL);
11244                   }
11245
11246                   break;
11247                 }
11248
11249                 default:
11250                   break;
11251               }
11252
11253               len -= size + 8;
11254               avc_data += size + 8;
11255             }
11256
11257             break;
11258           }
11259           case FOURCC_H265:
11260           case FOURCC_hvc1:
11261           case FOURCC_hev1:
11262           case FOURCC_dvh1:
11263           case FOURCC_dvhe:
11264           {
11265             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11266             const guint8 *hevc_data = stsd_entry_data + 0x56;
11267
11268             /* find hevc */
11269             while (len >= 0x8) {
11270               gint size;
11271
11272               if (QT_UINT32 (hevc_data) <= len)
11273                 size = QT_UINT32 (hevc_data) - 0x8;
11274               else
11275                 size = len - 0x8;
11276
11277               if (size < 1)
11278                 /* No real data, so break out */
11279                 break;
11280
11281               switch (QT_FOURCC (hevc_data + 0x4)) {
11282                 case FOURCC_hvcC:
11283                 {
11284                   /* parse, if found */
11285                   GstBuffer *buf;
11286
11287                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11288
11289                   /* First 4 bytes are the length of the atom, the next 4 bytes
11290                    * are the fourcc, the next 1 byte is the version, and the
11291                    * subsequent bytes are sequence parameter set like data. */
11292                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11293                       (entry->caps, hevc_data + 8 + 1, size - 1);
11294
11295                   buf = gst_buffer_new_and_alloc (size);
11296                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11297                   gst_caps_set_simple (entry->caps,
11298                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11299                   gst_buffer_unref (buf);
11300                   break;
11301                 }
11302                 default:
11303                   break;
11304               }
11305               len -= size + 8;
11306               hevc_data += size + 8;
11307             }
11308             break;
11309           }
11310           case FOURCC_mp4v:
11311           case FOURCC_MP4V:
11312           case FOURCC_fmp4:
11313           case FOURCC_FMP4:
11314           case FOURCC_xvid:
11315           case FOURCC_XVID:
11316           {
11317             GNode *glbl;
11318
11319             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11320                 GST_FOURCC_ARGS (fourcc));
11321
11322             /* codec data might be in glbl extension atom */
11323             glbl = mp4v ?
11324                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11325             if (glbl) {
11326               guint8 *data;
11327               GstBuffer *buf;
11328               gint len;
11329
11330               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11331               data = glbl->data;
11332               len = QT_UINT32 (data);
11333               if (len > 0x8) {
11334                 len -= 0x8;
11335                 buf = gst_buffer_new_and_alloc (len);
11336                 gst_buffer_fill (buf, 0, data + 8, len);
11337                 gst_caps_set_simple (entry->caps,
11338                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11339                 gst_buffer_unref (buf);
11340               }
11341             }
11342             break;
11343           }
11344           case FOURCC_mjp2:
11345           {
11346             /* see annex I of the jpeg2000 spec */
11347             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11348             const guint8 *data;
11349             const gchar *colorspace = NULL;
11350             gint ncomp = 0;
11351             guint32 ncomp_map = 0;
11352             gint32 *comp_map = NULL;
11353             guint32 nchan_def = 0;
11354             gint32 *chan_def = NULL;
11355
11356             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11357             /* some required atoms */
11358             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11359             if (!mjp2)
11360               break;
11361             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11362             if (!jp2h)
11363               break;
11364
11365             /* number of components; redundant with info in codestream, but useful
11366                to a muxer */
11367             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11368             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11369               break;
11370             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11371
11372             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11373             if (!colr)
11374               break;
11375             GST_DEBUG_OBJECT (qtdemux, "found colr");
11376             /* extract colour space info */
11377             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11378               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11379                 case 16:
11380                   colorspace = "sRGB";
11381                   break;
11382                 case 17:
11383                   colorspace = "GRAY";
11384                   break;
11385                 case 18:
11386                   colorspace = "sYUV";
11387                   break;
11388                 default:
11389                   colorspace = NULL;
11390                   break;
11391               }
11392             }
11393             if (!colorspace)
11394               /* colr is required, and only values 16, 17, and 18 are specified,
11395                  so error if we have no colorspace */
11396               break;
11397
11398             /* extract component mapping */
11399             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11400             if (cmap) {
11401               guint32 cmap_len = 0;
11402               int i;
11403               cmap_len = QT_UINT32 (cmap->data);
11404               if (cmap_len >= 8) {
11405                 /* normal box, subtract off header */
11406                 cmap_len -= 8;
11407                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11408                 if (cmap_len % 4 == 0) {
11409                   ncomp_map = (cmap_len / 4);
11410                   comp_map = g_new0 (gint32, ncomp_map);
11411                   for (i = 0; i < ncomp_map; i++) {
11412                     guint16 cmp;
11413                     guint8 mtyp, pcol;
11414                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11415                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11416                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11417                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11418                   }
11419                 }
11420               }
11421             }
11422             /* extract channel definitions */
11423             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11424             if (cdef) {
11425               guint32 cdef_len = 0;
11426               int i;
11427               cdef_len = QT_UINT32 (cdef->data);
11428               if (cdef_len >= 10) {
11429                 /* normal box, subtract off header and len */
11430                 cdef_len -= 10;
11431                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11432                 if (cdef_len % 6 == 0) {
11433                   nchan_def = (cdef_len / 6);
11434                   chan_def = g_new0 (gint32, nchan_def);
11435                   for (i = 0; i < nchan_def; i++)
11436                     chan_def[i] = -1;
11437                   for (i = 0; i < nchan_def; i++) {
11438                     guint16 cn, typ, asoc;
11439                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11440                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11441                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11442                     if (cn < nchan_def) {
11443                       switch (typ) {
11444                         case 0:
11445                           chan_def[cn] = asoc;
11446                           break;
11447                         case 1:
11448                           chan_def[cn] = 0;     /* alpha */
11449                           break;
11450                         default:
11451                           chan_def[cn] = -typ;
11452                       }
11453                     }
11454                   }
11455                 }
11456               }
11457             }
11458
11459             gst_caps_set_simple (entry->caps,
11460                 "num-components", G_TYPE_INT, ncomp, NULL);
11461             gst_caps_set_simple (entry->caps,
11462                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11463
11464             if (comp_map) {
11465               GValue arr = { 0, };
11466               GValue elt = { 0, };
11467               int i;
11468               g_value_init (&arr, GST_TYPE_ARRAY);
11469               g_value_init (&elt, G_TYPE_INT);
11470               for (i = 0; i < ncomp_map; i++) {
11471                 g_value_set_int (&elt, comp_map[i]);
11472                 gst_value_array_append_value (&arr, &elt);
11473               }
11474               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11475                   "component-map", &arr);
11476               g_value_unset (&elt);
11477               g_value_unset (&arr);
11478               g_free (comp_map);
11479             }
11480
11481             if (chan_def) {
11482               GValue arr = { 0, };
11483               GValue elt = { 0, };
11484               int i;
11485               g_value_init (&arr, GST_TYPE_ARRAY);
11486               g_value_init (&elt, G_TYPE_INT);
11487               for (i = 0; i < nchan_def; i++) {
11488                 g_value_set_int (&elt, chan_def[i]);
11489                 gst_value_array_append_value (&arr, &elt);
11490               }
11491               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11492                   "channel-definitions", &arr);
11493               g_value_unset (&elt);
11494               g_value_unset (&arr);
11495               g_free (chan_def);
11496             }
11497
11498             /* some optional atoms */
11499             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11500             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11501
11502             /* indicate possible fields in caps */
11503             if (field) {
11504               data = (guint8 *) field->data + 8;
11505               if (*data != 1)
11506                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11507                     (gint) * data, NULL);
11508             }
11509             /* add codec_data if provided */
11510             if (prefix) {
11511               GstBuffer *buf;
11512               gint len;
11513
11514               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11515               data = prefix->data;
11516               len = QT_UINT32 (data);
11517               if (len > 0x8) {
11518                 len -= 0x8;
11519                 buf = gst_buffer_new_and_alloc (len);
11520                 gst_buffer_fill (buf, 0, data + 8, len);
11521                 gst_caps_set_simple (entry->caps,
11522                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11523                 gst_buffer_unref (buf);
11524               }
11525             }
11526             break;
11527           }
11528           case FOURCC_SVQ3:
11529           case FOURCC_VP31:
11530           {
11531             GstBuffer *buf;
11532             GstBuffer *seqh = NULL;
11533             const guint8 *gamma_data = NULL;
11534             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11535
11536             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11537                 &seqh);
11538             if (gamma_data) {
11539               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11540                   QT_FP32 (gamma_data), NULL);
11541             }
11542             if (seqh) {
11543               /* sorry for the bad name, but we don't know what this is, other
11544                * than its own fourcc */
11545               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11546                   NULL);
11547               gst_buffer_unref (seqh);
11548             }
11549
11550             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11551             buf = gst_buffer_new_and_alloc (len);
11552             gst_buffer_fill (buf, 0, stsd_data, len);
11553             gst_caps_set_simple (entry->caps,
11554                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11555             gst_buffer_unref (buf);
11556             break;
11557           }
11558           case FOURCC_jpeg:
11559           {
11560             /* https://developer.apple.com/standards/qtff-2001.pdf,
11561              * page 92, "Video Sample Description", under table 3.1 */
11562             GstByteReader br;
11563
11564             const gint compressor_offset =
11565                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11566             const gint min_size = compressor_offset + 32 + 2 + 2;
11567             GNode *jpeg;
11568             guint32 len;
11569             guint16 color_table_id = 0;
11570             gboolean ok;
11571
11572             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11573
11574             /* recover information on interlaced/progressive */
11575             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11576             if (!jpeg)
11577               break;
11578
11579             len = QT_UINT32 (jpeg->data);
11580             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11581                 min_size);
11582             if (len >= min_size) {
11583               gst_byte_reader_init (&br, jpeg->data, len);
11584
11585               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11586               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11587               if (color_table_id != 0) {
11588                 /* the spec says there can be concatenated chunks in the data, and we want
11589                  * to find one called field. Walk through them. */
11590                 gint offset = min_size;
11591                 while (offset + 8 < len) {
11592                   guint32 size = 0, tag;
11593                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11594                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11595                   if (!ok || size < 8) {
11596                     GST_WARNING_OBJECT (qtdemux,
11597                         "Failed to walk optional chunk list");
11598                     break;
11599                   }
11600                   GST_DEBUG_OBJECT (qtdemux,
11601                       "Found optional %4.4s chunk, size %u",
11602                       (const char *) &tag, size);
11603                   if (tag == FOURCC_fiel) {
11604                     guint8 n_fields = 0, ordering = 0;
11605                     gst_byte_reader_get_uint8 (&br, &n_fields);
11606                     gst_byte_reader_get_uint8 (&br, &ordering);
11607                     if (n_fields == 1 || n_fields == 2) {
11608                       GST_DEBUG_OBJECT (qtdemux,
11609                           "Found fiel tag with %u fields, ordering %u",
11610                           n_fields, ordering);
11611                       if (n_fields == 2)
11612                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11613                             "interlace-mode", G_TYPE_STRING, "interleaved",
11614                             NULL);
11615                     } else {
11616                       GST_WARNING_OBJECT (qtdemux,
11617                           "Found fiel tag with invalid fields (%u)", n_fields);
11618                     }
11619                   }
11620                   offset += size;
11621                 }
11622               } else {
11623                 GST_DEBUG_OBJECT (qtdemux,
11624                     "Color table ID is 0, not trying to get interlacedness");
11625               }
11626             } else {
11627               GST_WARNING_OBJECT (qtdemux,
11628                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11629             }
11630
11631             break;
11632           }
11633           case FOURCC_rle_:
11634           case FOURCC_WRLE:
11635           {
11636             gst_caps_set_simple (entry->caps,
11637                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11638                 NULL);
11639             break;
11640           }
11641           case FOURCC_XiTh:
11642           {
11643             GNode *xith, *xdxt;
11644
11645             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11646             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11647             if (!xith)
11648               break;
11649
11650             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11651             if (!xdxt)
11652               break;
11653
11654             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11655             /* collect the headers and store them in a stream list so that we can
11656              * send them out first */
11657             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11658             break;
11659           }
11660           case FOURCC_ovc1:
11661           {
11662             GNode *ovc1;
11663             guint8 *ovc1_data;
11664             guint ovc1_len;
11665             GstBuffer *buf;
11666
11667             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11668             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11669             if (!ovc1)
11670               break;
11671             ovc1_data = ovc1->data;
11672             ovc1_len = QT_UINT32 (ovc1_data);
11673             if (ovc1_len <= 198) {
11674               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11675               break;
11676             }
11677             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11678             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11679             gst_caps_set_simple (entry->caps,
11680                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11681             gst_buffer_unref (buf);
11682             break;
11683           }
11684           case FOURCC_vc_1:
11685           {
11686             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11687             const guint8 *vc1_data = stsd_entry_data + 0x56;
11688
11689             /* find dvc1 */
11690             while (len >= 8) {
11691               gint size;
11692
11693               if (QT_UINT32 (vc1_data) <= len)
11694                 size = QT_UINT32 (vc1_data) - 8;
11695               else
11696                 size = len - 8;
11697
11698               if (size < 1)
11699                 /* No real data, so break out */
11700                 break;
11701
11702               switch (QT_FOURCC (vc1_data + 0x4)) {
11703                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11704                 {
11705                   GstBuffer *buf;
11706
11707                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11708                   buf = gst_buffer_new_and_alloc (size);
11709                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11710                   gst_caps_set_simple (entry->caps,
11711                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11712                   gst_buffer_unref (buf);
11713                   break;
11714                 }
11715                 default:
11716                   break;
11717               }
11718               len -= size + 8;
11719               vc1_data += size + 8;
11720             }
11721             break;
11722           }
11723           case FOURCC_av01:
11724           {
11725             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11726             const guint8 *av1_data = stsd_entry_data + 0x56;
11727
11728             /* find av1C */
11729             while (len >= 0x8) {
11730               gint size;
11731
11732               if (QT_UINT32 (av1_data) <= len)
11733                 size = QT_UINT32 (av1_data) - 0x8;
11734               else
11735                 size = len - 0x8;
11736
11737               if (size < 1)
11738                 /* No real data, so break out */
11739                 break;
11740
11741               switch (QT_FOURCC (av1_data + 0x4)) {
11742                 case FOURCC_av1C:
11743                 {
11744                   /* parse, if found */
11745                   GstBuffer *buf;
11746                   guint8 pres_delay_field;
11747
11748                   GST_DEBUG_OBJECT (qtdemux,
11749                       "found av1C codec_data in stsd of size %d", size);
11750
11751                   /* not enough data, just ignore and hope for the best */
11752                   if (size < 5)
11753                     break;
11754
11755                   /* Content is:
11756                    * 4 bytes: atom length
11757                    * 4 bytes: fourcc
11758                    * 1 byte: version
11759                    * 3 bytes: flags
11760                    * 3 bits: reserved
11761                    * 1 bits:  initial_presentation_delay_present
11762                    * 4 bits: initial_presentation_delay (if present else reserved
11763                    * rest: OBUs.
11764                    */
11765
11766                   if (av1_data[9] != 0) {
11767                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11768                     break;
11769                   }
11770
11771                   /* We skip initial_presentation_delay* for now */
11772                   pres_delay_field = *(av1_data + 12);
11773                   if (pres_delay_field & (1 << 5)) {
11774                     gst_caps_set_simple (entry->caps,
11775                         "presentation-delay", G_TYPE_INT,
11776                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11777                   }
11778                   if (size > 5) {
11779                     buf = gst_buffer_new_and_alloc (size - 5);
11780                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11781                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11782                     gst_caps_set_simple (entry->caps,
11783                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11784                     gst_buffer_unref (buf);
11785                   }
11786                   break;
11787                 }
11788                 default:
11789                   break;
11790               }
11791
11792               len -= size + 8;
11793               av1_data += size + 8;
11794             }
11795
11796             break;
11797           }
11798
11799             /* TODO: Need to parse vpcC for VP8 codec too.
11800              * Note that VPCodecConfigurationBox (vpcC) is defined for
11801              * vp08, vp09, and vp10 fourcc. */
11802           case FOURCC_vp09:
11803           {
11804             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11805             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11806
11807             /* find vpcC */
11808             while (len >= 0x8) {
11809               gint size;
11810
11811               if (QT_UINT32 (vpcc_data) <= len)
11812                 size = QT_UINT32 (vpcc_data) - 0x8;
11813               else
11814                 size = len - 0x8;
11815
11816               if (size < 1)
11817                 /* No real data, so break out */
11818                 break;
11819
11820               switch (QT_FOURCC (vpcc_data + 0x4)) {
11821                 case FOURCC_vpcC:
11822                 {
11823                   const gchar *profile_str = NULL;
11824                   const gchar *chroma_format_str = NULL;
11825                   guint8 profile;
11826                   guint8 bitdepth;
11827                   guint8 chroma_format;
11828                   GstVideoColorimetry cinfo;
11829
11830                   /* parse, if found */
11831                   GST_DEBUG_OBJECT (qtdemux,
11832                       "found vp codec_data in stsd of size %d", size);
11833
11834                   /* the meaning of "size" is length of the atom body, excluding
11835                    * atom length and fourcc fields */
11836                   if (size < 12)
11837                     break;
11838
11839                   /* Content is:
11840                    * 4 bytes: atom length
11841                    * 4 bytes: fourcc
11842                    * 1 byte: version
11843                    * 3 bytes: flags
11844                    * 1 byte: profile
11845                    * 1 byte: level
11846                    * 4 bits: bitDepth
11847                    * 3 bits: chromaSubsampling
11848                    * 1 bit: videoFullRangeFlag
11849                    * 1 byte: colourPrimaries
11850                    * 1 byte: transferCharacteristics
11851                    * 1 byte: matrixCoefficients
11852                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11853                    * rest: codecIntializationData (not used for vp8 and vp9)
11854                    */
11855
11856                   if (vpcc_data[8] != 1) {
11857                     GST_WARNING_OBJECT (qtdemux,
11858                         "unknown vpcC version %d", vpcc_data[8]);
11859                     break;
11860                   }
11861
11862                   profile = vpcc_data[12];
11863                   switch (profile) {
11864                     case 0:
11865                       profile_str = "0";
11866                       break;
11867                     case 1:
11868                       profile_str = "1";
11869                       break;
11870                     case 2:
11871                       profile_str = "2";
11872                       break;
11873                     case 3:
11874                       profile_str = "3";
11875                       break;
11876                     default:
11877                       break;
11878                   }
11879
11880                   if (profile_str) {
11881                     gst_caps_set_simple (entry->caps,
11882                         "profile", G_TYPE_STRING, profile_str, NULL);
11883                   }
11884
11885                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11886                    * but webm spec define various ones. Add level to caps
11887                    * if we really need it then */
11888
11889                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11890                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11891                     gst_caps_set_simple (entry->caps,
11892                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11893                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11894                   }
11895
11896                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11897                   switch (chroma_format) {
11898                     case 0:
11899                     case 1:
11900                       chroma_format_str = "4:2:0";
11901                       break;
11902                     case 2:
11903                       chroma_format_str = "4:2:2";
11904                       break;
11905                     case 3:
11906                       chroma_format_str = "4:4:4";
11907                       break;
11908                     default:
11909                       break;
11910                   }
11911
11912                   if (chroma_format_str) {
11913                     gst_caps_set_simple (entry->caps,
11914                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11915                         NULL);
11916                   }
11917
11918                   if ((vpcc_data[14] & 0x1) != 0)
11919                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
11920                   else
11921                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
11922                   cinfo.primaries =
11923                       gst_video_color_primaries_from_iso (vpcc_data[15]);
11924                   cinfo.transfer =
11925                       gst_video_transfer_function_from_iso (vpcc_data[16]);
11926                   cinfo.matrix =
11927                       gst_video_color_matrix_from_iso (vpcc_data[17]);
11928
11929                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
11930                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
11931                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
11932                     /* set this only if all values are known, otherwise this
11933                      * might overwrite valid ones parsed from other color box */
11934                     CUR_STREAM (stream)->colorimetry = cinfo;
11935                   }
11936                   break;
11937                 }
11938                 default:
11939                   break;
11940               }
11941
11942               len -= size + 8;
11943               vpcc_data += size + 8;
11944             }
11945
11946             break;
11947           }
11948           default:
11949             break;
11950         }
11951       }
11952
11953       GST_INFO_OBJECT (qtdemux,
11954           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11955           GST_FOURCC_ARGS (fourcc), entry->caps);
11956
11957     } else if (stream->subtype == FOURCC_soun) {
11958       GNode *wave;
11959       int version, samplesize;
11960       guint16 compression_id;
11961       gboolean amrwb = FALSE;
11962
11963       offset = 16;
11964       /* sample description entry (16) + sound sample description v0 (20) */
11965       if (len < 36)
11966         goto corrupt_file;
11967
11968       version = QT_UINT32 (stsd_entry_data + offset);
11969       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11970       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11971       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11972       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11973
11974       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11975       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11976           QT_UINT32 (stsd_entry_data + offset + 4));
11977       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11978       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11979       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11980       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11981           QT_UINT16 (stsd_entry_data + offset + 14));
11982       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11983
11984       if (compression_id == 0xfffe)
11985         entry->sampled = TRUE;
11986
11987       /* first assume uncompressed audio */
11988       entry->bytes_per_sample = samplesize / 8;
11989       entry->samples_per_frame = entry->n_channels;
11990       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11991       entry->samples_per_packet = entry->samples_per_frame;
11992       entry->bytes_per_packet = entry->bytes_per_sample;
11993
11994       offset = 36;
11995
11996       if (version == 0x00010000) {
11997         /* sample description entry (16) + sound sample description v1 (20+16) */
11998         if (len < 52)
11999           goto corrupt_file;
12000
12001         /* take information from here over the normal sample description */
12002         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12003         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12004         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12005         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12006
12007         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12008         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12009             entry->samples_per_packet);
12010         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12011             entry->bytes_per_packet);
12012         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12013             entry->bytes_per_frame);
12014         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12015             entry->bytes_per_sample);
12016
12017         if (!entry->sampled && entry->bytes_per_packet) {
12018           entry->samples_per_frame = (entry->bytes_per_frame /
12019               entry->bytes_per_packet) * entry->samples_per_packet;
12020           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12021               entry->samples_per_frame);
12022         }
12023       } else if (version == 0x00020000) {
12024         /* sample description entry (16) + sound sample description v2 (56) */
12025         if (len < 72)
12026           goto corrupt_file;
12027
12028         /* take information from here over the normal sample description */
12029         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12030         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12031         entry->samples_per_frame = entry->n_channels;
12032         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12033         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12034         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12035         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12036
12037         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12038         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12039         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12040         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12041             entry->bytes_per_sample * 8);
12042         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12043             QT_UINT32 (stsd_entry_data + offset + 24));
12044         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12045             entry->bytes_per_packet);
12046         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12047             entry->samples_per_packet);
12048       } else if (version != 0x00000) {
12049         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12050             version);
12051       }
12052
12053       switch (fourcc) {
12054           /* Yes, these have to be hard-coded */
12055         case FOURCC_MAC6:
12056         {
12057           entry->samples_per_packet = 6;
12058           entry->bytes_per_packet = 1;
12059           entry->bytes_per_frame = 1 * entry->n_channels;
12060           entry->bytes_per_sample = 1;
12061           entry->samples_per_frame = 6 * entry->n_channels;
12062           break;
12063         }
12064         case FOURCC_MAC3:
12065         {
12066           entry->samples_per_packet = 3;
12067           entry->bytes_per_packet = 1;
12068           entry->bytes_per_frame = 1 * entry->n_channels;
12069           entry->bytes_per_sample = 1;
12070           entry->samples_per_frame = 3 * entry->n_channels;
12071           break;
12072         }
12073         case FOURCC_ima4:
12074         {
12075           entry->samples_per_packet = 64;
12076           entry->bytes_per_packet = 34;
12077           entry->bytes_per_frame = 34 * entry->n_channels;
12078           entry->bytes_per_sample = 2;
12079           entry->samples_per_frame = 64 * entry->n_channels;
12080           break;
12081         }
12082         case FOURCC_ulaw:
12083         case FOURCC_alaw:
12084         {
12085           entry->samples_per_packet = 1;
12086           entry->bytes_per_packet = 1;
12087           entry->bytes_per_frame = 1 * entry->n_channels;
12088           entry->bytes_per_sample = 1;
12089           entry->samples_per_frame = 1 * entry->n_channels;
12090           break;
12091         }
12092         case FOURCC_agsm:
12093         {
12094           entry->samples_per_packet = 160;
12095           entry->bytes_per_packet = 33;
12096           entry->bytes_per_frame = 33 * entry->n_channels;
12097           entry->bytes_per_sample = 2;
12098           entry->samples_per_frame = 160 * entry->n_channels;
12099           break;
12100         }
12101           /* fix up any invalid header information from above */
12102         case FOURCC_twos:
12103         case FOURCC_sowt:
12104         case FOURCC_raw_:
12105         case FOURCC_lpcm:
12106           /* Sometimes these are set to 0 in the sound sample descriptions so
12107            * let's try to infer useful values from the other information we
12108            * have available */
12109           if (entry->bytes_per_sample == 0)
12110             entry->bytes_per_sample =
12111                 entry->bytes_per_frame / entry->n_channels;
12112           if (entry->bytes_per_sample == 0)
12113             entry->bytes_per_sample = samplesize / 8;
12114
12115           if (entry->bytes_per_frame == 0)
12116             entry->bytes_per_frame =
12117                 entry->bytes_per_sample * entry->n_channels;
12118
12119           if (entry->bytes_per_packet == 0)
12120             entry->bytes_per_packet = entry->bytes_per_sample;
12121
12122           if (entry->samples_per_frame == 0)
12123             entry->samples_per_frame = entry->n_channels;
12124
12125           if (entry->samples_per_packet == 0)
12126             entry->samples_per_packet = entry->samples_per_frame;
12127
12128           break;
12129         case FOURCC_in24:
12130         case FOURCC_in32:
12131         case FOURCC_fl32:
12132         case FOURCC_fl64:
12133         case FOURCC_s16l:{
12134           switch (fourcc) {
12135             case FOURCC_in24:
12136               entry->bytes_per_sample = 3;
12137               break;
12138             case FOURCC_in32:
12139             case FOURCC_fl32:
12140               entry->bytes_per_sample = 4;
12141               break;
12142             case FOURCC_fl64:
12143               entry->bytes_per_sample = 8;
12144               break;
12145             case FOURCC_s16l:
12146               entry->bytes_per_sample = 2;
12147               break;
12148             default:
12149               g_assert_not_reached ();
12150               break;
12151           }
12152           entry->samples_per_frame = entry->n_channels;
12153           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12154           entry->samples_per_packet = entry->samples_per_frame;
12155           entry->bytes_per_packet = entry->bytes_per_sample;
12156           break;
12157         }
12158         default:
12159           break;
12160       }
12161
12162       if (entry->caps)
12163         gst_caps_unref (entry->caps);
12164
12165       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12166           stsd_entry_data + 32, len - 16, &codec);
12167
12168       switch (fourcc) {
12169         case FOURCC_in24:
12170         case FOURCC_in32:
12171         case FOURCC_fl32:
12172         case FOURCC_fl64:
12173         {
12174           GNode *enda;
12175           GNode *fmt;
12176
12177           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12178
12179           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12180           if (!enda) {
12181             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12182             if (wave)
12183               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12184           }
12185           if (enda) {
12186             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12187             const gchar *format_str;
12188
12189             switch (fourcc) {
12190               case FOURCC_in24:
12191                 format_str = (enda_value) ? "S24LE" : "S24BE";
12192                 break;
12193               case FOURCC_in32:
12194                 format_str = (enda_value) ? "S32LE" : "S32BE";
12195                 break;
12196               case FOURCC_fl32:
12197                 format_str = (enda_value) ? "F32LE" : "F32BE";
12198                 break;
12199               case FOURCC_fl64:
12200                 format_str = (enda_value) ? "F64LE" : "F64BE";
12201                 break;
12202               default:
12203                 g_assert_not_reached ();
12204                 break;
12205             }
12206             gst_caps_set_simple (entry->caps,
12207                 "format", G_TYPE_STRING, format_str, NULL);
12208           }
12209           break;
12210         }
12211         case FOURCC_owma:
12212         {
12213           const guint8 *owma_data;
12214           const gchar *codec_name = NULL;
12215           guint owma_len;
12216           GstBuffer *buf;
12217           gint version = 1;
12218           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12219           /* FIXME this should also be gst_riff_strf_auds,
12220            * but the latter one is actually missing bits-per-sample :( */
12221           typedef struct
12222           {
12223             gint16 wFormatTag;
12224             gint16 nChannels;
12225             gint32 nSamplesPerSec;
12226             gint32 nAvgBytesPerSec;
12227             gint16 nBlockAlign;
12228             gint16 wBitsPerSample;
12229             gint16 cbSize;
12230           } WAVEFORMATEX;
12231           WAVEFORMATEX *wfex;
12232
12233           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12234           owma_data = stsd_entry_data;
12235           owma_len = QT_UINT32 (owma_data);
12236           if (owma_len <= 54) {
12237             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12238             break;
12239           }
12240           wfex = (WAVEFORMATEX *) (owma_data + 36);
12241           buf = gst_buffer_new_and_alloc (owma_len - 54);
12242           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12243           if (wfex->wFormatTag == 0x0161) {
12244             codec_name = "Windows Media Audio";
12245             version = 2;
12246           } else if (wfex->wFormatTag == 0x0162) {
12247             codec_name = "Windows Media Audio 9 Pro";
12248             version = 3;
12249           } else if (wfex->wFormatTag == 0x0163) {
12250             codec_name = "Windows Media Audio 9 Lossless";
12251             /* is that correct? gstffmpegcodecmap.c is missing it, but
12252              * fluendo codec seems to support it */
12253             version = 4;
12254           }
12255
12256           gst_caps_set_simple (entry->caps,
12257               "codec_data", GST_TYPE_BUFFER, buf,
12258               "wmaversion", G_TYPE_INT, version,
12259               "block_align", G_TYPE_INT,
12260               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12261               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12262               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12263               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12264           gst_buffer_unref (buf);
12265
12266           if (codec_name) {
12267             g_free (codec);
12268             codec = g_strdup (codec_name);
12269           }
12270           break;
12271         }
12272         case FOURCC_wma_:
12273         {
12274           gint len = QT_UINT32 (stsd_entry_data) - offset;
12275           const guint8 *wfex_data = stsd_entry_data + offset;
12276           const gchar *codec_name = NULL;
12277           gint version = 1;
12278           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12279           /* FIXME this should also be gst_riff_strf_auds,
12280            * but the latter one is actually missing bits-per-sample :( */
12281           typedef struct
12282           {
12283             gint16 wFormatTag;
12284             gint16 nChannels;
12285             gint32 nSamplesPerSec;
12286             gint32 nAvgBytesPerSec;
12287             gint16 nBlockAlign;
12288             gint16 wBitsPerSample;
12289             gint16 cbSize;
12290           } WAVEFORMATEX;
12291           WAVEFORMATEX wfex;
12292
12293           /* FIXME: unify with similar wavformatex parsing code above */
12294           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12295
12296           /* find wfex */
12297           while (len >= 8) {
12298             gint size;
12299
12300             if (QT_UINT32 (wfex_data) <= len)
12301               size = QT_UINT32 (wfex_data) - 8;
12302             else
12303               size = len - 8;
12304
12305             if (size < 1)
12306               /* No real data, so break out */
12307               break;
12308
12309             switch (QT_FOURCC (wfex_data + 4)) {
12310               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12311               {
12312                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12313
12314                 if (size < 8 + 18)
12315                   break;
12316
12317                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12318                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12319                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12320                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12321                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12322                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12323                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12324
12325                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12326                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12327                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12328                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12329                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12330                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12331
12332                 if (wfex.wFormatTag == 0x0161) {
12333                   codec_name = "Windows Media Audio";
12334                   version = 2;
12335                 } else if (wfex.wFormatTag == 0x0162) {
12336                   codec_name = "Windows Media Audio 9 Pro";
12337                   version = 3;
12338                 } else if (wfex.wFormatTag == 0x0163) {
12339                   codec_name = "Windows Media Audio 9 Lossless";
12340                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12341                    * fluendo codec seems to support it */
12342                   version = 4;
12343                 }
12344
12345                 gst_caps_set_simple (entry->caps,
12346                     "wmaversion", G_TYPE_INT, version,
12347                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12348                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12349                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12350                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12351
12352                 if (size > wfex.cbSize) {
12353                   GstBuffer *buf;
12354
12355                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12356                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12357                       size - wfex.cbSize);
12358                   gst_caps_set_simple (entry->caps,
12359                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12360                   gst_buffer_unref (buf);
12361                 } else {
12362                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12363                 }
12364
12365                 if (codec_name) {
12366                   g_free (codec);
12367                   codec = g_strdup (codec_name);
12368                 }
12369                 break;
12370               }
12371               default:
12372                 break;
12373             }
12374             len -= size + 8;
12375             wfex_data += size + 8;
12376           }
12377           break;
12378         }
12379         case FOURCC_opus:
12380         {
12381           const guint8 *opus_data;
12382           guint8 *channel_mapping = NULL;
12383           guint32 rate;
12384           guint8 channels;
12385           guint8 channel_mapping_family;
12386           guint8 stream_count;
12387           guint8 coupled_count;
12388           guint8 i;
12389
12390           opus_data = stsd_entry_data;
12391
12392           channels = GST_READ_UINT8 (opus_data + 45);
12393           rate = GST_READ_UINT32_LE (opus_data + 48);
12394           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12395           stream_count = GST_READ_UINT8 (opus_data + 55);
12396           coupled_count = GST_READ_UINT8 (opus_data + 56);
12397
12398           if (channels > 0) {
12399             channel_mapping = g_malloc (channels * sizeof (guint8));
12400             for (i = 0; i < channels; i++)
12401               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12402           }
12403
12404           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12405               channel_mapping_family, stream_count, coupled_count,
12406               channel_mapping);
12407           break;
12408         }
12409         default:
12410           break;
12411       }
12412
12413       if (codec) {
12414         GstStructure *s;
12415         gint bitrate = 0;
12416
12417         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12418             GST_TAG_AUDIO_CODEC, codec, NULL);
12419         g_free (codec);
12420         codec = NULL;
12421
12422         /* some bitrate info may have ended up in caps */
12423         s = gst_caps_get_structure (entry->caps, 0);
12424         gst_structure_get_int (s, "bitrate", &bitrate);
12425         if (bitrate > 0)
12426           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12427               GST_TAG_BITRATE, bitrate, NULL);
12428       }
12429
12430       esds = NULL;
12431       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12432       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12433         if (stream->protected) {
12434           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12435             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12436           }
12437           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12438             mp4a = NULL;
12439           }
12440         } else {
12441           mp4a = NULL;
12442         }
12443       }
12444
12445       wave = NULL;
12446       if (mp4a) {
12447         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12448         if (wave)
12449           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12450         if (!esds)
12451           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12452       }
12453
12454
12455       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12456          16 bits is a byte-swapped wave-style codec identifier,
12457          and we can find a WAVE header internally to a 'wave' atom here.
12458          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12459          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12460          is big-endian).
12461        */
12462       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12463         if (len < offset + 20) {
12464           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12465         } else {
12466           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12467           const guint8 *data = stsd_entry_data + offset + 16;
12468           GNode *wavenode;
12469           GNode *waveheadernode;
12470
12471           wavenode = g_node_new ((guint8 *) data);
12472           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12473             const guint8 *waveheader;
12474             guint32 headerlen;
12475
12476             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12477             if (waveheadernode) {
12478               waveheader = (const guint8 *) waveheadernode->data;
12479               headerlen = QT_UINT32 (waveheader);
12480
12481               if (headerlen > 8) {
12482                 gst_riff_strf_auds *header = NULL;
12483                 GstBuffer *headerbuf;
12484                 GstBuffer *extra;
12485
12486                 waveheader += 8;
12487                 headerlen -= 8;
12488
12489                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12490                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12491
12492                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12493                         headerbuf, &header, &extra)) {
12494                   gst_caps_unref (entry->caps);
12495                   /* FIXME: Need to do something with the channel reorder map */
12496                   entry->caps =
12497                       gst_riff_create_audio_caps (header->format, NULL, header,
12498                       extra, NULL, NULL, NULL);
12499
12500                   if (extra)
12501                     gst_buffer_unref (extra);
12502                   g_free (header);
12503                 }
12504               }
12505             } else
12506               GST_DEBUG ("Didn't find waveheadernode for this codec");
12507           }
12508           g_node_destroy (wavenode);
12509         }
12510       } else if (esds) {
12511         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12512             stream->stream_tags);
12513       } else {
12514         switch (fourcc) {
12515 #if 0
12516             /* FIXME: what is in the chunk? */
12517           case FOURCC_QDMC:
12518           {
12519             gint len = QT_UINT32 (stsd_data);
12520
12521             /* seems to be always = 116 = 0x74 */
12522             break;
12523           }
12524 #endif
12525           case FOURCC_QDM2:
12526           {
12527             gint len = QT_UINT32 (stsd_entry_data);
12528
12529             if (len > 0x3C) {
12530               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12531
12532               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12533               gst_caps_set_simple (entry->caps,
12534                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12535               gst_buffer_unref (buf);
12536             }
12537             gst_caps_set_simple (entry->caps,
12538                 "samplesize", G_TYPE_INT, samplesize, NULL);
12539             break;
12540           }
12541           case FOURCC_alac:
12542           {
12543             GNode *alac, *wave = NULL;
12544
12545             /* apparently, m4a has this atom appended directly in the stsd entry,
12546              * while mov has it in a wave atom */
12547             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12548             if (alac) {
12549               /* alac now refers to stsd entry atom */
12550               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12551               if (wave)
12552                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12553               else
12554                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12555             }
12556             if (alac) {
12557               const guint8 *alac_data = alac->data;
12558               gint len = QT_UINT32 (alac->data);
12559               GstBuffer *buf;
12560
12561               if (len < 36) {
12562                 GST_DEBUG_OBJECT (qtdemux,
12563                     "discarding alac atom with unexpected len %d", len);
12564               } else {
12565                 /* codec-data contains alac atom size and prefix,
12566                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12567                 buf = gst_buffer_new_and_alloc (len);
12568                 gst_buffer_fill (buf, 0, alac->data, len);
12569                 gst_caps_set_simple (entry->caps,
12570                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12571                 gst_buffer_unref (buf);
12572
12573                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12574                 entry->n_channels = QT_UINT8 (alac_data + 21);
12575                 entry->rate = QT_UINT32 (alac_data + 32);
12576                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12577               }
12578             }
12579             gst_caps_set_simple (entry->caps,
12580                 "samplesize", G_TYPE_INT, samplesize, NULL);
12581             break;
12582           }
12583           case FOURCC_fLaC:
12584           {
12585             /* The codingname of the sample entry is 'fLaC' */
12586             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12587
12588             if (flac) {
12589               /* The 'dfLa' box is added to the sample entry to convey
12590                  initializing information for the decoder. */
12591               const GNode *dfla =
12592                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12593
12594               if (dfla) {
12595                 const guint32 len = QT_UINT32 (dfla->data);
12596
12597                 /* Must contain at least dfLa box header (12),
12598                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12599                 if (len < 50) {
12600                   GST_DEBUG_OBJECT (qtdemux,
12601                       "discarding dfla atom with unexpected len %d", len);
12602                 } else {
12603                   /* skip dfLa header to get the METADATA_BLOCKs */
12604                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12605                   const guint32 metadata_blocks_len = len - 12;
12606
12607                   gchar *stream_marker = g_strdup ("fLaC");
12608                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12609                       strlen (stream_marker));
12610
12611                   guint32 index = 0;
12612                   guint32 remainder = 0;
12613                   guint32 block_size = 0;
12614                   gboolean is_last = FALSE;
12615
12616                   GValue array = G_VALUE_INIT;
12617                   GValue value = G_VALUE_INIT;
12618
12619                   g_value_init (&array, GST_TYPE_ARRAY);
12620                   g_value_init (&value, GST_TYPE_BUFFER);
12621
12622                   gst_value_set_buffer (&value, block);
12623                   gst_value_array_append_value (&array, &value);
12624                   g_value_reset (&value);
12625
12626                   gst_buffer_unref (block);
12627
12628                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12629                    * of data, and we haven't already finished parsing */
12630                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12631                     remainder = metadata_blocks_len - index;
12632
12633                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12634                     block_size = 4 +
12635                         (metadata_blocks[index + 1] << 16) +
12636                         (metadata_blocks[index + 2] << 8) +
12637                         metadata_blocks[index + 3];
12638
12639                     /* be careful not to read off end of box */
12640                     if (block_size > remainder) {
12641                       break;
12642                     }
12643
12644                     is_last = metadata_blocks[index] >> 7;
12645
12646                     block = gst_buffer_new_and_alloc (block_size);
12647
12648                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12649                         block_size);
12650
12651                     gst_value_set_buffer (&value, block);
12652                     gst_value_array_append_value (&array, &value);
12653                     g_value_reset (&value);
12654
12655                     gst_buffer_unref (block);
12656
12657                     index += block_size;
12658                   }
12659
12660                   /* only append the metadata if we successfully read all of it */
12661                   if (is_last) {
12662                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12663                             (stream)->caps, 0), "streamheader", &array);
12664                   } else {
12665                     GST_WARNING_OBJECT (qtdemux,
12666                         "discarding all METADATA_BLOCKs due to invalid "
12667                         "block_size %d at idx %d, rem %d", block_size, index,
12668                         remainder);
12669                   }
12670
12671                   g_value_unset (&value);
12672                   g_value_unset (&array);
12673
12674                   /* The sample rate obtained from the stsd may not be accurate
12675                    * since it cannot represent rates greater than 65535Hz, so
12676                    * override that value with the sample rate from the
12677                    * METADATA_BLOCK_STREAMINFO block */
12678                   CUR_STREAM (stream)->rate =
12679                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12680                 }
12681               }
12682             }
12683             break;
12684           }
12685           case FOURCC_sawb:
12686             /* Fallthrough! */
12687             amrwb = TRUE;
12688           case FOURCC_samr:
12689           {
12690             gint len = QT_UINT32 (stsd_entry_data);
12691
12692             if (len > 0x24) {
12693               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12694               guint bitrate;
12695
12696               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12697
12698               /* If we have enough data, let's try to get the 'damr' atom. See
12699                * the 3GPP container spec (26.244) for more details. */
12700               if ((len - 0x34) > 8 &&
12701                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12702                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12703                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12704               }
12705
12706               gst_caps_set_simple (entry->caps,
12707                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12708               gst_buffer_unref (buf);
12709             }
12710             break;
12711           }
12712           case FOURCC_mp4a:
12713           {
12714             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12715             gint len = QT_UINT32 (stsd_entry_data);
12716
12717             if (len >= 34) {
12718               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12719
12720               if (sound_version == 1) {
12721                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12722                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12723                 guint8 codec_data[2];
12724                 GstBuffer *buf;
12725                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12726
12727                 gint sample_rate_index =
12728                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12729
12730                 /* build AAC codec data */
12731                 codec_data[0] = profile << 3;
12732                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12733                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12734                 codec_data[1] |= (channels & 0xF) << 3;
12735
12736                 buf = gst_buffer_new_and_alloc (2);
12737                 gst_buffer_fill (buf, 0, codec_data, 2);
12738                 gst_caps_set_simple (entry->caps,
12739                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12740                 gst_buffer_unref (buf);
12741               }
12742             }
12743             break;
12744           }
12745           case FOURCC_lpcm:
12746           case FOURCC_in24:
12747           case FOURCC_in32:
12748           case FOURCC_fl32:
12749           case FOURCC_fl64:
12750           case FOURCC_s16l:
12751             /* Fully handled elsewhere */
12752             break;
12753           default:
12754             GST_INFO_OBJECT (qtdemux,
12755                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12756             break;
12757         }
12758       }
12759       GST_INFO_OBJECT (qtdemux,
12760           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12761           GST_FOURCC_ARGS (fourcc), entry->caps);
12762
12763     } else if (stream->subtype == FOURCC_strm) {
12764       if (fourcc == FOURCC_rtsp) {
12765         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12766       } else {
12767         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12768             GST_FOURCC_ARGS (fourcc));
12769         goto unknown_stream;
12770       }
12771       entry->sampled = TRUE;
12772     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12773         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12774         || stream->subtype == FOURCC_clcp) {
12775
12776       entry->sampled = TRUE;
12777       entry->sparse = TRUE;
12778
12779       entry->caps =
12780           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12781           &codec);
12782       if (codec) {
12783         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12784             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12785         g_free (codec);
12786         codec = NULL;
12787       }
12788
12789       /* hunt for sort-of codec data */
12790       switch (fourcc) {
12791         case FOURCC_mp4s:
12792         {
12793           GNode *mp4s = NULL;
12794           GNode *esds = NULL;
12795
12796           /* look for palette in a stsd->mp4s->esds sub-atom */
12797           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12798           if (mp4s)
12799             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12800           if (esds == NULL) {
12801             /* Invalid STSD */
12802             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12803             break;
12804           }
12805
12806           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12807               stream->stream_tags);
12808           break;
12809         }
12810         default:
12811           GST_INFO_OBJECT (qtdemux,
12812               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12813           break;
12814       }
12815       GST_INFO_OBJECT (qtdemux,
12816           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12817           GST_FOURCC_ARGS (fourcc), entry->caps);
12818     } else {
12819       /* everything in 1 sample */
12820       entry->sampled = TRUE;
12821
12822       entry->caps =
12823           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12824           &codec);
12825
12826       if (entry->caps == NULL)
12827         goto unknown_stream;
12828
12829       if (codec) {
12830         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12831             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12832         g_free (codec);
12833         codec = NULL;
12834       }
12835     }
12836
12837     /* promote to sampled format */
12838     if (entry->fourcc == FOURCC_samr) {
12839       /* force mono 8000 Hz for AMR */
12840       entry->sampled = TRUE;
12841       entry->n_channels = 1;
12842       entry->rate = 8000;
12843     } else if (entry->fourcc == FOURCC_sawb) {
12844       /* force mono 16000 Hz for AMR-WB */
12845       entry->sampled = TRUE;
12846       entry->n_channels = 1;
12847       entry->rate = 16000;
12848     } else if (entry->fourcc == FOURCC_mp4a) {
12849       entry->sampled = TRUE;
12850     }
12851
12852
12853     stsd_entry_data += len;
12854     remaining_stsd_len -= len;
12855
12856   }
12857
12858   /* collect sample information */
12859   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12860     goto samples_failed;
12861
12862   if (qtdemux->fragmented) {
12863     guint64 offset;
12864
12865     /* need all moov samples as basis; probably not many if any at all */
12866     /* prevent moof parsing taking of at this time */
12867     offset = qtdemux->moof_offset;
12868     qtdemux->moof_offset = 0;
12869     if (stream->n_samples &&
12870         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12871       qtdemux->moof_offset = offset;
12872       goto samples_failed;
12873     }
12874     qtdemux->moof_offset = offset;
12875     /* movie duration more reliable in this case (e.g. mehd) */
12876     if (qtdemux->segment.duration &&
12877         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12878       stream->duration =
12879           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12880   }
12881
12882   /* configure segments */
12883   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12884     goto segments_failed;
12885
12886   /* add some language tag, if useful */
12887   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12888       strcmp (stream->lang_id, "und")) {
12889     const gchar *lang_code;
12890
12891     /* convert ISO 639-2 code to ISO 639-1 */
12892     lang_code = gst_tag_get_language_code (stream->lang_id);
12893     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12894         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12895   }
12896
12897   /* Check for UDTA tags */
12898   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12899     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12900   }
12901
12902   /* Insert and sort new stream in track-id order.
12903    * This will help in comparing old/new streams during stream update check */
12904   g_ptr_array_add (qtdemux->active_streams, stream);
12905   g_ptr_array_sort (qtdemux->active_streams,
12906       (GCompareFunc) qtdemux_track_id_compare_func);
12907   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12908       QTDEMUX_N_STREAMS (qtdemux));
12909
12910   return TRUE;
12911
12912 /* ERRORS */
12913 corrupt_file:
12914   {
12915     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12916         (_("This file is corrupt and cannot be played.")), (NULL));
12917     if (stream)
12918       gst_qtdemux_stream_unref (stream);
12919     return FALSE;
12920   }
12921 error_encrypted:
12922   {
12923     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12924     gst_qtdemux_stream_unref (stream);
12925     return FALSE;
12926   }
12927 samples_failed:
12928 segments_failed:
12929   {
12930     /* we posted an error already */
12931     /* free stbl sub-atoms */
12932     gst_qtdemux_stbl_free (stream);
12933     gst_qtdemux_stream_unref (stream);
12934     return FALSE;
12935   }
12936 existing_stream:
12937   {
12938     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12939         track_id);
12940     return TRUE;
12941   }
12942 unknown_stream:
12943   {
12944     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12945         GST_FOURCC_ARGS (stream->subtype));
12946     gst_qtdemux_stream_unref (stream);
12947     return TRUE;
12948   }
12949 }
12950
12951 /* If we can estimate the overall bitrate, and don't have information about the
12952  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12953  * the overall bitrate minus the sum of the bitrates of all other streams. This
12954  * should be useful for the common case where we have one audio and one video
12955  * stream and can estimate the bitrate of one, but not the other. */
12956 static void
12957 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12958 {
12959   QtDemuxStream *stream = NULL;
12960   gint64 size, sys_bitrate, sum_bitrate = 0;
12961   GstClockTime duration;
12962   guint bitrate;
12963   gint i;
12964
12965   if (qtdemux->fragmented)
12966     return;
12967
12968   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12969
12970   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12971       || size <= 0) {
12972     GST_DEBUG_OBJECT (qtdemux,
12973         "Size in bytes of the stream not known - bailing");
12974     return;
12975   }
12976
12977   /* Subtract the header size */
12978   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12979       size, qtdemux->header_size);
12980
12981   if (size < qtdemux->header_size)
12982     return;
12983
12984   size = size - qtdemux->header_size;
12985
12986   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12987     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12988     return;
12989   }
12990
12991   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12992     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12993     switch (str->subtype) {
12994       case FOURCC_soun:
12995       case FOURCC_vide:
12996         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12997             CUR_STREAM (str)->caps);
12998         /* retrieve bitrate, prefer avg then max */
12999         bitrate = 0;
13000         if (str->stream_tags) {
13001           if (gst_tag_list_get_uint (str->stream_tags,
13002                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13003             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13004           if (gst_tag_list_get_uint (str->stream_tags,
13005                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13006             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13007           if (gst_tag_list_get_uint (str->stream_tags,
13008                   GST_TAG_BITRATE, &bitrate))
13009             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13010         }
13011         if (bitrate)
13012           sum_bitrate += bitrate;
13013         else {
13014           if (stream) {
13015             GST_DEBUG_OBJECT (qtdemux,
13016                 ">1 stream with unknown bitrate - bailing");
13017             return;
13018           } else
13019             stream = str;
13020         }
13021
13022       default:
13023         /* For other subtypes, we assume no significant impact on bitrate */
13024         break;
13025     }
13026   }
13027
13028   if (!stream) {
13029     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13030     return;
13031   }
13032
13033   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13034
13035   if (sys_bitrate < sum_bitrate) {
13036     /* This can happen, since sum_bitrate might be derived from maximum
13037      * bitrates and not average bitrates */
13038     GST_DEBUG_OBJECT (qtdemux,
13039         "System bitrate less than sum bitrate - bailing");
13040     return;
13041   }
13042
13043   bitrate = sys_bitrate - sum_bitrate;
13044   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13045       ", Stream bitrate = %u", sys_bitrate, bitrate);
13046
13047   if (!stream->stream_tags)
13048     stream->stream_tags = gst_tag_list_new_empty ();
13049   else
13050     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13051
13052   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13053       GST_TAG_BITRATE, bitrate, NULL);
13054 }
13055
13056 static GstFlowReturn
13057 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13058 {
13059   GstFlowReturn ret = GST_FLOW_OK;
13060   gint i;
13061
13062   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13063
13064   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13065     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13066     guint32 sample_num = 0;
13067
13068     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13069         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13070
13071     if (qtdemux->fragmented && qtdemux->pullbased) {
13072       /* need all moov samples first */
13073       GST_OBJECT_LOCK (qtdemux);
13074       while (stream->n_samples == 0)
13075         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13076           break;
13077       GST_OBJECT_UNLOCK (qtdemux);
13078     } else {
13079       /* discard any stray moof */
13080       qtdemux->moof_offset = 0;
13081     }
13082
13083     /* prepare braking */
13084     if (ret != GST_FLOW_ERROR)
13085       ret = GST_FLOW_OK;
13086
13087     /* in pull mode, we should have parsed some sample info by now;
13088      * and quite some code will not handle no samples.
13089      * in push mode, we'll just have to deal with it */
13090     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13091       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13092       g_ptr_array_remove_index (qtdemux->active_streams, i);
13093       i--;
13094       continue;
13095     } else if (stream->track_id == qtdemux->chapters_track_id &&
13096         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13097       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13098          so that it doesn't look like a subtitle track */
13099       g_ptr_array_remove_index (qtdemux->active_streams, i);
13100       i--;
13101       continue;
13102     }
13103
13104     /* parse the initial sample for use in setting the frame rate cap */
13105     while (sample_num == 0 && sample_num < stream->n_samples) {
13106       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13107         break;
13108       ++sample_num;
13109     }
13110   }
13111
13112   return ret;
13113 }
13114
13115 static gboolean
13116 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13117 {
13118   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13119 }
13120
13121 static gboolean
13122 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13123 {
13124   gint i;
13125
13126   /* Different length, updated */
13127   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13128     return TRUE;
13129
13130   /* streams in list are sorted in track-id order */
13131   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13132     /* Different stream-id, updated */
13133     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13134             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13135       return TRUE;
13136   }
13137
13138   return FALSE;
13139 }
13140
13141 static gboolean
13142 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13143     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13144 {
13145   /* Connect old stream's srcpad to new stream */
13146   newstream->pad = oldstream->pad;
13147   oldstream->pad = NULL;
13148
13149   /* unset new_stream to prevent stream-start event */
13150   newstream->new_stream = FALSE;
13151
13152   return gst_qtdemux_configure_stream (qtdemux, newstream);
13153 }
13154
13155 static gboolean
13156 qtdemux_update_streams (GstQTDemux * qtdemux)
13157 {
13158   gint i;
13159   g_assert (qtdemux->streams_aware);
13160
13161   /* At below, figure out which stream in active_streams has identical stream-id
13162    * with that of in old_streams. If there is matching stream-id,
13163    * corresponding newstream will not be exposed again,
13164    * but demux will reuse srcpad of matched old stream
13165    *
13166    * active_streams : newly created streams from the latest moov
13167    * old_streams : existing streams (belong to previous moov)
13168    */
13169
13170   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13171     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13172     QtDemuxStream *oldstream = NULL;
13173     guint target;
13174
13175     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13176         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13177
13178     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13179             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13180       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13181
13182       /* null pad stream cannot be reused */
13183       if (oldstream->pad == NULL)
13184         oldstream = NULL;
13185     }
13186
13187     if (oldstream) {
13188       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13189
13190       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13191         return FALSE;
13192
13193       /* we don't need to preserve order of old streams */
13194       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13195     } else {
13196       GstTagList *list;
13197
13198       /* now we have all info and can expose */
13199       list = stream->stream_tags;
13200       stream->stream_tags = NULL;
13201       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13202         return FALSE;
13203     }
13204   }
13205
13206   return TRUE;
13207 }
13208
13209 /* Must be called with expose lock */
13210 static GstFlowReturn
13211 qtdemux_expose_streams (GstQTDemux * qtdemux)
13212 {
13213   gint i;
13214
13215   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13216
13217   if (!qtdemux_is_streams_update (qtdemux)) {
13218     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13219     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13220       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13221       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13222       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13223         return GST_FLOW_ERROR;
13224     }
13225
13226     g_ptr_array_set_size (qtdemux->old_streams, 0);
13227     qtdemux->need_segment = TRUE;
13228
13229     return GST_FLOW_OK;
13230   }
13231
13232   if (qtdemux->streams_aware) {
13233     if (!qtdemux_update_streams (qtdemux))
13234       return GST_FLOW_ERROR;
13235   } else {
13236     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13237       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13238       GstTagList *list;
13239
13240       /* now we have all info and can expose */
13241       list = stream->stream_tags;
13242       stream->stream_tags = NULL;
13243       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13244         return GST_FLOW_ERROR;
13245
13246     }
13247   }
13248
13249   gst_qtdemux_guess_bitrate (qtdemux);
13250
13251   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13252
13253   /* If we have still old_streams, it's no more used stream */
13254   for (i = 0; i < qtdemux->old_streams->len; i++) {
13255     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13256
13257     if (stream->pad) {
13258       GstEvent *event;
13259
13260       event = gst_event_new_eos ();
13261       if (qtdemux->segment_seqnum)
13262         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13263
13264       gst_pad_push_event (stream->pad, event);
13265     }
13266   }
13267
13268   g_ptr_array_set_size (qtdemux->old_streams, 0);
13269
13270   /* check if we should post a redirect in case there is a single trak
13271    * and it is a redirecting trak */
13272   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13273       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13274     GstMessage *m;
13275
13276     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13277         "an external content");
13278     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13279         gst_structure_new ("redirect",
13280             "new-location", G_TYPE_STRING,
13281             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13282     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13283     g_free (qtdemux->redirect_location);
13284     qtdemux->redirect_location =
13285         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13286   }
13287
13288   g_ptr_array_foreach (qtdemux->active_streams,
13289       (GFunc) qtdemux_do_allocation, qtdemux);
13290
13291   qtdemux->need_segment = TRUE;
13292
13293   qtdemux->exposed = TRUE;
13294   return GST_FLOW_OK;
13295 }
13296
13297 typedef struct
13298 {
13299   GstStructure *structure;      /* helper for sort function */
13300   gchar *location;
13301   guint min_req_bitrate;
13302   guint min_req_qt_version;
13303 } GstQtReference;
13304
13305 static gint
13306 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13307 {
13308   GstQtReference *ref_a = (GstQtReference *) a;
13309   GstQtReference *ref_b = (GstQtReference *) b;
13310
13311   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13312     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13313
13314   /* known bitrates go before unknown; higher bitrates go first */
13315   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13316 }
13317
13318 /* sort the redirects and post a message for the application.
13319  */
13320 static void
13321 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13322 {
13323   GstQtReference *best;
13324   GstStructure *s;
13325   GstMessage *msg;
13326   GValue list_val = { 0, };
13327   GList *l;
13328
13329   g_assert (references != NULL);
13330
13331   references = g_list_sort (references, qtdemux_redirects_sort_func);
13332
13333   best = (GstQtReference *) references->data;
13334
13335   g_value_init (&list_val, GST_TYPE_LIST);
13336
13337   for (l = references; l != NULL; l = l->next) {
13338     GstQtReference *ref = (GstQtReference *) l->data;
13339     GValue struct_val = { 0, };
13340
13341     ref->structure = gst_structure_new ("redirect",
13342         "new-location", G_TYPE_STRING, ref->location, NULL);
13343
13344     if (ref->min_req_bitrate > 0) {
13345       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13346           ref->min_req_bitrate, NULL);
13347     }
13348
13349     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13350     g_value_set_boxed (&struct_val, ref->structure);
13351     gst_value_list_append_value (&list_val, &struct_val);
13352     g_value_unset (&struct_val);
13353     /* don't free anything here yet, since we need best->structure below */
13354   }
13355
13356   g_assert (best != NULL);
13357   s = gst_structure_copy (best->structure);
13358
13359   if (g_list_length (references) > 1) {
13360     gst_structure_set_value (s, "locations", &list_val);
13361   }
13362
13363   g_value_unset (&list_val);
13364
13365   for (l = references; l != NULL; l = l->next) {
13366     GstQtReference *ref = (GstQtReference *) l->data;
13367
13368     gst_structure_free (ref->structure);
13369     g_free (ref->location);
13370     g_free (ref);
13371   }
13372   g_list_free (references);
13373
13374   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13375   g_free (qtdemux->redirect_location);
13376   qtdemux->redirect_location =
13377       g_strdup (gst_structure_get_string (s, "new-location"));
13378   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13379   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13380 }
13381
13382 /* look for redirect nodes, collect all redirect information and
13383  * process it.
13384  */
13385 static gboolean
13386 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13387 {
13388   GNode *rmra, *rmda, *rdrf;
13389
13390   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13391   if (rmra) {
13392     GList *redirects = NULL;
13393
13394     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13395     while (rmda) {
13396       GstQtReference ref = { NULL, NULL, 0, 0 };
13397       GNode *rmdr, *rmvc;
13398
13399       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13400         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13401         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13402             ref.min_req_bitrate);
13403       }
13404
13405       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13406         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13407         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13408
13409 #ifndef GST_DISABLE_GST_DEBUG
13410         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13411 #endif
13412         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13413
13414         GST_LOG_OBJECT (qtdemux,
13415             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13416             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13417             bitmask, check_type);
13418         if (package == FOURCC_qtim && check_type == 0) {
13419           ref.min_req_qt_version = version;
13420         }
13421       }
13422
13423       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13424       if (rdrf) {
13425         guint32 ref_type;
13426         guint8 *ref_data;
13427         guint ref_len;
13428
13429         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13430         if (ref_len > 20) {
13431           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13432           ref_data = (guint8 *) rdrf->data + 20;
13433           if (ref_type == FOURCC_alis) {
13434             guint record_len, record_version, fn_len;
13435
13436             if (ref_len > 70) {
13437               /* MacOSX alias record, google for alias-layout.txt */
13438               record_len = QT_UINT16 (ref_data + 4);
13439               record_version = QT_UINT16 (ref_data + 4 + 2);
13440               fn_len = QT_UINT8 (ref_data + 50);
13441               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13442                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13443               }
13444             } else {
13445               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13446                   ref_len);
13447             }
13448           } else if (ref_type == FOURCC_url_) {
13449             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13450           } else {
13451             GST_DEBUG_OBJECT (qtdemux,
13452                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13453                 GST_FOURCC_ARGS (ref_type));
13454           }
13455           if (ref.location != NULL) {
13456             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13457             redirects =
13458                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13459           } else {
13460             GST_WARNING_OBJECT (qtdemux,
13461                 "Failed to extract redirect location from rdrf atom");
13462           }
13463         } else {
13464           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13465         }
13466       }
13467
13468       /* look for others */
13469       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13470     }
13471
13472     if (redirects != NULL) {
13473       qtdemux_process_redirects (qtdemux, redirects);
13474     }
13475   }
13476   return TRUE;
13477 }
13478
13479 static GstTagList *
13480 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13481 {
13482   const gchar *fmt;
13483
13484   if (tags == NULL) {
13485     tags = gst_tag_list_new_empty ();
13486     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13487   }
13488
13489   if (qtdemux->major_brand == FOURCC_mjp2)
13490     fmt = "Motion JPEG 2000";
13491   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13492     fmt = "3GP";
13493   else if (qtdemux->major_brand == FOURCC_qt__)
13494     fmt = "Quicktime";
13495   else if (qtdemux->fragmented)
13496     fmt = "ISO fMP4";
13497   else
13498     fmt = "ISO MP4/M4A";
13499
13500   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13501       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13502
13503   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13504       fmt, NULL);
13505
13506   return tags;
13507 }
13508
13509 /* we have read the complete moov node now.
13510  * This function parses all of the relevant info, creates the traks and
13511  * prepares all data structures for playback
13512  */
13513 static gboolean
13514 qtdemux_parse_tree (GstQTDemux * qtdemux)
13515 {
13516   GNode *mvhd;
13517   GNode *trak;
13518   GNode *udta;
13519   GNode *mvex;
13520   GNode *pssh;
13521   guint64 creation_time;
13522   GstDateTime *datetime = NULL;
13523   gint version;
13524
13525   /* make sure we have a usable taglist */
13526   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13527
13528   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13529   if (mvhd == NULL) {
13530     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13531     return qtdemux_parse_redirects (qtdemux);
13532   }
13533
13534   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13535   if (version == 1) {
13536     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13537     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13538     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13539   } else if (version == 0) {
13540     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13541     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13542     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13543   } else {
13544     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13545     return FALSE;
13546   }
13547
13548   /* Moving qt creation time (secs since 1904) to unix time */
13549   if (creation_time != 0) {
13550     /* Try to use epoch first as it should be faster and more commonly found */
13551     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13552       gint64 now_s;
13553
13554       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13555       /* some data cleansing sanity */
13556       now_s = g_get_real_time () / G_USEC_PER_SEC;
13557       if (now_s + 24 * 3600 < creation_time) {
13558         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13559       } else {
13560         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13561       }
13562     } else {
13563       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13564       GDateTime *dt, *dt_local;
13565
13566       dt = g_date_time_add_seconds (base_dt, creation_time);
13567       dt_local = g_date_time_to_local (dt);
13568       datetime = gst_date_time_new_from_g_date_time (dt_local);
13569
13570       g_date_time_unref (base_dt);
13571       g_date_time_unref (dt);
13572     }
13573   }
13574   if (datetime) {
13575     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13576     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13577         datetime, NULL);
13578     gst_date_time_unref (datetime);
13579   }
13580
13581   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13582   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13583
13584   /* check for fragmented file and get some (default) data */
13585   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13586   if (mvex) {
13587     GNode *mehd;
13588     GstByteReader mehd_data;
13589
13590     /* let track parsing or anyone know weird stuff might happen ... */
13591     qtdemux->fragmented = TRUE;
13592
13593     /* compensate for total duration */
13594     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13595     if (mehd)
13596       qtdemux_parse_mehd (qtdemux, &mehd_data);
13597   }
13598
13599   /* Update the movie segment duration, unless it was directly given to us
13600    * by upstream. Otherwise let it as is, as we don't want to mangle the
13601    * duration provided by upstream that may come e.g. from a MPD file. */
13602   if (!qtdemux->upstream_format_is_time) {
13603     GstClockTime duration;
13604     /* set duration in the segment info */
13605     gst_qtdemux_get_duration (qtdemux, &duration);
13606     qtdemux->segment.duration = duration;
13607     /* also do not exceed duration; stop is set that way post seek anyway,
13608      * and segment activation falls back to duration,
13609      * whereas loop only checks stop, so let's align this here as well */
13610     qtdemux->segment.stop = duration;
13611   }
13612
13613   /* parse all traks */
13614   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13615   while (trak) {
13616     qtdemux_parse_trak (qtdemux, trak);
13617     /* iterate all siblings */
13618     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13619   }
13620
13621   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13622
13623   /* find tags */
13624   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13625   if (udta) {
13626     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13627   } else {
13628     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13629   }
13630
13631   /* maybe also some tags in meta box */
13632   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13633   if (udta) {
13634     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13635     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13636   } else {
13637     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13638   }
13639
13640   /* parse any protection system info */
13641   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13642   while (pssh) {
13643     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13644     qtdemux_parse_pssh (qtdemux, pssh);
13645     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13646   }
13647
13648   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13649
13650   return TRUE;
13651 }
13652
13653 /* taken from ffmpeg */
13654 static int
13655 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13656 {
13657   int count = 4;
13658   int len = 0;
13659
13660   while (count--) {
13661     int c;
13662
13663     if (ptr >= end)
13664       return -1;
13665
13666     c = *ptr++;
13667     len = (len << 7) | (c & 0x7f);
13668     if (!(c & 0x80))
13669       break;
13670   }
13671   *end_out = ptr;
13672   return len;
13673 }
13674
13675 static GList *
13676 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13677     gsize codec_data_size)
13678 {
13679   GList *list = NULL;
13680   guint8 *p = codec_data;
13681   gint i, offset, num_packets;
13682   guint *length, last;
13683
13684   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13685
13686   if (codec_data == NULL || codec_data_size == 0)
13687     goto error;
13688
13689   /* start of the stream and vorbis audio or theora video, need to
13690    * send the codec_priv data as first three packets */
13691   num_packets = p[0] + 1;
13692   GST_DEBUG_OBJECT (qtdemux,
13693       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13694       (guint) num_packets, codec_data_size);
13695
13696   /* Let's put some limits, Don't think there even is a xiph codec
13697    * with more than 3-4 headers */
13698   if (G_UNLIKELY (num_packets > 16)) {
13699     GST_WARNING_OBJECT (qtdemux,
13700         "Unlikely number of xiph headers, most likely not valid");
13701     goto error;
13702   }
13703
13704   length = g_alloca (num_packets * sizeof (guint));
13705   last = 0;
13706   offset = 1;
13707
13708   /* first packets, read length values */
13709   for (i = 0; i < num_packets - 1; i++) {
13710     length[i] = 0;
13711     while (offset < codec_data_size) {
13712       length[i] += p[offset];
13713       if (p[offset++] != 0xff)
13714         break;
13715     }
13716     last += length[i];
13717   }
13718   if (offset + last > codec_data_size)
13719     goto error;
13720
13721   /* last packet is the remaining size */
13722   length[i] = codec_data_size - offset - last;
13723
13724   for (i = 0; i < num_packets; i++) {
13725     GstBuffer *hdr;
13726
13727     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13728
13729     if (offset + length[i] > codec_data_size)
13730       goto error;
13731
13732     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13733     list = g_list_append (list, hdr);
13734
13735     offset += length[i];
13736   }
13737
13738   return list;
13739
13740   /* ERRORS */
13741 error:
13742   {
13743     if (list != NULL)
13744       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13745     return NULL;
13746   }
13747
13748 }
13749
13750 /* this can change the codec originally present in @list */
13751 static void
13752 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13753     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13754 {
13755   int len = QT_UINT32 (esds->data);
13756   guint8 *ptr = esds->data;
13757   guint8 *end = ptr + len;
13758   int tag;
13759   guint8 *data_ptr = NULL;
13760   int data_len = 0;
13761   guint8 object_type_id = 0;
13762   guint8 stream_type = 0;
13763   const char *codec_name = NULL;
13764   GstCaps *caps = NULL;
13765
13766   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13767   ptr += 8;
13768   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13769   ptr += 4;
13770   while (ptr + 1 < end) {
13771     tag = QT_UINT8 (ptr);
13772     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13773     ptr++;
13774     len = read_descr_size (ptr, end, &ptr);
13775     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13776
13777     /* Check the stated amount of data is available for reading */
13778     if (len < 0 || ptr + len > end)
13779       break;
13780
13781     switch (tag) {
13782       case ES_DESCRIPTOR_TAG:
13783         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13784         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13785         ptr += 3;
13786         break;
13787       case DECODER_CONFIG_DESC_TAG:{
13788         guint max_bitrate, avg_bitrate;
13789
13790         object_type_id = QT_UINT8 (ptr);
13791         stream_type = QT_UINT8 (ptr + 1) >> 2;
13792         max_bitrate = QT_UINT32 (ptr + 5);
13793         avg_bitrate = QT_UINT32 (ptr + 9);
13794         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13795         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13796         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13797         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13798         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13799         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13800           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13801               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13802         }
13803         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13804           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13805               avg_bitrate, NULL);
13806         }
13807         ptr += 13;
13808         break;
13809       }
13810       case DECODER_SPECIFIC_INFO_TAG:
13811         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13812         if (object_type_id == 0xe0 && len == 0x40) {
13813           guint8 *data;
13814           GstStructure *s;
13815           guint32 clut[16];
13816           gint i;
13817
13818           GST_DEBUG_OBJECT (qtdemux,
13819               "Have VOBSUB palette. Creating palette event");
13820           /* move to decConfigDescr data and read palette */
13821           data = ptr;
13822           for (i = 0; i < 16; i++) {
13823             clut[i] = QT_UINT32 (data);
13824             data += 4;
13825           }
13826
13827           s = gst_structure_new ("application/x-gst-dvd", "event",
13828               G_TYPE_STRING, "dvd-spu-clut-change",
13829               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13830               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13831               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13832               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13833               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13834               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13835               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13836               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13837               NULL);
13838
13839           /* store event and trigger custom processing */
13840           stream->pending_event =
13841               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13842         } else {
13843           /* Generic codec_data handler puts it on the caps */
13844           data_ptr = ptr;
13845           data_len = len;
13846         }
13847
13848         ptr += len;
13849         break;
13850       case SL_CONFIG_DESC_TAG:
13851         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13852         ptr += 1;
13853         break;
13854       default:
13855         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13856             tag);
13857         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13858         ptr += len;
13859         break;
13860     }
13861   }
13862
13863   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13864    * in use, and should also be used to override some other parameters for some
13865    * codecs. */
13866   switch (object_type_id) {
13867     case 0x20:                 /* MPEG-4 */
13868       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13869        * profile_and_level_indication */
13870       if (data_ptr != NULL && data_len >= 5 &&
13871           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13872         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13873             data_ptr + 4, data_len - 4);
13874       }
13875       break;                    /* Nothing special needed here */
13876     case 0x21:                 /* H.264 */
13877       codec_name = "H.264 / AVC";
13878       caps = gst_caps_new_simple ("video/x-h264",
13879           "stream-format", G_TYPE_STRING, "avc",
13880           "alignment", G_TYPE_STRING, "au", NULL);
13881       break;
13882     case 0x40:                 /* AAC (any) */
13883     case 0x66:                 /* AAC Main */
13884     case 0x67:                 /* AAC LC */
13885     case 0x68:                 /* AAC SSR */
13886       /* Override channels and rate based on the codec_data, as it's often
13887        * wrong. */
13888       /* Only do so for basic setup without HE-AAC extension */
13889       if (data_ptr && data_len == 2) {
13890         guint channels, rate;
13891
13892         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13893         if (channels > 0)
13894           entry->n_channels = channels;
13895
13896         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13897         if (rate > 0)
13898           entry->rate = rate;
13899       }
13900
13901       /* Set level and profile if possible */
13902       if (data_ptr != NULL && data_len >= 2) {
13903         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13904             data_ptr, data_len);
13905       } else {
13906         const gchar *profile_str = NULL;
13907         GstBuffer *buffer;
13908         GstMapInfo map;
13909         guint8 *codec_data;
13910         gint rate_idx, profile;
13911
13912         /* No codec_data, let's invent something.
13913          * FIXME: This is wrong for SBR! */
13914
13915         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13916
13917         buffer = gst_buffer_new_and_alloc (2);
13918         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13919         codec_data = map.data;
13920
13921         rate_idx =
13922             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13923             (stream)->rate);
13924
13925         switch (object_type_id) {
13926           case 0x66:
13927             profile_str = "main";
13928             profile = 0;
13929             break;
13930           case 0x67:
13931             profile_str = "lc";
13932             profile = 1;
13933             break;
13934           case 0x68:
13935             profile_str = "ssr";
13936             profile = 2;
13937             break;
13938           default:
13939             profile = 3;
13940             break;
13941         }
13942
13943         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13944         codec_data[1] =
13945             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13946
13947         gst_buffer_unmap (buffer, &map);
13948         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13949             GST_TYPE_BUFFER, buffer, NULL);
13950         gst_buffer_unref (buffer);
13951
13952         if (profile_str) {
13953           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13954               G_TYPE_STRING, profile_str, NULL);
13955         }
13956       }
13957       break;
13958     case 0x60:                 /* MPEG-2, various profiles */
13959     case 0x61:
13960     case 0x62:
13961     case 0x63:
13962     case 0x64:
13963     case 0x65:
13964       codec_name = "MPEG-2 video";
13965       caps = gst_caps_new_simple ("video/mpeg",
13966           "mpegversion", G_TYPE_INT, 2,
13967           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13968       break;
13969     case 0x69:                 /* MPEG-2 BC audio */
13970     case 0x6B:                 /* MPEG-1 audio */
13971       caps = gst_caps_new_simple ("audio/mpeg",
13972           "mpegversion", G_TYPE_INT, 1, NULL);
13973       codec_name = "MPEG-1 audio";
13974       break;
13975     case 0x6A:                 /* MPEG-1 */
13976       codec_name = "MPEG-1 video";
13977       caps = gst_caps_new_simple ("video/mpeg",
13978           "mpegversion", G_TYPE_INT, 1,
13979           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13980       break;
13981     case 0x6C:                 /* MJPEG */
13982       caps =
13983           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13984           NULL);
13985       codec_name = "Motion-JPEG";
13986       break;
13987     case 0x6D:                 /* PNG */
13988       caps =
13989           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13990           NULL);
13991       codec_name = "PNG still images";
13992       break;
13993     case 0x6E:                 /* JPEG2000 */
13994       codec_name = "JPEG-2000";
13995       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13996       break;
13997     case 0xA4:                 /* Dirac */
13998       codec_name = "Dirac";
13999       caps = gst_caps_new_empty_simple ("video/x-dirac");
14000       break;
14001     case 0xA5:                 /* AC3 */
14002       codec_name = "AC-3 audio";
14003       caps = gst_caps_new_simple ("audio/x-ac3",
14004           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14005       break;
14006     case 0xA9:                 /* AC3 */
14007       codec_name = "DTS audio";
14008       caps = gst_caps_new_simple ("audio/x-dts",
14009           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14010       break;
14011     case 0xDD:
14012       if (stream_type == 0x05 && data_ptr) {
14013         GList *headers =
14014             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14015         if (headers) {
14016           GList *tmp;
14017           GValue arr_val = G_VALUE_INIT;
14018           GValue buf_val = G_VALUE_INIT;
14019           GstStructure *s;
14020
14021           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14022           codec_name = "Vorbis";
14023           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14024           g_value_init (&arr_val, GST_TYPE_ARRAY);
14025           g_value_init (&buf_val, GST_TYPE_BUFFER);
14026           for (tmp = headers; tmp; tmp = tmp->next) {
14027             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14028             gst_value_array_append_value (&arr_val, &buf_val);
14029           }
14030           s = gst_caps_get_structure (caps, 0);
14031           gst_structure_take_value (s, "streamheader", &arr_val);
14032           g_value_unset (&buf_val);
14033           g_list_free (headers);
14034
14035           data_ptr = NULL;
14036           data_len = 0;
14037         }
14038       }
14039       break;
14040     case 0xE1:                 /* QCELP */
14041       /* QCELP, the codec_data is a riff tag (little endian) with
14042        * 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). */
14043       caps = gst_caps_new_empty_simple ("audio/qcelp");
14044       codec_name = "QCELP";
14045       break;
14046     default:
14047       break;
14048   }
14049
14050   /* If we have a replacement caps, then change our caps for this stream */
14051   if (caps) {
14052     gst_caps_unref (entry->caps);
14053     entry->caps = caps;
14054   }
14055
14056   if (codec_name && list)
14057     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14058         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14059
14060   /* Add the codec_data attribute to caps, if we have it */
14061   if (data_ptr) {
14062     GstBuffer *buffer;
14063
14064     buffer = gst_buffer_new_and_alloc (data_len);
14065     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14066
14067     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14068     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14069
14070     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14071         buffer, NULL);
14072     gst_buffer_unref (buffer);
14073   }
14074
14075 }
14076
14077 static inline GstCaps *
14078 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14079 {
14080   GstCaps *caps;
14081   guint i;
14082   char *s, fourstr[5];
14083
14084   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14085   for (i = 0; i < 4; i++) {
14086     if (!g_ascii_isalnum (fourstr[i]))
14087       fourstr[i] = '_';
14088   }
14089   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14090   caps = gst_caps_new_empty_simple (s);
14091   g_free (s);
14092   return caps;
14093 }
14094
14095 #define _codec(name) \
14096   do { \
14097     if (codec_name) { \
14098       *codec_name = g_strdup (name); \
14099     } \
14100   } while (0)
14101
14102 static GstCaps *
14103 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14104     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14105     const guint8 * stsd_entry_data, gchar ** codec_name)
14106 {
14107   GstCaps *caps = NULL;
14108   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14109
14110   switch (fourcc) {
14111     case FOURCC_png:
14112       _codec ("PNG still images");
14113       caps = gst_caps_new_empty_simple ("image/png");
14114       break;
14115     case FOURCC_jpeg:
14116       _codec ("JPEG still images");
14117       caps =
14118           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14119           NULL);
14120       break;
14121     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14122     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14123     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14124     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14125       _codec ("Motion-JPEG");
14126       caps =
14127           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14128           NULL);
14129       break;
14130     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14131       _codec ("Motion-JPEG format B");
14132       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14133       break;
14134     case FOURCC_mjp2:
14135       _codec ("JPEG-2000");
14136       /* override to what it should be according to spec, avoid palette_data */
14137       entry->bits_per_sample = 24;
14138       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14139       break;
14140     case FOURCC_SVQ3:
14141       _codec ("Sorensen video v.3");
14142       caps = gst_caps_new_simple ("video/x-svq",
14143           "svqversion", G_TYPE_INT, 3, NULL);
14144       break;
14145     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14146     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14147       _codec ("Sorensen video v.1");
14148       caps = gst_caps_new_simple ("video/x-svq",
14149           "svqversion", G_TYPE_INT, 1, NULL);
14150       break;
14151     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14152       caps = gst_caps_new_empty_simple ("video/x-raw");
14153       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14154       _codec ("Windows Raw RGB");
14155       stream->alignment = 32;
14156       break;
14157     case FOURCC_raw_:
14158     {
14159       guint16 bps;
14160
14161       bps = QT_UINT16 (stsd_entry_data + 82);
14162       switch (bps) {
14163         case 15:
14164           format = GST_VIDEO_FORMAT_RGB15;
14165           break;
14166         case 16:
14167           format = GST_VIDEO_FORMAT_RGB16;
14168           break;
14169         case 24:
14170           format = GST_VIDEO_FORMAT_RGB;
14171           break;
14172         case 32:
14173           format = GST_VIDEO_FORMAT_ARGB;
14174           break;
14175         default:
14176           /* unknown */
14177           break;
14178       }
14179       break;
14180     }
14181     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14182       format = GST_VIDEO_FORMAT_I420;
14183       break;
14184     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14185     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14186       format = GST_VIDEO_FORMAT_I420;
14187       break;
14188     case FOURCC_2vuy:
14189     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14190       format = GST_VIDEO_FORMAT_UYVY;
14191       break;
14192     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14193       format = GST_VIDEO_FORMAT_v308;
14194       break;
14195     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14196       format = GST_VIDEO_FORMAT_v216;
14197       break;
14198     case FOURCC_v210:
14199       format = GST_VIDEO_FORMAT_v210;
14200       break;
14201     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14202       format = GST_VIDEO_FORMAT_r210;
14203       break;
14204       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14205          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14206          format = GST_VIDEO_FORMAT_v410;
14207          break;
14208        */
14209       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14210        * but different order than AYUV
14211        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14212        format = GST_VIDEO_FORMAT_v408;
14213        break;
14214        */
14215     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14216     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14217       _codec ("MPEG-1 video");
14218       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14219           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14220       break;
14221     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14222     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14223     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14224     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14225     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14226     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14227     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14228     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14229     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14230     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14231     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14232     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14233     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14234     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14235     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14236     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14237     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14238     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14239     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14240     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14241     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14242     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14243     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14244     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14245     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14246     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14247     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14248     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14249     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14250     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14251     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14252     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14253     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14254     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14255     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14256     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14257     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14258     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14259     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14260     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14261     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14262     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14263     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14264     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14265     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14266     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14267     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14268       _codec ("MPEG-2 video");
14269       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14270           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14271       break;
14272     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14273       _codec ("GIF still images");
14274       caps = gst_caps_new_empty_simple ("image/gif");
14275       break;
14276     case FOURCC_h263:
14277     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14278     case FOURCC_s263:
14279     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14280       _codec ("H.263");
14281       /* ffmpeg uses the height/width props, don't know why */
14282       caps = gst_caps_new_simple ("video/x-h263",
14283           "variant", G_TYPE_STRING, "itu", NULL);
14284       break;
14285     case FOURCC_mp4v:
14286     case FOURCC_MP4V:
14287       _codec ("MPEG-4 video");
14288       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14289           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14290       break;
14291     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14292     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14293       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14294       caps = gst_caps_new_simple ("video/x-msmpeg",
14295           "msmpegversion", G_TYPE_INT, 43, NULL);
14296       break;
14297     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14298       _codec ("DivX 3");
14299       caps = gst_caps_new_simple ("video/x-divx",
14300           "divxversion", G_TYPE_INT, 3, NULL);
14301       break;
14302     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14303     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14304       _codec ("DivX 4");
14305       caps = gst_caps_new_simple ("video/x-divx",
14306           "divxversion", G_TYPE_INT, 4, NULL);
14307       break;
14308     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14309       _codec ("DivX 5");
14310       caps = gst_caps_new_simple ("video/x-divx",
14311           "divxversion", G_TYPE_INT, 5, NULL);
14312       break;
14313
14314     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14315       _codec ("FFV1");
14316       caps = gst_caps_new_simple ("video/x-ffv",
14317           "ffvversion", G_TYPE_INT, 1, NULL);
14318       break;
14319
14320     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14321     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14322     case FOURCC_XVID:
14323     case FOURCC_xvid:
14324     case FOURCC_FMP4:
14325     case FOURCC_fmp4:
14326     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14327       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14328           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14329       _codec ("MPEG-4");
14330       break;
14331
14332     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14333       _codec ("Cinepak");
14334       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14335       break;
14336     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14337       _codec ("Apple QuickDraw");
14338       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14339       break;
14340     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14341       _codec ("Apple video");
14342       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14343       break;
14344     case FOURCC_H264:
14345     case FOURCC_avc1:
14346     case FOURCC_dva1:
14347       _codec ("H.264 / AVC");
14348       caps = gst_caps_new_simple ("video/x-h264",
14349           "stream-format", G_TYPE_STRING, "avc",
14350           "alignment", G_TYPE_STRING, "au", NULL);
14351       break;
14352     case FOURCC_avc3:
14353     case FOURCC_dvav:
14354       _codec ("H.264 / AVC");
14355       caps = gst_caps_new_simple ("video/x-h264",
14356           "stream-format", G_TYPE_STRING, "avc3",
14357           "alignment", G_TYPE_STRING, "au", NULL);
14358       break;
14359     case FOURCC_H265:
14360     case FOURCC_hvc1:
14361     case FOURCC_dvh1:
14362       _codec ("H.265 / HEVC");
14363       caps = gst_caps_new_simple ("video/x-h265",
14364           "stream-format", G_TYPE_STRING, "hvc1",
14365           "alignment", G_TYPE_STRING, "au", NULL);
14366       break;
14367     case FOURCC_hev1:
14368     case FOURCC_dvhe:
14369       _codec ("H.265 / HEVC");
14370       caps = gst_caps_new_simple ("video/x-h265",
14371           "stream-format", G_TYPE_STRING, "hev1",
14372           "alignment", G_TYPE_STRING, "au", NULL);
14373       break;
14374     case FOURCC_rle_:
14375       _codec ("Run-length encoding");
14376       caps = gst_caps_new_simple ("video/x-rle",
14377           "layout", G_TYPE_STRING, "quicktime", NULL);
14378       break;
14379     case FOURCC_WRLE:
14380       _codec ("Run-length encoding");
14381       caps = gst_caps_new_simple ("video/x-rle",
14382           "layout", G_TYPE_STRING, "microsoft", NULL);
14383       break;
14384     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14385     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14386       _codec ("Indeo Video 3");
14387       caps = gst_caps_new_simple ("video/x-indeo",
14388           "indeoversion", G_TYPE_INT, 3, NULL);
14389       break;
14390     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14391     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14392       _codec ("Intel Video 4");
14393       caps = gst_caps_new_simple ("video/x-indeo",
14394           "indeoversion", G_TYPE_INT, 4, NULL);
14395       break;
14396     case FOURCC_dvcp:
14397     case FOURCC_dvc_:
14398     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14399     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14400     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14401     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14402     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14403     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14404       _codec ("DV Video");
14405       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14406           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14407       break;
14408     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14409     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14410       _codec ("DVCPro50 Video");
14411       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14412           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14413       break;
14414     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14415     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14416       _codec ("DVCProHD Video");
14417       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14418           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14419       break;
14420     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14421       _codec ("Apple Graphics (SMC)");
14422       caps = gst_caps_new_empty_simple ("video/x-smc");
14423       break;
14424     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14425       _codec ("VP3");
14426       caps = gst_caps_new_empty_simple ("video/x-vp3");
14427       break;
14428     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14429       _codec ("VP6 Flash");
14430       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14431       break;
14432     case FOURCC_XiTh:
14433       _codec ("Theora");
14434       caps = gst_caps_new_empty_simple ("video/x-theora");
14435       /* theora uses one byte of padding in the data stream because it does not
14436        * allow 0 sized packets while theora does */
14437       entry->padding = 1;
14438       break;
14439     case FOURCC_drac:
14440       _codec ("Dirac");
14441       caps = gst_caps_new_empty_simple ("video/x-dirac");
14442       break;
14443     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14444       _codec ("TIFF still images");
14445       caps = gst_caps_new_empty_simple ("image/tiff");
14446       break;
14447     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14448       _codec ("Apple Intermediate Codec");
14449       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14450       break;
14451     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14452       _codec ("AVID DNxHD");
14453       caps = gst_caps_from_string ("video/x-dnxhd");
14454       break;
14455     case FOURCC_VP80:
14456     case FOURCC_vp08:
14457       _codec ("On2 VP8");
14458       caps = gst_caps_from_string ("video/x-vp8");
14459       break;
14460     case FOURCC_vp09:
14461       _codec ("Google VP9");
14462       caps = gst_caps_from_string ("video/x-vp9");
14463       break;
14464     case FOURCC_apcs:
14465       _codec ("Apple ProRes LT");
14466       caps =
14467           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14468           NULL);
14469       break;
14470     case FOURCC_apch:
14471       _codec ("Apple ProRes HQ");
14472       caps =
14473           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14474           NULL);
14475       break;
14476     case FOURCC_apcn:
14477       _codec ("Apple ProRes");
14478       caps =
14479           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14480           "standard", NULL);
14481       break;
14482     case FOURCC_apco:
14483       _codec ("Apple ProRes Proxy");
14484       caps =
14485           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14486           "proxy", NULL);
14487       break;
14488     case FOURCC_ap4h:
14489       _codec ("Apple ProRes 4444");
14490       caps =
14491           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14492           "4444", NULL);
14493       break;
14494     case FOURCC_ap4x:
14495       _codec ("Apple ProRes 4444 XQ");
14496       caps =
14497           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14498           "4444xq", NULL);
14499       break;
14500     case FOURCC_cfhd:
14501       _codec ("GoPro CineForm");
14502       caps = gst_caps_from_string ("video/x-cineform");
14503       break;
14504     case FOURCC_vc_1:
14505     case FOURCC_ovc1:
14506       _codec ("VC-1");
14507       caps = gst_caps_new_simple ("video/x-wmv",
14508           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14509       break;
14510     case FOURCC_av01:
14511       _codec ("AV1");
14512       caps = gst_caps_new_empty_simple ("video/x-av1");
14513       break;
14514     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14515     default:
14516     {
14517       caps = _get_unknown_codec_name ("video", fourcc);
14518       break;
14519     }
14520   }
14521
14522   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14523     GstVideoInfo info;
14524
14525     gst_video_info_init (&info);
14526     gst_video_info_set_format (&info, format, entry->width, entry->height);
14527
14528     caps = gst_video_info_to_caps (&info);
14529     *codec_name = gst_pb_utils_get_codec_description (caps);
14530
14531     /* enable clipping for raw video streams */
14532     stream->need_clip = TRUE;
14533     stream->alignment = 32;
14534   }
14535
14536   return caps;
14537 }
14538
14539 static guint
14540 round_up_pow2 (guint n)
14541 {
14542   n = n - 1;
14543   n = n | (n >> 1);
14544   n = n | (n >> 2);
14545   n = n | (n >> 4);
14546   n = n | (n >> 8);
14547   n = n | (n >> 16);
14548   return n + 1;
14549 }
14550
14551 static GstCaps *
14552 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14553     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14554     int len, gchar ** codec_name)
14555 {
14556   GstCaps *caps;
14557   const GstStructure *s;
14558   const gchar *name;
14559   gint endian = 0;
14560   GstAudioFormat format = 0;
14561   gint depth;
14562
14563   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14564
14565   depth = entry->bytes_per_packet * 8;
14566
14567   switch (fourcc) {
14568     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14569     case FOURCC_raw_:
14570       /* 8-bit audio is unsigned */
14571       if (depth == 8)
14572         format = GST_AUDIO_FORMAT_U8;
14573       /* otherwise it's signed and big-endian just like 'twos' */
14574     case FOURCC_twos:
14575       endian = G_BIG_ENDIAN;
14576       /* fall-through */
14577     case FOURCC_sowt:
14578     {
14579       gchar *str;
14580
14581       if (!endian)
14582         endian = G_LITTLE_ENDIAN;
14583
14584       if (!format)
14585         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14586
14587       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14588       _codec (str);
14589       g_free (str);
14590
14591       caps = gst_caps_new_simple ("audio/x-raw",
14592           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14593           "layout", G_TYPE_STRING, "interleaved", NULL);
14594       stream->alignment = GST_ROUND_UP_8 (depth);
14595       stream->alignment = round_up_pow2 (stream->alignment);
14596       break;
14597     }
14598     case FOURCC_fl64:
14599       _codec ("Raw 64-bit floating-point audio");
14600       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14601        * endian later */
14602       caps = gst_caps_new_simple ("audio/x-raw",
14603           "format", G_TYPE_STRING, "F64BE",
14604           "layout", G_TYPE_STRING, "interleaved", NULL);
14605       stream->alignment = 8;
14606       break;
14607     case FOURCC_fl32:
14608       _codec ("Raw 32-bit floating-point audio");
14609       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14610        * endian later */
14611       caps = gst_caps_new_simple ("audio/x-raw",
14612           "format", G_TYPE_STRING, "F32BE",
14613           "layout", G_TYPE_STRING, "interleaved", NULL);
14614       stream->alignment = 4;
14615       break;
14616     case FOURCC_in24:
14617       _codec ("Raw 24-bit PCM audio");
14618       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14619        * endian later */
14620       caps = gst_caps_new_simple ("audio/x-raw",
14621           "format", G_TYPE_STRING, "S24BE",
14622           "layout", G_TYPE_STRING, "interleaved", NULL);
14623       stream->alignment = 4;
14624       break;
14625     case FOURCC_in32:
14626       _codec ("Raw 32-bit PCM audio");
14627       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14628        * endian later */
14629       caps = gst_caps_new_simple ("audio/x-raw",
14630           "format", G_TYPE_STRING, "S32BE",
14631           "layout", G_TYPE_STRING, "interleaved", NULL);
14632       stream->alignment = 4;
14633       break;
14634     case FOURCC_s16l:
14635       _codec ("Raw 16-bit PCM audio");
14636       caps = gst_caps_new_simple ("audio/x-raw",
14637           "format", G_TYPE_STRING, "S16LE",
14638           "layout", G_TYPE_STRING, "interleaved", NULL);
14639       stream->alignment = 2;
14640       break;
14641     case FOURCC_ulaw:
14642       _codec ("Mu-law audio");
14643       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14644       break;
14645     case FOURCC_alaw:
14646       _codec ("A-law audio");
14647       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14648       break;
14649     case 0x0200736d:
14650     case 0x6d730002:
14651       _codec ("Microsoft ADPCM");
14652       /* Microsoft ADPCM-ACM code 2 */
14653       caps = gst_caps_new_simple ("audio/x-adpcm",
14654           "layout", G_TYPE_STRING, "microsoft", NULL);
14655       break;
14656     case 0x1100736d:
14657     case 0x6d730011:
14658       _codec ("DVI/IMA ADPCM");
14659       caps = gst_caps_new_simple ("audio/x-adpcm",
14660           "layout", G_TYPE_STRING, "dvi", NULL);
14661       break;
14662     case 0x1700736d:
14663     case 0x6d730017:
14664       _codec ("DVI/Intel IMA ADPCM");
14665       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14666       caps = gst_caps_new_simple ("audio/x-adpcm",
14667           "layout", G_TYPE_STRING, "quicktime", NULL);
14668       break;
14669     case 0x5500736d:
14670     case 0x6d730055:
14671       /* MPEG layer 3, CBR only (pre QT4.1) */
14672     case FOURCC__mp3:
14673     case FOURCC_mp3_:
14674       _codec ("MPEG-1 layer 3");
14675       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14676       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14677           "mpegversion", G_TYPE_INT, 1, NULL);
14678       break;
14679     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14680       _codec ("MPEG-1 layer 2");
14681       /* MPEG layer 2 */
14682       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14683           "mpegversion", G_TYPE_INT, 1, NULL);
14684       break;
14685     case 0x20736d:
14686     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14687       _codec ("EAC-3 audio");
14688       caps = gst_caps_new_simple ("audio/x-eac3",
14689           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14690       entry->sampled = TRUE;
14691       break;
14692     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14693     case FOURCC_ac_3:
14694       _codec ("AC-3 audio");
14695       caps = gst_caps_new_simple ("audio/x-ac3",
14696           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14697       entry->sampled = TRUE;
14698       break;
14699     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14700     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14701       _codec ("DTS audio");
14702       caps = gst_caps_new_simple ("audio/x-dts",
14703           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14704       entry->sampled = TRUE;
14705       break;
14706     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14707     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14708       _codec ("DTS-HD audio");
14709       caps = gst_caps_new_simple ("audio/x-dts",
14710           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14711       entry->sampled = TRUE;
14712       break;
14713     case FOURCC_MAC3:
14714       _codec ("MACE-3");
14715       caps = gst_caps_new_simple ("audio/x-mace",
14716           "maceversion", G_TYPE_INT, 3, NULL);
14717       break;
14718     case FOURCC_MAC6:
14719       _codec ("MACE-6");
14720       caps = gst_caps_new_simple ("audio/x-mace",
14721           "maceversion", G_TYPE_INT, 6, NULL);
14722       break;
14723     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14724       /* ogg/vorbis */
14725       caps = gst_caps_new_empty_simple ("application/ogg");
14726       break;
14727     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14728       _codec ("DV audio");
14729       caps = gst_caps_new_empty_simple ("audio/x-dv");
14730       break;
14731     case FOURCC_mp4a:
14732       _codec ("MPEG-4 AAC audio");
14733       caps = gst_caps_new_simple ("audio/mpeg",
14734           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14735           "stream-format", G_TYPE_STRING, "raw", NULL);
14736       break;
14737     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14738       _codec ("QDesign Music");
14739       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14740       break;
14741     case FOURCC_QDM2:
14742       _codec ("QDesign Music v.2");
14743       /* FIXME: QDesign music version 2 (no constant) */
14744       if (FALSE && data) {
14745         caps = gst_caps_new_simple ("audio/x-qdm2",
14746             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14747             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14748             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14749       } else {
14750         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14751       }
14752       break;
14753     case FOURCC_agsm:
14754       _codec ("GSM audio");
14755       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14756       break;
14757     case FOURCC_samr:
14758       _codec ("AMR audio");
14759       caps = gst_caps_new_empty_simple ("audio/AMR");
14760       break;
14761     case FOURCC_sawb:
14762       _codec ("AMR-WB audio");
14763       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14764       break;
14765     case FOURCC_ima4:
14766       _codec ("Quicktime IMA ADPCM");
14767       caps = gst_caps_new_simple ("audio/x-adpcm",
14768           "layout", G_TYPE_STRING, "quicktime", NULL);
14769       break;
14770     case FOURCC_alac:
14771       _codec ("Apple lossless audio");
14772       caps = gst_caps_new_empty_simple ("audio/x-alac");
14773       break;
14774     case FOURCC_fLaC:
14775       _codec ("Free Lossless Audio Codec");
14776       caps = gst_caps_new_simple ("audio/x-flac",
14777           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14778       break;
14779     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14780       _codec ("QualComm PureVoice");
14781       caps = gst_caps_from_string ("audio/qcelp");
14782       break;
14783     case FOURCC_wma_:
14784     case FOURCC_owma:
14785       _codec ("WMA");
14786       caps = gst_caps_new_empty_simple ("audio/x-wma");
14787       break;
14788     case FOURCC_opus:
14789       _codec ("Opus");
14790       caps = gst_caps_new_empty_simple ("audio/x-opus");
14791       break;
14792     case FOURCC_lpcm:
14793     {
14794       guint32 flags = 0;
14795       guint32 depth = 0;
14796       guint32 width = 0;
14797       GstAudioFormat format;
14798       enum
14799       {
14800         FLAG_IS_FLOAT = 0x1,
14801         FLAG_IS_BIG_ENDIAN = 0x2,
14802         FLAG_IS_SIGNED = 0x4,
14803         FLAG_IS_PACKED = 0x8,
14804         FLAG_IS_ALIGNED_HIGH = 0x10,
14805         FLAG_IS_NON_INTERLEAVED = 0x20
14806       };
14807       _codec ("Raw LPCM audio");
14808
14809       if (data && len >= 36) {
14810         depth = QT_UINT32 (data + 24);
14811         flags = QT_UINT32 (data + 28);
14812         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14813       }
14814       if ((flags & FLAG_IS_FLOAT) == 0) {
14815         if (depth == 0)
14816           depth = 16;
14817         if (width == 0)
14818           width = 16;
14819         if ((flags & FLAG_IS_ALIGNED_HIGH))
14820           depth = width;
14821
14822         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14823             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14824             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14825         caps = gst_caps_new_simple ("audio/x-raw",
14826             "format", G_TYPE_STRING,
14827             format !=
14828             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14829             "UNKNOWN", "layout", G_TYPE_STRING,
14830             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14831             "interleaved", NULL);
14832         stream->alignment = GST_ROUND_UP_8 (depth);
14833         stream->alignment = round_up_pow2 (stream->alignment);
14834       } else {
14835         if (width == 0)
14836           width = 32;
14837         if (width == 64) {
14838           if (flags & FLAG_IS_BIG_ENDIAN)
14839             format = GST_AUDIO_FORMAT_F64BE;
14840           else
14841             format = GST_AUDIO_FORMAT_F64LE;
14842         } else {
14843           if (flags & FLAG_IS_BIG_ENDIAN)
14844             format = GST_AUDIO_FORMAT_F32BE;
14845           else
14846             format = GST_AUDIO_FORMAT_F32LE;
14847         }
14848         caps = gst_caps_new_simple ("audio/x-raw",
14849             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14850             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14851             "non-interleaved" : "interleaved", NULL);
14852         stream->alignment = width / 8;
14853       }
14854       break;
14855     }
14856     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14857     {
14858       _codec ("AC4");
14859       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14860       break;
14861     }
14862     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14863       /* ? */
14864     default:
14865     {
14866       caps = _get_unknown_codec_name ("audio", fourcc);
14867       break;
14868     }
14869   }
14870
14871   if (caps) {
14872     GstCaps *templ_caps =
14873         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14874     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14875     gst_caps_unref (caps);
14876     gst_caps_unref (templ_caps);
14877     caps = intersection;
14878   }
14879
14880   /* enable clipping for raw audio streams */
14881   s = gst_caps_get_structure (caps, 0);
14882   name = gst_structure_get_name (s);
14883   if (g_str_has_prefix (name, "audio/x-raw")) {
14884     stream->need_clip = TRUE;
14885     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14886     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14887     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
14888         stream->max_buffer_size);
14889   }
14890   return caps;
14891 }
14892
14893 static GstCaps *
14894 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14895     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14896     const guint8 * stsd_entry_data, gchar ** codec_name)
14897 {
14898   GstCaps *caps;
14899
14900   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14901
14902   switch (fourcc) {
14903     case FOURCC_mp4s:
14904       _codec ("DVD subtitle");
14905       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14906       stream->need_process = TRUE;
14907       break;
14908     case FOURCC_text:
14909       _codec ("Quicktime timed text");
14910       goto text;
14911     case FOURCC_tx3g:
14912       _codec ("3GPP timed text");
14913     text:
14914       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14915           "utf8", NULL);
14916       /* actual text piece needs to be extracted */
14917       stream->need_process = TRUE;
14918       break;
14919     case FOURCC_stpp:
14920       _codec ("XML subtitles");
14921       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14922       break;
14923     case FOURCC_c608:
14924       _codec ("CEA 608 Closed Caption");
14925       caps =
14926           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14927           G_TYPE_STRING, "s334-1a", NULL);
14928       stream->need_process = TRUE;
14929       stream->need_split = TRUE;
14930       break;
14931     case FOURCC_c708:
14932       _codec ("CEA 708 Closed Caption");
14933       caps =
14934           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
14935           G_TYPE_STRING, "cdp", NULL);
14936       stream->need_process = TRUE;
14937       break;
14938
14939     default:
14940     {
14941       caps = _get_unknown_codec_name ("text", fourcc);
14942       break;
14943     }
14944   }
14945   return caps;
14946 }
14947
14948 static GstCaps *
14949 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14950     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14951     const guint8 * stsd_entry_data, gchar ** codec_name)
14952 {
14953   GstCaps *caps;
14954
14955   switch (fourcc) {
14956     case FOURCC_m1v:
14957       _codec ("MPEG 1 video");
14958       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14959           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14960       break;
14961     default:
14962       caps = NULL;
14963       break;
14964   }
14965   return caps;
14966 }
14967
14968 static void
14969 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14970     const gchar * system_id)
14971 {
14972   gint i;
14973
14974   if (!qtdemux->protection_system_ids)
14975     qtdemux->protection_system_ids =
14976         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14977   /* Check whether we already have an entry for this system ID. */
14978   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14979     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14980     if (g_ascii_strcasecmp (system_id, id) == 0) {
14981       return;
14982     }
14983   }
14984   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14985   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14986           -1));
14987 }