qtdemux: Add support for version 1 cslg boxes
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 #define gst_qtdemux_parent_class parent_class
293 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
294 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
295     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
296
297 static void gst_qtdemux_dispose (GObject * object);
298 static void gst_qtdemux_finalize (GObject * object);
299
300 static guint32
301 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
302     GstClockTime media_time);
303 static guint32
304 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
305     QtDemuxStream * str, gint64 media_offset);
306
307 #if 0
308 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
309 static GstIndex *gst_qtdemux_get_index (GstElement * element);
310 #endif
311 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
312     GstStateChange transition);
313 static void gst_qtdemux_set_context (GstElement * element,
314     GstContext * context);
315 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
316 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
317     GstObject * parent, GstPadMode mode, gboolean active);
318
319 static void gst_qtdemux_loop (GstPad * pad);
320 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
321     GstBuffer * inbuf);
322 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
323     GstEvent * event);
324 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
325     GstQuery * query);
326 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
327 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
328     QtDemuxStream * stream);
329 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
330     QtDemuxStream * stream);
331 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
332     gboolean force);
333
334 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
335
336 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
337     const guint8 * buffer, guint length);
338 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
339     const guint8 * buffer, guint length);
340 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
341
342 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
343     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
344     GstTagList * list);
345 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
346     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
347     const guint8 * stsd_entry_data, gchar ** codec_name);
348 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
350     const guint8 * data, int len, gchar ** codec_name);
351 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
352     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
353     gchar ** codec_name);
354 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * stsd_entry_data, gchar ** codec_name);
357
358 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
359     QtDemuxStream * stream, guint32 n);
360 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
361 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
363 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
364 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
365 static void qtdemux_do_allocation (QtDemuxStream * stream,
366     GstQTDemux * qtdemux);
367 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
369 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
370     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
371     GstClockTime * _start, GstClockTime * _stop);
372 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
373     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
374
375 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
376 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
377
378 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
379
380 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
381     QtDemuxStream * stream, guint sample_index);
382 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
383     const gchar * id);
384 static void qtdemux_gst_structure_free (GstStructure * gststructure);
385 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
386
387 static void
388 gst_qtdemux_class_init (GstQTDemuxClass * klass)
389 {
390   GObjectClass *gobject_class;
391   GstElementClass *gstelement_class;
392
393   gobject_class = (GObjectClass *) klass;
394   gstelement_class = (GstElementClass *) klass;
395
396   parent_class = g_type_class_peek_parent (klass);
397
398   gobject_class->dispose = gst_qtdemux_dispose;
399   gobject_class->finalize = gst_qtdemux_finalize;
400
401   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
402 #if 0
403   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
404   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
405 #endif
406   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
407
408   gst_tag_register_musicbrainz_tags ();
409
410   gst_element_class_add_static_pad_template (gstelement_class,
411       &gst_qtdemux_sink_template);
412   gst_element_class_add_static_pad_template (gstelement_class,
413       &gst_qtdemux_videosrc_template);
414   gst_element_class_add_static_pad_template (gstelement_class,
415       &gst_qtdemux_audiosrc_template);
416   gst_element_class_add_static_pad_template (gstelement_class,
417       &gst_qtdemux_subsrc_template);
418   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
419       "Codec/Demuxer",
420       "Demultiplex a QuickTime file into audio and video streams",
421       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
422
423   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
424   gst_riff_init ();
425 }
426
427 static void
428 gst_qtdemux_init (GstQTDemux * qtdemux)
429 {
430   qtdemux->sinkpad =
431       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
432   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
433   gst_pad_set_activatemode_function (qtdemux->sinkpad,
434       qtdemux_sink_activate_mode);
435   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
436   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
437   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
438   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
439
440   qtdemux->adapter = gst_adapter_new ();
441   g_queue_init (&qtdemux->protection_event_queue);
442   qtdemux->flowcombiner = gst_flow_combiner_new ();
443   g_mutex_init (&qtdemux->expose_lock);
444
445   qtdemux->active_streams = g_ptr_array_new_with_free_func
446       ((GDestroyNotify) gst_qtdemux_stream_unref);
447   qtdemux->old_streams = g_ptr_array_new_with_free_func
448       ((GDestroyNotify) gst_qtdemux_stream_unref);
449
450   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
451
452   gst_qtdemux_reset (qtdemux, TRUE);
453 }
454
455 static void
456 gst_qtdemux_finalize (GObject * object)
457 {
458   GstQTDemux *qtdemux = GST_QTDEMUX (object);
459
460   g_free (qtdemux->redirect_location);
461
462   G_OBJECT_CLASS (parent_class)->finalize (object);
463 }
464
465 static void
466 gst_qtdemux_dispose (GObject * object)
467 {
468   GstQTDemux *qtdemux = GST_QTDEMUX (object);
469
470   if (qtdemux->adapter) {
471     g_object_unref (G_OBJECT (qtdemux->adapter));
472     qtdemux->adapter = NULL;
473   }
474   gst_tag_list_unref (qtdemux->tag_list);
475   gst_flow_combiner_free (qtdemux->flowcombiner);
476   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
477       NULL);
478   g_queue_clear (&qtdemux->protection_event_queue);
479
480   g_free (qtdemux->cenc_aux_info_sizes);
481   qtdemux->cenc_aux_info_sizes = NULL;
482   g_mutex_clear (&qtdemux->expose_lock);
483
484   g_ptr_array_free (qtdemux->active_streams, TRUE);
485   g_ptr_array_free (qtdemux->old_streams, TRUE);
486
487   G_OBJECT_CLASS (parent_class)->dispose (object);
488 }
489
490 static void
491 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
492 {
493   if (qtdemux->redirect_location) {
494     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
495         (_("This file contains no playable streams.")),
496         ("no known streams found, a redirect message has been posted"),
497         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
498   } else {
499     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
500         (_("This file contains no playable streams.")),
501         ("no known streams found"));
502   }
503 }
504
505 static GstBuffer *
506 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
507 {
508   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
509       mem, size, 0, size, mem, free_func);
510 }
511
512 static GstFlowReturn
513 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
514     GstBuffer ** buf)
515 {
516   GstFlowReturn flow;
517   GstMapInfo map;
518   gsize bsize;
519
520   if (G_UNLIKELY (size == 0)) {
521     GstFlowReturn ret;
522     GstBuffer *tmp = NULL;
523
524     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
525     if (ret != GST_FLOW_OK)
526       return ret;
527
528     gst_buffer_map (tmp, &map, GST_MAP_READ);
529     size = QT_UINT32 (map.data);
530     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
531
532     gst_buffer_unmap (tmp, &map);
533     gst_buffer_unref (tmp);
534   }
535
536   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
537   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
538     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
539       /* we're pulling header but already got most interesting bits,
540        * so never mind the rest (e.g. tags) (that much) */
541       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
542           size);
543       return GST_FLOW_EOS;
544     } else {
545       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
546           (_("This file is invalid and cannot be played.")),
547           ("atom has bogus size %" G_GUINT64_FORMAT, size));
548       return GST_FLOW_ERROR;
549     }
550   }
551
552   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
553
554   if (G_UNLIKELY (flow != GST_FLOW_OK))
555     return flow;
556
557   bsize = gst_buffer_get_size (*buf);
558   /* Catch short reads - we don't want any partial atoms */
559   if (G_UNLIKELY (bsize < size)) {
560     GST_WARNING_OBJECT (qtdemux,
561         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
562     gst_buffer_unref (*buf);
563     *buf = NULL;
564     return GST_FLOW_EOS;
565   }
566
567   return flow;
568 }
569
570 #if 1
571 static gboolean
572 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
573     GstFormat src_format, gint64 src_value, GstFormat dest_format,
574     gint64 * dest_value)
575 {
576   gboolean res = TRUE;
577   QtDemuxStream *stream = gst_pad_get_element_private (pad);
578   gint32 index;
579
580   if (stream->subtype != FOURCC_vide) {
581     res = FALSE;
582     goto done;
583   }
584
585   switch (src_format) {
586     case GST_FORMAT_TIME:
587       switch (dest_format) {
588         case GST_FORMAT_BYTES:{
589           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
590           if (-1 == index) {
591             res = FALSE;
592             goto done;
593           }
594
595           *dest_value = stream->samples[index].offset;
596
597           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
598               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
599               GST_TIME_ARGS (src_value), *dest_value);
600           break;
601         }
602         default:
603           res = FALSE;
604           break;
605       }
606       break;
607     case GST_FORMAT_BYTES:
608       switch (dest_format) {
609         case GST_FORMAT_TIME:{
610           index =
611               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
612               stream, src_value);
613
614           if (-1 == index) {
615             res = FALSE;
616             goto done;
617           }
618
619           *dest_value =
620               QTSTREAMTIME_TO_GSTTIME (stream,
621               stream->samples[index].timestamp);
622           GST_DEBUG_OBJECT (qtdemux,
623               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
624               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
625           break;
626         }
627         default:
628           res = FALSE;
629           break;
630       }
631       break;
632     default:
633       res = FALSE;
634       break;
635   }
636
637 done:
638   return res;
639 }
640 #endif
641
642 static gboolean
643 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
644 {
645   gboolean res = FALSE;
646
647   *duration = GST_CLOCK_TIME_NONE;
648
649   if (qtdemux->duration != 0 &&
650       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
651     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
652     res = TRUE;
653   } else {
654     *duration = GST_CLOCK_TIME_NONE;
655   }
656
657   return res;
658 }
659
660 static gboolean
661 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
662     GstQuery * query)
663 {
664   gboolean res = FALSE;
665   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
666
667   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
668
669   switch (GST_QUERY_TYPE (query)) {
670     case GST_QUERY_POSITION:{
671       GstFormat fmt;
672
673       gst_query_parse_position (query, &fmt, NULL);
674       if (fmt == GST_FORMAT_TIME
675           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
676         gst_query_set_position (query, GST_FORMAT_TIME,
677             qtdemux->segment.position);
678         res = TRUE;
679       }
680     }
681       break;
682     case GST_QUERY_DURATION:{
683       GstFormat fmt;
684
685       gst_query_parse_duration (query, &fmt, NULL);
686       if (fmt == GST_FORMAT_TIME) {
687         /* First try to query upstream */
688         res = gst_pad_query_default (pad, parent, query);
689         if (!res) {
690           GstClockTime duration;
691           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
692             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
693             res = TRUE;
694           }
695         }
696       }
697       break;
698     }
699     case GST_QUERY_CONVERT:{
700       GstFormat src_fmt, dest_fmt;
701       gint64 src_value, dest_value = 0;
702
703       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
704
705       res = gst_qtdemux_src_convert (qtdemux, pad,
706           src_fmt, src_value, dest_fmt, &dest_value);
707       if (res)
708         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
709
710       break;
711     }
712     case GST_QUERY_FORMATS:
713       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
714       res = TRUE;
715       break;
716     case GST_QUERY_SEEKING:{
717       GstFormat fmt;
718       gboolean seekable;
719
720       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
721
722       if (fmt == GST_FORMAT_BYTES) {
723         /* We always refuse BYTES seeks from downstream */
724         break;
725       }
726
727       /* try upstream first */
728       res = gst_pad_query_default (pad, parent, query);
729
730       if (!res) {
731         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
732         if (fmt == GST_FORMAT_TIME) {
733           GstClockTime duration;
734
735           gst_qtdemux_get_duration (qtdemux, &duration);
736           seekable = TRUE;
737           if (!qtdemux->pullbased) {
738             GstQuery *q;
739
740             /* we might be able with help from upstream */
741             seekable = FALSE;
742             q = gst_query_new_seeking (GST_FORMAT_BYTES);
743             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
744               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
745               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
746             }
747             gst_query_unref (q);
748           }
749           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
750           res = TRUE;
751         }
752       }
753       break;
754     }
755     case GST_QUERY_SEGMENT:
756     {
757       GstFormat format;
758       gint64 start, stop;
759
760       format = qtdemux->segment.format;
761
762       start =
763           gst_segment_to_stream_time (&qtdemux->segment, format,
764           qtdemux->segment.start);
765       if ((stop = qtdemux->segment.stop) == -1)
766         stop = qtdemux->segment.duration;
767       else
768         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
769
770       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
771       res = TRUE;
772       break;
773     }
774     default:
775       res = gst_pad_query_default (pad, parent, query);
776       break;
777   }
778
779   return res;
780 }
781
782 static void
783 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
784 {
785   if (G_LIKELY (stream->pad)) {
786     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
787         GST_DEBUG_PAD_NAME (stream->pad));
788
789     if (!gst_tag_list_is_empty (stream->stream_tags)) {
790       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
791           stream->stream_tags);
792       gst_pad_push_event (stream->pad,
793           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
794     }
795
796     if (G_UNLIKELY (stream->send_global_tags)) {
797       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
798           qtdemux->tag_list);
799       gst_pad_push_event (stream->pad,
800           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
801       stream->send_global_tags = FALSE;
802     }
803   }
804 }
805
806 /* push event on all source pads; takes ownership of the event */
807 static void
808 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
809 {
810   gboolean has_valid_stream = FALSE;
811   GstEventType etype = GST_EVENT_TYPE (event);
812   guint i;
813
814   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
815       GST_EVENT_TYPE_NAME (event));
816
817   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
818     GstPad *pad;
819     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
820     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
821
822     if ((pad = stream->pad)) {
823       has_valid_stream = TRUE;
824
825       if (etype == GST_EVENT_EOS) {
826         /* let's not send twice */
827         if (stream->sent_eos)
828           continue;
829         stream->sent_eos = TRUE;
830       }
831
832       gst_pad_push_event (pad, gst_event_ref (event));
833     }
834   }
835
836   gst_event_unref (event);
837
838   /* if it is EOS and there are no pads, post an error */
839   if (!has_valid_stream && etype == GST_EVENT_EOS) {
840     gst_qtdemux_post_no_playable_stream_error (qtdemux);
841   }
842 }
843
844 typedef struct
845 {
846   guint64 media_time;
847 } FindData;
848
849 static gint
850 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
851 {
852   if ((gint64) s1->timestamp > *media_time)
853     return 1;
854   if ((gint64) s1->timestamp == *media_time)
855     return 0;
856
857   return -1;
858 }
859
860 /* find the index of the sample that includes the data for @media_time using a
861  * binary search.  Only to be called in optimized cases of linear search below.
862  *
863  * Returns the index of the sample with the corresponding *DTS*.
864  */
865 static guint32
866 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
867     guint64 media_time)
868 {
869   QtDemuxSample *result;
870   guint32 index;
871
872   /* convert media_time to mov format */
873   media_time =
874       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
875
876   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
877       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
878       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
879
880   if (G_LIKELY (result))
881     index = result - str->samples;
882   else
883     index = 0;
884
885   return index;
886 }
887
888
889
890 /* find the index of the sample that includes the data for @media_offset using a
891  * linear search
892  *
893  * Returns the index of the sample.
894  */
895 static guint32
896 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
897     QtDemuxStream * str, gint64 media_offset)
898 {
899   QtDemuxSample *result = str->samples;
900   guint32 index = 0;
901
902   if (result == NULL || str->n_samples == 0)
903     return -1;
904
905   if (media_offset == result->offset)
906     return index;
907
908   result++;
909   while (index < str->n_samples - 1) {
910     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
911       goto parse_failed;
912
913     if (media_offset < result->offset)
914       break;
915
916     index++;
917     result++;
918   }
919   return index;
920
921   /* ERRORS */
922 parse_failed:
923   {
924     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
925     return -1;
926   }
927 }
928
929 /* find the index of the sample that includes the data for @media_time using a
930  * linear search, and keeping in mind that not all samples may have been parsed
931  * yet.  If possible, it will delegate to binary search.
932  *
933  * Returns the index of the sample.
934  */
935 static guint32
936 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
937     GstClockTime media_time)
938 {
939   guint32 index = 0;
940   guint64 mov_time;
941   QtDemuxSample *sample;
942
943   /* convert media_time to mov format */
944   mov_time =
945       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
946
947   sample = str->samples;
948   if (mov_time == sample->timestamp + sample->pts_offset)
949     return index;
950
951   /* use faster search if requested time in already parsed range */
952   sample = str->samples + str->stbl_index;
953   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
954     index = gst_qtdemux_find_index (qtdemux, str, media_time);
955     sample = str->samples + index;
956   } else {
957     while (index < str->n_samples - 1) {
958       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
959         goto parse_failed;
960
961       sample = str->samples + index + 1;
962       if (mov_time < sample->timestamp) {
963         sample = str->samples + index;
964         break;
965       }
966
967       index++;
968     }
969   }
970
971   /* sample->timestamp is now <= media_time, need to find the corresponding
972    * PTS now by looking backwards */
973   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
974     index--;
975     sample = str->samples + index;
976   }
977
978   return index;
979
980   /* ERRORS */
981 parse_failed:
982   {
983     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
984     return -1;
985   }
986 }
987
988 /* find the index of the keyframe needed to decode the sample at @index
989  * of stream @str, or of a subsequent keyframe (depending on @next)
990  *
991  * Returns the index of the keyframe.
992  */
993 static guint32
994 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
995     guint32 index, gboolean next)
996 {
997   guint32 new_index = index;
998
999   if (index >= str->n_samples) {
1000     new_index = str->n_samples;
1001     goto beach;
1002   }
1003
1004   /* all keyframes, return index */
1005   if (str->all_keyframe) {
1006     new_index = index;
1007     goto beach;
1008   }
1009
1010   /* else search until we have a keyframe */
1011   while (new_index < str->n_samples) {
1012     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1013       goto parse_failed;
1014
1015     if (str->samples[new_index].keyframe)
1016       break;
1017
1018     if (new_index == 0)
1019       break;
1020
1021     if (next)
1022       new_index++;
1023     else
1024       new_index--;
1025   }
1026
1027   if (new_index == str->n_samples) {
1028     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1029     new_index = -1;
1030   }
1031
1032 beach:
1033   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1034       "gave %u", next ? "after" : "before", index, new_index);
1035
1036   return new_index;
1037
1038   /* ERRORS */
1039 parse_failed:
1040   {
1041     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1042     return -1;
1043   }
1044 }
1045
1046 /* find the segment for @time_position for @stream
1047  *
1048  * Returns the index of the segment containing @time_position.
1049  * Returns the last segment and sets the @eos variable to TRUE
1050  * if the time is beyond the end. @eos may be NULL
1051  */
1052 static guint32
1053 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1054     GstClockTime time_position)
1055 {
1056   gint i;
1057   guint32 seg_idx;
1058
1059   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1060       GST_TIME_ARGS (time_position));
1061
1062   seg_idx = -1;
1063   for (i = 0; i < stream->n_segments; i++) {
1064     QtDemuxSegment *segment = &stream->segments[i];
1065
1066     GST_LOG_OBJECT (stream->pad,
1067         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1068         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1069
1070     /* For the last segment we include stop_time in the last segment */
1071     if (i < stream->n_segments - 1) {
1072       if (segment->time <= time_position && time_position < segment->stop_time) {
1073         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1074         seg_idx = i;
1075         break;
1076       }
1077     } else {
1078       /* Last segment always matches */
1079       seg_idx = i;
1080       break;
1081     }
1082   }
1083   return seg_idx;
1084 }
1085
1086 /* move the stream @str to the sample position @index.
1087  *
1088  * Updates @str->sample_index and marks discontinuity if needed.
1089  */
1090 static void
1091 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1092     guint32 index)
1093 {
1094   /* no change needed */
1095   if (index == str->sample_index)
1096     return;
1097
1098   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1099       str->n_samples);
1100
1101   /* position changed, we have a discont */
1102   str->sample_index = index;
1103   str->offset_in_sample = 0;
1104   /* Each time we move in the stream we store the position where we are
1105    * starting from */
1106   str->from_sample = index;
1107   str->discont = TRUE;
1108 }
1109
1110 static void
1111 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1112     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1113 {
1114   guint64 min_offset;
1115   gint64 min_byte_offset = -1;
1116   guint i;
1117
1118   min_offset = desired_time;
1119
1120   /* for each stream, find the index of the sample in the segment
1121    * and move back to the previous keyframe. */
1122   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1123     QtDemuxStream *str;
1124     guint32 index, kindex;
1125     guint32 seg_idx;
1126     GstClockTime media_start;
1127     GstClockTime media_time;
1128     GstClockTime seg_time;
1129     QtDemuxSegment *seg;
1130     gboolean empty_segment = FALSE;
1131
1132     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1133
1134     if (CUR_STREAM (str)->sparse && !use_sparse)
1135       continue;
1136
1137     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1138     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1139
1140     /* get segment and time in the segment */
1141     seg = &str->segments[seg_idx];
1142     seg_time = (desired_time - seg->time) * seg->rate;
1143
1144     while (QTSEGMENT_IS_EMPTY (seg)) {
1145       seg_time = 0;
1146       empty_segment = TRUE;
1147       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1148           seg_idx);
1149       seg_idx++;
1150       if (seg_idx == str->n_segments)
1151         break;
1152       seg = &str->segments[seg_idx];
1153     }
1154
1155     if (seg_idx == str->n_segments) {
1156       /* FIXME track shouldn't have the last segment as empty, but if it
1157        * happens we better handle it */
1158       continue;
1159     }
1160
1161     /* get the media time in the segment */
1162     media_start = seg->media_start + seg_time;
1163
1164     /* get the index of the sample with media time */
1165     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1166     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1167         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1168         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1169         empty_segment);
1170
1171     /* shift to next frame if we are looking for next keyframe */
1172     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1173         && index < str->stbl_index)
1174       index++;
1175
1176     if (!empty_segment) {
1177       /* find previous keyframe */
1178       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1179
1180       /* we will settle for one before if none found after */
1181       if (next && kindex == -1)
1182         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1183
1184       /* Update the requested time whenever a keyframe was found, to make it
1185        * accurate and avoid having the first buffer fall outside of the segment
1186        */
1187       if (kindex != -1) {
1188         index = kindex;
1189
1190         /* get timestamp of keyframe */
1191         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1192         GST_DEBUG_OBJECT (qtdemux,
1193             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1194             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1195             str->samples[kindex].offset);
1196
1197         /* keyframes in the segment get a chance to change the
1198          * desired_offset. keyframes out of the segment are
1199          * ignored. */
1200         if (media_time >= seg->media_start) {
1201           GstClockTime seg_time;
1202
1203           /* this keyframe is inside the segment, convert back to
1204            * segment time */
1205           seg_time = (media_time - seg->media_start) + seg->time;
1206           if ((!next && (seg_time < min_offset)) ||
1207               (next && (seg_time > min_offset)))
1208             min_offset = seg_time;
1209         }
1210       }
1211     }
1212
1213     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1214       min_byte_offset = str->samples[index].offset;
1215   }
1216
1217   if (key_time)
1218     *key_time = min_offset;
1219   if (key_offset)
1220     *key_offset = min_byte_offset;
1221 }
1222
1223 static gboolean
1224 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1225     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1226 {
1227   gboolean res;
1228
1229   g_return_val_if_fail (format != NULL, FALSE);
1230   g_return_val_if_fail (cur != NULL, FALSE);
1231   g_return_val_if_fail (stop != NULL, FALSE);
1232
1233   if (*format == GST_FORMAT_TIME)
1234     return TRUE;
1235
1236   res = TRUE;
1237   if (cur_type != GST_SEEK_TYPE_NONE)
1238     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1239   if (res && stop_type != GST_SEEK_TYPE_NONE)
1240     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1241
1242   if (res)
1243     *format = GST_FORMAT_TIME;
1244
1245   return res;
1246 }
1247
1248 /* perform seek in push based mode:
1249    find BYTE position to move to based on time and delegate to upstream
1250 */
1251 static gboolean
1252 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1253 {
1254   gdouble rate;
1255   GstFormat format;
1256   GstSeekFlags flags;
1257   GstSeekType cur_type, stop_type;
1258   gint64 cur, stop, key_cur;
1259   gboolean res;
1260   gint64 byte_cur;
1261   gint64 original_stop;
1262   guint32 seqnum;
1263
1264   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1265
1266   gst_event_parse_seek (event, &rate, &format, &flags,
1267       &cur_type, &cur, &stop_type, &stop);
1268   seqnum = gst_event_get_seqnum (event);
1269
1270   /* Directly send the instant-rate-change event here before taking the
1271    * stream-lock so that it can be applied as soon as possible */
1272   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1273     GstEvent *ev;
1274
1275     /* instant rate change only supported if direction does not change. All
1276      * other requirements are already checked before creating the seek event
1277      * but let's double-check here to be sure */
1278     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1279         (qtdemux->segment.rate < 0 && rate > 0) ||
1280         cur_type != GST_SEEK_TYPE_NONE ||
1281         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1282       GST_ERROR_OBJECT (qtdemux,
1283           "Instant rate change seeks only supported in the "
1284           "same direction, without flushing and position change");
1285       return FALSE;
1286     }
1287
1288     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1289         (GstSegmentFlags) flags);
1290     gst_event_set_seqnum (ev, seqnum);
1291     gst_qtdemux_push_event (qtdemux, ev);
1292     return TRUE;
1293   }
1294
1295   /* only forward streaming and seeking is possible */
1296   if (rate <= 0)
1297     goto unsupported_seek;
1298
1299   /* convert to TIME if needed and possible */
1300   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1301           stop_type, &stop))
1302     goto no_format;
1303
1304   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1305    * the original stop position to use when upstream pushes the new segment
1306    * for this seek */
1307   original_stop = stop;
1308   stop = -1;
1309
1310   /* find reasonable corresponding BYTE position,
1311    * also try to mind about keyframes, since we can not go back a bit for them
1312    * later on */
1313   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1314    * mostly just work, but let's not yet boldly go there  ... */
1315   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1316
1317   if (byte_cur == -1)
1318     goto abort_seek;
1319
1320   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1321       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1322       stop);
1323
1324   GST_OBJECT_LOCK (qtdemux);
1325   qtdemux->seek_offset = byte_cur;
1326   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1327     qtdemux->push_seek_start = cur;
1328   } else {
1329     qtdemux->push_seek_start = key_cur;
1330   }
1331
1332   if (stop_type == GST_SEEK_TYPE_NONE) {
1333     qtdemux->push_seek_stop = qtdemux->segment.stop;
1334   } else {
1335     qtdemux->push_seek_stop = original_stop;
1336   }
1337   GST_OBJECT_UNLOCK (qtdemux);
1338
1339   qtdemux->segment_seqnum = seqnum;
1340   /* BYTE seek event */
1341   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1342       stop_type, stop);
1343   gst_event_set_seqnum (event, seqnum);
1344   res = gst_pad_push_event (qtdemux->sinkpad, event);
1345
1346   return res;
1347
1348   /* ERRORS */
1349 abort_seek:
1350   {
1351     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1352         "seek aborted.");
1353     return FALSE;
1354   }
1355 unsupported_seek:
1356   {
1357     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1358     return FALSE;
1359   }
1360 no_format:
1361   {
1362     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1363     return FALSE;
1364   }
1365 }
1366
1367 /* perform the seek.
1368  *
1369  * We set all segment_indexes in the streams to unknown and
1370  * adjust the time_position to the desired position. this is enough
1371  * to trigger a segment switch in the streaming thread to start
1372  * streaming from the desired position.
1373  *
1374  * Keyframe seeking is a little more complicated when dealing with
1375  * segments. Ideally we want to move to the previous keyframe in
1376  * the segment but there might not be a keyframe in the segment. In
1377  * fact, none of the segments could contain a keyframe. We take a
1378  * practical approach: seek to the previous keyframe in the segment,
1379  * if there is none, seek to the beginning of the segment.
1380  *
1381  * Called with STREAM_LOCK
1382  */
1383 static gboolean
1384 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1385     guint32 seqnum, GstSeekFlags flags)
1386 {
1387   gint64 desired_offset;
1388   guint i;
1389
1390   desired_offset = segment->position;
1391
1392   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1393       GST_TIME_ARGS (desired_offset));
1394
1395   /* may not have enough fragmented info to do this adjustment,
1396    * and we can't scan (and probably should not) at this time with
1397    * possibly flushing upstream */
1398   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1399     gint64 min_offset;
1400     gboolean next, before, after;
1401
1402     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1403     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1404     next = after && !before;
1405     if (segment->rate < 0)
1406       next = !next;
1407
1408     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1409         NULL);
1410     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1411         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1412     desired_offset = min_offset;
1413   }
1414
1415   /* and set all streams to the final position */
1416   GST_OBJECT_LOCK (qtdemux);
1417   gst_flow_combiner_reset (qtdemux->flowcombiner);
1418   GST_OBJECT_UNLOCK (qtdemux);
1419   qtdemux->segment_seqnum = seqnum;
1420   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1421     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1422
1423     stream->time_position = desired_offset;
1424     stream->accumulated_base = 0;
1425     stream->sample_index = -1;
1426     stream->offset_in_sample = 0;
1427     stream->segment_index = -1;
1428     stream->sent_eos = FALSE;
1429     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1430
1431     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1432       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1433   }
1434   segment->position = desired_offset;
1435   if (segment->rate >= 0) {
1436     segment->start = desired_offset;
1437     /* We need to update time as we update start in that direction */
1438     segment->time = desired_offset;
1439
1440     /* we stop at the end */
1441     if (segment->stop == -1)
1442       segment->stop = segment->duration;
1443   } else {
1444     segment->stop = desired_offset;
1445   }
1446
1447   if (qtdemux->fragmented)
1448     qtdemux->fragmented_seek_pending = TRUE;
1449
1450   return TRUE;
1451 }
1452
1453 /* do a seek in pull based mode */
1454 static gboolean
1455 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1456 {
1457   gdouble rate = 1.0;
1458   GstFormat format;
1459   GstSeekFlags flags;
1460   GstSeekType cur_type, stop_type;
1461   gint64 cur, stop;
1462   gboolean flush, instant_rate_change;
1463   gboolean update;
1464   GstSegment seeksegment;
1465   guint32 seqnum = GST_SEQNUM_INVALID;
1466   GstEvent *flush_event;
1467   gboolean ret;
1468
1469   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1470
1471   gst_event_parse_seek (event, &rate, &format, &flags,
1472       &cur_type, &cur, &stop_type, &stop);
1473   seqnum = gst_event_get_seqnum (event);
1474
1475   /* we have to have a format as the segment format. Try to convert
1476    * if not. */
1477   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1478           stop_type, &stop))
1479     goto no_format;
1480
1481   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1482
1483   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1484   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1485
1486   /* Directly send the instant-rate-change event here before taking the
1487    * stream-lock so that it can be applied as soon as possible */
1488   if (instant_rate_change) {
1489     GstEvent *ev;
1490
1491     /* instant rate change only supported if direction does not change. All
1492      * other requirements are already checked before creating the seek event
1493      * but let's double-check here to be sure */
1494     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1495         (qtdemux->segment.rate < 0 && rate > 0) ||
1496         cur_type != GST_SEEK_TYPE_NONE ||
1497         stop_type != GST_SEEK_TYPE_NONE || flush) {
1498       GST_ERROR_OBJECT (qtdemux,
1499           "Instant rate change seeks only supported in the "
1500           "same direction, without flushing and position change");
1501       return FALSE;
1502     }
1503
1504     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1505         (GstSegmentFlags) flags);
1506     gst_event_set_seqnum (ev, seqnum);
1507     gst_qtdemux_push_event (qtdemux, ev);
1508     return TRUE;
1509   }
1510
1511   /* stop streaming, either by flushing or by pausing the task */
1512   if (flush) {
1513     flush_event = gst_event_new_flush_start ();
1514     if (seqnum != GST_SEQNUM_INVALID)
1515       gst_event_set_seqnum (flush_event, seqnum);
1516     /* unlock upstream pull_range */
1517     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1518     /* make sure out loop function exits */
1519     gst_qtdemux_push_event (qtdemux, flush_event);
1520   } else {
1521     /* non flushing seek, pause the task */
1522     gst_pad_pause_task (qtdemux->sinkpad);
1523   }
1524
1525   /* wait for streaming to finish */
1526   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1527
1528   /* copy segment, we need this because we still need the old
1529    * segment when we close the current segment. */
1530   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1531
1532   /* configure the segment with the seek variables */
1533   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1534   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1535           cur_type, cur, stop_type, stop, &update)) {
1536     ret = FALSE;
1537     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1538   } else {
1539     /* now do the seek */
1540     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1541   }
1542
1543   /* prepare for streaming again */
1544   if (flush) {
1545     flush_event = gst_event_new_flush_stop (TRUE);
1546     if (seqnum != GST_SEQNUM_INVALID)
1547       gst_event_set_seqnum (flush_event, seqnum);
1548
1549     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1550     gst_qtdemux_push_event (qtdemux, flush_event);
1551   }
1552
1553   /* commit the new segment */
1554   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1555
1556   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1557     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1558         qtdemux->segment.format, qtdemux->segment.position);
1559     if (seqnum != GST_SEQNUM_INVALID)
1560       gst_message_set_seqnum (msg, seqnum);
1561     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1562   }
1563
1564   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1565   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1566       qtdemux->sinkpad, NULL);
1567
1568   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1569
1570   return ret;
1571
1572   /* ERRORS */
1573 no_format:
1574   {
1575     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1576     return FALSE;
1577   }
1578 }
1579
1580 static gboolean
1581 qtdemux_ensure_index (GstQTDemux * qtdemux)
1582 {
1583   guint i;
1584
1585   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1586
1587   /* Build complete index */
1588   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1589     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1590
1591     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1592       GST_LOG_OBJECT (qtdemux,
1593           "Building complete index of track-id %u for seeking failed!",
1594           stream->track_id);
1595       return FALSE;
1596     }
1597   }
1598
1599   return TRUE;
1600 }
1601
1602 static gboolean
1603 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1604     GstEvent * event)
1605 {
1606   gboolean res = TRUE;
1607   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1608
1609   switch (GST_EVENT_TYPE (event)) {
1610     case GST_EVENT_RECONFIGURE:
1611       GST_OBJECT_LOCK (qtdemux);
1612       gst_flow_combiner_reset (qtdemux->flowcombiner);
1613       GST_OBJECT_UNLOCK (qtdemux);
1614       res = gst_pad_event_default (pad, parent, event);
1615       break;
1616     case GST_EVENT_SEEK:
1617     {
1618       GstSeekFlags flags = 0;
1619       GstFormat seek_format;
1620       gboolean instant_rate_change;
1621
1622 #ifndef GST_DISABLE_GST_DEBUG
1623       GstClockTime ts = gst_util_get_timestamp ();
1624 #endif
1625       guint32 seqnum = gst_event_get_seqnum (event);
1626
1627       qtdemux->received_seek = TRUE;
1628
1629       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1630           NULL);
1631       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1632
1633       if (seqnum == qtdemux->segment_seqnum) {
1634         GST_LOG_OBJECT (pad,
1635             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1636         gst_event_unref (event);
1637         return TRUE;
1638       }
1639
1640       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1641         /* seek should be handled by upstream, we might need to re-download fragments */
1642         GST_DEBUG_OBJECT (qtdemux,
1643             "let upstream handle seek for fragmented playback");
1644         goto upstream;
1645       }
1646
1647       if (seek_format == GST_FORMAT_BYTES) {
1648         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1649         gst_event_unref (event);
1650         return FALSE;
1651       }
1652
1653       gst_event_parse_seek_trickmode_interval (event,
1654           &qtdemux->trickmode_interval);
1655
1656       /* Build complete index for seeking;
1657        * if not a fragmented file at least and we're really doing a seek,
1658        * not just an instant-rate-change */
1659       if (!qtdemux->fragmented && !instant_rate_change) {
1660         if (!qtdemux_ensure_index (qtdemux))
1661           goto index_failed;
1662       }
1663 #ifndef GST_DISABLE_GST_DEBUG
1664       ts = gst_util_get_timestamp () - ts;
1665       GST_INFO_OBJECT (qtdemux,
1666           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1667 #endif
1668       if (qtdemux->pullbased) {
1669         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1670       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1671         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1672         res = TRUE;
1673       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1674           && QTDEMUX_N_STREAMS (qtdemux)
1675           && !qtdemux->fragmented) {
1676         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1677       } else {
1678         GST_DEBUG_OBJECT (qtdemux,
1679             "ignoring seek in push mode in current state");
1680         res = FALSE;
1681       }
1682       gst_event_unref (event);
1683     }
1684       break;
1685     default:
1686     upstream:
1687       res = gst_pad_event_default (pad, parent, event);
1688       break;
1689   }
1690
1691 done:
1692   return res;
1693
1694   /* ERRORS */
1695 index_failed:
1696   {
1697     GST_ERROR_OBJECT (qtdemux, "Index failed");
1698     gst_event_unref (event);
1699     res = FALSE;
1700     goto done;
1701   }
1702 }
1703
1704 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1705  *
1706  * If @fw is false, the coding order is explored backwards.
1707  *
1708  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1709  * sample is found for that track.
1710  *
1711  * The stream and sample index of the sample with the minimum offset in the direction explored
1712  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1713  *
1714  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1715  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1716  * @_stream and @_index. */
1717 static void
1718 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1719     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1720 {
1721   gint i, index;
1722   gint64 time, min_time;
1723   QtDemuxStream *stream;
1724   gint iter;
1725
1726   min_time = -1;
1727   stream = NULL;
1728   index = -1;
1729
1730   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1731     QtDemuxStream *str;
1732     gint inc;
1733     gboolean set_sample;
1734
1735     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1736     set_sample = !set;
1737
1738     if (fw) {
1739       i = 0;
1740       inc = 1;
1741     } else {
1742       i = str->n_samples - 1;
1743       inc = -1;
1744     }
1745
1746     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1747       if (str->samples[i].size == 0)
1748         continue;
1749
1750       if (fw && (str->samples[i].offset < byte_pos))
1751         continue;
1752
1753       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1754         continue;
1755
1756       /* move stream to first available sample */
1757       if (set) {
1758         gst_qtdemux_move_stream (qtdemux, str, i);
1759         set_sample = TRUE;
1760       }
1761
1762       /* avoid index from sparse streams since they might be far away */
1763       if (!CUR_STREAM (str)->sparse) {
1764         /* determine min/max time */
1765         time = QTSAMPLE_PTS (str, &str->samples[i]);
1766         if (min_time == -1 || (!fw && time > min_time) ||
1767             (fw && time < min_time)) {
1768           min_time = time;
1769         }
1770
1771         /* determine stream with leading sample, to get its position */
1772         if (!stream ||
1773             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1774             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1775           stream = str;
1776           index = i;
1777         }
1778       }
1779       break;
1780     }
1781
1782     /* no sample for this stream, mark eos */
1783     if (!set_sample)
1784       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1785   }
1786
1787   if (_time)
1788     *_time = min_time;
1789   if (_stream)
1790     *_stream = stream;
1791   if (_index)
1792     *_index = index;
1793 }
1794
1795 /* Copied from mpegtsbase code */
1796 /* FIXME: replace this function when we add new util function for stream-id creation */
1797 static gchar *
1798 _get_upstream_id (GstQTDemux * demux)
1799 {
1800   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1801
1802   if (!upstream_id) {
1803     /* Try to create one from the upstream URI, else use a randome number */
1804     GstQuery *query;
1805     gchar *uri = NULL;
1806
1807     /* Try to generate one from the URI query and
1808      * if it fails take a random number instead */
1809     query = gst_query_new_uri ();
1810     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1811       gst_query_parse_uri (query, &uri);
1812     }
1813
1814     if (uri) {
1815       GChecksum *cs;
1816
1817       /* And then generate an SHA256 sum of the URI */
1818       cs = g_checksum_new (G_CHECKSUM_SHA256);
1819       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1820       g_free (uri);
1821       upstream_id = g_strdup (g_checksum_get_string (cs));
1822       g_checksum_free (cs);
1823     } else {
1824       /* Just get some random number if the URI query fails */
1825       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1826           "implementing a deterministic way of creating a stream-id");
1827       upstream_id =
1828           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1829           g_random_int (), g_random_int ());
1830     }
1831
1832     gst_query_unref (query);
1833   }
1834   return upstream_id;
1835 }
1836
1837 static QtDemuxStream *
1838 _create_stream (GstQTDemux * demux, guint32 track_id)
1839 {
1840   QtDemuxStream *stream;
1841   gchar *upstream_id;
1842
1843   stream = g_new0 (QtDemuxStream, 1);
1844   stream->demux = demux;
1845   stream->track_id = track_id;
1846   upstream_id = _get_upstream_id (demux);
1847   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1848   g_free (upstream_id);
1849   /* new streams always need a discont */
1850   stream->discont = TRUE;
1851   /* we enable clipping for raw audio/video streams */
1852   stream->need_clip = FALSE;
1853   stream->process_func = NULL;
1854   stream->segment_index = -1;
1855   stream->time_position = 0;
1856   stream->sample_index = -1;
1857   stream->offset_in_sample = 0;
1858   stream->new_stream = TRUE;
1859   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1860   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1861   stream->protected = FALSE;
1862   stream->protection_scheme_type = 0;
1863   stream->protection_scheme_version = 0;
1864   stream->protection_scheme_info = NULL;
1865   stream->n_samples_moof = 0;
1866   stream->duration_moof = 0;
1867   stream->duration_last_moof = 0;
1868   stream->alignment = 1;
1869   stream->stream_tags = gst_tag_list_new_empty ();
1870   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1871   g_queue_init (&stream->protection_scheme_event_queue);
1872   stream->ref_count = 1;
1873   /* consistent default for push based mode */
1874   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1875   return stream;
1876 }
1877
1878 static gboolean
1879 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1880 {
1881   GstStructure *structure;
1882   const gchar *variant;
1883   const GstCaps *mediacaps = NULL;
1884
1885   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1886
1887   structure = gst_caps_get_structure (caps, 0);
1888   variant = gst_structure_get_string (structure, "variant");
1889
1890   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1891     QtDemuxStream *stream;
1892     const GValue *value;
1893
1894     demux->fragmented = TRUE;
1895     demux->mss_mode = TRUE;
1896
1897     if (QTDEMUX_N_STREAMS (demux) > 1) {
1898       /* can't do this, we can only renegotiate for another mss format */
1899       return FALSE;
1900     }
1901
1902     value = gst_structure_get_value (structure, "media-caps");
1903     /* create stream */
1904     if (value) {
1905       const GValue *timescale_v;
1906
1907       /* TODO update when stream changes during playback */
1908
1909       if (QTDEMUX_N_STREAMS (demux) == 0) {
1910         stream = _create_stream (demux, 1);
1911         g_ptr_array_add (demux->active_streams, stream);
1912         /* mss has no stsd/stsd entry, use id 0 as default */
1913         stream->stsd_entries_length = 1;
1914         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1915         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1916       } else {
1917         stream = QTDEMUX_NTH_STREAM (demux, 0);
1918       }
1919
1920       timescale_v = gst_structure_get_value (structure, "timescale");
1921       if (timescale_v) {
1922         stream->timescale = g_value_get_uint64 (timescale_v);
1923       } else {
1924         /* default mss timescale */
1925         stream->timescale = 10000000;
1926       }
1927       demux->timescale = stream->timescale;
1928
1929       mediacaps = gst_value_get_caps (value);
1930       if (!CUR_STREAM (stream)->caps
1931           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1932         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1933             mediacaps);
1934         stream->new_caps = TRUE;
1935       }
1936       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1937       structure = gst_caps_get_structure (mediacaps, 0);
1938       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1939         stream->subtype = FOURCC_vide;
1940
1941         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1942         gst_structure_get_int (structure, "height",
1943             &CUR_STREAM (stream)->height);
1944         gst_structure_get_fraction (structure, "framerate",
1945             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1946       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1947         gint rate = 0;
1948         stream->subtype = FOURCC_soun;
1949         gst_structure_get_int (structure, "channels",
1950             &CUR_STREAM (stream)->n_channels);
1951         gst_structure_get_int (structure, "rate", &rate);
1952         CUR_STREAM (stream)->rate = rate;
1953       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1954         if (gst_structure_has_field (structure, "original-media-type")) {
1955           const gchar *media_type =
1956               gst_structure_get_string (structure, "original-media-type");
1957           if (g_str_has_prefix (media_type, "video")) {
1958             stream->subtype = FOURCC_vide;
1959           } else if (g_str_has_prefix (media_type, "audio")) {
1960             stream->subtype = FOURCC_soun;
1961           }
1962         }
1963       }
1964     }
1965     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1966   } else {
1967     demux->mss_mode = FALSE;
1968   }
1969
1970   return TRUE;
1971 }
1972
1973 static void
1974 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1975 {
1976   gint i;
1977
1978   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1979   gst_pad_stop_task (qtdemux->sinkpad);
1980
1981   if (hard || qtdemux->upstream_format_is_time) {
1982     qtdemux->state = QTDEMUX_STATE_INITIAL;
1983     qtdemux->neededbytes = 16;
1984     qtdemux->todrop = 0;
1985     qtdemux->pullbased = FALSE;
1986     g_clear_pointer (&qtdemux->redirect_location, g_free);
1987     qtdemux->first_mdat = -1;
1988     qtdemux->header_size = 0;
1989     qtdemux->mdatoffset = -1;
1990     qtdemux->restoredata_offset = -1;
1991     if (qtdemux->mdatbuffer)
1992       gst_buffer_unref (qtdemux->mdatbuffer);
1993     if (qtdemux->restoredata_buffer)
1994       gst_buffer_unref (qtdemux->restoredata_buffer);
1995     qtdemux->mdatbuffer = NULL;
1996     qtdemux->restoredata_buffer = NULL;
1997     qtdemux->mdatleft = 0;
1998     qtdemux->mdatsize = 0;
1999     if (qtdemux->comp_brands)
2000       gst_buffer_unref (qtdemux->comp_brands);
2001     qtdemux->comp_brands = NULL;
2002     qtdemux->last_moov_offset = -1;
2003     if (qtdemux->moov_node_compressed) {
2004       g_node_destroy (qtdemux->moov_node_compressed);
2005       if (qtdemux->moov_node)
2006         g_free (qtdemux->moov_node->data);
2007     }
2008     qtdemux->moov_node_compressed = NULL;
2009     if (qtdemux->moov_node)
2010       g_node_destroy (qtdemux->moov_node);
2011     qtdemux->moov_node = NULL;
2012     if (qtdemux->tag_list)
2013       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2014     qtdemux->tag_list = gst_tag_list_new_empty ();
2015     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2016 #if 0
2017     if (qtdemux->element_index)
2018       gst_object_unref (qtdemux->element_index);
2019     qtdemux->element_index = NULL;
2020 #endif
2021     qtdemux->major_brand = 0;
2022     qtdemux->upstream_format_is_time = FALSE;
2023     qtdemux->upstream_seekable = FALSE;
2024     qtdemux->upstream_size = 0;
2025
2026     qtdemux->fragment_start = -1;
2027     qtdemux->fragment_start_offset = -1;
2028     qtdemux->duration = 0;
2029     qtdemux->moof_offset = 0;
2030     qtdemux->chapters_track_id = 0;
2031     qtdemux->have_group_id = FALSE;
2032     qtdemux->group_id = G_MAXUINT;
2033
2034     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2035         NULL);
2036     g_queue_clear (&qtdemux->protection_event_queue);
2037
2038     qtdemux->received_seek = FALSE;
2039     qtdemux->first_moof_already_parsed = FALSE;
2040   }
2041   qtdemux->offset = 0;
2042   gst_adapter_clear (qtdemux->adapter);
2043   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2044   qtdemux->need_segment = TRUE;
2045
2046   if (hard) {
2047     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2048     qtdemux->trickmode_interval = 0;
2049     g_ptr_array_set_size (qtdemux->active_streams, 0);
2050     g_ptr_array_set_size (qtdemux->old_streams, 0);
2051     qtdemux->n_video_streams = 0;
2052     qtdemux->n_audio_streams = 0;
2053     qtdemux->n_sub_streams = 0;
2054     qtdemux->exposed = FALSE;
2055     qtdemux->fragmented = FALSE;
2056     qtdemux->mss_mode = FALSE;
2057     gst_caps_replace (&qtdemux->media_caps, NULL);
2058     qtdemux->timescale = 0;
2059     qtdemux->got_moov = FALSE;
2060     qtdemux->cenc_aux_info_offset = 0;
2061     qtdemux->cenc_aux_info_sizes = NULL;
2062     qtdemux->cenc_aux_sample_count = 0;
2063     if (qtdemux->protection_system_ids) {
2064       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2065       qtdemux->protection_system_ids = NULL;
2066     }
2067     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2068         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2069         GST_BIN_FLAG_STREAMS_AWARE);
2070
2071     if (qtdemux->preferred_protection_system_id) {
2072       g_free (qtdemux->preferred_protection_system_id);
2073       qtdemux->preferred_protection_system_id = NULL;
2074     }
2075   } else if (qtdemux->mss_mode) {
2076     gst_flow_combiner_reset (qtdemux->flowcombiner);
2077     g_ptr_array_foreach (qtdemux->active_streams,
2078         (GFunc) gst_qtdemux_stream_clear, NULL);
2079   } else {
2080     gst_flow_combiner_reset (qtdemux->flowcombiner);
2081     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2082       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2083       stream->sent_eos = FALSE;
2084       stream->time_position = 0;
2085       stream->accumulated_base = 0;
2086       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2087     }
2088   }
2089 }
2090
2091
2092 /* Maps the @segment to the qt edts internal segments and pushes
2093  * the corresponding segment event.
2094  *
2095  * If it ends up being at a empty segment, a gap will be pushed and the next
2096  * edts segment will be activated in sequence.
2097  *
2098  * To be used in push-mode only */
2099 static void
2100 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2101 {
2102   gint i, iter;
2103
2104   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2105     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2106
2107     stream->time_position = segment->start;
2108
2109     /* in push mode we should be guaranteed that we will have empty segments
2110      * at the beginning and then one segment after, other scenarios are not
2111      * supported and are discarded when parsing the edts */
2112     for (i = 0; i < stream->n_segments; i++) {
2113       if (stream->segments[i].stop_time > segment->start) {
2114         /* push the empty segment and move to the next one */
2115         gst_qtdemux_activate_segment (qtdemux, stream, i,
2116             stream->time_position);
2117         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2118           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2119               stream->time_position);
2120
2121           /* accumulate previous segments */
2122           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2123             stream->accumulated_base +=
2124                 (stream->segment.stop -
2125                 stream->segment.start) / ABS (stream->segment.rate);
2126           continue;
2127         }
2128
2129         g_assert (i == stream->n_segments - 1);
2130       }
2131     }
2132   }
2133 }
2134
2135 static void
2136 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2137     GPtrArray * src)
2138 {
2139   guint i;
2140   guint len;
2141
2142   len = src->len;
2143
2144   if (len == 0)
2145     return;
2146
2147   for (i = 0; i < len; i++) {
2148     QtDemuxStream *stream = g_ptr_array_index (src, i);
2149
2150 #ifndef GST_DISABLE_GST_DEBUG
2151     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2152         stream, GST_STR_NULL (stream->stream_id), dest);
2153 #endif
2154     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2155   }
2156
2157   g_ptr_array_set_size (src, 0);
2158 }
2159
2160 static gboolean
2161 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2162     GstEvent * event)
2163 {
2164   GstQTDemux *demux = GST_QTDEMUX (parent);
2165   gboolean res = TRUE;
2166
2167   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2168
2169   switch (GST_EVENT_TYPE (event)) {
2170     case GST_EVENT_SEGMENT:
2171     {
2172       gint64 offset = 0;
2173       QtDemuxStream *stream;
2174       gint idx;
2175       GstSegment segment;
2176
2177       /* some debug output */
2178       gst_event_copy_segment (event, &segment);
2179       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2180           &segment);
2181
2182       if (segment.format == GST_FORMAT_TIME) {
2183         demux->upstream_format_is_time = TRUE;
2184         demux->segment_seqnum = gst_event_get_seqnum (event);
2185       } else {
2186         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2187             "not in time format");
2188
2189         /* chain will send initial newsegment after pads have been added */
2190         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2191           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2192           goto exit;
2193         }
2194       }
2195
2196       /* check if this matches a time seek we received previously
2197        * FIXME for backwards compatibility reasons we use the
2198        * seek_offset here to compare. In the future we might want to
2199        * change this to use the seqnum as it uniquely should identify
2200        * the segment that corresponds to the seek. */
2201       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2202           ", received segment offset %" G_GINT64_FORMAT,
2203           demux->seek_offset, segment.start);
2204       if (segment.format == GST_FORMAT_BYTES
2205           && demux->seek_offset == segment.start) {
2206         GST_OBJECT_LOCK (demux);
2207         offset = segment.start;
2208
2209         segment.format = GST_FORMAT_TIME;
2210         segment.start = demux->push_seek_start;
2211         segment.stop = demux->push_seek_stop;
2212         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2213             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2214             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2215         GST_OBJECT_UNLOCK (demux);
2216       }
2217
2218       /* we only expect a BYTE segment, e.g. following a seek */
2219       if (segment.format == GST_FORMAT_BYTES) {
2220         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2221           offset = segment.start;
2222
2223           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2224               NULL, (gint64 *) & segment.start);
2225           if ((gint64) segment.start < 0)
2226             segment.start = 0;
2227         }
2228         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2229           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2230               NULL, (gint64 *) & segment.stop);
2231           /* keyframe seeking should already arrange for start >= stop,
2232            * but make sure in other rare cases */
2233           segment.stop = MAX (segment.stop, segment.start);
2234         }
2235       } else if (segment.format == GST_FORMAT_TIME) {
2236         /* push all data on the adapter before starting this
2237          * new segment */
2238         gst_qtdemux_process_adapter (demux, TRUE);
2239       } else {
2240         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2241         goto exit;
2242       }
2243
2244       /* We shouldn't modify upstream driven TIME FORMAT segment */
2245       if (!demux->upstream_format_is_time) {
2246         /* accept upstream's notion of segment and distribute along */
2247         segment.format = GST_FORMAT_TIME;
2248         segment.position = segment.time = segment.start;
2249         segment.duration = demux->segment.duration;
2250         segment.base = gst_segment_to_running_time (&demux->segment,
2251             GST_FORMAT_TIME, demux->segment.position);
2252       }
2253
2254       gst_segment_copy_into (&segment, &demux->segment);
2255       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2256
2257       /* map segment to internal qt segments and push on each stream */
2258       if (QTDEMUX_N_STREAMS (demux)) {
2259         demux->need_segment = TRUE;
2260         gst_qtdemux_check_send_pending_segment (demux);
2261       }
2262
2263       /* clear leftover in current segment, if any */
2264       gst_adapter_clear (demux->adapter);
2265
2266       /* set up streaming thread */
2267       demux->offset = offset;
2268       if (demux->upstream_format_is_time) {
2269         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2270             "set values to restart reading from a new atom");
2271         demux->neededbytes = 16;
2272         demux->todrop = 0;
2273       } else {
2274         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2275             NULL);
2276         if (stream) {
2277           demux->todrop = stream->samples[idx].offset - offset;
2278           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2279         } else {
2280           /* set up for EOS */
2281           demux->neededbytes = -1;
2282           demux->todrop = 0;
2283         }
2284       }
2285     exit:
2286       gst_event_unref (event);
2287       res = TRUE;
2288       goto drop;
2289     }
2290     case GST_EVENT_FLUSH_START:
2291     {
2292       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2293         gst_event_unref (event);
2294         goto drop;
2295       }
2296       QTDEMUX_EXPOSE_LOCK (demux);
2297       res = gst_pad_event_default (demux->sinkpad, parent, event);
2298       QTDEMUX_EXPOSE_UNLOCK (demux);
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_STOP:
2302     {
2303       guint64 dur;
2304
2305       dur = demux->segment.duration;
2306       gst_qtdemux_reset (demux, FALSE);
2307       demux->segment.duration = dur;
2308
2309       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2310         gst_event_unref (event);
2311         goto drop;
2312       }
2313       break;
2314     }
2315     case GST_EVENT_EOS:
2316       /* If we are in push mode, and get an EOS before we've seen any streams,
2317        * then error out - we have nowhere to send the EOS */
2318       if (!demux->pullbased) {
2319         gint i;
2320         gboolean has_valid_stream = FALSE;
2321         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2322           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2323             has_valid_stream = TRUE;
2324             break;
2325           }
2326         }
2327         if (!has_valid_stream)
2328           gst_qtdemux_post_no_playable_stream_error (demux);
2329         else {
2330           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2331               (guint) gst_adapter_available (demux->adapter));
2332           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2333             res = FALSE;
2334           }
2335         }
2336       }
2337       break;
2338     case GST_EVENT_CAPS:{
2339       GstCaps *caps = NULL;
2340
2341       gst_event_parse_caps (event, &caps);
2342       gst_qtdemux_setcaps (demux, caps);
2343       res = TRUE;
2344       gst_event_unref (event);
2345       goto drop;
2346     }
2347     case GST_EVENT_PROTECTION:
2348     {
2349       const gchar *system_id = NULL;
2350
2351       gst_event_parse_protection (event, &system_id, NULL, NULL);
2352       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2353           system_id);
2354       gst_qtdemux_append_protection_system_id (demux, system_id);
2355       /* save the event for later, for source pads that have not been created */
2356       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2357       /* send it to all pads that already exist */
2358       gst_qtdemux_push_event (demux, event);
2359       res = TRUE;
2360       goto drop;
2361     }
2362     case GST_EVENT_STREAM_START:
2363     {
2364       res = TRUE;
2365       gst_event_unref (event);
2366
2367       /* Drain all the buffers */
2368       gst_qtdemux_process_adapter (demux, TRUE);
2369       gst_qtdemux_reset (demux, FALSE);
2370       /* We expect new moov box after new stream-start event */
2371       if (demux->exposed) {
2372         gst_qtdemux_stream_concat (demux,
2373             demux->old_streams, demux->active_streams);
2374       }
2375
2376       goto drop;
2377     }
2378     default:
2379       break;
2380   }
2381
2382   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2383
2384 drop:
2385   return res;
2386 }
2387
2388 static gboolean
2389 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2390     GstQuery * query)
2391 {
2392   GstQTDemux *demux = GST_QTDEMUX (parent);
2393   gboolean res = FALSE;
2394
2395   switch (GST_QUERY_TYPE (query)) {
2396     case GST_QUERY_BITRATE:
2397     {
2398       GstClockTime duration;
2399
2400       /* populate demux->upstream_size if not done yet */
2401       gst_qtdemux_check_seekability (demux);
2402
2403       if (demux->upstream_size != -1
2404           && gst_qtdemux_get_duration (demux, &duration)) {
2405         guint bitrate =
2406             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2407             duration);
2408
2409         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2410             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2411             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2412
2413         /* TODO: better results based on ranges/index tables */
2414         gst_query_set_bitrate (query, bitrate);
2415         res = TRUE;
2416       }
2417       break;
2418     }
2419     default:
2420       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2421       break;
2422   }
2423
2424   return res;
2425 }
2426
2427
2428 #if 0
2429 static void
2430 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2431 {
2432   GstQTDemux *demux = GST_QTDEMUX (element);
2433
2434   GST_OBJECT_LOCK (demux);
2435   if (demux->element_index)
2436     gst_object_unref (demux->element_index);
2437   if (index) {
2438     demux->element_index = gst_object_ref (index);
2439   } else {
2440     demux->element_index = NULL;
2441   }
2442   GST_OBJECT_UNLOCK (demux);
2443   /* object lock might be taken again */
2444   if (index)
2445     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2446   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2447       demux->element_index, demux->index_id);
2448 }
2449
2450 static GstIndex *
2451 gst_qtdemux_get_index (GstElement * element)
2452 {
2453   GstIndex *result = NULL;
2454   GstQTDemux *demux = GST_QTDEMUX (element);
2455
2456   GST_OBJECT_LOCK (demux);
2457   if (demux->element_index)
2458     result = gst_object_ref (demux->element_index);
2459   GST_OBJECT_UNLOCK (demux);
2460
2461   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2462
2463   return result;
2464 }
2465 #endif
2466
2467 static void
2468 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2469 {
2470   g_free ((gpointer) stream->stco.data);
2471   stream->stco.data = NULL;
2472   g_free ((gpointer) stream->stsz.data);
2473   stream->stsz.data = NULL;
2474   g_free ((gpointer) stream->stsc.data);
2475   stream->stsc.data = NULL;
2476   g_free ((gpointer) stream->stts.data);
2477   stream->stts.data = NULL;
2478   g_free ((gpointer) stream->stss.data);
2479   stream->stss.data = NULL;
2480   g_free ((gpointer) stream->stps.data);
2481   stream->stps.data = NULL;
2482   g_free ((gpointer) stream->ctts.data);
2483   stream->ctts.data = NULL;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2488 {
2489   g_free (stream->segments);
2490   stream->segments = NULL;
2491   stream->segment_index = -1;
2492   stream->accumulated_base = 0;
2493 }
2494
2495 static void
2496 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2497 {
2498   g_free (stream->samples);
2499   stream->samples = NULL;
2500   gst_qtdemux_stbl_free (stream);
2501
2502   /* fragments */
2503   g_free (stream->ra_entries);
2504   stream->ra_entries = NULL;
2505   stream->n_ra_entries = 0;
2506
2507   stream->sample_index = -1;
2508   stream->stbl_index = -1;
2509   stream->n_samples = 0;
2510   stream->time_position = 0;
2511
2512   stream->n_samples_moof = 0;
2513   stream->duration_moof = 0;
2514   stream->duration_last_moof = 0;
2515 }
2516
2517 static void
2518 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2519 {
2520   gint i;
2521   if (stream->allocator)
2522     gst_object_unref (stream->allocator);
2523   while (stream->buffers) {
2524     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2525     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2526   }
2527   for (i = 0; i < stream->stsd_entries_length; i++) {
2528     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2529     if (entry->rgb8_palette) {
2530       gst_memory_unref (entry->rgb8_palette);
2531       entry->rgb8_palette = NULL;
2532     }
2533     entry->sparse = FALSE;
2534   }
2535
2536   if (stream->stream_tags)
2537     gst_tag_list_unref (stream->stream_tags);
2538
2539   stream->stream_tags = gst_tag_list_new_empty ();
2540   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2541   g_free (stream->redirect_uri);
2542   stream->redirect_uri = NULL;
2543   stream->sent_eos = FALSE;
2544   stream->protected = FALSE;
2545   if (stream->protection_scheme_info) {
2546     if (stream->protection_scheme_type == FOURCC_cenc
2547         || stream->protection_scheme_type == FOURCC_cbcs) {
2548       QtDemuxCencSampleSetInfo *info =
2549           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2550       if (info->default_properties)
2551         gst_structure_free (info->default_properties);
2552       if (info->crypto_info)
2553         g_ptr_array_free (info->crypto_info, TRUE);
2554     }
2555     if (stream->protection_scheme_type == FOURCC_aavd) {
2556       QtDemuxAavdEncryptionInfo *info =
2557           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2558       if (info->default_properties)
2559         gst_structure_free (info->default_properties);
2560     }
2561     g_free (stream->protection_scheme_info);
2562     stream->protection_scheme_info = NULL;
2563   }
2564   stream->protection_scheme_type = 0;
2565   stream->protection_scheme_version = 0;
2566   g_queue_foreach (&stream->protection_scheme_event_queue,
2567       (GFunc) gst_event_unref, NULL);
2568   g_queue_clear (&stream->protection_scheme_event_queue);
2569   gst_qtdemux_stream_flush_segments_data (stream);
2570   gst_qtdemux_stream_flush_samples_data (stream);
2571 }
2572
2573 static void
2574 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2575 {
2576   gint i;
2577   gst_qtdemux_stream_clear (stream);
2578   for (i = 0; i < stream->stsd_entries_length; i++) {
2579     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2580     if (entry->caps) {
2581       gst_caps_unref (entry->caps);
2582       entry->caps = NULL;
2583     }
2584   }
2585   g_free (stream->stsd_entries);
2586   stream->stsd_entries = NULL;
2587   stream->stsd_entries_length = 0;
2588 }
2589
2590 static QtDemuxStream *
2591 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2592 {
2593   g_atomic_int_add (&stream->ref_count, 1);
2594
2595   return stream;
2596 }
2597
2598 static void
2599 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2600 {
2601   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2602     gst_qtdemux_stream_reset (stream);
2603     gst_tag_list_unref (stream->stream_tags);
2604     if (stream->pad) {
2605       GstQTDemux *demux = stream->demux;
2606       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2607       GST_OBJECT_LOCK (demux);
2608       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2609       GST_OBJECT_UNLOCK (demux);
2610     }
2611     g_free (stream->stream_id);
2612     g_free (stream);
2613   }
2614 }
2615
2616 static GstStateChangeReturn
2617 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2618 {
2619   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2620   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2621
2622   switch (transition) {
2623     case GST_STATE_CHANGE_READY_TO_PAUSED:
2624       gst_qtdemux_reset (qtdemux, TRUE);
2625       break;
2626     default:
2627       break;
2628   }
2629
2630   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2631
2632   switch (transition) {
2633     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2634       gst_qtdemux_reset (qtdemux, TRUE);
2635       break;
2636     }
2637     default:
2638       break;
2639   }
2640
2641   return result;
2642 }
2643
2644 static void
2645 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2646 {
2647   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2648
2649   g_return_if_fail (GST_IS_CONTEXT (context));
2650
2651   if (gst_context_has_context_type (context,
2652           "drm-preferred-decryption-system-id")) {
2653     const GstStructure *s;
2654
2655     s = gst_context_get_structure (context);
2656     g_free (qtdemux->preferred_protection_system_id);
2657     qtdemux->preferred_protection_system_id =
2658         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2659     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2660         qtdemux->preferred_protection_system_id);
2661   }
2662
2663   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2664 }
2665
2666 static void
2667 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2668 {
2669   /* counts as header data */
2670   qtdemux->header_size += length;
2671
2672   /* only consider at least a sufficiently complete ftyp atom */
2673   if (length >= 20) {
2674     GstBuffer *buf;
2675
2676     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2677     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2678         GST_FOURCC_ARGS (qtdemux->major_brand));
2679     if (qtdemux->comp_brands)
2680       gst_buffer_unref (qtdemux->comp_brands);
2681     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2682     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2683   }
2684 }
2685
2686 static void
2687 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2688     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2689     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2690     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2691     const guint8 * constant_iv)
2692 {
2693   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2694   gst_buffer_fill (kid_buf, 0, kid, 16);
2695   if (info->default_properties)
2696     gst_structure_free (info->default_properties);
2697   info->default_properties =
2698       gst_structure_new ("application/x-cenc",
2699       "iv_size", G_TYPE_UINT, iv_size,
2700       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2701       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2702   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2703       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2704   gst_buffer_unref (kid_buf);
2705   if (protection_scheme_type == FOURCC_cbcs) {
2706     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2707       gst_structure_set (info->default_properties, "crypt_byte_block",
2708           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2709           skip_byte_block, NULL);
2710     }
2711     if (constant_iv != NULL) {
2712       GstBuffer *constant_iv_buf =
2713           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2714       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2715       gst_structure_set (info->default_properties, "constant_iv_size",
2716           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2717           NULL);
2718       gst_buffer_unref (constant_iv_buf);
2719     }
2720     gst_structure_set (info->default_properties, "cipher-mode",
2721         G_TYPE_STRING, "cbcs", NULL);
2722   } else {
2723     gst_structure_set (info->default_properties, "cipher-mode",
2724         G_TYPE_STRING, "cenc", NULL);
2725   }
2726 }
2727
2728 static gboolean
2729 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2730     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2731 {
2732   guint32 algorithm_id = 0;
2733   const guint8 *kid;
2734   gboolean is_encrypted = TRUE;
2735   guint8 iv_size = 8;
2736
2737   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2738     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2739     return FALSE;
2740   }
2741
2742   algorithm_id >>= 8;
2743   if (algorithm_id == 0) {
2744     is_encrypted = FALSE;
2745   } else if (algorithm_id == 1) {
2746     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2747   } else if (algorithm_id == 2) {
2748     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2749   }
2750
2751   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2752     return FALSE;
2753
2754   if (!gst_byte_reader_get_data (br, 16, &kid))
2755     return FALSE;
2756
2757   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2758       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2759   gst_structure_set (info->default_properties, "piff_algorithm_id",
2760       G_TYPE_UINT, algorithm_id, NULL);
2761   return TRUE;
2762 }
2763
2764
2765 static void
2766 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2767     guint offset)
2768 {
2769   GstByteReader br;
2770   guint8 version;
2771   guint32 flags = 0;
2772   guint i;
2773   guint iv_size = 8;
2774   QtDemuxStream *stream;
2775   GstStructure *structure;
2776   QtDemuxCencSampleSetInfo *ss_info = NULL;
2777   const gchar *system_id;
2778   gboolean uses_sub_sample_encryption = FALSE;
2779   guint32 sample_count;
2780
2781   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2782     return;
2783
2784   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2785
2786   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2787   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2788     GST_WARNING_OBJECT (qtdemux,
2789         "Attempting PIFF box parsing on an unencrypted stream.");
2790     return;
2791   }
2792
2793   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2794       G_TYPE_STRING, &system_id, NULL);
2795   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2796
2797   stream->protected = TRUE;
2798   stream->protection_scheme_type = FOURCC_cenc;
2799
2800   if (!stream->protection_scheme_info)
2801     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2802
2803   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2804   if (!ss_info->default_properties) {
2805     ss_info->default_properties =
2806         gst_structure_new ("application/x-cenc",
2807         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2808         NULL);
2809
2810   }
2811
2812   if (ss_info->crypto_info) {
2813     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2814     g_ptr_array_free (ss_info->crypto_info, TRUE);
2815     ss_info->crypto_info = NULL;
2816   }
2817
2818   /* skip UUID */
2819   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2820
2821   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2822     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2823     return;
2824   }
2825
2826   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2827     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2828     return;
2829   }
2830
2831   if ((flags & 0x000001)) {
2832     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2833             &br))
2834       return;
2835   } else if ((flags & 0x000002)) {
2836     uses_sub_sample_encryption = TRUE;
2837   }
2838
2839   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2840           &iv_size)) {
2841     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2842     return;
2843   }
2844
2845   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2846     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2847     return;
2848   }
2849
2850   ss_info->crypto_info =
2851       g_ptr_array_new_full (sample_count,
2852       (GDestroyNotify) qtdemux_gst_structure_free);
2853
2854   for (i = 0; i < sample_count; ++i) {
2855     GstStructure *properties;
2856     guint8 *data;
2857     GstBuffer *buf;
2858
2859     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2860     if (properties == NULL) {
2861       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2862       qtdemux->cenc_aux_sample_count = i;
2863       return;
2864     }
2865
2866     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2867       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2868       gst_structure_free (properties);
2869       qtdemux->cenc_aux_sample_count = i;
2870       return;
2871     }
2872     buf = gst_buffer_new_wrapped (data, iv_size);
2873     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2874     gst_buffer_unref (buf);
2875
2876     if (uses_sub_sample_encryption) {
2877       guint16 n_subsamples;
2878       const GValue *kid_buf_value;
2879
2880       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2881           || n_subsamples == 0) {
2882         GST_ERROR_OBJECT (qtdemux,
2883             "failed to get subsample count for sample %u", i);
2884         gst_structure_free (properties);
2885         qtdemux->cenc_aux_sample_count = i;
2886         return;
2887       }
2888       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2889       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2890         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2891             i);
2892         gst_structure_free (properties);
2893         qtdemux->cenc_aux_sample_count = i;
2894         return;
2895       }
2896       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2897
2898       kid_buf_value =
2899           gst_structure_get_value (ss_info->default_properties, "kid");
2900
2901       gst_structure_set (properties,
2902           "subsample_count", G_TYPE_UINT, n_subsamples,
2903           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2904       gst_structure_set_value (properties, "kid", kid_buf_value);
2905       gst_buffer_unref (buf);
2906     } else {
2907       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2908     }
2909
2910     g_ptr_array_add (ss_info->crypto_info, properties);
2911   }
2912
2913   qtdemux->cenc_aux_sample_count = sample_count;
2914 }
2915
2916 static void
2917 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2918 {
2919   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2920     0x97, 0xA9, 0x42, 0xE8,
2921     0x9C, 0x71, 0x99, 0x94,
2922     0x91, 0xE3, 0xAF, 0xAC
2923   };
2924   static const guint8 playready_uuid[] = {
2925     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2926     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2927   };
2928
2929   static const guint8 piff_sample_encryption_uuid[] = {
2930     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2931     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2932   };
2933
2934   guint offset;
2935
2936   /* counts as header data */
2937   qtdemux->header_size += length;
2938
2939   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2940
2941   if (length <= offset + 16) {
2942     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2943     return;
2944   }
2945
2946   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2947     GstBuffer *buf;
2948     GstTagList *taglist;
2949
2950     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2951         length - offset - 16, NULL);
2952     taglist = gst_tag_list_from_xmp_buffer (buf);
2953     gst_buffer_unref (buf);
2954
2955     /* make sure we have a usable taglist */
2956     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2957
2958     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2959
2960   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2961     int len;
2962     const gunichar2 *s_utf16;
2963     char *contents;
2964
2965     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2966     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2967     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2968     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2969
2970     g_free (contents);
2971
2972     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2973         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2974         (NULL));
2975   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2976     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2977   } else {
2978     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2979         GST_READ_UINT32_LE (buffer + offset),
2980         GST_READ_UINT32_LE (buffer + offset + 4),
2981         GST_READ_UINT32_LE (buffer + offset + 8),
2982         GST_READ_UINT32_LE (buffer + offset + 12));
2983   }
2984 }
2985
2986 static void
2987 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2988 {
2989   GstSidxParser sidx_parser;
2990   GstIsoffParserResult res;
2991   guint consumed;
2992
2993   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2994
2995   res =
2996       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2997       &consumed);
2998   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2999   if (res == GST_ISOFF_QT_PARSER_DONE) {
3000     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3001   }
3002   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3003 }
3004
3005 /* caller verifies at least 8 bytes in buf */
3006 static void
3007 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3008     guint64 * plength, guint32 * pfourcc)
3009 {
3010   guint64 length;
3011   guint32 fourcc;
3012
3013   length = QT_UINT32 (data);
3014   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3015   fourcc = QT_FOURCC (data + 4);
3016   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3017
3018   if (length == 0) {
3019     length = G_MAXUINT64;
3020   } else if (length == 1 && size >= 16) {
3021     /* this means we have an extended size, which is the 64 bit value of
3022      * the next 8 bytes */
3023     length = QT_UINT64 (data + 8);
3024     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3025   }
3026
3027   if (plength)
3028     *plength = length;
3029   if (pfourcc)
3030     *pfourcc = fourcc;
3031 }
3032
3033 static gboolean
3034 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3035 {
3036   guint32 version = 0;
3037   GstClockTime duration = 0;
3038
3039   if (!gst_byte_reader_get_uint32_be (br, &version))
3040     goto failed;
3041
3042   version >>= 24;
3043   if (version == 1) {
3044     if (!gst_byte_reader_get_uint64_be (br, &duration))
3045       goto failed;
3046   } else {
3047     guint32 dur = 0;
3048
3049     if (!gst_byte_reader_get_uint32_be (br, &dur))
3050       goto failed;
3051     duration = dur;
3052   }
3053
3054   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3055   qtdemux->duration = duration;
3056
3057   return TRUE;
3058
3059 failed:
3060   {
3061     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3062     return FALSE;
3063   }
3064 }
3065
3066 static gboolean
3067 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3068     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3069 {
3070   if (!stream->parsed_trex && qtdemux->moov_node) {
3071     GNode *mvex, *trex;
3072     GstByteReader trex_data;
3073
3074     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3075     if (mvex) {
3076       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3077           &trex_data);
3078       while (trex) {
3079         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3080
3081         /* skip version/flags */
3082         if (!gst_byte_reader_skip (&trex_data, 4))
3083           goto next;
3084         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3085           goto next;
3086         if (id != stream->track_id)
3087           goto next;
3088         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3089           goto next;
3090         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3091           goto next;
3092         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3093           goto next;
3094         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3095           goto next;
3096
3097         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3098             "duration %d,  size %d, flags 0x%x", stream->track_id,
3099             dur, size, flags);
3100
3101         stream->parsed_trex = TRUE;
3102         stream->def_sample_description_index = sdi;
3103         stream->def_sample_duration = dur;
3104         stream->def_sample_size = size;
3105         stream->def_sample_flags = flags;
3106
3107       next:
3108         /* iterate all siblings */
3109         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3110             &trex_data);
3111       }
3112     }
3113   }
3114
3115   *ds_duration = stream->def_sample_duration;
3116   *ds_size = stream->def_sample_size;
3117   *ds_flags = stream->def_sample_flags;
3118
3119   /* even then, above values are better than random ... */
3120   if (G_UNLIKELY (!stream->parsed_trex)) {
3121     GST_WARNING_OBJECT (qtdemux,
3122         "failed to find fragment defaults for stream %d", stream->track_id);
3123     return FALSE;
3124   }
3125
3126   return TRUE;
3127 }
3128
3129 /* This method should be called whenever a more accurate duration might
3130  * have been found. It will update all relevant variables if/where needed
3131  */
3132 static void
3133 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3134 {
3135   guint i;
3136   guint64 movdur;
3137   GstClockTime prevdur;
3138
3139   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3140
3141   if (movdur > qtdemux->duration) {
3142     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3143     GST_DEBUG_OBJECT (qtdemux,
3144         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3145         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3146     qtdemux->duration = movdur;
3147     GST_DEBUG_OBJECT (qtdemux,
3148         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3149         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3150         GST_TIME_ARGS (qtdemux->segment.stop));
3151     if (qtdemux->segment.duration == prevdur) {
3152       /* If the current segment has duration/stop identical to previous duration
3153        * update them also (because they were set at that point in time with
3154        * the wrong duration */
3155       /* We convert the value *from* the timescale version to avoid rounding errors */
3156       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3157       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3158       qtdemux->segment.duration = fixeddur;
3159       qtdemux->segment.stop = fixeddur;
3160     }
3161   }
3162
3163   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3164     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3165
3166     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3167     if (movdur > stream->duration) {
3168       GST_DEBUG_OBJECT (qtdemux,
3169           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3170           GST_TIME_ARGS (duration));
3171       stream->duration = movdur;
3172       /* internal duration tracking state has been updated above, so */
3173       /* preserve an open-ended dummy segment rather than repeatedly updating
3174        * it and spamming downstream accordingly with segment events */
3175       /* also mangle the edit list end time when fragmented with a single edit
3176        * list that may only cover any non-fragmented data */
3177       if ((stream->dummy_segment ||
3178               (qtdemux->fragmented && stream->n_segments == 1)) &&
3179           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3180         /* Update all dummy values to new duration */
3181         stream->segments[0].stop_time = duration;
3182         stream->segments[0].duration = duration;
3183         stream->segments[0].media_stop = duration;
3184
3185         /* let downstream know we possibly have a new stop time */
3186         if (stream->segment_index != -1) {
3187           GstClockTime pos;
3188
3189           if (qtdemux->segment.rate >= 0) {
3190             pos = stream->segment.start;
3191           } else {
3192             pos = stream->segment.stop;
3193           }
3194
3195           gst_qtdemux_stream_update_segment (qtdemux, stream,
3196               stream->segment_index, pos, NULL, NULL);
3197         }
3198       }
3199     }
3200   }
3201 }
3202
3203 static gboolean
3204 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3205     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3206     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3207     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3208     gboolean has_tfdt)
3209 {
3210   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3211   guint64 timestamp;
3212   gint32 data_offset = 0;
3213   guint32 flags = 0, first_flags = 0, samples_count = 0;
3214   gint i;
3215   guint8 *data;
3216   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3217   QtDemuxSample *sample;
3218   gboolean ismv = FALSE;
3219   gint64 initial_offset;
3220
3221   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3222       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3223       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3224       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3225
3226   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3227     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3228     return TRUE;
3229   }
3230
3231   /* presence of stss or not can't really tell us much,
3232    * and flags and so on tend to be marginally reliable in these files */
3233   if (stream->subtype == FOURCC_soun) {
3234     GST_DEBUG_OBJECT (qtdemux,
3235         "sound track in fragmented file; marking all keyframes");
3236     stream->all_keyframe = TRUE;
3237   }
3238
3239   if (!gst_byte_reader_skip (trun, 1) ||
3240       !gst_byte_reader_get_uint24_be (trun, &flags))
3241     goto fail;
3242
3243   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3244     goto fail;
3245
3246   if (flags & TR_DATA_OFFSET) {
3247     /* note this is really signed */
3248     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3249       goto fail;
3250     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3251     /* default base offset = first byte of moof */
3252     if (*base_offset == -1) {
3253       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3254       *base_offset = moof_offset;
3255     }
3256     *running_offset = *base_offset + data_offset;
3257   } else {
3258     /* if no offset at all, that would mean data starts at moof start,
3259      * which is a bit wrong and is ismv crappy way, so compensate
3260      * assuming data is in mdat following moof */
3261     if (*base_offset == -1) {
3262       *base_offset = moof_offset + moof_length + 8;
3263       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3264       ismv = TRUE;
3265     }
3266     if (*running_offset == -1)
3267       *running_offset = *base_offset;
3268   }
3269
3270   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3271       *running_offset);
3272   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3273       data_offset, flags, samples_count);
3274
3275   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3276     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3277       GST_DEBUG_OBJECT (qtdemux,
3278           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3279       flags ^= TR_FIRST_SAMPLE_FLAGS;
3280     } else {
3281       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3282         goto fail;
3283       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3284     }
3285   }
3286
3287   /* FIXME ? spec says other bits should also be checked to determine
3288    * entry size (and prefix size for that matter) */
3289   entry_size = 0;
3290   dur_offset = size_offset = 0;
3291   if (flags & TR_SAMPLE_DURATION) {
3292     GST_LOG_OBJECT (qtdemux, "entry duration present");
3293     dur_offset = entry_size;
3294     entry_size += 4;
3295   }
3296   if (flags & TR_SAMPLE_SIZE) {
3297     GST_LOG_OBJECT (qtdemux, "entry size present");
3298     size_offset = entry_size;
3299     entry_size += 4;
3300   }
3301   if (flags & TR_SAMPLE_FLAGS) {
3302     GST_LOG_OBJECT (qtdemux, "entry flags present");
3303     flags_offset = entry_size;
3304     entry_size += 4;
3305   }
3306   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3307     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3308     ct_offset = entry_size;
3309     entry_size += 4;
3310   }
3311
3312   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3313     goto fail;
3314   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3315
3316   if (stream->n_samples + samples_count >=
3317       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3318     goto index_too_big;
3319
3320   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3321       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3322       (stream->n_samples + samples_count) *
3323       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3324
3325   /* create a new array of samples if it's the first sample parsed */
3326   if (stream->n_samples == 0) {
3327     g_assert (stream->samples == NULL);
3328     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3329     /* or try to reallocate it with space enough to insert the new samples */
3330   } else
3331     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3332         stream->n_samples + samples_count);
3333   if (stream->samples == NULL)
3334     goto out_of_memory;
3335
3336   if (qtdemux->fragment_start != -1) {
3337     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3338     qtdemux->fragment_start = -1;
3339   } else {
3340     if (stream->n_samples == 0) {
3341       if (decode_ts > 0) {
3342         timestamp = decode_ts;
3343       } else if (stream->pending_seek != NULL) {
3344         /* if we don't have a timestamp from a tfdt box, we'll use the one
3345          * from the mfra seek table */
3346         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3347             GST_TIME_ARGS (stream->pending_seek->ts));
3348
3349         /* FIXME: this is not fully correct, the timestamp refers to the random
3350          * access sample refered to in the tfra entry, which may not necessarily
3351          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3352         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3353       } else {
3354         timestamp = 0;
3355       }
3356
3357       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3358       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3359           GST_TIME_ARGS (gst_ts));
3360     } else {
3361       /* subsequent fragments extend stream */
3362       timestamp =
3363           stream->samples[stream->n_samples - 1].timestamp +
3364           stream->samples[stream->n_samples - 1].duration;
3365
3366       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3367        * difference (1 sec.) between decode_ts and timestamp, prefer the
3368        * former */
3369       if (has_tfdt && !qtdemux->upstream_format_is_time
3370           && ABSDIFF (decode_ts, timestamp) >
3371           MAX (stream->duration_last_moof / 2,
3372               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3373         GST_INFO_OBJECT (qtdemux,
3374             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3375             ") are significantly different (more than %" GST_TIME_FORMAT
3376             "), using decode_ts",
3377             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3378             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3379             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3380                     MAX (stream->duration_last_moof / 2,
3381                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3382         timestamp = decode_ts;
3383       }
3384
3385       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3386       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3387           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3388     }
3389   }
3390
3391   initial_offset = *running_offset;
3392
3393   sample = stream->samples + stream->n_samples;
3394   for (i = 0; i < samples_count; i++) {
3395     guint32 dur, size, sflags, ct;
3396
3397     /* first read sample data */
3398     if (flags & TR_SAMPLE_DURATION) {
3399       dur = QT_UINT32 (data + dur_offset);
3400     } else {
3401       dur = d_sample_duration;
3402     }
3403     if (flags & TR_SAMPLE_SIZE) {
3404       size = QT_UINT32 (data + size_offset);
3405     } else {
3406       size = d_sample_size;
3407     }
3408     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3409       if (i == 0) {
3410         sflags = first_flags;
3411       } else {
3412         sflags = d_sample_flags;
3413       }
3414     } else if (flags & TR_SAMPLE_FLAGS) {
3415       sflags = QT_UINT32 (data + flags_offset);
3416     } else {
3417       sflags = d_sample_flags;
3418     }
3419     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3420       ct = QT_UINT32 (data + ct_offset);
3421     } else {
3422       ct = 0;
3423     }
3424     data += entry_size;
3425
3426     /* fill the sample information */
3427     sample->offset = *running_offset;
3428     sample->pts_offset = ct;
3429     sample->size = size;
3430     sample->timestamp = timestamp;
3431     sample->duration = dur;
3432     /* sample-is-difference-sample */
3433     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3434      * now idea how it relates to bitfield other than massive LE/BE confusion */
3435     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3436     *running_offset += size;
3437     timestamp += dur;
3438     stream->duration_moof += dur;
3439     sample++;
3440   }
3441
3442   /* Update total duration if needed */
3443   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3444
3445   /* Pre-emptively figure out size of mdat based on trun information.
3446    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3447    * size, else we will still be able to use this when dealing with gap'ed
3448    * input */
3449   qtdemux->mdatleft = *running_offset - initial_offset;
3450   qtdemux->mdatoffset = initial_offset;
3451   qtdemux->mdatsize = qtdemux->mdatleft;
3452
3453   stream->n_samples += samples_count;
3454   stream->n_samples_moof += samples_count;
3455
3456   if (stream->pending_seek != NULL)
3457     stream->pending_seek = NULL;
3458
3459   return TRUE;
3460
3461 fail:
3462   {
3463     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3464     return FALSE;
3465   }
3466 out_of_memory:
3467   {
3468     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3469         stream->n_samples);
3470     return FALSE;
3471   }
3472 index_too_big:
3473   {
3474     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3475         "be larger than %uMB (broken file?)", stream->n_samples,
3476         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3477     return FALSE;
3478   }
3479 }
3480
3481 /* find stream with @id */
3482 static inline QtDemuxStream *
3483 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3484 {
3485   QtDemuxStream *stream;
3486   gint i;
3487
3488   /* check */
3489   if (G_UNLIKELY (!id)) {
3490     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3491     return NULL;
3492   }
3493
3494   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3495     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3496     if (stream->track_id == id)
3497       return stream;
3498   }
3499   if (qtdemux->mss_mode) {
3500     /* mss should have only 1 stream anyway */
3501     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3502   }
3503
3504   return NULL;
3505 }
3506
3507 static gboolean
3508 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3509     guint32 * fragment_number)
3510 {
3511   if (!gst_byte_reader_skip (mfhd, 4))
3512     goto fail;
3513   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3514     goto fail;
3515   return TRUE;
3516 fail:
3517   {
3518     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3519     return FALSE;
3520   }
3521 }
3522
3523 static gboolean
3524 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3525     QtDemuxStream ** stream, guint32 * default_sample_duration,
3526     guint32 * default_sample_size, guint32 * default_sample_flags,
3527     gint64 * base_offset)
3528 {
3529   guint32 flags = 0;
3530   guint32 track_id = 0;
3531
3532   if (!gst_byte_reader_skip (tfhd, 1) ||
3533       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3534     goto invalid_track;
3535
3536   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3537     goto invalid_track;
3538
3539   *stream = qtdemux_find_stream (qtdemux, track_id);
3540   if (G_UNLIKELY (!*stream))
3541     goto unknown_stream;
3542
3543   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3544     *base_offset = qtdemux->moof_offset;
3545
3546   if (flags & TF_BASE_DATA_OFFSET)
3547     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3548       goto invalid_track;
3549
3550   /* obtain stream defaults */
3551   qtdemux_parse_trex (qtdemux, *stream,
3552       default_sample_duration, default_sample_size, default_sample_flags);
3553
3554   (*stream)->stsd_sample_description_id =
3555       (*stream)->def_sample_description_index - 1;
3556
3557   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3558     guint32 sample_description_index;
3559     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3560       goto invalid_track;
3561     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3562   }
3563
3564   if (qtdemux->mss_mode) {
3565     /* mss has no stsd entry */
3566     (*stream)->stsd_sample_description_id = 0;
3567   }
3568
3569   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3570     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3571       goto invalid_track;
3572
3573   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3574     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3575       goto invalid_track;
3576
3577   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3578     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3579       goto invalid_track;
3580
3581   return TRUE;
3582
3583 invalid_track:
3584   {
3585     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3586     return FALSE;
3587   }
3588 unknown_stream:
3589   {
3590     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3591     return TRUE;
3592   }
3593 }
3594
3595 static gboolean
3596 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3597     guint64 * decode_time)
3598 {
3599   guint32 version = 0;
3600
3601   if (!gst_byte_reader_get_uint32_be (br, &version))
3602     return FALSE;
3603
3604   version >>= 24;
3605   if (version == 1) {
3606     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3607       goto failed;
3608   } else {
3609     guint32 dec_time = 0;
3610     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3611       goto failed;
3612     *decode_time = dec_time;
3613   }
3614
3615   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3616       *decode_time);
3617
3618   return TRUE;
3619
3620 failed:
3621   {
3622     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3623     return FALSE;
3624   }
3625 }
3626
3627 /* Returns a pointer to a GstStructure containing the properties of
3628  * the stream sample identified by @sample_index. The caller must unref
3629  * the returned object after use. Returns NULL if unsuccessful. */
3630 static GstStructure *
3631 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3632     QtDemuxStream * stream, guint sample_index)
3633 {
3634   QtDemuxCencSampleSetInfo *info = NULL;
3635
3636   g_return_val_if_fail (stream != NULL, NULL);
3637   g_return_val_if_fail (stream->protected, NULL);
3638   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3639
3640   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3641
3642   /* Currently, cenc properties for groups of samples are not supported, so
3643    * simply return a copy of the default sample properties */
3644   return gst_structure_copy (info->default_properties);
3645 }
3646
3647 /* Parses the sizes of sample auxiliary information contained within a stream,
3648  * as given in a saiz box. Returns array of sample_count guint8 size values,
3649  * or NULL on failure */
3650 static guint8 *
3651 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3652     GstByteReader * br, guint32 * sample_count)
3653 {
3654   guint32 flags = 0;
3655   guint8 *info_sizes;
3656   guint8 default_info_size;
3657
3658   g_return_val_if_fail (qtdemux != NULL, NULL);
3659   g_return_val_if_fail (stream != NULL, NULL);
3660   g_return_val_if_fail (br != NULL, NULL);
3661   g_return_val_if_fail (sample_count != NULL, NULL);
3662
3663   if (!gst_byte_reader_get_uint32_be (br, &flags))
3664     return NULL;
3665
3666   if (flags & 0x1) {
3667     /* aux_info_type and aux_info_type_parameter are ignored */
3668     if (!gst_byte_reader_skip (br, 8))
3669       return NULL;
3670   }
3671
3672   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3673     return NULL;
3674   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3675
3676   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3677     return NULL;
3678   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3679
3680
3681   if (default_info_size == 0) {
3682     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3683       return NULL;
3684     }
3685   } else {
3686     info_sizes = g_new (guint8, *sample_count);
3687     memset (info_sizes, default_info_size, *sample_count);
3688   }
3689
3690   return info_sizes;
3691 }
3692
3693 /* Parses the offset of sample auxiliary information contained within a stream,
3694  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3695 static gboolean
3696 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3697     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3698     guint64 * offset)
3699 {
3700   guint8 version = 0;
3701   guint32 flags = 0;
3702   guint32 aux_info_type = 0;
3703   guint32 aux_info_type_parameter = 0;
3704   guint32 entry_count;
3705   guint32 off_32;
3706   guint64 off_64;
3707   const guint8 *aux_info_type_data = NULL;
3708
3709   g_return_val_if_fail (qtdemux != NULL, FALSE);
3710   g_return_val_if_fail (stream != NULL, FALSE);
3711   g_return_val_if_fail (br != NULL, FALSE);
3712   g_return_val_if_fail (offset != NULL, FALSE);
3713
3714   if (!gst_byte_reader_get_uint8 (br, &version))
3715     return FALSE;
3716
3717   if (!gst_byte_reader_get_uint24_be (br, &flags))
3718     return FALSE;
3719
3720   if (flags & 0x1) {
3721
3722     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3723       return FALSE;
3724     aux_info_type = QT_FOURCC (aux_info_type_data);
3725
3726     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3727       return FALSE;
3728   } else if (stream->protected) {
3729     aux_info_type = stream->protection_scheme_type;
3730   } else {
3731     aux_info_type = CUR_STREAM (stream)->fourcc;
3732   }
3733
3734   if (info_type)
3735     *info_type = aux_info_type;
3736   if (info_type_parameter)
3737     *info_type_parameter = aux_info_type_parameter;
3738
3739   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3740       "aux_info_type_parameter:  %#06x",
3741       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3742
3743   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3744     return FALSE;
3745
3746   if (entry_count != 1) {
3747     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3748     return FALSE;
3749   }
3750
3751   if (version == 0) {
3752     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3753       return FALSE;
3754     *offset = (guint64) off_32;
3755   } else {
3756     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3757       return FALSE;
3758     *offset = off_64;
3759   }
3760
3761   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3762   return TRUE;
3763 }
3764
3765 static void
3766 qtdemux_gst_structure_free (GstStructure * gststructure)
3767 {
3768   if (gststructure) {
3769     gst_structure_free (gststructure);
3770   }
3771 }
3772
3773 /* Parses auxiliary information relating to samples protected using
3774  * Common Encryption (cenc); the format of this information
3775  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3776  * otherwise. */
3777 static gboolean
3778 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3779     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3780 {
3781   QtDemuxCencSampleSetInfo *ss_info = NULL;
3782   guint8 size;
3783   gint i;
3784   GPtrArray *old_crypto_info = NULL;
3785   guint old_entries = 0;
3786
3787   g_return_val_if_fail (qtdemux != NULL, FALSE);
3788   g_return_val_if_fail (stream != NULL, FALSE);
3789   g_return_val_if_fail (br != NULL, FALSE);
3790   g_return_val_if_fail (stream->protected, FALSE);
3791   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3792
3793   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3794
3795   if (ss_info->crypto_info) {
3796     old_crypto_info = ss_info->crypto_info;
3797     /* Count number of non-null entries remaining at the tail end */
3798     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3799       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3800         break;
3801       old_entries++;
3802     }
3803   }
3804
3805   ss_info->crypto_info =
3806       g_ptr_array_new_full (sample_count + old_entries,
3807       (GDestroyNotify) qtdemux_gst_structure_free);
3808
3809   /* We preserve old entries because we parse the next moof in advance
3810    * of consuming all samples from the previous moof, and otherwise
3811    * we'd discard the corresponding crypto info for the samples
3812    * from the previous fragment. */
3813   if (old_entries) {
3814     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3815         old_entries);
3816     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3817       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3818               i));
3819       g_ptr_array_index (old_crypto_info, i) = NULL;
3820     }
3821   }
3822
3823   if (old_crypto_info) {
3824     /* Everything now belongs to the new array */
3825     g_ptr_array_free (old_crypto_info, TRUE);
3826   }
3827
3828   for (i = 0; i < sample_count; ++i) {
3829     GstStructure *properties;
3830     guint16 n_subsamples = 0;
3831     guint8 *data;
3832     guint iv_size;
3833     GstBuffer *buf;
3834     gboolean could_read_iv;
3835
3836     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3837     if (properties == NULL) {
3838       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3839       return FALSE;
3840     }
3841     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3842       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3843       gst_structure_free (properties);
3844       return FALSE;
3845     }
3846     could_read_iv =
3847         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3848     if (could_read_iv) {
3849       buf = gst_buffer_new_wrapped (data, iv_size);
3850       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3851       gst_buffer_unref (buf);
3852     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3853       const GValue *constant_iv_size_value =
3854           gst_structure_get_value (properties, "constant_iv_size");
3855       const GValue *constant_iv_value =
3856           gst_structure_get_value (properties, "iv");
3857       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3858         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3859         gst_structure_free (properties);
3860         return FALSE;
3861       }
3862       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3863       gst_structure_remove_field (properties, "constant_iv_size");
3864     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3865       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3866       gst_structure_free (properties);
3867       return FALSE;
3868     }
3869     size = info_sizes[i];
3870     if (size > iv_size) {
3871       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3872           || !(n_subsamples > 0)) {
3873         gst_structure_free (properties);
3874         GST_ERROR_OBJECT (qtdemux,
3875             "failed to get subsample count for sample %u", i);
3876         return FALSE;
3877       }
3878       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3879       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3880         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3881             i);
3882         gst_structure_free (properties);
3883         return FALSE;
3884       }
3885       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3886       if (!buf) {
3887         gst_structure_free (properties);
3888         return FALSE;
3889       }
3890       gst_structure_set (properties,
3891           "subsample_count", G_TYPE_UINT, n_subsamples,
3892           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3893       gst_buffer_unref (buf);
3894     } else {
3895       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3896     }
3897     g_ptr_array_add (ss_info->crypto_info, properties);
3898   }
3899   return TRUE;
3900 }
3901
3902 /* Converts a UUID in raw byte form to a string representation, as defined in
3903  * RFC 4122. The caller takes ownership of the returned string and is
3904  * responsible for freeing it after use. */
3905 static gchar *
3906 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3907 {
3908   const guint8 *uuid = (const guint8 *) uuid_bytes;
3909
3910   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3911       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3912       uuid[0], uuid[1], uuid[2], uuid[3],
3913       uuid[4], uuid[5], uuid[6], uuid[7],
3914       uuid[8], uuid[9], uuid[10], uuid[11],
3915       uuid[12], uuid[13], uuid[14], uuid[15]);
3916 }
3917
3918 /* Parses a Protection System Specific Header box (pssh), as defined in the
3919  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3920  * information needed by a specific content protection system in order to
3921  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3922  * otherwise. */
3923 static gboolean
3924 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3925 {
3926   gchar *sysid_string;
3927   guint32 pssh_size = QT_UINT32 (node->data);
3928   GstBuffer *pssh = NULL;
3929   GstEvent *event = NULL;
3930   guint32 parent_box_type;
3931   gint i;
3932
3933   if (G_UNLIKELY (pssh_size < 32U)) {
3934     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3935     return FALSE;
3936   }
3937
3938   sysid_string =
3939       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3940
3941   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3942
3943   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3944   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3945       gst_buffer_get_size (pssh));
3946
3947   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3948
3949   /* Push an event containing the pssh box onto the queues of all streams. */
3950   event = gst_event_new_protection (sysid_string, pssh,
3951       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3952   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3953     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3954     GST_TRACE_OBJECT (qtdemux,
3955         "adding protection event for stream %s and system %s",
3956         stream->stream_id, sysid_string);
3957     g_queue_push_tail (&stream->protection_scheme_event_queue,
3958         gst_event_ref (event));
3959   }
3960   g_free (sysid_string);
3961   gst_event_unref (event);
3962   gst_buffer_unref (pssh);
3963   return TRUE;
3964 }
3965
3966 static gboolean
3967 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3968     guint64 moof_offset, QtDemuxStream * stream)
3969 {
3970   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3971   GNode *uuid_node;
3972   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3973   GNode *saiz_node, *saio_node, *pssh_node;
3974   GstByteReader saiz_data, saio_data;
3975   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3976   gint64 base_offset, running_offset;
3977   guint32 frag_num;
3978   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3979
3980   /* NOTE @stream ignored */
3981
3982   moof_node = g_node_new ((guint8 *) buffer);
3983   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3984   qtdemux_node_dump (qtdemux, moof_node);
3985
3986   /* Get fragment number from mfhd and check it's valid */
3987   mfhd_node =
3988       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3989   if (mfhd_node == NULL)
3990     goto missing_mfhd;
3991   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3992     goto fail;
3993   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3994
3995   /* unknown base_offset to start with */
3996   base_offset = running_offset = -1;
3997   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3998   while (traf_node) {
3999     guint64 decode_time = 0;
4000
4001     /* Fragment Header node */
4002     tfhd_node =
4003         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4004         &tfhd_data);
4005     if (!tfhd_node)
4006       goto missing_tfhd;
4007     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4008             &ds_size, &ds_flags, &base_offset))
4009       goto missing_tfhd;
4010
4011     /* The following code assumes at most a single set of sample auxiliary
4012      * data in the fragment (consisting of a saiz box and a corresponding saio
4013      * box); in theory, however, there could be multiple sets of sample
4014      * auxiliary data in a fragment. */
4015     saiz_node =
4016         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4017         &saiz_data);
4018     if (saiz_node) {
4019       guint32 info_type = 0;
4020       guint64 offset = 0;
4021       guint32 info_type_parameter = 0;
4022
4023       g_free (qtdemux->cenc_aux_info_sizes);
4024
4025       qtdemux->cenc_aux_info_sizes =
4026           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4027           &qtdemux->cenc_aux_sample_count);
4028       if (qtdemux->cenc_aux_info_sizes == NULL) {
4029         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4030         goto fail;
4031       }
4032       saio_node =
4033           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4034           &saio_data);
4035       if (!saio_node) {
4036         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4037         g_free (qtdemux->cenc_aux_info_sizes);
4038         qtdemux->cenc_aux_info_sizes = NULL;
4039         goto fail;
4040       }
4041
4042       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4043                   &info_type, &info_type_parameter, &offset))) {
4044         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4045         g_free (qtdemux->cenc_aux_info_sizes);
4046         qtdemux->cenc_aux_info_sizes = NULL;
4047         goto fail;
4048       }
4049       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4050         offset += (guint64) (base_offset - qtdemux->moof_offset);
4051       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4052           && info_type_parameter == 0U) {
4053         GstByteReader br;
4054         if (offset > length) {
4055           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4056           qtdemux->cenc_aux_info_offset = offset;
4057         } else {
4058           gst_byte_reader_init (&br, buffer + offset, length - offset);
4059           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4060                   qtdemux->cenc_aux_info_sizes,
4061                   qtdemux->cenc_aux_sample_count)) {
4062             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4063             g_free (qtdemux->cenc_aux_info_sizes);
4064             qtdemux->cenc_aux_info_sizes = NULL;
4065             goto fail;
4066           }
4067         }
4068       }
4069     }
4070
4071     tfdt_node =
4072         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4073         &tfdt_data);
4074     if (tfdt_node) {
4075       /* We'll use decode_time to interpolate timestamps
4076        * in case the input timestamps are missing */
4077       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4078
4079       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4080           " (%" GST_TIME_FORMAT ")", decode_time,
4081           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4082                   decode_time) : GST_CLOCK_TIME_NONE));
4083
4084       /* Discard the fragment buffer timestamp info to avoid using it.
4085        * Rely on tfdt instead as it is more accurate than the timestamp
4086        * that is fetched from a manifest/playlist and is usually
4087        * less accurate. */
4088       qtdemux->fragment_start = -1;
4089     }
4090
4091     if (G_UNLIKELY (!stream)) {
4092       /* we lost track of offset, we'll need to regain it,
4093        * but can delay complaining until later or avoid doing so altogether */
4094       base_offset = -2;
4095       goto next;
4096     }
4097     if (G_UNLIKELY (base_offset < -1))
4098       goto lost_offset;
4099
4100     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4101
4102     if (!qtdemux->pullbased) {
4103       /* Sample tables can grow enough to be problematic if the system memory
4104        * is very low (e.g. embedded devices) and the videos very long
4105        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4106        * Fortunately, we can easily discard them for each new fragment when
4107        * we know qtdemux will not receive seeks outside of the current fragment.
4108        * adaptivedemux honors this assumption.
4109        * This optimization is also useful for applications that use qtdemux as
4110        * a push-based simple demuxer, like Media Source Extensions. */
4111       gst_qtdemux_stream_flush_samples_data (stream);
4112     }
4113
4114     /* initialise moof sample data */
4115     stream->n_samples_moof = 0;
4116     stream->duration_last_moof = stream->duration_moof;
4117     stream->duration_moof = 0;
4118
4119     /* Track Run node */
4120     trun_node =
4121         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4122         &trun_data);
4123     while (trun_node) {
4124       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4125           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4126           &running_offset, decode_time, (tfdt_node != NULL));
4127       /* iterate all siblings */
4128       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4129           &trun_data);
4130     }
4131
4132     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4133     if (uuid_node) {
4134       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4135       guint32 box_length = QT_UINT32 (uuid_buffer);
4136
4137       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4138     }
4139
4140     /* if no new base_offset provided for next traf,
4141      * base is end of current traf */
4142     base_offset = running_offset;
4143     running_offset = -1;
4144
4145     if (stream->n_samples_moof && stream->duration_moof)
4146       stream->new_caps = TRUE;
4147
4148   next:
4149     /* iterate all siblings */
4150     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4151   }
4152
4153   /* parse any protection system info */
4154   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4155   while (pssh_node) {
4156     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4157     qtdemux_parse_pssh (qtdemux, pssh_node);
4158     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4159   }
4160
4161   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4162       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4163       && min_dts != 0) {
4164     /* Unless the user has explicitly requested another seek, perform an
4165      * internal seek to the time specified in the tfdt.
4166      *
4167      * This way if the user opens a file where the first tfdt is 1 hour
4168      * into the presentation, they will not have to wait 1 hour for run
4169      * time to catch up and actual playback to start. */
4170     gint i;
4171
4172     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4173         "performing an internal seek to %" GST_TIME_FORMAT,
4174         GST_TIME_ARGS (min_dts));
4175
4176     qtdemux->segment.start = min_dts;
4177     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4178
4179     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4180       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4181       stream->time_position = min_dts;
4182     }
4183
4184     /* Before this code was run a segment was already sent when the moov was
4185      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4186      * be emitted after a moov, and we can emit a second segment anyway for
4187      * special cases like this. */
4188     qtdemux->need_segment = TRUE;
4189   }
4190
4191   qtdemux->first_moof_already_parsed = TRUE;
4192
4193   g_node_destroy (moof_node);
4194   return TRUE;
4195
4196 missing_tfhd:
4197   {
4198     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4199     goto fail;
4200   }
4201 missing_mfhd:
4202   {
4203     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4204     goto fail;
4205   }
4206 lost_offset:
4207   {
4208     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4209     goto fail;
4210   }
4211 fail:
4212   {
4213     g_node_destroy (moof_node);
4214     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4215         (_("This file is corrupt and cannot be played.")), (NULL));
4216     return FALSE;
4217   }
4218 }
4219
4220 #if 0
4221 /* might be used if some day we actually use mfra & co
4222  * for random access to fragments,
4223  * but that will require quite some modifications and much less relying
4224  * on a sample array */
4225 #endif
4226
4227 static gboolean
4228 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4229 {
4230   QtDemuxStream *stream;
4231   guint32 ver_flags, track_id, len, num_entries, i;
4232   guint value_size, traf_size, trun_size, sample_size;
4233   guint64 time = 0, moof_offset = 0;
4234 #if 0
4235   GstBuffer *buf = NULL;
4236   GstFlowReturn ret;
4237 #endif
4238   GstByteReader tfra;
4239
4240   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4241
4242   if (!gst_byte_reader_skip (&tfra, 8))
4243     return FALSE;
4244
4245   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4246     return FALSE;
4247
4248   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4249       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4250       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4251     return FALSE;
4252
4253   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4254
4255   stream = qtdemux_find_stream (qtdemux, track_id);
4256   if (stream == NULL)
4257     goto unknown_trackid;
4258
4259   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4260   sample_size = (len & 3) + 1;
4261   trun_size = ((len & 12) >> 2) + 1;
4262   traf_size = ((len & 48) >> 4) + 1;
4263
4264   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4265       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4266
4267   if (num_entries == 0)
4268     goto no_samples;
4269
4270   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4271           value_size + value_size + traf_size + trun_size + sample_size))
4272     goto corrupt_file;
4273
4274   g_free (stream->ra_entries);
4275   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4276   stream->n_ra_entries = num_entries;
4277
4278   for (i = 0; i < num_entries; i++) {
4279     qt_atom_parser_get_offset (&tfra, value_size, &time);
4280     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4281     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4282     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4283     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4284
4285     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4286
4287     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4288         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4289
4290     stream->ra_entries[i].ts = time;
4291     stream->ra_entries[i].moof_offset = moof_offset;
4292
4293     /* don't want to go through the entire file and read all moofs at startup */
4294 #if 0
4295     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4296     if (ret != GST_FLOW_OK)
4297       goto corrupt_file;
4298     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4299         moof_offset, stream);
4300     gst_buffer_unref (buf);
4301 #endif
4302   }
4303
4304   check_update_duration (qtdemux, time);
4305
4306   return TRUE;
4307
4308 /* ERRORS */
4309 unknown_trackid:
4310   {
4311     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4312     return FALSE;
4313   }
4314 corrupt_file:
4315   {
4316     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4317     return FALSE;
4318   }
4319 no_samples:
4320   {
4321     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4322     return FALSE;
4323   }
4324 }
4325
4326 static gboolean
4327 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4328 {
4329   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4330   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4331   GstBuffer *mfro = NULL, *mfra = NULL;
4332   GstFlowReturn flow;
4333   gboolean ret = FALSE;
4334   GNode *mfra_node, *tfra_node;
4335   guint64 mfra_offset = 0;
4336   guint32 fourcc, mfra_size;
4337   gint64 len;
4338
4339   /* query upstream size in bytes */
4340   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4341     goto size_query_failed;
4342
4343   /* mfro box should be at the very end of the file */
4344   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4345   if (flow != GST_FLOW_OK)
4346     goto exit;
4347
4348   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4349
4350   fourcc = QT_FOURCC (mfro_map.data + 4);
4351   if (fourcc != FOURCC_mfro)
4352     goto exit;
4353
4354   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4355   if (mfro_map.size < 16)
4356     goto invalid_mfro_size;
4357
4358   mfra_size = QT_UINT32 (mfro_map.data + 12);
4359   if (mfra_size >= len)
4360     goto invalid_mfra_size;
4361
4362   mfra_offset = len - mfra_size;
4363
4364   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4365       mfra_offset, mfra_size);
4366
4367   /* now get and parse mfra box */
4368   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4369   if (flow != GST_FLOW_OK)
4370     goto broken_file;
4371
4372   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4373
4374   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4375   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4376
4377   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4378
4379   while (tfra_node) {
4380     qtdemux_parse_tfra (qtdemux, tfra_node);
4381     /* iterate all siblings */
4382     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4383   }
4384   g_node_destroy (mfra_node);
4385
4386   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4387   ret = TRUE;
4388
4389 exit:
4390
4391   if (mfro) {
4392     if (mfro_map.memory != NULL)
4393       gst_buffer_unmap (mfro, &mfro_map);
4394     gst_buffer_unref (mfro);
4395   }
4396   if (mfra) {
4397     if (mfra_map.memory != NULL)
4398       gst_buffer_unmap (mfra, &mfra_map);
4399     gst_buffer_unref (mfra);
4400   }
4401   return ret;
4402
4403 /* ERRORS */
4404 size_query_failed:
4405   {
4406     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4407     goto exit;
4408   }
4409 invalid_mfro_size:
4410   {
4411     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4412     goto exit;
4413   }
4414 invalid_mfra_size:
4415   {
4416     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4417     goto exit;
4418   }
4419 broken_file:
4420   {
4421     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4422     goto exit;
4423   }
4424 }
4425
4426 static guint64
4427 add_offset (guint64 offset, guint64 advance)
4428 {
4429   /* Avoid 64-bit overflow by clamping */
4430   if (offset > G_MAXUINT64 - advance)
4431     return G_MAXUINT64;
4432   return offset + advance;
4433 }
4434
4435 static GstFlowReturn
4436 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4437 {
4438   guint64 length = 0;
4439   guint32 fourcc = 0;
4440   GstBuffer *buf = NULL;
4441   GstFlowReturn ret = GST_FLOW_OK;
4442   guint64 cur_offset = qtdemux->offset;
4443   GstMapInfo map;
4444
4445   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4446   if (G_UNLIKELY (ret != GST_FLOW_OK))
4447     goto beach;
4448   gst_buffer_map (buf, &map, GST_MAP_READ);
4449   if (G_LIKELY (map.size >= 8))
4450     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4451   gst_buffer_unmap (buf, &map);
4452   gst_buffer_unref (buf);
4453
4454   /* maybe we already got most we needed, so only consider this eof */
4455   if (G_UNLIKELY (length == 0)) {
4456     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4457         (_("Invalid atom size.")),
4458         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4459             GST_FOURCC_ARGS (fourcc)));
4460     ret = GST_FLOW_EOS;
4461     goto beach;
4462   }
4463
4464   switch (fourcc) {
4465     case FOURCC_moof:
4466       /* record for later parsing when needed */
4467       if (!qtdemux->moof_offset) {
4468         qtdemux->moof_offset = qtdemux->offset;
4469       }
4470       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4471         /* FIXME */
4472       } else {
4473         qtdemux->offset += length;      /* skip moof and keep going */
4474       }
4475       if (qtdemux->got_moov) {
4476         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4477         ret = GST_FLOW_EOS;
4478         goto beach;
4479       }
4480       break;
4481     case FOURCC_mdat:
4482     case FOURCC_free:
4483     case FOURCC_skip:
4484     case FOURCC_wide:
4485     case FOURCC_PICT:
4486     case FOURCC_pnot:
4487     {
4488       GST_LOG_OBJECT (qtdemux,
4489           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4490           GST_FOURCC_ARGS (fourcc), cur_offset);
4491       qtdemux->offset = add_offset (qtdemux->offset, length);
4492       break;
4493     }
4494     case FOURCC_moov:
4495     {
4496       GstBuffer *moov = NULL;
4497
4498       if (qtdemux->got_moov) {
4499         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4500         qtdemux->offset = add_offset (qtdemux->offset, length);
4501         goto beach;
4502       }
4503
4504       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4505       if (ret != GST_FLOW_OK)
4506         goto beach;
4507       gst_buffer_map (moov, &map, GST_MAP_READ);
4508
4509       if (length != map.size) {
4510         /* Some files have a 'moov' atom at the end of the file which contains
4511          * a terminal 'free' atom where the body of the atom is missing.
4512          * Check for, and permit, this special case.
4513          */
4514         if (map.size >= 8) {
4515           guint8 *final_data = map.data + (map.size - 8);
4516           guint32 final_length = QT_UINT32 (final_data);
4517           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4518
4519           if (final_fourcc == FOURCC_free
4520               && map.size + final_length - 8 == length) {
4521             /* Ok, we've found that special case. Allocate a new buffer with
4522              * that free atom actually present. */
4523             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4524             gst_buffer_fill (newmoov, 0, map.data, map.size);
4525             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4526             gst_buffer_unmap (moov, &map);
4527             gst_buffer_unref (moov);
4528             moov = newmoov;
4529             gst_buffer_map (moov, &map, GST_MAP_READ);
4530           }
4531         }
4532       }
4533
4534       if (length != map.size) {
4535         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4536             (_("This file is incomplete and cannot be played.")),
4537             ("We got less than expected (received %" G_GSIZE_FORMAT
4538                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4539                 (guint) length, cur_offset));
4540         gst_buffer_unmap (moov, &map);
4541         gst_buffer_unref (moov);
4542         ret = GST_FLOW_ERROR;
4543         goto beach;
4544       }
4545       qtdemux->offset += length;
4546
4547       qtdemux_parse_moov (qtdemux, map.data, length);
4548       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4549
4550       qtdemux_parse_tree (qtdemux);
4551       if (qtdemux->moov_node_compressed) {
4552         g_node_destroy (qtdemux->moov_node_compressed);
4553         g_free (qtdemux->moov_node->data);
4554       }
4555       qtdemux->moov_node_compressed = NULL;
4556       g_node_destroy (qtdemux->moov_node);
4557       qtdemux->moov_node = NULL;
4558       gst_buffer_unmap (moov, &map);
4559       gst_buffer_unref (moov);
4560       qtdemux->got_moov = TRUE;
4561
4562       break;
4563     }
4564     case FOURCC_ftyp:
4565     {
4566       GstBuffer *ftyp = NULL;
4567
4568       /* extract major brand; might come in handy for ISO vs QT issues */
4569       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4570       if (ret != GST_FLOW_OK)
4571         goto beach;
4572       qtdemux->offset += length;
4573       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4574       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4575       gst_buffer_unmap (ftyp, &map);
4576       gst_buffer_unref (ftyp);
4577       break;
4578     }
4579     case FOURCC_uuid:
4580     {
4581       GstBuffer *uuid = NULL;
4582
4583       /* uuid are extension atoms */
4584       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4585       if (ret != GST_FLOW_OK)
4586         goto beach;
4587       qtdemux->offset += length;
4588       gst_buffer_map (uuid, &map, GST_MAP_READ);
4589       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4590       gst_buffer_unmap (uuid, &map);
4591       gst_buffer_unref (uuid);
4592       break;
4593     }
4594     case FOURCC_sidx:
4595     {
4596       GstBuffer *sidx = NULL;
4597       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4598       if (ret != GST_FLOW_OK)
4599         goto beach;
4600       qtdemux->offset += length;
4601       gst_buffer_map (sidx, &map, GST_MAP_READ);
4602       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4603       gst_buffer_unmap (sidx, &map);
4604       gst_buffer_unref (sidx);
4605       break;
4606     }
4607     default:
4608     {
4609       GstBuffer *unknown = NULL;
4610
4611       GST_LOG_OBJECT (qtdemux,
4612           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4613           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4614           cur_offset);
4615       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4616       if (ret != GST_FLOW_OK)
4617         goto beach;
4618       gst_buffer_map (unknown, &map, GST_MAP_READ);
4619       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4620       gst_buffer_unmap (unknown, &map);
4621       gst_buffer_unref (unknown);
4622       qtdemux->offset += length;
4623       break;
4624     }
4625   }
4626
4627 beach:
4628   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4629     /* digested all data, show what we have */
4630     qtdemux_prepare_streams (qtdemux);
4631     QTDEMUX_EXPOSE_LOCK (qtdemux);
4632     ret = qtdemux_expose_streams (qtdemux);
4633     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4634
4635     qtdemux->state = QTDEMUX_STATE_MOVIE;
4636     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4637         qtdemux->state);
4638     return ret;
4639   }
4640   return ret;
4641 }
4642
4643 /* Seeks to the previous keyframe of the indexed stream and
4644  * aligns other streams with respect to the keyframe timestamp
4645  * of indexed stream. Only called in case of Reverse Playback
4646  */
4647 static GstFlowReturn
4648 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4649 {
4650   guint32 seg_idx = 0, k_index = 0;
4651   guint32 ref_seg_idx, ref_k_index;
4652   GstClockTime k_pos = 0, last_stop = 0;
4653   QtDemuxSegment *seg = NULL;
4654   QtDemuxStream *ref_str = NULL;
4655   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4656   guint64 target_ts;
4657   gint i;
4658
4659   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4660    * and finally align all the other streams on that timestamp with their
4661    * respective keyframes */
4662   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4663     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4664
4665     /* No candidate yet, take the first stream */
4666     if (!ref_str) {
4667       ref_str = str;
4668       continue;
4669     }
4670
4671     /* So that stream has a segment, we prefer video streams */
4672     if (str->subtype == FOURCC_vide) {
4673       ref_str = str;
4674       break;
4675     }
4676   }
4677
4678   if (G_UNLIKELY (!ref_str)) {
4679     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4680     goto eos;
4681   }
4682
4683   if (G_UNLIKELY (!ref_str->from_sample)) {
4684     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4685     goto eos;
4686   }
4687
4688   /* So that stream has been playing from from_sample to to_sample. We will
4689    * get the timestamp of the previous sample and search for a keyframe before
4690    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4691   if (ref_str->subtype == FOURCC_vide) {
4692     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4693         ref_str->from_sample - 1, FALSE);
4694   } else {
4695     if (ref_str->from_sample >= 10)
4696       k_index = ref_str->from_sample - 10;
4697     else
4698       k_index = 0;
4699   }
4700
4701   target_ts =
4702       ref_str->samples[k_index].timestamp +
4703       ref_str->samples[k_index].pts_offset;
4704
4705   /* get current segment for that stream */
4706   seg = &ref_str->segments[ref_str->segment_index];
4707   /* Use segment start in original timescale for comparisons */
4708   seg_media_start_mov = seg->trak_media_start;
4709
4710   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4711       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4712       k_index, target_ts, seg_media_start_mov,
4713       GST_TIME_ARGS (seg->media_start));
4714
4715   /* Crawl back through segments to find the one containing this I frame */
4716   while (target_ts < seg_media_start_mov) {
4717     GST_DEBUG_OBJECT (qtdemux,
4718         "keyframe position (sample %u) is out of segment %u " " target %"
4719         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4720         ref_str->segment_index, target_ts, seg_media_start_mov);
4721
4722     if (G_UNLIKELY (!ref_str->segment_index)) {
4723       /* Reached first segment, let's consider it's EOS */
4724       goto eos;
4725     }
4726     ref_str->segment_index--;
4727     seg = &ref_str->segments[ref_str->segment_index];
4728     /* Use segment start in original timescale for comparisons */
4729     seg_media_start_mov = seg->trak_media_start;
4730   }
4731   /* Calculate time position of the keyframe and where we should stop */
4732   k_pos =
4733       QTSTREAMTIME_TO_GSTTIME (ref_str,
4734       target_ts - seg->trak_media_start) + seg->time;
4735   last_stop =
4736       QTSTREAMTIME_TO_GSTTIME (ref_str,
4737       ref_str->samples[ref_str->from_sample].timestamp -
4738       seg->trak_media_start) + seg->time;
4739
4740   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4741       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4742       k_index, GST_TIME_ARGS (k_pos));
4743
4744   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4745   qtdemux->segment.position = last_stop;
4746   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4747       GST_TIME_ARGS (last_stop));
4748
4749   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4750     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4751     goto eos;
4752   }
4753
4754   ref_seg_idx = ref_str->segment_index;
4755   ref_k_index = k_index;
4756
4757   /* Align them all on this */
4758   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4759     guint32 index = 0;
4760     GstClockTime seg_time = 0;
4761     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4762
4763     /* aligning reference stream again might lead to backing up to yet another
4764      * keyframe (due to timestamp rounding issues),
4765      * potentially putting more load on downstream; so let's try to avoid */
4766     if (str == ref_str) {
4767       seg_idx = ref_seg_idx;
4768       seg = &str->segments[seg_idx];
4769       k_index = ref_k_index;
4770       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4771           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4772     } else {
4773       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4774       GST_DEBUG_OBJECT (qtdemux,
4775           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4776           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4777
4778       /* get segment and time in the segment */
4779       seg = &str->segments[seg_idx];
4780       seg_time = k_pos - seg->time;
4781
4782       /* get the media time in the segment.
4783        * No adjustment for empty "filler" segments */
4784       if (seg->media_start != GST_CLOCK_TIME_NONE)
4785         seg_time += seg->media_start;
4786
4787       /* get the index of the sample with media time */
4788       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4789       GST_DEBUG_OBJECT (qtdemux,
4790           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4791           GST_TIME_ARGS (seg_time), index);
4792
4793       /* find previous keyframe */
4794       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4795     }
4796
4797     /* Remember until where we want to go */
4798     str->to_sample = str->from_sample - 1;
4799     /* Define our time position */
4800     target_ts =
4801         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4802     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4803     if (seg->media_start != GST_CLOCK_TIME_NONE)
4804       str->time_position -= seg->media_start;
4805
4806     /* Now seek back in time */
4807     gst_qtdemux_move_stream (qtdemux, str, k_index);
4808     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4809         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4810         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4811   }
4812
4813   return GST_FLOW_OK;
4814
4815 eos:
4816   return GST_FLOW_EOS;
4817 }
4818
4819 /*
4820  * Gets the current qt segment start, stop and position for the
4821  * given time offset. This is used in update_segment()
4822  */
4823 static void
4824 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4825     QtDemuxStream * stream, GstClockTime offset,
4826     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4827 {
4828   GstClockTime seg_time;
4829   GstClockTime start, stop, time;
4830   QtDemuxSegment *segment;
4831
4832   segment = &stream->segments[stream->segment_index];
4833
4834   /* get time in this segment */
4835   seg_time = (offset - segment->time) * segment->rate;
4836
4837   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4838       GST_TIME_ARGS (seg_time));
4839
4840   if (G_UNLIKELY (seg_time > segment->duration)) {
4841     GST_LOG_OBJECT (stream->pad,
4842         "seg_time > segment->duration %" GST_TIME_FORMAT,
4843         GST_TIME_ARGS (segment->duration));
4844     seg_time = segment->duration;
4845   }
4846
4847   /* qtdemux->segment.stop is in outside-time-realm, whereas
4848    * segment->media_stop is in track-time-realm.
4849    *
4850    * In order to compare the two, we need to bring segment.stop
4851    * into the track-time-realm
4852    *
4853    * FIXME - does this comment still hold? Don't see any conversion here */
4854
4855   stop = qtdemux->segment.stop;
4856   if (stop == GST_CLOCK_TIME_NONE)
4857     stop = qtdemux->segment.duration;
4858   if (stop == GST_CLOCK_TIME_NONE)
4859     stop = segment->media_stop;
4860   else
4861     stop =
4862         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4863
4864   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4865     start = segment->time + seg_time;
4866     time = offset;
4867     stop = start - seg_time + segment->duration;
4868   } else if (qtdemux->segment.rate >= 0) {
4869     start = MIN (segment->media_start + seg_time, stop);
4870     time = offset;
4871   } else {
4872     if (segment->media_start >= qtdemux->segment.start) {
4873       time = segment->time;
4874     } else {
4875       time = segment->time + (qtdemux->segment.start - segment->media_start);
4876     }
4877
4878     start = MAX (segment->media_start, qtdemux->segment.start);
4879     stop = MIN (segment->media_start + seg_time, stop);
4880   }
4881
4882   *_start = start;
4883   *_stop = stop;
4884   *_time = time;
4885 }
4886
4887 /*
4888  * Updates the qt segment used for the stream and pushes a new segment event
4889  * downstream on this stream's pad.
4890  */
4891 static gboolean
4892 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4893     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4894     GstClockTime * _stop)
4895 {
4896   QtDemuxSegment *segment;
4897   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4898   gdouble rate;
4899   GstEvent *event;
4900
4901   /* update the current segment */
4902   stream->segment_index = seg_idx;
4903
4904   /* get the segment */
4905   segment = &stream->segments[seg_idx];
4906
4907   if (G_UNLIKELY (offset < segment->time)) {
4908     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4909         GST_TIME_ARGS (segment->time));
4910     return FALSE;
4911   }
4912
4913   /* segment lies beyond total indicated duration */
4914   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4915           segment->time > qtdemux->segment.duration)) {
4916     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4917         " < segment->time %" GST_TIME_FORMAT,
4918         GST_TIME_ARGS (qtdemux->segment.duration),
4919         GST_TIME_ARGS (segment->time));
4920     return FALSE;
4921   }
4922
4923   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4924       &start, &stop, &time);
4925
4926   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4927       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4928       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4929
4930   /* combine global rate with that of the segment */
4931   rate = segment->rate * qtdemux->segment.rate;
4932
4933   /* Copy flags from main segment */
4934   stream->segment.flags = qtdemux->segment.flags;
4935
4936   /* update the segment values used for clipping */
4937   stream->segment.offset = qtdemux->segment.offset;
4938   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4939   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4940   stream->segment.rate = rate;
4941   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4942       stream->cslg_shift);
4943   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4944       stream->cslg_shift);
4945   stream->segment.time = time;
4946   stream->segment.position = stream->segment.start;
4947
4948   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4949       &stream->segment);
4950
4951   /* now prepare and send the segment */
4952   if (stream->pad) {
4953     event = gst_event_new_segment (&stream->segment);
4954     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4955       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4956     }
4957     gst_pad_push_event (stream->pad, event);
4958     /* assume we can send more data now */
4959     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4960     /* clear to send tags on this pad now */
4961     gst_qtdemux_push_tags (qtdemux, stream);
4962   }
4963
4964   if (_start)
4965     *_start = start;
4966   if (_stop)
4967     *_stop = stop;
4968
4969   return TRUE;
4970 }
4971
4972 /* activate the given segment number @seg_idx of @stream at time @offset.
4973  * @offset is an absolute global position over all the segments.
4974  *
4975  * This will push out a NEWSEGMENT event with the right values and
4976  * position the stream index to the first decodable sample before
4977  * @offset.
4978  */
4979 static gboolean
4980 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4981     guint32 seg_idx, GstClockTime offset)
4982 {
4983   QtDemuxSegment *segment;
4984   guint32 index, kf_index;
4985   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4986
4987   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4988       seg_idx, GST_TIME_ARGS (offset));
4989
4990   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4991           &start, &stop))
4992     return FALSE;
4993
4994   segment = &stream->segments[stream->segment_index];
4995
4996   /* in the fragmented case, we pick a fragment that starts before our
4997    * desired position and rely on downstream to wait for a keyframe
4998    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4999    * tfra entries tells us which trun/sample the key unit is in, but we don't
5000    * make use of this additional information at the moment) */
5001   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5002     stream->to_sample = G_MAXUINT32;
5003     return TRUE;
5004   } else {
5005     /* well, it will be taken care of below */
5006     qtdemux->fragmented_seek_pending = FALSE;
5007     /* FIXME ideally the do_fragmented_seek can be done right here,
5008      * rather than at loop level
5009      * (which might even allow handling edit lists in a fragmented file) */
5010   }
5011
5012   /* We don't need to look for a sample in push-based */
5013   if (!qtdemux->pullbased)
5014     return TRUE;
5015
5016   /* and move to the keyframe before the indicated media time of the
5017    * segment */
5018   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5019     if (qtdemux->segment.rate >= 0) {
5020       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5021       stream->to_sample = G_MAXUINT32;
5022       GST_DEBUG_OBJECT (stream->pad,
5023           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5024           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5025           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5026     } else {
5027       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5028       stream->to_sample = index;
5029       GST_DEBUG_OBJECT (stream->pad,
5030           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5031           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5032           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5033     }
5034   } else {
5035     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5036         "this is an empty segment");
5037     return TRUE;
5038   }
5039
5040   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5041    * encountered an error and printed a message so we return appropriately */
5042   if (index == -1)
5043     return FALSE;
5044
5045   /* we're at the right spot */
5046   if (index == stream->sample_index) {
5047     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5048     return TRUE;
5049   }
5050
5051   /* find keyframe of the target index */
5052   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5053
5054   /* go back two frames to provide lead-in for non-raw audio decoders */
5055   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5056     guint32 lead_in = 2;
5057     guint32 old_index = kf_index;
5058     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5059
5060     if (gst_structure_has_name (s, "audio/mpeg")) {
5061       gint mpegversion;
5062       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5063           && mpegversion == 1) {
5064         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5065         lead_in = 30;
5066       }
5067     }
5068
5069     kf_index = MAX (kf_index, lead_in) - lead_in;
5070     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5071       GST_DEBUG_OBJECT (stream->pad,
5072           "Moving backwards %u frames to ensure sufficient sound lead-in",
5073           old_index - kf_index);
5074     } else {
5075       kf_index = old_index;
5076     }
5077   }
5078
5079   /* if we move forwards, we don't have to go back to the previous
5080    * keyframe since we already sent that. We can also just jump to
5081    * the keyframe right before the target index if there is one. */
5082   if (index > stream->sample_index) {
5083     /* moving forwards check if we move past a keyframe */
5084     if (kf_index > stream->sample_index) {
5085       GST_DEBUG_OBJECT (stream->pad,
5086           "moving forwards to keyframe at %u "
5087           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5088           kf_index,
5089           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5090           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5091       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5092     } else {
5093       GST_DEBUG_OBJECT (stream->pad,
5094           "moving forwards, keyframe at %u "
5095           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5096           kf_index,
5097           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5098           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5099     }
5100   } else {
5101     GST_DEBUG_OBJECT (stream->pad,
5102         "moving backwards to %sframe at %u "
5103         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5104         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5105         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5106         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5107     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5108   }
5109
5110   return TRUE;
5111 }
5112
5113 /* prepare to get the current sample of @stream, getting essential values.
5114  *
5115  * This function will also prepare and send the segment when needed.
5116  *
5117  * Return FALSE if the stream is EOS.
5118  *
5119  * PULL-BASED
5120  */
5121 static gboolean
5122 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5123     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5124     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5125     gboolean * keyframe)
5126 {
5127   QtDemuxSample *sample;
5128   GstClockTime time_position;
5129   guint32 seg_idx;
5130
5131   g_return_val_if_fail (stream != NULL, FALSE);
5132
5133   time_position = stream->time_position;
5134   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5135     goto eos;
5136
5137   seg_idx = stream->segment_index;
5138   if (G_UNLIKELY (seg_idx == -1)) {
5139     /* find segment corresponding to time_position if we are looking
5140      * for a segment. */
5141     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5142   }
5143
5144   /* different segment, activate it, sample_index will be set. */
5145   if (G_UNLIKELY (stream->segment_index != seg_idx))
5146     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5147
5148   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5149               segments[stream->segment_index]))) {
5150     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5151
5152     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5153         " prepare empty sample");
5154
5155     *empty = TRUE;
5156     *pts = *dts = time_position;
5157     *duration = seg->duration - (time_position - seg->time);
5158
5159     return TRUE;
5160   }
5161
5162   *empty = FALSE;
5163
5164   if (stream->sample_index == -1)
5165     stream->sample_index = 0;
5166
5167   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5168       stream->sample_index, stream->n_samples);
5169
5170   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5171     if (!qtdemux->fragmented)
5172       goto eos;
5173
5174     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5175     do {
5176       GstFlowReturn flow;
5177
5178       GST_OBJECT_LOCK (qtdemux);
5179       flow = qtdemux_add_fragmented_samples (qtdemux);
5180       GST_OBJECT_UNLOCK (qtdemux);
5181
5182       if (flow != GST_FLOW_OK)
5183         goto eos;
5184     }
5185     while (stream->sample_index >= stream->n_samples);
5186   }
5187
5188   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5189     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5190         stream->sample_index);
5191     return FALSE;
5192   }
5193
5194   /* now get the info for the sample we're at */
5195   sample = &stream->samples[stream->sample_index];
5196
5197   *dts = QTSAMPLE_DTS (stream, sample);
5198   *pts = QTSAMPLE_PTS (stream, sample);
5199   *offset = sample->offset;
5200   *size = sample->size;
5201   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5202   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5203
5204   return TRUE;
5205
5206   /* special cases */
5207 eos:
5208   {
5209     stream->time_position = GST_CLOCK_TIME_NONE;
5210     return FALSE;
5211   }
5212 }
5213
5214 /* move to the next sample in @stream.
5215  *
5216  * Moves to the next segment when needed.
5217  */
5218 static void
5219 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5220 {
5221   QtDemuxSample *sample;
5222   QtDemuxSegment *segment;
5223
5224   /* get current segment */
5225   segment = &stream->segments[stream->segment_index];
5226
5227   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5228     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5229     goto next_segment;
5230   }
5231
5232   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5233     /* Mark the stream as EOS */
5234     GST_DEBUG_OBJECT (qtdemux,
5235         "reached max allowed sample %u, mark EOS", stream->to_sample);
5236     stream->time_position = GST_CLOCK_TIME_NONE;
5237     return;
5238   }
5239
5240   /* move to next sample */
5241   stream->sample_index++;
5242   stream->offset_in_sample = 0;
5243
5244   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5245       stream->n_samples);
5246
5247   /* reached the last sample, we need the next segment */
5248   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5249     goto next_segment;
5250
5251   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5252     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5253         stream->sample_index);
5254     return;
5255   }
5256
5257   /* get next sample */
5258   sample = &stream->samples[stream->sample_index];
5259
5260   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5261       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5262       GST_TIME_ARGS (segment->media_stop));
5263
5264   /* see if we are past the segment */
5265   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5266     goto next_segment;
5267
5268   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5269     /* inside the segment, update time_position, looks very familiar to
5270      * GStreamer segments, doesn't it? */
5271     stream->time_position =
5272         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5273   } else {
5274     /* not yet in segment, time does not yet increment. This means
5275      * that we are still prerolling keyframes to the decoder so it can
5276      * decode the first sample of the segment. */
5277     stream->time_position = segment->time;
5278   }
5279   return;
5280
5281   /* move to the next segment */
5282 next_segment:
5283   {
5284     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5285
5286     if (stream->segment_index == stream->n_segments - 1) {
5287       /* are we at the end of the last segment, we're EOS */
5288       stream->time_position = GST_CLOCK_TIME_NONE;
5289     } else {
5290       /* else we're only at the end of the current segment */
5291       stream->time_position = segment->stop_time;
5292     }
5293     /* make sure we select a new segment */
5294
5295     /* accumulate previous segments */
5296     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5297       stream->accumulated_base +=
5298           (stream->segment.stop -
5299           stream->segment.start) / ABS (stream->segment.rate);
5300
5301     stream->segment_index = -1;
5302   }
5303 }
5304
5305 static void
5306 gst_qtdemux_sync_streams (GstQTDemux * demux)
5307 {
5308   gint i;
5309
5310   if (QTDEMUX_N_STREAMS (demux) <= 1)
5311     return;
5312
5313   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5314     QtDemuxStream *stream;
5315     GstClockTime end_time;
5316
5317     stream = QTDEMUX_NTH_STREAM (demux, i);
5318
5319     if (!stream->pad)
5320       continue;
5321
5322     /* TODO advance time on subtitle streams here, if any some day */
5323
5324     /* some clips/trailers may have unbalanced streams at the end,
5325      * so send EOS on shorter stream to prevent stalling others */
5326
5327     /* do not mess with EOS if SEGMENT seeking */
5328     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5329       continue;
5330
5331     if (demux->pullbased) {
5332       /* loop mode is sample time based */
5333       if (!STREAM_IS_EOS (stream))
5334         continue;
5335     } else {
5336       /* push mode is byte position based */
5337       if (stream->n_samples &&
5338           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5339         continue;
5340     }
5341
5342     if (stream->sent_eos)
5343       continue;
5344
5345     /* only act if some gap */
5346     end_time = stream->segments[stream->n_segments - 1].stop_time;
5347     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5348         ", stream end: %" GST_TIME_FORMAT,
5349         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5350     if (GST_CLOCK_TIME_IS_VALID (end_time)
5351         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5352       GstEvent *event;
5353
5354       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5355           GST_PAD_NAME (stream->pad));
5356       stream->sent_eos = TRUE;
5357       event = gst_event_new_eos ();
5358       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5359         gst_event_set_seqnum (event, demux->segment_seqnum);
5360       gst_pad_push_event (stream->pad, event);
5361     }
5362   }
5363 }
5364
5365 /* EOS and NOT_LINKED need to be combined. This means that we return:
5366  *
5367  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5368  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5369  */
5370 static GstFlowReturn
5371 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5372     GstFlowReturn ret)
5373 {
5374   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5375
5376   if (stream->pad)
5377     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5378         ret);
5379   else
5380     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5381
5382   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5383   return ret;
5384 }
5385
5386 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5387  * completely clipped
5388  *
5389  * Should be used only with raw buffers */
5390 static GstBuffer *
5391 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5392     GstBuffer * buf)
5393 {
5394   guint64 start, stop, cstart, cstop, diff;
5395   GstClockTime pts, duration;
5396   gsize size, osize;
5397   gint num_rate, denom_rate;
5398   gint frame_size;
5399   gboolean clip_data;
5400   guint offset;
5401
5402   osize = size = gst_buffer_get_size (buf);
5403   offset = 0;
5404
5405   /* depending on the type, setup the clip parameters */
5406   if (stream->subtype == FOURCC_soun) {
5407     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5408     num_rate = GST_SECOND;
5409     denom_rate = (gint) CUR_STREAM (stream)->rate;
5410     clip_data = TRUE;
5411   } else if (stream->subtype == FOURCC_vide) {
5412     frame_size = size;
5413     num_rate = CUR_STREAM (stream)->fps_n;
5414     denom_rate = CUR_STREAM (stream)->fps_d;
5415     clip_data = FALSE;
5416   } else
5417     goto wrong_type;
5418
5419   if (frame_size <= 0)
5420     goto bad_frame_size;
5421
5422   /* we can only clip if we have a valid pts */
5423   pts = GST_BUFFER_PTS (buf);
5424   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5425     goto no_pts;
5426
5427   duration = GST_BUFFER_DURATION (buf);
5428
5429   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5430     duration =
5431         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5432   }
5433
5434   start = pts;
5435   stop = start + duration;
5436
5437   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5438               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5439     goto clipped;
5440
5441   /* see if some clipping happened */
5442   diff = cstart - start;
5443   if (diff > 0) {
5444     pts += diff;
5445     duration -= diff;
5446
5447     if (clip_data) {
5448       /* bring clipped time to samples and to bytes */
5449       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5450       diff *= frame_size;
5451
5452       GST_DEBUG_OBJECT (qtdemux,
5453           "clipping start to %" GST_TIME_FORMAT " %"
5454           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5455
5456       offset = diff;
5457       size -= diff;
5458     }
5459   }
5460   diff = stop - cstop;
5461   if (diff > 0) {
5462     duration -= diff;
5463
5464     if (clip_data) {
5465       /* bring clipped time to samples and then to bytes */
5466       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5467       diff *= frame_size;
5468       GST_DEBUG_OBJECT (qtdemux,
5469           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5470           " bytes", GST_TIME_ARGS (cstop), diff);
5471       size -= diff;
5472     }
5473   }
5474
5475   if (offset != 0 || size != osize)
5476     gst_buffer_resize (buf, offset, size);
5477
5478   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5479   GST_BUFFER_PTS (buf) = pts;
5480   GST_BUFFER_DURATION (buf) = duration;
5481
5482   return buf;
5483
5484   /* dropped buffer */
5485 wrong_type:
5486   {
5487     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5488     return buf;
5489   }
5490 bad_frame_size:
5491   {
5492     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5493     return buf;
5494   }
5495 no_pts:
5496   {
5497     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5498     return buf;
5499   }
5500 clipped:
5501   {
5502     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5503     gst_buffer_unref (buf);
5504     return NULL;
5505   }
5506 }
5507
5508 static GstBuffer *
5509 gst_qtdemux_align_buffer (GstQTDemux * demux,
5510     GstBuffer * buffer, gsize alignment)
5511 {
5512   GstMapInfo map;
5513
5514   gst_buffer_map (buffer, &map, GST_MAP_READ);
5515
5516   if (map.size < sizeof (guintptr)) {
5517     gst_buffer_unmap (buffer, &map);
5518     return buffer;
5519   }
5520
5521   if (((guintptr) map.data) & (alignment - 1)) {
5522     GstBuffer *new_buffer;
5523     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5524
5525     new_buffer = gst_buffer_new_allocate (NULL,
5526         gst_buffer_get_size (buffer), &params);
5527
5528     /* Copy data "by hand", so ensure alignment is kept: */
5529     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5530
5531     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5532     GST_DEBUG_OBJECT (demux,
5533         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5534         alignment);
5535
5536     gst_buffer_unmap (buffer, &map);
5537     gst_buffer_unref (buffer);
5538
5539     return new_buffer;
5540   }
5541
5542   gst_buffer_unmap (buffer, &map);
5543   return buffer;
5544 }
5545
5546 static guint8 *
5547 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5548     gsize * res)
5549 {
5550   guint8 *storage;
5551   gsize i;
5552
5553   /* We are converting from pairs to triplets */
5554   *res = ccpair_size / 2 * 3;
5555   storage = g_malloc (*res);
5556   for (i = 0; i * 2 < ccpair_size; i += 1) {
5557     /* FIXME: Use line offset 0 as we simply can't know here */
5558     if (field == 1)
5559       storage[i * 3] = 0x80 | 0x00;
5560     else
5561       storage[i * 3] = 0x00 | 0x00;
5562     storage[i * 3 + 1] = ccpair[i * 2];
5563     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5564   }
5565
5566   return storage;
5567 }
5568
5569 static guint8 *
5570 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5571     gsize * cclen)
5572 {
5573   guint8 *res = NULL;
5574   guint32 atom_length, fourcc;
5575   QtDemuxStreamStsdEntry *stsd_entry;
5576
5577   GST_MEMDUMP ("caption atom", data, size);
5578
5579   /* There might be multiple atoms */
5580
5581   *cclen = 0;
5582   if (size < 8)
5583     goto invalid_cdat;
5584   atom_length = QT_UINT32 (data);
5585   fourcc = QT_FOURCC (data + 4);
5586   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5587     goto invalid_cdat;
5588
5589   GST_DEBUG_OBJECT (stream->pad, "here");
5590
5591   /* Check if we have something compatible */
5592   stsd_entry = CUR_STREAM (stream);
5593   switch (stsd_entry->fourcc) {
5594     case FOURCC_c608:{
5595       guint8 *cdat = NULL, *cdt2 = NULL;
5596       gsize cdat_size = 0, cdt2_size = 0;
5597       /* Should be cdat or cdt2 */
5598       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5599         GST_WARNING_OBJECT (stream->pad,
5600             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5601             GST_FOURCC_ARGS (fourcc));
5602         goto invalid_cdat;
5603       }
5604
5605       /* Convert to S334-1 Annex A byte triplet */
5606       if (fourcc == FOURCC_cdat)
5607         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5608       else
5609         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5610       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5611           size, atom_length);
5612
5613       /* Check for another atom ? */
5614       if (size > atom_length + 8) {
5615         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5616         if (size >= atom_length + new_atom_length) {
5617           fourcc = QT_FOURCC (data + atom_length + 4);
5618           if (fourcc == FOURCC_cdat) {
5619             if (cdat == NULL)
5620               cdat =
5621                   convert_to_s334_1a (data + atom_length + 8,
5622                   new_atom_length - 8, 1, &cdat_size);
5623             else
5624               GST_WARNING_OBJECT (stream->pad,
5625                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5626           } else {
5627             if (cdt2 == NULL)
5628               cdt2 =
5629                   convert_to_s334_1a (data + atom_length + 8,
5630                   new_atom_length - 8, 2, &cdt2_size);
5631             else
5632               GST_WARNING_OBJECT (stream->pad,
5633                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5634           }
5635         }
5636       }
5637
5638       *cclen = cdat_size + cdt2_size;
5639       res = g_malloc (*cclen);
5640       if (cdat_size)
5641         memcpy (res, cdat, cdat_size);
5642       if (cdt2_size)
5643         memcpy (res + cdat_size, cdt2, cdt2_size);
5644       g_free (cdat);
5645       g_free (cdt2);
5646     }
5647       break;
5648     case FOURCC_c708:
5649       if (fourcc != FOURCC_ccdp) {
5650         GST_WARNING_OBJECT (stream->pad,
5651             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5652             GST_FOURCC_ARGS (fourcc));
5653         goto invalid_cdat;
5654       }
5655       *cclen = atom_length - 8;
5656       res = g_memdup2 (data + 8, *cclen);
5657       break;
5658     default:
5659       /* Keep this here in case other closed caption formats are added */
5660       g_assert_not_reached ();
5661       break;
5662   }
5663
5664   GST_MEMDUMP ("Output", res, *cclen);
5665   return res;
5666
5667   /* Errors */
5668 invalid_cdat:
5669   GST_WARNING ("[cdat] atom is too small or invalid");
5670   return NULL;
5671 }
5672
5673 /* Handle Closed Caption sample buffers.
5674  * The input buffer metadata must be writable,
5675  * but time/duration etc not yet set and need not be preserved */
5676 static GstBuffer *
5677 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5678     GstBuffer * buf)
5679 {
5680   GstBuffer *outbuf = NULL;
5681   GstMapInfo map;
5682   guint8 *cc;
5683   gsize cclen = 0;
5684
5685   gst_buffer_map (buf, &map, GST_MAP_READ);
5686
5687   /* empty buffer is sent to terminate previous subtitle */
5688   if (map.size <= 2) {
5689     gst_buffer_unmap (buf, &map);
5690     gst_buffer_unref (buf);
5691     return NULL;
5692   }
5693
5694   /* For closed caption, we need to extract the information from the
5695    * [cdat],[cdt2] or [ccdp] atom */
5696   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5697   gst_buffer_unmap (buf, &map);
5698   if (cc) {
5699     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5700     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5701   } else {
5702     /* Conversion failed or there's nothing */
5703   }
5704   gst_buffer_unref (buf);
5705
5706   return outbuf;
5707 }
5708
5709 /* DVD subpicture specific sample handling.
5710  * the input buffer metadata must be writable,
5711  * but time/duration etc not yet set and need not be preserved */
5712 static GstBuffer *
5713 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5714     GstBuffer * buf)
5715 {
5716   /* send a one time dvd clut event */
5717   if (stream->pending_event && stream->pad)
5718     gst_pad_push_event (stream->pad, stream->pending_event);
5719   stream->pending_event = NULL;
5720
5721   /* empty buffer is sent to terminate previous subtitle */
5722   if (gst_buffer_get_size (buf) <= 2) {
5723     gst_buffer_unref (buf);
5724     return NULL;
5725   }
5726
5727   /* That's all the processing needed for subpictures */
5728   return buf;
5729 }
5730
5731 /* Timed text formats
5732  * the input buffer metadata must be writable,
5733  * but time/duration etc not yet set and need not be preserved */
5734 static GstBuffer *
5735 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5736     GstBuffer * buf)
5737 {
5738   GstBuffer *outbuf = NULL;
5739   GstMapInfo map;
5740   guint nsize = 0;
5741   gchar *str;
5742
5743   /* not many cases for now */
5744   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5745           stream->subtype != FOURCC_sbtl)) {
5746     return buf;
5747   }
5748
5749   gst_buffer_map (buf, &map, GST_MAP_READ);
5750
5751   /* empty buffer is sent to terminate previous subtitle */
5752   if (map.size <= 2) {
5753     gst_buffer_unmap (buf, &map);
5754     gst_buffer_unref (buf);
5755     return NULL;
5756   }
5757
5758   nsize = GST_READ_UINT16_BE (map.data);
5759   nsize = MIN (nsize, map.size - 2);
5760
5761   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5762       nsize, map.size);
5763
5764   /* takes care of UTF-8 validation or UTF-16 recognition,
5765    * no other encoding expected */
5766   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5767   gst_buffer_unmap (buf, &map);
5768
5769   if (str) {
5770     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5771     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5772   } else {
5773     /* this should not really happen unless the subtitle is corrupted */
5774   }
5775   gst_buffer_unref (buf);
5776
5777   /* FIXME ? convert optional subsequent style info to markup */
5778
5779   return outbuf;
5780 }
5781
5782 /* WebVTT sample handling according to 14496-30 */
5783 static GstBuffer *
5784 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5785     GstBuffer * buf)
5786 {
5787   GstBuffer *outbuf = NULL;
5788   GstMapInfo map;
5789
5790   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5791     g_assert_not_reached ();    /* The buffer must be mappable */
5792   }
5793
5794   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5795     GstEvent *gap = NULL;
5796     /* Push a gap event */
5797     stream->segment.position = GST_BUFFER_PTS (buf);
5798     gap =
5799         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5800     gst_pad_push_event (stream->pad, gap);
5801
5802     if (GST_BUFFER_DURATION_IS_VALID (buf))
5803       stream->segment.position += GST_BUFFER_DURATION (buf);
5804   } else {
5805     outbuf =
5806         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5807         GST_BUFFER_DURATION (buf), map.data, map.size);
5808     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5809   }
5810
5811   gst_buffer_unmap (buf, &map);
5812   gst_buffer_unref (buf);
5813
5814   return outbuf;
5815 }
5816
5817 static GstFlowReturn
5818 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5819     GstBuffer * buf)
5820 {
5821   GstFlowReturn ret = GST_FLOW_OK;
5822   GstClockTime pts, duration;
5823
5824   if (stream->need_clip)
5825     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5826
5827   if (G_UNLIKELY (buf == NULL))
5828     goto exit;
5829
5830   if (G_UNLIKELY (stream->discont)) {
5831     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5832     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5833     stream->discont = FALSE;
5834   } else {
5835     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5836   }
5837
5838   GST_LOG_OBJECT (qtdemux,
5839       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5840       ", duration %" GST_TIME_FORMAT " on pad %s",
5841       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5842       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5843       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5844
5845   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5846     GstStructure *crypto_info;
5847     QtDemuxAavdEncryptionInfo *info =
5848         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5849
5850     crypto_info = gst_structure_copy (info->default_properties);
5851     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5852       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5853   }
5854
5855   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5856           || stream->protection_scheme_type == FOURCC_cbcs)) {
5857     GstStructure *crypto_info;
5858     QtDemuxCencSampleSetInfo *info =
5859         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5860     gint index;
5861     GstEvent *event;
5862
5863     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5864       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5865           GST_PTR_FORMAT, event);
5866       gst_pad_push_event (stream->pad, event);
5867     }
5868
5869     if (info->crypto_info == NULL) {
5870       if (stream->protection_scheme_type == FOURCC_cbcs) {
5871         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5872         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5873           GST_ERROR_OBJECT (qtdemux,
5874               "failed to attach cbcs metadata to buffer");
5875           qtdemux_gst_structure_free (crypto_info);
5876         } else {
5877           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5878         }
5879       } else {
5880         GST_DEBUG_OBJECT (qtdemux,
5881             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5882       }
5883     } else {
5884       /* The end of the crypto_info array matches our n_samples position,
5885        * so count backward from there */
5886       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5887       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5888         /* steal structure from array */
5889         crypto_info = g_ptr_array_index (info->crypto_info, index);
5890         g_ptr_array_index (info->crypto_info, index) = NULL;
5891         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5892             info->crypto_info->len);
5893         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5894           GST_ERROR_OBJECT (qtdemux,
5895               "failed to attach cenc metadata to buffer");
5896       } else {
5897         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5898             index, stream->sample_index);
5899       }
5900     }
5901   }
5902
5903   if (stream->alignment > 1)
5904     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5905
5906   pts = GST_BUFFER_PTS (buf);
5907   duration = GST_BUFFER_DURATION (buf);
5908
5909   ret = gst_pad_push (stream->pad, buf);
5910
5911   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5912     /* mark position in stream, we'll need this to know when to send GAP event */
5913     stream->segment.position = pts + duration;
5914   }
5915
5916 exit:
5917
5918   return ret;
5919 }
5920
5921 static GstFlowReturn
5922 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5923     GstBuffer * buf)
5924 {
5925   GstFlowReturn ret = GST_FLOW_OK;
5926
5927   if (stream->subtype == FOURCC_clcp
5928       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5929     GstMapInfo map;
5930     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5931     guint n_triplets, i;
5932     guint field1_off = 0, field2_off = 0;
5933
5934     /* We have to split CEA608 buffers so that each outgoing buffer contains
5935      * one byte pair per field according to the framerate of the video track.
5936      *
5937      * If there is only a single byte pair per field we don't have to do
5938      * anything
5939      */
5940
5941     gst_buffer_map (buf, &map, GST_MAP_READ);
5942
5943     n_triplets = map.size / 3;
5944     for (i = 0; i < n_triplets; i++) {
5945       if (map.data[3 * i] & 0x80)
5946         n_field1++;
5947       else
5948         n_field2++;
5949     }
5950
5951     g_assert (n_field1 || n_field2);
5952
5953     /* If there's more than 1 frame we have to split, otherwise we can just
5954      * pass through */
5955     if (n_field1 > 1 || n_field2 > 1) {
5956       n_output_buffers =
5957           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5958           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5959
5960       for (i = 0; i < n_output_buffers; i++) {
5961         GstBuffer *outbuf =
5962             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5963         GstMapInfo outmap;
5964         guint8 *outptr;
5965
5966         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5967         outptr = outmap.data;
5968
5969         if (n_field1) {
5970           gboolean found = FALSE;
5971
5972           while (map.data + field1_off < map.data + map.size) {
5973             if (map.data[field1_off] & 0x80) {
5974               memcpy (outptr, &map.data[field1_off], 3);
5975               field1_off += 3;
5976               found = TRUE;
5977               break;
5978             }
5979             field1_off += 3;
5980           }
5981
5982           if (!found) {
5983             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5984
5985             memcpy (outptr, empty, 3);
5986           }
5987
5988           outptr += 3;
5989         }
5990
5991         if (n_field2) {
5992           gboolean found = FALSE;
5993
5994           while (map.data + field2_off < map.data + map.size) {
5995             if ((map.data[field2_off] & 0x80) == 0) {
5996               memcpy (outptr, &map.data[field2_off], 3);
5997               field2_off += 3;
5998               found = TRUE;
5999               break;
6000             }
6001             field2_off += 3;
6002           }
6003
6004           if (!found) {
6005             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6006
6007             memcpy (outptr, empty, 3);
6008           }
6009
6010           outptr += 3;
6011         }
6012
6013         gst_buffer_unmap (outbuf, &outmap);
6014
6015         GST_BUFFER_PTS (outbuf) =
6016             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6017             GST_SECOND * CUR_STREAM (stream)->fps_d,
6018             CUR_STREAM (stream)->fps_n);
6019         GST_BUFFER_DURATION (outbuf) =
6020             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6021             CUR_STREAM (stream)->fps_n);
6022         GST_BUFFER_OFFSET (outbuf) = -1;
6023         GST_BUFFER_OFFSET_END (outbuf) = -1;
6024
6025         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6026
6027         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6028           break;
6029       }
6030       gst_buffer_unmap (buf, &map);
6031       gst_buffer_unref (buf);
6032     } else {
6033       gst_buffer_unmap (buf, &map);
6034       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6035     }
6036   } else {
6037     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6038   }
6039
6040   return ret;
6041 }
6042
6043 /* Sets a buffer's attributes properly and pushes it downstream.
6044  * Also checks for additional actions and custom processing that may
6045  * need to be done first.
6046  */
6047 static GstFlowReturn
6048 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6049     QtDemuxStream * stream, GstBuffer * buf,
6050     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6051     gboolean keyframe, GstClockTime position, guint64 byte_position)
6052 {
6053   GstFlowReturn ret = GST_FLOW_OK;
6054
6055   /* offset the timestamps according to the edit list */
6056
6057   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6058     gchar *url;
6059     GstMapInfo map;
6060
6061     gst_buffer_map (buf, &map, GST_MAP_READ);
6062     url = g_strndup ((gchar *) map.data, map.size);
6063     gst_buffer_unmap (buf, &map);
6064     if (url != NULL && strlen (url) != 0) {
6065       /* we have RTSP redirect now */
6066       g_free (qtdemux->redirect_location);
6067       qtdemux->redirect_location = g_strdup (url);
6068       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6069           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6070               gst_structure_new ("redirect",
6071                   "new-location", G_TYPE_STRING, url, NULL)));
6072     } else {
6073       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6074           "posting");
6075     }
6076     g_free (url);
6077   }
6078
6079   /* position reporting */
6080   if (qtdemux->segment.rate >= 0) {
6081     qtdemux->segment.position = position;
6082     gst_qtdemux_sync_streams (qtdemux);
6083   }
6084
6085   if (G_UNLIKELY (!stream->pad)) {
6086     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6087     gst_buffer_unref (buf);
6088     goto exit;
6089   }
6090
6091   /* send out pending buffers */
6092   while (stream->buffers) {
6093     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6094
6095     if (G_UNLIKELY (stream->discont)) {
6096       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6097       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6098       stream->discont = FALSE;
6099     } else {
6100       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6101     }
6102
6103     if (stream->alignment > 1)
6104       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6105     gst_pad_push (stream->pad, buffer);
6106
6107     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6108   }
6109
6110   /* we're going to modify the metadata */
6111   buf = gst_buffer_make_writable (buf);
6112
6113   GST_BUFFER_DTS (buf) = dts;
6114   GST_BUFFER_PTS (buf) = pts;
6115   GST_BUFFER_DURATION (buf) = duration;
6116   GST_BUFFER_OFFSET (buf) = -1;
6117   GST_BUFFER_OFFSET_END (buf) = -1;
6118
6119   if (G_UNLIKELY (stream->process_func))
6120     buf = stream->process_func (qtdemux, stream, buf);
6121
6122   if (!buf) {
6123     goto exit;
6124   }
6125
6126   if (!keyframe) {
6127     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6128     stream->on_keyframe = FALSE;
6129   } else {
6130     stream->on_keyframe = TRUE;
6131   }
6132
6133   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6134     gst_buffer_append_memory (buf,
6135         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6136
6137   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6138     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6139   }
6140 #if 0
6141   if (G_UNLIKELY (qtdemux->element_index)) {
6142     GstClockTime stream_time;
6143
6144     stream_time =
6145         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6146         timestamp);
6147     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6148       GST_LOG_OBJECT (qtdemux,
6149           "adding association %" GST_TIME_FORMAT "-> %"
6150           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6151       gst_index_add_association (qtdemux->element_index,
6152           qtdemux->index_id,
6153           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6154           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6155           GST_FORMAT_BYTES, byte_position, NULL);
6156     }
6157   }
6158 #endif
6159
6160   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6161
6162 exit:
6163   return ret;
6164 }
6165
6166 static const QtDemuxRandomAccessEntry *
6167 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6168     GstClockTime pos, gboolean after)
6169 {
6170   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6171   guint n_entries = stream->n_ra_entries;
6172   guint i;
6173
6174   /* we assume the table is sorted */
6175   for (i = 0; i < n_entries; ++i) {
6176     if (entries[i].ts > pos)
6177       break;
6178   }
6179
6180   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6181    * probably okay to assume that the index lists the very first fragment */
6182   if (i == 0)
6183     return &entries[0];
6184
6185   if (after)
6186     return &entries[i];
6187   else
6188     return &entries[i - 1];
6189 }
6190
6191 static gboolean
6192 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6193 {
6194   const QtDemuxRandomAccessEntry *best_entry = NULL;
6195   gint i;
6196
6197   GST_OBJECT_LOCK (qtdemux);
6198
6199   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6200
6201   /* first see if we can determine where to go to using mfra,
6202    * before we start clearing things */
6203   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6204     const QtDemuxRandomAccessEntry *entry;
6205     QtDemuxStream *stream;
6206     gboolean is_audio_or_video;
6207
6208     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6209
6210     if (stream->ra_entries == NULL)
6211       continue;
6212
6213     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6214       is_audio_or_video = TRUE;
6215     else
6216       is_audio_or_video = FALSE;
6217
6218     entry =
6219         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6220         stream->time_position, !is_audio_or_video);
6221
6222     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6223         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6224
6225     stream->pending_seek = entry;
6226
6227     /* decide position to jump to just based on audio/video tracks, not subs */
6228     if (!is_audio_or_video)
6229       continue;
6230
6231     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6232       best_entry = entry;
6233   }
6234
6235   /* no luck, will handle seek otherwise */
6236   if (best_entry == NULL) {
6237     GST_OBJECT_UNLOCK (qtdemux);
6238     return FALSE;
6239   }
6240
6241   /* ok, now we can prepare for processing as of located moof */
6242   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6243     QtDemuxStream *stream;
6244
6245     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6246
6247     g_free (stream->samples);
6248     stream->samples = NULL;
6249     stream->n_samples = 0;
6250     stream->stbl_index = -1;    /* no samples have yet been parsed */
6251     stream->sample_index = -1;
6252
6253     if (stream->protection_scheme_info) {
6254       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6255       if (stream->protection_scheme_type == FOURCC_cenc
6256           || stream->protection_scheme_type == FOURCC_cbcs) {
6257         QtDemuxCencSampleSetInfo *info =
6258             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6259         if (info->crypto_info) {
6260           g_ptr_array_free (info->crypto_info, TRUE);
6261           info->crypto_info = NULL;
6262         }
6263       }
6264     }
6265   }
6266
6267   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6268       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6269       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6270       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6271
6272   qtdemux->moof_offset = best_entry->moof_offset;
6273
6274   qtdemux_add_fragmented_samples (qtdemux);
6275
6276   GST_OBJECT_UNLOCK (qtdemux);
6277   return TRUE;
6278 }
6279
6280 static GstFlowReturn
6281 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6282 {
6283   GstFlowReturn ret = GST_FLOW_OK;
6284   GstBuffer *buf = NULL;
6285   QtDemuxStream *stream, *target_stream = NULL;
6286   GstClockTime min_time;
6287   guint64 offset = 0;
6288   GstClockTime dts = GST_CLOCK_TIME_NONE;
6289   GstClockTime pts = GST_CLOCK_TIME_NONE;
6290   GstClockTime duration = 0;
6291   gboolean keyframe = FALSE;
6292   guint sample_size = 0;
6293   guint num_samples = 1;
6294   gboolean empty = 0;
6295   guint size;
6296   gint i;
6297
6298   if (qtdemux->fragmented_seek_pending) {
6299     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6300     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6301       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6302       qtdemux->fragmented_seek_pending = FALSE;
6303     } else {
6304       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6305     }
6306   }
6307
6308   /* Figure out the next stream sample to output, min_time is expressed in
6309    * global time and runs over the edit list segments. */
6310   min_time = G_MAXUINT64;
6311   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6312     GstClockTime position;
6313
6314     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6315     position = stream->time_position;
6316
6317     if (!GST_CLOCK_TIME_IS_VALID (position))
6318       continue;
6319
6320     if (stream->segment_index != -1) {
6321       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6322       position += segment->media_start;
6323     }
6324
6325     /* position of -1 is EOS */
6326     if (position < min_time) {
6327       min_time = position;
6328       target_stream = stream;
6329     }
6330   }
6331   /* all are EOS */
6332   if (G_UNLIKELY (target_stream == NULL)) {
6333     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6334     goto eos;
6335   }
6336
6337   /* check for segment end */
6338   if (G_UNLIKELY (qtdemux->segment.stop != -1
6339           && qtdemux->segment.rate >= 0
6340           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6341     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6342     target_stream->time_position = GST_CLOCK_TIME_NONE;
6343     goto eos_stream;
6344   }
6345
6346   /* gap events for subtitle streams */
6347   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6348     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6349     if (stream->pad) {
6350       GstClockTime gap_threshold;
6351
6352       /* Only send gap events on non-subtitle streams if lagging way behind. */
6353       if (stream->subtype == FOURCC_subp
6354           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6355           stream->subtype == FOURCC_wvtt)
6356         gap_threshold = 1 * GST_SECOND;
6357       else
6358         gap_threshold = 3 * GST_SECOND;
6359
6360       /* send gap events until the stream catches up */
6361       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6362       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6363           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6364           stream->segment.position + gap_threshold < min_time) {
6365         GstEvent *gap =
6366             gst_event_new_gap (stream->segment.position, gap_threshold);
6367         gst_pad_push_event (stream->pad, gap);
6368         stream->segment.position += gap_threshold;
6369       }
6370     }
6371   }
6372
6373   stream = target_stream;
6374   /* fetch info for the current sample of this stream */
6375   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6376               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6377     goto eos_stream;
6378
6379   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6380   if (stream->new_caps) {
6381     gst_qtdemux_configure_stream (qtdemux, stream);
6382     qtdemux_do_allocation (stream, qtdemux);
6383   }
6384
6385   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6386   if (G_UNLIKELY (qtdemux->segment.
6387           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6388     if (stream->subtype == FOURCC_vide) {
6389       if (!keyframe) {
6390         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6391             stream->track_id);
6392         goto next;
6393       } else if (qtdemux->trickmode_interval > 0) {
6394         GstClockTimeDiff interval;
6395
6396         if (qtdemux->segment.rate > 0)
6397           interval = stream->time_position - stream->last_keyframe_dts;
6398         else
6399           interval = stream->last_keyframe_dts - stream->time_position;
6400
6401         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6402             && interval < qtdemux->trickmode_interval) {
6403           GST_LOG_OBJECT (qtdemux,
6404               "Skipping keyframe within interval on track-id %u",
6405               stream->track_id);
6406           goto next;
6407         } else {
6408           stream->last_keyframe_dts = stream->time_position;
6409         }
6410       }
6411     }
6412   }
6413
6414   GST_DEBUG_OBJECT (qtdemux,
6415       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6416       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6417       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6418       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6419       GST_TIME_ARGS (duration));
6420
6421   if (G_UNLIKELY (empty)) {
6422     /* empty segment, push a gap if there's a second or more
6423      * difference and move to the next one */
6424     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6425       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6426     stream->segment.position = pts + duration;
6427     goto next;
6428   }
6429
6430   /* hmm, empty sample, skip and move to next sample */
6431   if (G_UNLIKELY (sample_size <= 0))
6432     goto next;
6433
6434   /* last pushed sample was out of boundary, goto next sample */
6435   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6436     goto next;
6437
6438   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6439     GST_DEBUG_OBJECT (qtdemux,
6440         "size %d larger than stream max_buffer_size %d, trimming",
6441         sample_size, stream->max_buffer_size);
6442     size =
6443         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6444   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6445       && sample_size < stream->min_buffer_size) {
6446     guint start_sample_index = stream->sample_index;
6447     guint accumulated_size = sample_size;
6448     guint64 expected_next_offset = offset + sample_size;
6449
6450     GST_DEBUG_OBJECT (qtdemux,
6451         "size %d smaller than stream min_buffer_size %d, combining with the next",
6452         sample_size, stream->min_buffer_size);
6453
6454     while (stream->sample_index < stream->to_sample
6455         && stream->sample_index + 1 < stream->n_samples) {
6456       const QtDemuxSample *next_sample;
6457
6458       /* Increment temporarily */
6459       stream->sample_index++;
6460
6461       /* Failed to parse sample so let's go back to the previous one that was
6462        * still successful */
6463       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6464         stream->sample_index--;
6465         break;
6466       }
6467
6468       next_sample = &stream->samples[stream->sample_index];
6469
6470       /* Not contiguous with the previous sample so let's go back to the
6471        * previous one that was still successful */
6472       if (next_sample->offset != expected_next_offset) {
6473         stream->sample_index--;
6474         break;
6475       }
6476
6477       accumulated_size += next_sample->size;
6478       expected_next_offset += next_sample->size;
6479       if (accumulated_size >= stream->min_buffer_size)
6480         break;
6481     }
6482
6483     num_samples = stream->sample_index + 1 - start_sample_index;
6484     stream->sample_index = start_sample_index;
6485     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6486         num_samples, accumulated_size);
6487     size = accumulated_size;
6488   } else {
6489     size = sample_size;
6490   }
6491
6492   if (qtdemux->cenc_aux_info_offset > 0) {
6493     GstMapInfo map;
6494     GstByteReader br;
6495     GstBuffer *aux_info = NULL;
6496
6497     /* pull the data stored before the sample */
6498     ret =
6499         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6500         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6501     if (G_UNLIKELY (ret != GST_FLOW_OK))
6502       goto beach;
6503     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6504     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6505     gst_byte_reader_init (&br, map.data + 8, map.size);
6506     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6507             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6508       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6509       gst_buffer_unmap (aux_info, &map);
6510       gst_buffer_unref (aux_info);
6511       ret = GST_FLOW_ERROR;
6512       goto beach;
6513     }
6514     gst_buffer_unmap (aux_info, &map);
6515     gst_buffer_unref (aux_info);
6516   }
6517
6518   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6519       offset);
6520
6521   if (stream->use_allocator) {
6522     /* if we have a per-stream allocator, use it */
6523     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6524   }
6525
6526   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6527       size, &buf);
6528   if (G_UNLIKELY (ret != GST_FLOW_OK))
6529     goto beach;
6530
6531   /* Update for both splitting and combining of samples */
6532   if (size != sample_size) {
6533     pts += gst_util_uint64_scale_int (GST_SECOND,
6534         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6535         stream->timescale);
6536     dts +=
6537         gst_util_uint64_scale_int (GST_SECOND,
6538         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6539         stream->timescale);
6540     duration =
6541         gst_util_uint64_scale_int (GST_SECOND,
6542         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6543   }
6544
6545   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6546       dts, pts, duration, keyframe, min_time, offset);
6547
6548   if (size < sample_size) {
6549     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6550     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6551
6552     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6553         sample->timestamp +
6554         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6555     if (time_position >= segment->media_start) {
6556       /* inside the segment, update time_position, looks very familiar to
6557        * GStreamer segments, doesn't it? */
6558       stream->time_position = (time_position - segment->media_start) +
6559           segment->time;
6560     } else {
6561       /* not yet in segment, time does not yet increment. This means
6562        * that we are still prerolling keyframes to the decoder so it can
6563        * decode the first sample of the segment. */
6564       stream->time_position = segment->time;
6565     }
6566   } else if (size > sample_size) {
6567     /* Increase to the last sample we already pulled so that advancing
6568      * below brings us to the next sample we need to pull */
6569     stream->sample_index += num_samples - 1;
6570   }
6571
6572   /* combine flows */
6573   GST_OBJECT_LOCK (qtdemux);
6574   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6575   GST_OBJECT_UNLOCK (qtdemux);
6576   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6577    * we have no more data for the pad to push */
6578   if (ret == GST_FLOW_EOS)
6579     ret = GST_FLOW_OK;
6580
6581   stream->offset_in_sample += size;
6582   if (stream->offset_in_sample >= sample_size) {
6583     gst_qtdemux_advance_sample (qtdemux, stream);
6584   }
6585   goto beach;
6586
6587 next:
6588   gst_qtdemux_advance_sample (qtdemux, stream);
6589
6590 beach:
6591   return ret;
6592
6593   /* special cases */
6594 eos:
6595   {
6596     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6597     ret = GST_FLOW_EOS;
6598     goto beach;
6599   }
6600 eos_stream:
6601   {
6602     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6603     /* EOS will be raised if all are EOS */
6604     ret = GST_FLOW_OK;
6605     goto beach;
6606   }
6607 }
6608
6609 static void
6610 gst_qtdemux_loop (GstPad * pad)
6611 {
6612   GstQTDemux *qtdemux;
6613   guint64 cur_offset;
6614   GstFlowReturn ret;
6615
6616   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6617
6618   cur_offset = qtdemux->offset;
6619   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6620       cur_offset, qt_demux_state_string (qtdemux->state));
6621
6622   switch (qtdemux->state) {
6623     case QTDEMUX_STATE_INITIAL:
6624     case QTDEMUX_STATE_HEADER:
6625       ret = gst_qtdemux_loop_state_header (qtdemux);
6626       break;
6627     case QTDEMUX_STATE_MOVIE:
6628       ret = gst_qtdemux_loop_state_movie (qtdemux);
6629       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6630         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6631       }
6632       break;
6633     default:
6634       /* ouch */
6635       goto invalid_state;
6636   }
6637
6638   /* if something went wrong, pause */
6639   if (ret != GST_FLOW_OK)
6640     goto pause;
6641
6642 done:
6643   gst_object_unref (qtdemux);
6644   return;
6645
6646   /* ERRORS */
6647 invalid_state:
6648   {
6649     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6650         (NULL), ("streaming stopped, invalid state"));
6651     gst_pad_pause_task (pad);
6652     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6653     goto done;
6654   }
6655 pause:
6656   {
6657     const gchar *reason = gst_flow_get_name (ret);
6658
6659     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6660
6661     gst_pad_pause_task (pad);
6662
6663     /* fatal errors need special actions */
6664     /* check EOS */
6665     if (ret == GST_FLOW_EOS) {
6666       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6667         /* we have no streams, post an error */
6668         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6669       }
6670       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6671         gint64 stop;
6672
6673         if ((stop = qtdemux->segment.stop) == -1)
6674           stop = qtdemux->segment.duration;
6675
6676         if (qtdemux->segment.rate >= 0) {
6677           GstMessage *message;
6678           GstEvent *event;
6679
6680           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6681           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6682               GST_FORMAT_TIME, stop);
6683           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6684           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6685             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6686             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6687           }
6688           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6689           gst_qtdemux_push_event (qtdemux, event);
6690         } else {
6691           GstMessage *message;
6692           GstEvent *event;
6693
6694           /*  For Reverse Playback */
6695           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6696           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6697               GST_FORMAT_TIME, qtdemux->segment.start);
6698           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6699               qtdemux->segment.start);
6700           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6701             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6702             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6703           }
6704           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6705           gst_qtdemux_push_event (qtdemux, event);
6706         }
6707       } else {
6708         GstEvent *event;
6709
6710         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6711         event = gst_event_new_eos ();
6712         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6713           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6714         gst_qtdemux_push_event (qtdemux, event);
6715       }
6716     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6717       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6718       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6719     }
6720     goto done;
6721   }
6722 }
6723
6724 /*
6725  * has_next_entry
6726  *
6727  * Returns if there are samples to be played.
6728  */
6729 static gboolean
6730 has_next_entry (GstQTDemux * demux)
6731 {
6732   QtDemuxStream *stream;
6733   gint i;
6734
6735   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6736
6737   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6738     stream = QTDEMUX_NTH_STREAM (demux, i);
6739
6740     if (stream->sample_index == -1) {
6741       stream->sample_index = 0;
6742       stream->offset_in_sample = 0;
6743     }
6744
6745     if (stream->sample_index >= stream->n_samples) {
6746       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6747       continue;
6748     }
6749     GST_DEBUG_OBJECT (demux, "Found a sample");
6750     return TRUE;
6751   }
6752
6753   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6754   return FALSE;
6755 }
6756
6757 /*
6758  * next_entry_size
6759  *
6760  * Returns the size of the first entry at the current offset.
6761  * If -1, there are none (which means EOS or empty file).
6762  */
6763 static guint64
6764 next_entry_size (GstQTDemux * demux)
6765 {
6766   QtDemuxStream *stream, *target_stream = NULL;
6767   guint64 smalloffs = (guint64) - 1;
6768   QtDemuxSample *sample;
6769   gint i;
6770
6771   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6772       demux->offset);
6773
6774   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6775     stream = QTDEMUX_NTH_STREAM (demux, i);
6776
6777     if (stream->sample_index == -1) {
6778       stream->sample_index = 0;
6779       stream->offset_in_sample = 0;
6780     }
6781
6782     if (stream->sample_index >= stream->n_samples) {
6783       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6784       continue;
6785     }
6786
6787     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6788       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6789           stream->sample_index);
6790       return -1;
6791     }
6792
6793     sample = &stream->samples[stream->sample_index];
6794
6795     GST_LOG_OBJECT (demux,
6796         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6797         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6798         stream->sample_index, sample->offset, sample->size);
6799
6800     if (((smalloffs == -1)
6801             || (sample->offset < smalloffs)) && (sample->size)) {
6802       smalloffs = sample->offset;
6803       target_stream = stream;
6804     }
6805   }
6806
6807   if (!target_stream)
6808     return -1;
6809
6810   GST_LOG_OBJECT (demux,
6811       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6812       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6813
6814   stream = target_stream;
6815   sample = &stream->samples[stream->sample_index];
6816
6817   if (sample->offset >= demux->offset) {
6818     demux->todrop = sample->offset - demux->offset;
6819     return sample->size + demux->todrop;
6820   }
6821
6822   GST_DEBUG_OBJECT (demux,
6823       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6824   return -1;
6825 }
6826
6827 static void
6828 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6829 {
6830   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6831
6832   gst_element_post_message (GST_ELEMENT_CAST (demux),
6833       gst_message_new_element (GST_OBJECT_CAST (demux),
6834           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6835 }
6836
6837 static gboolean
6838 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6839 {
6840   GstEvent *event;
6841   gboolean res = 0;
6842
6843   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6844
6845   event =
6846       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6847       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6848       GST_SEEK_TYPE_NONE, -1);
6849
6850   /* store seqnum to drop flush events, they don't need to reach downstream */
6851   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6852   res = gst_pad_push_event (demux->sinkpad, event);
6853   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6854
6855   return res;
6856 }
6857
6858 /* check for seekable upstream, above and beyond a mere query */
6859 static void
6860 gst_qtdemux_check_seekability (GstQTDemux * demux)
6861 {
6862   GstQuery *query;
6863   gboolean seekable = FALSE;
6864   gint64 start = -1, stop = -1;
6865
6866   if (demux->upstream_size)
6867     return;
6868
6869   if (demux->upstream_format_is_time)
6870     return;
6871
6872   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6873   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6874     GST_DEBUG_OBJECT (demux, "seeking query failed");
6875     goto done;
6876   }
6877
6878   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6879
6880   /* try harder to query upstream size if we didn't get it the first time */
6881   if (seekable && stop == -1) {
6882     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6883     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6884   }
6885
6886   /* if upstream doesn't know the size, it's likely that it's not seekable in
6887    * practice even if it technically may be seekable */
6888   if (seekable && (start != 0 || stop <= start)) {
6889     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6890     seekable = FALSE;
6891   }
6892
6893 done:
6894   gst_query_unref (query);
6895
6896   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6897       G_GUINT64_FORMAT ")", seekable, start, stop);
6898   demux->upstream_seekable = seekable;
6899   demux->upstream_size = seekable ? stop : -1;
6900 }
6901
6902 static void
6903 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6904 {
6905   g_return_if_fail (bytes <= demux->todrop);
6906
6907   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6908   gst_adapter_flush (demux->adapter, bytes);
6909   demux->neededbytes -= bytes;
6910   demux->offset += bytes;
6911   demux->todrop -= bytes;
6912 }
6913
6914 /* PUSH-MODE only: Send a segment, if not done already. */
6915 static void
6916 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6917 {
6918   if (G_UNLIKELY (demux->need_segment)) {
6919     gint i;
6920
6921     if (!demux->upstream_format_is_time) {
6922       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6923     } else {
6924       GstEvent *segment_event;
6925       segment_event = gst_event_new_segment (&demux->segment);
6926       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6927         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6928       gst_qtdemux_push_event (demux, segment_event);
6929     }
6930
6931     demux->need_segment = FALSE;
6932
6933     /* clear to send tags on all streams */
6934     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6935       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6936       gst_qtdemux_push_tags (demux, stream);
6937       if (CUR_STREAM (stream)->sparse) {
6938         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6939         gst_pad_push_event (stream->pad,
6940             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6941       }
6942     }
6943   }
6944 }
6945
6946 /* Used for push mode only. */
6947 static void
6948 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6949     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6950 {
6951   GstClockTime ts, dur;
6952
6953   ts = pos;
6954   dur =
6955       stream->segments[segment_index].duration - (pos -
6956       stream->segments[segment_index].time);
6957   stream->time_position += dur;
6958
6959   /* Only gaps with a duration of at least one second are propagated.
6960    * Same workaround as in pull mode.
6961    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6962   if (dur >= GST_SECOND) {
6963     GstEvent *gap;
6964     gap = gst_event_new_gap (ts, dur);
6965
6966     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6967         "segment: %" GST_PTR_FORMAT, gap);
6968     gst_pad_push_event (stream->pad, gap);
6969   }
6970 }
6971
6972 static GstFlowReturn
6973 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6974 {
6975   GstQTDemux *demux;
6976
6977   demux = GST_QTDEMUX (parent);
6978
6979   GST_DEBUG_OBJECT (demux,
6980       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6981       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6982       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6983       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6984       gst_buffer_get_size (inbuf), demux->offset);
6985
6986   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6987     gboolean is_gap_input = FALSE;
6988     gint i;
6989
6990     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6991
6992     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6993       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6994     }
6995
6996     /* Check if we can land back on our feet in the case where upstream is
6997      * handling the seeking/pushing of samples with gaps in between (like
6998      * in the case of trick-mode DASH for example) */
6999     if (demux->upstream_format_is_time
7000         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7001       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7002         guint32 res;
7003         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7004         GST_LOG_OBJECT (demux,
7005             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7006             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7007         res =
7008             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7009             stream, GST_BUFFER_OFFSET (inbuf));
7010         if (res != -1) {
7011           QtDemuxSample *sample = &stream->samples[res];
7012           GST_LOG_OBJECT (demux,
7013               "Checking if sample %d from track-id %u is valid (offset:%"
7014               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7015               stream->track_id, sample->offset, sample->size);
7016           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7017             GST_LOG_OBJECT (demux,
7018                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7019                 res);
7020             is_gap_input = TRUE;
7021             /* We can go back to standard playback mode */
7022             demux->state = QTDEMUX_STATE_MOVIE;
7023             /* Remember which sample this stream is at */
7024             stream->sample_index = res;
7025             /* Finally update all push-based values to the expected values */
7026             demux->neededbytes = stream->samples[res].size;
7027             demux->offset = GST_BUFFER_OFFSET (inbuf);
7028             demux->mdatleft =
7029                 demux->mdatsize - demux->offset + demux->mdatoffset;
7030             demux->todrop = 0;
7031           }
7032         }
7033       }
7034       if (!is_gap_input) {
7035         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7036         /* Reset state if it's a real discont */
7037         demux->neededbytes = 16;
7038         demux->state = QTDEMUX_STATE_INITIAL;
7039         demux->offset = GST_BUFFER_OFFSET (inbuf);
7040         gst_adapter_clear (demux->adapter);
7041       }
7042     }
7043     /* Reverse fragmented playback, need to flush all we have before
7044      * consuming a new fragment.
7045      * The samples array have the timestamps calculated by accumulating the
7046      * durations but this won't work for reverse playback of fragments as
7047      * the timestamps of a subsequent fragment should be smaller than the
7048      * previously received one. */
7049     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7050       gst_qtdemux_process_adapter (demux, TRUE);
7051       g_ptr_array_foreach (demux->active_streams,
7052           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7053     }
7054   }
7055
7056   gst_adapter_push (demux->adapter, inbuf);
7057
7058   GST_DEBUG_OBJECT (demux,
7059       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7060       demux->neededbytes, gst_adapter_available (demux->adapter));
7061
7062   return gst_qtdemux_process_adapter (demux, FALSE);
7063 }
7064
7065 static GstFlowReturn
7066 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7067 {
7068   GstFlowReturn ret = GST_FLOW_OK;
7069
7070   /* we never really mean to buffer that much */
7071   if (demux->neededbytes == -1) {
7072     goto eos;
7073   }
7074
7075   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7076       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7077
7078 #ifndef GST_DISABLE_GST_DEBUG
7079     {
7080       guint64 discont_offset, distance_from_discont;
7081
7082       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7083       distance_from_discont =
7084           gst_adapter_distance_from_discont (demux->adapter);
7085
7086       GST_DEBUG_OBJECT (demux,
7087           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7088           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7089           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7090           demux->offset, discont_offset, distance_from_discont);
7091     }
7092 #endif
7093
7094     switch (demux->state) {
7095       case QTDEMUX_STATE_INITIAL:{
7096         const guint8 *data;
7097         guint32 fourcc;
7098         guint64 size;
7099
7100         gst_qtdemux_check_seekability (demux);
7101
7102         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7103
7104         /* get fourcc/length, set neededbytes */
7105         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7106             &size, &fourcc);
7107         gst_adapter_unmap (demux->adapter);
7108         data = NULL;
7109         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7110             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7111         if (size == 0) {
7112           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7113               (_("This file is invalid and cannot be played.")),
7114               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7115                   GST_FOURCC_ARGS (fourcc)));
7116           ret = GST_FLOW_ERROR;
7117           break;
7118         }
7119         if (fourcc == FOURCC_mdat) {
7120           gint next_entry = next_entry_size (demux);
7121           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7122                   || !demux->fragmented)) {
7123             /* we have the headers, start playback */
7124             demux->state = QTDEMUX_STATE_MOVIE;
7125             demux->neededbytes = next_entry;
7126             demux->mdatleft = size;
7127             demux->mdatsize = demux->mdatleft;
7128           } else {
7129             /* no headers yet, try to get them */
7130             guint bs;
7131             gboolean res;
7132             guint64 old, target;
7133
7134           buffer_data:
7135             old = demux->offset;
7136             target = old + size;
7137
7138             /* try to jump over the atom with a seek */
7139             /* only bother if it seems worth doing so,
7140              * and avoids possible upstream/server problems */
7141             if (demux->upstream_seekable &&
7142                 demux->upstream_size > 4 * (1 << 20)) {
7143               res = qtdemux_seek_offset (demux, target);
7144             } else {
7145               GST_DEBUG_OBJECT (demux, "skipping seek");
7146               res = FALSE;
7147             }
7148
7149             if (res) {
7150               GST_DEBUG_OBJECT (demux, "seek success");
7151               /* remember the offset fo the first mdat so we can seek back to it
7152                * after we have the headers */
7153               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7154                 demux->first_mdat = old;
7155                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7156                     demux->first_mdat);
7157               }
7158               /* seek worked, continue reading */
7159               demux->offset = target;
7160               demux->neededbytes = 16;
7161               demux->state = QTDEMUX_STATE_INITIAL;
7162             } else {
7163               /* seek failed, need to buffer */
7164               demux->offset = old;
7165               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7166               /* there may be multiple mdat (or alike) buffers */
7167               /* sanity check */
7168               if (demux->mdatbuffer)
7169                 bs = gst_buffer_get_size (demux->mdatbuffer);
7170               else
7171                 bs = 0;
7172               if (size + bs > 10 * (1 << 20))
7173                 goto no_moov;
7174               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7175               demux->neededbytes = size;
7176               if (!demux->mdatbuffer)
7177                 demux->mdatoffset = demux->offset;
7178             }
7179           }
7180         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7181           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7182               (_("This file is invalid and cannot be played.")),
7183               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7184                   GST_FOURCC_ARGS (fourcc), size));
7185           ret = GST_FLOW_ERROR;
7186           break;
7187         } else {
7188           /* this means we already started buffering and still no moov header,
7189            * let's continue buffering everything till we get moov */
7190           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7191                   || fourcc == FOURCC_moof))
7192             goto buffer_data;
7193           demux->neededbytes = size;
7194           demux->state = QTDEMUX_STATE_HEADER;
7195         }
7196         break;
7197       }
7198       case QTDEMUX_STATE_HEADER:{
7199         const guint8 *data;
7200         guint32 fourcc;
7201
7202         GST_DEBUG_OBJECT (demux, "In header");
7203
7204         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7205
7206         /* parse the header */
7207         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7208             &fourcc);
7209         if (fourcc == FOURCC_moov) {
7210           /* in usual fragmented setup we could try to scan for more
7211            * and end up at the the moov (after mdat) again */
7212           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7213               (!demux->fragmented
7214                   || demux->last_moov_offset == demux->offset)) {
7215             GST_DEBUG_OBJECT (demux,
7216                 "Skipping moov atom as we have (this) one already");
7217           } else {
7218             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7219
7220             if (demux->got_moov && demux->fragmented) {
7221               GST_DEBUG_OBJECT (demux,
7222                   "Got a second moov, clean up data from old one");
7223               if (demux->moov_node_compressed) {
7224                 g_node_destroy (demux->moov_node_compressed);
7225                 if (demux->moov_node)
7226                   g_free (demux->moov_node->data);
7227               }
7228               demux->moov_node_compressed = NULL;
7229               if (demux->moov_node)
7230                 g_node_destroy (demux->moov_node);
7231               demux->moov_node = NULL;
7232             }
7233
7234             demux->last_moov_offset = demux->offset;
7235
7236             /* Update streams with new moov */
7237             gst_qtdemux_stream_concat (demux,
7238                 demux->old_streams, demux->active_streams);
7239
7240             qtdemux_parse_moov (demux, data, demux->neededbytes);
7241             qtdemux_node_dump (demux, demux->moov_node);
7242             qtdemux_parse_tree (demux);
7243             qtdemux_prepare_streams (demux);
7244             QTDEMUX_EXPOSE_LOCK (demux);
7245             qtdemux_expose_streams (demux);
7246             QTDEMUX_EXPOSE_UNLOCK (demux);
7247
7248             demux->got_moov = TRUE;
7249
7250             gst_qtdemux_check_send_pending_segment (demux);
7251
7252             if (demux->moov_node_compressed) {
7253               g_node_destroy (demux->moov_node_compressed);
7254               g_free (demux->moov_node->data);
7255             }
7256             demux->moov_node_compressed = NULL;
7257             g_node_destroy (demux->moov_node);
7258             demux->moov_node = NULL;
7259             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7260           }
7261         } else if (fourcc == FOURCC_moof) {
7262           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7263             guint64 dist = 0;
7264             GstClockTime prev_pts;
7265             guint64 prev_offset;
7266             guint64 adapter_discont_offset, adapter_discont_dist;
7267
7268             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7269
7270             /*
7271              * The timestamp of the moof buffer is relevant as some scenarios
7272              * won't have the initial timestamp in the atoms. Whenever a new
7273              * buffer has started, we get that buffer's PTS and use it as a base
7274              * timestamp for the trun entries.
7275              *
7276              * To keep track of the current buffer timestamp and starting point
7277              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7278              * from the beginning of the buffer, with the distance and demux->offset
7279              * we know if it is still the same buffer or not.
7280              */
7281             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7282             prev_offset = demux->offset - dist;
7283             if (demux->fragment_start_offset == -1
7284                 || prev_offset > demux->fragment_start_offset) {
7285               demux->fragment_start_offset = prev_offset;
7286               demux->fragment_start = prev_pts;
7287               GST_DEBUG_OBJECT (demux,
7288                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7289                   GST_TIME_FORMAT, demux->fragment_start_offset,
7290                   GST_TIME_ARGS (demux->fragment_start));
7291             }
7292
7293             /* We can't use prev_offset() here because this would require
7294              * upstream to set consistent and correct offsets on all buffers
7295              * since the discont. Nothing ever did that in the past and we
7296              * would break backwards compatibility here then.
7297              * Instead take the offset we had at the last discont and count
7298              * the bytes from there. This works with old code as there would
7299              * be no discont between moov and moof, and also works with
7300              * adaptivedemux which correctly sets offset and will set the
7301              * DISCONT flag accordingly when needed.
7302              *
7303              * We also only do this for upstream TIME segments as otherwise
7304              * there are potential backwards compatibility problems with
7305              * seeking in PUSH mode and upstream providing inconsistent
7306              * timestamps. */
7307             adapter_discont_offset =
7308                 gst_adapter_offset_at_discont (demux->adapter);
7309             adapter_discont_dist =
7310                 gst_adapter_distance_from_discont (demux->adapter);
7311
7312             GST_DEBUG_OBJECT (demux,
7313                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7314                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7315                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7316
7317             if (demux->upstream_format_is_time) {
7318               demux->moof_offset = adapter_discont_offset;
7319               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7320                 demux->moof_offset += adapter_discont_dist;
7321               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7322                 demux->moof_offset = demux->offset;
7323             } else {
7324               demux->moof_offset = demux->offset;
7325             }
7326
7327             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7328                     demux->moof_offset, NULL)) {
7329               gst_adapter_unmap (demux->adapter);
7330               ret = GST_FLOW_ERROR;
7331               goto done;
7332             }
7333
7334             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7335             if (demux->mss_mode && !demux->exposed) {
7336               QTDEMUX_EXPOSE_LOCK (demux);
7337               qtdemux_expose_streams (demux);
7338               QTDEMUX_EXPOSE_UNLOCK (demux);
7339             }
7340
7341             gst_qtdemux_check_send_pending_segment (demux);
7342           } else {
7343             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7344           }
7345         } else if (fourcc == FOURCC_ftyp) {
7346           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7347           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7348         } else if (fourcc == FOURCC_uuid) {
7349           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7350           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7351         } else if (fourcc == FOURCC_sidx) {
7352           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7353           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7354         } else {
7355           switch (fourcc) {
7356             case FOURCC_styp:
7357               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7358                * FALLTHROUGH */
7359             case FOURCC_skip:
7360             case FOURCC_free:
7361               /* [free] and [skip] are padding atoms */
7362               GST_DEBUG_OBJECT (demux,
7363                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7364                   GST_FOURCC_ARGS (fourcc));
7365               break;
7366             default:
7367               GST_WARNING_OBJECT (demux,
7368                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7369                   GST_FOURCC_ARGS (fourcc));
7370               /* Let's jump that one and go back to initial state */
7371               break;
7372           }
7373         }
7374         gst_adapter_unmap (demux->adapter);
7375         data = NULL;
7376
7377         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7378           gsize remaining_data_size = 0;
7379
7380           /* the mdat was before the header */
7381           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7382               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7383           /* restore our adapter/offset view of things with upstream;
7384            * put preceding buffered data ahead of current moov data.
7385            * This should also handle evil mdat, moov, mdat cases and alike */
7386           gst_adapter_flush (demux->adapter, demux->neededbytes);
7387
7388           /* Store any remaining data after the mdat for later usage */
7389           remaining_data_size = gst_adapter_available (demux->adapter);
7390           if (remaining_data_size > 0) {
7391             g_assert (demux->restoredata_buffer == NULL);
7392             demux->restoredata_buffer =
7393                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7394             demux->restoredata_offset = demux->offset + demux->neededbytes;
7395             GST_DEBUG_OBJECT (demux,
7396                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7397                 G_GUINT64_FORMAT, remaining_data_size,
7398                 demux->restoredata_offset);
7399           }
7400
7401           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7402           demux->mdatbuffer = NULL;
7403           demux->offset = demux->mdatoffset;
7404           demux->neededbytes = next_entry_size (demux);
7405           demux->state = QTDEMUX_STATE_MOVIE;
7406           demux->mdatleft = gst_adapter_available (demux->adapter);
7407           demux->mdatsize = demux->mdatleft;
7408         } else {
7409           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7410           gst_adapter_flush (demux->adapter, demux->neededbytes);
7411
7412           /* only go back to the mdat if there are samples to play */
7413           if (demux->got_moov && demux->first_mdat != -1
7414               && has_next_entry (demux)) {
7415             gboolean res;
7416
7417             /* we need to seek back */
7418             res = qtdemux_seek_offset (demux, demux->first_mdat);
7419             if (res) {
7420               demux->offset = demux->first_mdat;
7421             } else {
7422               GST_DEBUG_OBJECT (demux, "Seek back failed");
7423             }
7424           } else {
7425             demux->offset += demux->neededbytes;
7426           }
7427           demux->neededbytes = 16;
7428           demux->state = QTDEMUX_STATE_INITIAL;
7429         }
7430
7431         break;
7432       }
7433       case QTDEMUX_STATE_BUFFER_MDAT:{
7434         GstBuffer *buf;
7435         guint8 fourcc[4];
7436
7437         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7438             demux->offset);
7439         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7440         gst_buffer_extract (buf, 0, fourcc, 4);
7441         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7442             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7443         if (demux->mdatbuffer)
7444           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7445         else
7446           demux->mdatbuffer = buf;
7447         demux->offset += demux->neededbytes;
7448         demux->neededbytes = 16;
7449         demux->state = QTDEMUX_STATE_INITIAL;
7450         gst_qtdemux_post_progress (demux, 1, 1);
7451
7452         break;
7453       }
7454       case QTDEMUX_STATE_MOVIE:{
7455         QtDemuxStream *stream = NULL;
7456         QtDemuxSample *sample;
7457         GstClockTime dts, pts, duration;
7458         gboolean keyframe;
7459         gint i;
7460
7461         GST_DEBUG_OBJECT (demux,
7462             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7463
7464         if (demux->fragmented) {
7465           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7466               demux->mdatleft);
7467           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7468             /* if needed data starts within this atom,
7469              * then it should not exceed this atom */
7470             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7471               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7472                   (_("This file is invalid and cannot be played.")),
7473                   ("sample data crosses atom boundary"));
7474               ret = GST_FLOW_ERROR;
7475               break;
7476             }
7477             demux->mdatleft -= demux->neededbytes;
7478           } else {
7479             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7480             /* so we are dropping more than left in this atom */
7481             gst_qtdemux_drop_data (demux, demux->mdatleft);
7482             demux->mdatleft = 0;
7483
7484             /* need to resume atom parsing so we do not miss any other pieces */
7485             demux->state = QTDEMUX_STATE_INITIAL;
7486             demux->neededbytes = 16;
7487
7488             /* check if there was any stored post mdat data from previous buffers */
7489             if (demux->restoredata_buffer) {
7490               g_assert (gst_adapter_available (demux->adapter) == 0);
7491
7492               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7493               demux->restoredata_buffer = NULL;
7494               demux->offset = demux->restoredata_offset;
7495             }
7496
7497             break;
7498           }
7499         }
7500
7501         if (demux->todrop) {
7502           if (demux->cenc_aux_info_offset > 0) {
7503             GstByteReader br;
7504             const guint8 *data;
7505
7506             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7507             data = gst_adapter_map (demux->adapter, demux->todrop);
7508             gst_byte_reader_init (&br, data + 8, demux->todrop);
7509             if (!qtdemux_parse_cenc_aux_info (demux,
7510                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7511                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7512               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7513               ret = GST_FLOW_ERROR;
7514               gst_adapter_unmap (demux->adapter);
7515               g_free (demux->cenc_aux_info_sizes);
7516               demux->cenc_aux_info_sizes = NULL;
7517               goto done;
7518             }
7519             demux->cenc_aux_info_offset = 0;
7520             g_free (demux->cenc_aux_info_sizes);
7521             demux->cenc_aux_info_sizes = NULL;
7522             gst_adapter_unmap (demux->adapter);
7523           }
7524           gst_qtdemux_drop_data (demux, demux->todrop);
7525         }
7526
7527         /* first buffer? */
7528         /* initial newsegment sent here after having added pads,
7529          * possible others in sink_event */
7530         gst_qtdemux_check_send_pending_segment (demux);
7531
7532         /* Figure out which stream this packet belongs to */
7533         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7534           stream = QTDEMUX_NTH_STREAM (demux, i);
7535           if (stream->sample_index >= stream->n_samples) {
7536             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7537             stream = NULL;
7538             continue;
7539           }
7540           GST_LOG_OBJECT (demux,
7541               "Checking track-id %u (sample_index:%d / offset:%"
7542               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7543               stream->sample_index,
7544               stream->samples[stream->sample_index].offset,
7545               stream->samples[stream->sample_index].size);
7546
7547           if (stream->samples[stream->sample_index].offset == demux->offset)
7548             break;
7549         }
7550
7551         if (G_UNLIKELY (stream == NULL))
7552           goto unknown_stream;
7553
7554         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7555
7556         if (stream->new_caps) {
7557           gst_qtdemux_configure_stream (demux, stream);
7558         }
7559
7560         /* Put data in a buffer, set timestamps, caps, ... */
7561         sample = &stream->samples[stream->sample_index];
7562
7563         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7564           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7565               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7566
7567           dts = QTSAMPLE_DTS (stream, sample);
7568           pts = QTSAMPLE_PTS (stream, sample);
7569           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7570           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7571
7572           /* check for segment end */
7573           if (G_UNLIKELY (demux->segment.stop != -1
7574                   && demux->segment.stop <= pts && stream->on_keyframe)
7575               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7576             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7577             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7578
7579             /* skip this data, stream is EOS */
7580             gst_adapter_flush (demux->adapter, demux->neededbytes);
7581             demux->offset += demux->neededbytes;
7582
7583             /* check if all streams are eos */
7584             ret = GST_FLOW_EOS;
7585             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7586               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7587                 ret = GST_FLOW_OK;
7588                 break;
7589               }
7590             }
7591           } else {
7592             GstBuffer *outbuf;
7593
7594             outbuf =
7595                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7596
7597             /* FIXME: should either be an assert or a plain check */
7598             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7599
7600             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7601                 dts, pts, duration, keyframe, dts, demux->offset);
7602           }
7603
7604           /* combine flows */
7605           GST_OBJECT_LOCK (demux);
7606           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7607           GST_OBJECT_UNLOCK (demux);
7608         } else {
7609           /* skip this data, stream is EOS */
7610           gst_adapter_flush (demux->adapter, demux->neededbytes);
7611         }
7612
7613         stream->sample_index++;
7614         stream->offset_in_sample = 0;
7615
7616         /* update current offset and figure out size of next buffer */
7617         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7618             demux->offset, demux->neededbytes);
7619         demux->offset += demux->neededbytes;
7620         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7621             demux->offset);
7622
7623
7624         if (ret == GST_FLOW_EOS) {
7625           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7626           demux->neededbytes = -1;
7627           goto eos;
7628         }
7629
7630         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7631           if (demux->fragmented) {
7632             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7633             /* there may be more to follow, only finish this atom */
7634             demux->todrop = demux->mdatleft;
7635             demux->neededbytes = demux->todrop;
7636             break;
7637           }
7638           goto eos;
7639         }
7640         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7641           goto non_ok_unlinked_flow;
7642         }
7643         break;
7644       }
7645       default:
7646         goto invalid_state;
7647     }
7648   }
7649
7650   /* when buffering movie data, at least show user something is happening */
7651   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7652       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7653     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7654         demux->neededbytes);
7655   }
7656 done:
7657
7658   return ret;
7659
7660   /* ERRORS */
7661 non_ok_unlinked_flow:
7662   {
7663     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7664         gst_flow_get_name (ret));
7665     return ret;
7666   }
7667 unknown_stream:
7668   {
7669     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7670     ret = GST_FLOW_ERROR;
7671     goto done;
7672   }
7673 eos:
7674   {
7675     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7676     ret = GST_FLOW_EOS;
7677     goto done;
7678   }
7679 invalid_state:
7680   {
7681     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7682         (NULL), ("qtdemuxer invalid state %d", demux->state));
7683     ret = GST_FLOW_ERROR;
7684     goto done;
7685   }
7686 no_moov:
7687   {
7688     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7689         (NULL), ("no 'moov' atom within the first 10 MB"));
7690     ret = GST_FLOW_ERROR;
7691     goto done;
7692   }
7693 }
7694
7695 static gboolean
7696 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7697 {
7698   GstQuery *query;
7699   gboolean pull_mode;
7700
7701   query = gst_query_new_scheduling ();
7702
7703   if (!gst_pad_peer_query (sinkpad, query)) {
7704     gst_query_unref (query);
7705     goto activate_push;
7706   }
7707
7708   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7709       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7710   gst_query_unref (query);
7711
7712   if (!pull_mode)
7713     goto activate_push;
7714
7715   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7716   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7717
7718 activate_push:
7719   {
7720     GST_DEBUG_OBJECT (sinkpad, "activating push");
7721     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7722   }
7723 }
7724
7725 static gboolean
7726 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7727     GstPadMode mode, gboolean active)
7728 {
7729   gboolean res;
7730   GstQTDemux *demux = GST_QTDEMUX (parent);
7731
7732   switch (mode) {
7733     case GST_PAD_MODE_PUSH:
7734       demux->pullbased = FALSE;
7735       res = TRUE;
7736       break;
7737     case GST_PAD_MODE_PULL:
7738       if (active) {
7739         demux->pullbased = TRUE;
7740         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7741             sinkpad, NULL);
7742       } else {
7743         res = gst_pad_stop_task (sinkpad);
7744       }
7745       break;
7746     default:
7747       res = FALSE;
7748       break;
7749   }
7750   return res;
7751 }
7752
7753 #ifdef HAVE_ZLIB
7754 static void *
7755 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7756 {
7757   guint8 *buffer;
7758   z_stream z;
7759   int ret;
7760
7761   memset (&z, 0, sizeof (z));
7762   z.zalloc = NULL;
7763   z.zfree = NULL;
7764   z.opaque = NULL;
7765
7766   if ((ret = inflateInit (&z)) != Z_OK) {
7767     GST_ERROR ("inflateInit() returned %d", ret);
7768     return NULL;
7769   }
7770
7771   z.next_in = z_buffer;
7772   z.avail_in = z_length;
7773
7774   buffer = (guint8 *) g_malloc (*length);
7775   z.avail_out = *length;
7776   z.next_out = (Bytef *) buffer;
7777   do {
7778     ret = inflate (&z, Z_NO_FLUSH);
7779     if (ret == Z_STREAM_END) {
7780       break;
7781     } else if (ret != Z_OK) {
7782       GST_WARNING ("inflate() returned %d", ret);
7783       break;
7784     }
7785
7786     *length += 4096;
7787     buffer = (guint8 *) g_realloc (buffer, *length);
7788     z.next_out = (Bytef *) (buffer + z.total_out);
7789     z.avail_out += 4096;
7790   } while (z.avail_in > 0);
7791
7792   if (ret != Z_STREAM_END) {
7793     g_free (buffer);
7794     buffer = NULL;
7795     *length = 0;
7796   } else {
7797     *length = z.total_out;
7798   }
7799
7800   inflateEnd (&z);
7801
7802   return buffer;
7803 }
7804 #endif /* HAVE_ZLIB */
7805
7806 static gboolean
7807 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7808 {
7809   GNode *cmov;
7810
7811   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7812
7813   /* counts as header data */
7814   qtdemux->header_size += length;
7815
7816   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7817   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7818
7819   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7820   if (cmov) {
7821     guint32 method;
7822     GNode *dcom;
7823     GNode *cmvd;
7824     guint32 dcom_len;
7825
7826     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7827     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7828     if (dcom == NULL || cmvd == NULL)
7829       goto invalid_compression;
7830
7831     dcom_len = QT_UINT32 (dcom->data);
7832     if (dcom_len < 12)
7833       goto invalid_compression;
7834
7835     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7836     switch (method) {
7837 #ifdef HAVE_ZLIB
7838       case FOURCC_zlib:{
7839         guint uncompressed_length;
7840         guint compressed_length;
7841         guint8 *buf;
7842         guint32 cmvd_len;
7843
7844         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7845         if (cmvd_len < 12)
7846           goto invalid_compression;
7847
7848         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7849         compressed_length = cmvd_len - 12;
7850         GST_LOG ("length = %u", uncompressed_length);
7851
7852         buf =
7853             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7854             compressed_length, &uncompressed_length);
7855
7856         if (buf) {
7857           qtdemux->moov_node_compressed = qtdemux->moov_node;
7858           qtdemux->moov_node = g_node_new (buf);
7859
7860           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7861               uncompressed_length);
7862         }
7863         break;
7864       }
7865 #endif /* HAVE_ZLIB */
7866       default:
7867         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7868             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7869         break;
7870     }
7871   }
7872   return TRUE;
7873
7874   /* ERRORS */
7875 invalid_compression:
7876   {
7877     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7878     return FALSE;
7879   }
7880 }
7881
7882 static gboolean
7883 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7884     const guint8 * end)
7885 {
7886   while (G_UNLIKELY (buf < end)) {
7887     GNode *child;
7888     guint32 len;
7889
7890     if (G_UNLIKELY (buf + 4 > end)) {
7891       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7892       break;
7893     }
7894     len = QT_UINT32 (buf);
7895     if (G_UNLIKELY (len == 0)) {
7896       GST_LOG_OBJECT (qtdemux, "empty container");
7897       break;
7898     }
7899     if (G_UNLIKELY (len < 8)) {
7900       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7901       break;
7902     }
7903     if (G_UNLIKELY (len > (end - buf))) {
7904       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7905           (gint) (end - buf));
7906       break;
7907     }
7908
7909     child = g_node_new ((guint8 *) buf);
7910     g_node_append (node, child);
7911     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7912     qtdemux_parse_node (qtdemux, child, buf, len);
7913
7914     buf += len;
7915   }
7916   return TRUE;
7917 }
7918
7919 static gboolean
7920 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7921     GNode * xdxt)
7922 {
7923   int len = QT_UINT32 (xdxt->data);
7924   guint8 *buf = xdxt->data;
7925   guint8 *end = buf + len;
7926   GstBuffer *buffer;
7927
7928   /* skip size and type */
7929   buf += 8;
7930   end -= 8;
7931
7932   while (buf < end) {
7933     gint size;
7934     guint32 type;
7935
7936     size = QT_UINT32 (buf);
7937     type = QT_FOURCC (buf + 4);
7938
7939     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7940
7941     if (buf + size > end || size <= 0)
7942       break;
7943
7944     buf += 8;
7945     size -= 8;
7946
7947     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7948         GST_FOURCC_ARGS (type));
7949
7950     switch (type) {
7951       case FOURCC_tCtH:
7952         buffer = gst_buffer_new_and_alloc (size);
7953         gst_buffer_fill (buffer, 0, buf, size);
7954         stream->buffers = g_slist_append (stream->buffers, buffer);
7955         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7956         break;
7957       case FOURCC_tCt_:
7958         buffer = gst_buffer_new_and_alloc (size);
7959         gst_buffer_fill (buffer, 0, buf, size);
7960         stream->buffers = g_slist_append (stream->buffers, buffer);
7961         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7962         break;
7963       case FOURCC_tCtC:
7964         buffer = gst_buffer_new_and_alloc (size);
7965         gst_buffer_fill (buffer, 0, buf, size);
7966         stream->buffers = g_slist_append (stream->buffers, buffer);
7967         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7968         break;
7969       default:
7970         GST_WARNING_OBJECT (qtdemux,
7971             "unknown theora cookie %" GST_FOURCC_FORMAT,
7972             GST_FOURCC_ARGS (type));
7973         break;
7974     }
7975     buf += size;
7976   }
7977   return TRUE;
7978 }
7979
7980 static gboolean
7981 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7982     guint length)
7983 {
7984   guint32 fourcc = 0;
7985   guint32 node_length = 0;
7986   const QtNodeType *type;
7987   const guint8 *end;
7988
7989   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7990
7991   if (G_UNLIKELY (length < 8))
7992     goto not_enough_data;
7993
7994   node_length = QT_UINT32 (buffer);
7995   fourcc = QT_FOURCC (buffer + 4);
7996
7997   /* ignore empty nodes */
7998   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7999     return TRUE;
8000
8001   type = qtdemux_type_get (fourcc);
8002
8003   end = buffer + length;
8004
8005   GST_LOG_OBJECT (qtdemux,
8006       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8007       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8008
8009   if (node_length > length)
8010     goto broken_atom_size;
8011
8012   if (type->flags & QT_FLAG_CONTAINER) {
8013     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8014   } else {
8015     switch (fourcc) {
8016       case FOURCC_stsd:
8017       {
8018         if (node_length < 20) {
8019           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8020           break;
8021         }
8022         GST_DEBUG_OBJECT (qtdemux,
8023             "parsing stsd (sample table, sample description) atom");
8024         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8025         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8026         break;
8027       }
8028       case FOURCC_mp4a:
8029       case FOURCC_alac:
8030       case FOURCC_fLaC:
8031       case FOURCC_aavd:
8032       {
8033         guint32 version;
8034         guint32 offset;
8035         guint min_size;
8036
8037         /* also read alac (or whatever) in stead of mp4a in the following,
8038          * since a similar layout is used in other cases as well */
8039         if (fourcc == FOURCC_mp4a)
8040           min_size = 20;
8041         else if (fourcc == FOURCC_fLaC)
8042           min_size = 86;
8043         else
8044           min_size = 40;
8045
8046         /* There are two things we might encounter here: a true mp4a atom, and
8047            an mp4a entry in an stsd atom. The latter is what we're interested
8048            in, and it looks like an atom, but isn't really one. The true mp4a
8049            atom is short, so we detect it based on length here. */
8050         if (length < min_size) {
8051           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8052               GST_FOURCC_ARGS (fourcc));
8053           break;
8054         }
8055
8056         /* 'version' here is the sound sample description version. Types 0 and
8057            1 are documented in the QTFF reference, but type 2 is not: it's
8058            described in Apple header files instead (struct SoundDescriptionV2
8059            in Movies.h) */
8060         version = QT_UINT16 (buffer + 16);
8061
8062         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8063             GST_FOURCC_ARGS (fourcc), version);
8064
8065         /* parse any esds descriptors */
8066         switch (version) {
8067           case 0:
8068             offset = 0x24;
8069             break;
8070           case 1:
8071             offset = 0x34;
8072             break;
8073           case 2:
8074             offset = 0x48;
8075             break;
8076           default:
8077             GST_WARNING_OBJECT (qtdemux,
8078                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8079                 GST_FOURCC_ARGS (fourcc), version);
8080             offset = 0;
8081             break;
8082         }
8083         if (offset)
8084           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8085         break;
8086       }
8087       case FOURCC_mp4v:
8088       case FOURCC_MP4V:
8089       case FOURCC_fmp4:
8090       case FOURCC_FMP4:
8091       case FOURCC_apcs:
8092       case FOURCC_apch:
8093       case FOURCC_apcn:
8094       case FOURCC_apco:
8095       case FOURCC_ap4h:
8096       case FOURCC_xvid:
8097       case FOURCC_XVID:
8098       case FOURCC_H264:
8099       case FOURCC_avc1:
8100       case FOURCC_avc3:
8101       case FOURCC_H265:
8102       case FOURCC_hvc1:
8103       case FOURCC_hev1:
8104       case FOURCC_dvh1:
8105       case FOURCC_dvhe:
8106       case FOURCC_mjp2:
8107       case FOURCC_encv:
8108       {
8109         guint32 version;
8110         guint32 str_len;
8111
8112         /* codec_data is contained inside these atoms, which all have
8113          * the same format. */
8114         /* video sample description size is 86 bytes without extension.
8115          * node_length have to be bigger than 86 bytes because video sample
8116          * description can include extensions such as esds, fiel, glbl, etc. */
8117         if (node_length < 86) {
8118           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8119               " sample description length too short (%u < 86)",
8120               GST_FOURCC_ARGS (fourcc), node_length);
8121           break;
8122         }
8123
8124         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8125             GST_FOURCC_ARGS (fourcc));
8126
8127         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8128          *              its data format.
8129          * revision level (2 bytes) : must be set to 0. */
8130         version = QT_UINT32 (buffer + 16);
8131         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8132
8133         /* compressor name : PASCAL string and informative purposes
8134          * first byte : the number of bytes to be displayed.
8135          *              it has to be less than 32 because it is reserved
8136          *              space of 32 bytes total including itself. */
8137         str_len = QT_UINT8 (buffer + 50);
8138         if (str_len < 32)
8139           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8140               (char *) buffer + 51);
8141         else
8142           GST_WARNING_OBJECT (qtdemux,
8143               "compressorname length too big (%u > 31)", str_len);
8144
8145         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8146             end - buffer);
8147         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8148         break;
8149       }
8150       case FOURCC_meta:
8151       {
8152         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8153
8154         /* You are reading this correctly. QTFF specifies that the
8155          * metadata atom is a short atom, whereas ISO BMFF specifies
8156          * it's a full atom. But since so many people are doing things
8157          * differently, we actually peek into the atom to see which
8158          * variant it is */
8159         if (length < 16) {
8160           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8161               GST_FOURCC_ARGS (fourcc));
8162           break;
8163         }
8164         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8165           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8166            * starts with a 'hdlr' atom */
8167           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8168         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8169           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8170            * with version/flags both set to zero */
8171           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8172         } else
8173           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8174         break;
8175       }
8176       case FOURCC_mp4s:
8177       {
8178         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8179         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8180         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8181         break;
8182       }
8183       case FOURCC_XiTh:
8184       {
8185         guint32 version;
8186         guint32 offset;
8187
8188         if (length < 16) {
8189           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8190               GST_FOURCC_ARGS (fourcc));
8191           break;
8192         }
8193
8194         version = QT_UINT32 (buffer + 12);
8195         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8196
8197         switch (version) {
8198           case 0x00000001:
8199             offset = 0x62;
8200             break;
8201           default:
8202             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8203             offset = 0;
8204             break;
8205         }
8206         if (offset) {
8207           if (length < offset) {
8208             GST_WARNING_OBJECT (qtdemux,
8209                 "skipping too small %" GST_FOURCC_FORMAT " box",
8210                 GST_FOURCC_ARGS (fourcc));
8211             break;
8212           }
8213           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8214         }
8215         break;
8216       }
8217       case FOURCC_in24:
8218       {
8219         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8220         break;
8221       }
8222       case FOURCC_uuid:
8223       {
8224         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8225         break;
8226       }
8227       case FOURCC_enca:
8228       {
8229         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8230         break;
8231       }
8232       default:
8233         if (!strcmp (type->name, "unknown"))
8234           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8235         break;
8236     }
8237   }
8238   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8239       GST_FOURCC_ARGS (fourcc));
8240   return TRUE;
8241
8242 /* ERRORS */
8243 not_enough_data:
8244   {
8245     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8246         (_("This file is corrupt and cannot be played.")),
8247         ("Not enough data for an atom header, got only %u bytes", length));
8248     return FALSE;
8249   }
8250 broken_atom_size:
8251   {
8252     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8253         (_("This file is corrupt and cannot be played.")),
8254         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8255             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8256             length));
8257     return FALSE;
8258   }
8259 }
8260
8261 static void
8262 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8263 {
8264 /* FIXME: This can only reliably work if demuxers have a
8265  * separate streaming thread per srcpad. This should be
8266  * done in a demuxer base class, which integrates parts
8267  * of multiqueue
8268  *
8269  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8270  */
8271 #if 0
8272   GstQuery *query;
8273
8274   query = gst_query_new_allocation (stream->caps, FALSE);
8275
8276   if (!gst_pad_peer_query (stream->pad, query)) {
8277     /* not a problem, just debug a little */
8278     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8279   }
8280
8281   if (stream->allocator)
8282     gst_object_unref (stream->allocator);
8283
8284   if (gst_query_get_n_allocation_params (query) > 0) {
8285     /* try the allocator */
8286     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8287         &stream->params);
8288     stream->use_allocator = TRUE;
8289   } else {
8290     stream->allocator = NULL;
8291     gst_allocation_params_init (&stream->params);
8292     stream->use_allocator = FALSE;
8293   }
8294   gst_query_unref (query);
8295 #endif
8296 }
8297
8298 static gboolean
8299 pad_query (const GValue * item, GValue * value, gpointer user_data)
8300 {
8301   GstPad *pad = g_value_get_object (item);
8302   GstQuery *query = user_data;
8303   gboolean res;
8304
8305   res = gst_pad_peer_query (pad, query);
8306
8307   if (res) {
8308     g_value_set_boolean (value, TRUE);
8309     return FALSE;
8310   }
8311
8312   GST_INFO_OBJECT (pad, "pad peer query failed");
8313   return TRUE;
8314 }
8315
8316 static gboolean
8317 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8318     GstPadDirection direction)
8319 {
8320   GstIterator *it;
8321   GstIteratorFoldFunction func = pad_query;
8322   GValue res = { 0, };
8323
8324   g_value_init (&res, G_TYPE_BOOLEAN);
8325   g_value_set_boolean (&res, FALSE);
8326
8327   /* Ask neighbor */
8328   if (direction == GST_PAD_SRC)
8329     it = gst_element_iterate_src_pads (element);
8330   else
8331     it = gst_element_iterate_sink_pads (element);
8332
8333   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8334     gst_iterator_resync (it);
8335
8336   gst_iterator_free (it);
8337
8338   return g_value_get_boolean (&res);
8339 }
8340
8341 static void
8342 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8343     QtDemuxStream * stream)
8344 {
8345   GstQuery *query;
8346   GstContext *ctxt;
8347   GstElement *element = GST_ELEMENT (qtdemux);
8348   GstStructure *st;
8349   gchar **filtered_sys_ids;
8350   GValue event_list = G_VALUE_INIT;
8351   GList *walk;
8352
8353   /* 1. Check if we already have the context. */
8354   if (qtdemux->preferred_protection_system_id != NULL) {
8355     GST_LOG_OBJECT (element,
8356         "already have the protection context, no need to request it again");
8357     return;
8358   }
8359
8360   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8361   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8362       (const gchar **) qtdemux->protection_system_ids->pdata);
8363
8364   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8365       qtdemux->protection_system_ids->len - 1);
8366   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8367       "decryptors for %u of them, running context request",
8368       qtdemux->protection_system_ids->len,
8369       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8370
8371
8372   if (stream->protection_scheme_event_queue.length) {
8373     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8374         stream->protection_scheme_event_queue.length);
8375     walk = stream->protection_scheme_event_queue.tail;
8376   } else {
8377     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8378         qtdemux->protection_event_queue.length);
8379     walk = qtdemux->protection_event_queue.tail;
8380   }
8381
8382   g_value_init (&event_list, GST_TYPE_LIST);
8383   for (; walk; walk = g_list_previous (walk)) {
8384     GValue *event_value = g_new0 (GValue, 1);
8385     g_value_init (event_value, GST_TYPE_EVENT);
8386     g_value_set_boxed (event_value, walk->data);
8387     gst_value_list_append_and_take_value (&event_list, event_value);
8388   }
8389
8390   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8391    *      check if downstream already has a context of the specific type
8392    *  2b) Query upstream as above.
8393    */
8394   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8395   st = gst_query_writable_structure (query);
8396   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8397       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8398       NULL);
8399   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8400   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8401     gst_query_parse_context (query, &ctxt);
8402     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8403     gst_element_set_context (element, ctxt);
8404   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8405     gst_query_parse_context (query, &ctxt);
8406     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8407     gst_element_set_context (element, ctxt);
8408   } else {
8409     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8410      *    the required context type and afterwards check if a
8411      *    usable context was set now as in 1). The message could
8412      *    be handled by the parent bins of the element and the
8413      *    application.
8414      */
8415     GstMessage *msg;
8416
8417     GST_INFO_OBJECT (element, "posting need context message");
8418     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8419         "drm-preferred-decryption-system-id");
8420     st = (GstStructure *) gst_message_get_structure (msg);
8421     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8422         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8423         NULL);
8424
8425     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8426     gst_element_post_message (element, msg);
8427   }
8428
8429   g_strfreev (filtered_sys_ids);
8430   g_value_unset (&event_list);
8431   gst_query_unref (query);
8432 }
8433
8434 static gboolean
8435 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8436     QtDemuxStream * stream)
8437 {
8438   GstStructure *s;
8439   const gchar *selected_system = NULL;
8440
8441   g_return_val_if_fail (qtdemux != NULL, FALSE);
8442   g_return_val_if_fail (stream != NULL, FALSE);
8443   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8444       FALSE);
8445
8446   if (stream->protection_scheme_type == FOURCC_aavd) {
8447     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8448     if (!gst_structure_has_name (s, "application/x-aavd")) {
8449       gst_structure_set (s,
8450           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8451           NULL);
8452       gst_structure_set_name (s, "application/x-aavd");
8453     }
8454     return TRUE;
8455   }
8456
8457   if (stream->protection_scheme_type != FOURCC_cenc
8458       && stream->protection_scheme_type != FOURCC_cbcs) {
8459     GST_ERROR_OBJECT (qtdemux,
8460         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8461         GST_FOURCC_ARGS (stream->protection_scheme_type));
8462     return FALSE;
8463   }
8464
8465   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8466   if (!gst_structure_has_name (s, "application/x-cenc")) {
8467     gst_structure_set (s,
8468         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8469     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8470         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8471         NULL);
8472     gst_structure_set_name (s, "application/x-cenc");
8473   }
8474
8475   if (qtdemux->protection_system_ids == NULL) {
8476     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8477         "cenc protection system information has been found, not setting a "
8478         "protection system UUID");
8479     return TRUE;
8480   }
8481
8482   gst_qtdemux_request_protection_context (qtdemux, stream);
8483   if (qtdemux->preferred_protection_system_id != NULL) {
8484     const gchar *preferred_system_array[] =
8485         { qtdemux->preferred_protection_system_id, NULL };
8486
8487     selected_system = gst_protection_select_system (preferred_system_array);
8488
8489     if (selected_system) {
8490       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8491           qtdemux->preferred_protection_system_id);
8492     } else {
8493       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8494           "because there is no available decryptor",
8495           qtdemux->preferred_protection_system_id);
8496     }
8497   }
8498
8499   if (!selected_system) {
8500     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8501     selected_system = gst_protection_select_system ((const gchar **)
8502         qtdemux->protection_system_ids->pdata);
8503     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8504         qtdemux->protection_system_ids->len - 1);
8505   }
8506
8507   if (!selected_system) {
8508     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8509         "suitable decryptor element has been found");
8510     return FALSE;
8511   }
8512
8513   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8514       selected_system);
8515
8516   gst_structure_set (s,
8517       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8518       NULL);
8519
8520   return TRUE;
8521 }
8522
8523 static gboolean
8524 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8525 {
8526   /* fps is calculated base on the duration of the average framerate since
8527    * qt does not have a fixed framerate. */
8528   gboolean fps_available = TRUE;
8529   guint32 first_duration = 0;
8530
8531   if (stream->n_samples > 0)
8532     first_duration = stream->samples[0].duration;
8533
8534   if ((stream->n_samples == 1 && first_duration == 0)
8535       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8536     /* still frame */
8537     CUR_STREAM (stream)->fps_n = 0;
8538     CUR_STREAM (stream)->fps_d = 1;
8539   } else {
8540     if (stream->duration == 0 || stream->n_samples < 2) {
8541       CUR_STREAM (stream)->fps_n = stream->timescale;
8542       CUR_STREAM (stream)->fps_d = 1;
8543       fps_available = FALSE;
8544     } else {
8545       GstClockTime avg_duration;
8546       guint64 duration;
8547       guint32 n_samples;
8548
8549       /* duration and n_samples can be updated for fragmented format
8550        * so, framerate of fragmented format is calculated using data in a moof */
8551       if (qtdemux->fragmented && stream->n_samples_moof > 0
8552           && stream->duration_moof > 0) {
8553         n_samples = stream->n_samples_moof;
8554         duration = stream->duration_moof;
8555       } else {
8556         n_samples = stream->n_samples;
8557         duration = stream->duration;
8558       }
8559
8560       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8561       /* stream->duration is guint64, timescale, n_samples are guint32 */
8562       avg_duration =
8563           gst_util_uint64_scale_round (duration -
8564           first_duration, GST_SECOND,
8565           (guint64) (stream->timescale) * (n_samples - 1));
8566
8567       GST_LOG_OBJECT (qtdemux,
8568           "Calculating avg sample duration based on stream (or moof) duration %"
8569           G_GUINT64_FORMAT
8570           " minus first sample %u, leaving %d samples gives %"
8571           GST_TIME_FORMAT, duration, first_duration,
8572           n_samples - 1, GST_TIME_ARGS (avg_duration));
8573
8574       fps_available =
8575           gst_video_guess_framerate (avg_duration,
8576           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8577
8578       GST_DEBUG_OBJECT (qtdemux,
8579           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8580           stream->timescale, CUR_STREAM (stream)->fps_n,
8581           CUR_STREAM (stream)->fps_d);
8582     }
8583   }
8584
8585   return fps_available;
8586 }
8587
8588 static gboolean
8589 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8590 {
8591   if (stream->subtype == FOURCC_vide) {
8592     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8593
8594     if (CUR_STREAM (stream)->caps) {
8595       CUR_STREAM (stream)->caps =
8596           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8597
8598       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8599         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8600             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8601             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8602
8603       /* set framerate if calculated framerate is reliable */
8604       if (fps_available) {
8605         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8606             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8607             CUR_STREAM (stream)->fps_d, NULL);
8608       }
8609
8610       /* calculate pixel-aspect-ratio using display width and height */
8611       GST_DEBUG_OBJECT (qtdemux,
8612           "video size %dx%d, target display size %dx%d",
8613           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8614           stream->display_width, stream->display_height);
8615       /* qt file might have pasp atom */
8616       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8617         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8618             CUR_STREAM (stream)->par_h);
8619         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8620             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8621             CUR_STREAM (stream)->par_h, NULL);
8622       } else if (stream->display_width > 0 && stream->display_height > 0
8623           && CUR_STREAM (stream)->width > 0
8624           && CUR_STREAM (stream)->height > 0) {
8625         gint n, d;
8626
8627         /* calculate the pixel aspect ratio using the display and pixel w/h */
8628         n = stream->display_width * CUR_STREAM (stream)->height;
8629         d = stream->display_height * CUR_STREAM (stream)->width;
8630         if (n == d)
8631           n = d = 1;
8632         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8633         CUR_STREAM (stream)->par_w = n;
8634         CUR_STREAM (stream)->par_h = d;
8635         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8636             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8637             CUR_STREAM (stream)->par_h, NULL);
8638       }
8639
8640       if (CUR_STREAM (stream)->interlace_mode > 0) {
8641         if (CUR_STREAM (stream)->interlace_mode == 1) {
8642           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8643               G_TYPE_STRING, "progressive", NULL);
8644         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8645           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8646               G_TYPE_STRING, "interleaved", NULL);
8647           if (CUR_STREAM (stream)->field_order == 9) {
8648             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8649                 G_TYPE_STRING, "top-field-first", NULL);
8650           } else if (CUR_STREAM (stream)->field_order == 14) {
8651             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8652                 G_TYPE_STRING, "bottom-field-first", NULL);
8653           }
8654         }
8655       }
8656
8657       /* Create incomplete colorimetry here if needed */
8658       if (CUR_STREAM (stream)->colorimetry.range ||
8659           CUR_STREAM (stream)->colorimetry.matrix ||
8660           CUR_STREAM (stream)->colorimetry.transfer
8661           || CUR_STREAM (stream)->colorimetry.primaries) {
8662         gchar *colorimetry =
8663             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8664         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8665             G_TYPE_STRING, colorimetry, NULL);
8666         g_free (colorimetry);
8667       }
8668
8669       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8670         guint par_w = 1, par_h = 1;
8671
8672         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8673           par_w = CUR_STREAM (stream)->par_w;
8674           par_h = CUR_STREAM (stream)->par_h;
8675         }
8676
8677         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8678                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8679                 par_h)) {
8680           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8681         }
8682
8683         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8684             "multiview-mode", G_TYPE_STRING,
8685             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8686             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8687             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8688       }
8689     }
8690   }
8691
8692   else if (stream->subtype == FOURCC_soun) {
8693     if (CUR_STREAM (stream)->caps) {
8694       CUR_STREAM (stream)->caps =
8695           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8696       if (CUR_STREAM (stream)->rate > 0)
8697         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8698             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8699       if (CUR_STREAM (stream)->n_channels > 0)
8700         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8701             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8702       if (CUR_STREAM (stream)->n_channels > 2) {
8703         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8704          * correctly; this is just the minimum we can do - assume
8705          * we don't actually have any channel positions. */
8706         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8707             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8708       }
8709     }
8710   }
8711
8712   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8713     const GstStructure *s;
8714     QtDemuxStream *fps_stream = NULL;
8715     gboolean fps_available = FALSE;
8716
8717     /* CEA608 closed caption tracks are a bit special in that each sample
8718      * can contain CCs for multiple frames, and CCs can be omitted and have to
8719      * be inferred from the duration of the sample then.
8720      *
8721      * As such we take the framerate from the (first) video track here for
8722      * CEA608 as there must be one CC byte pair for every video frame
8723      * according to the spec.
8724      *
8725      * For CEA708 all is fine and there is one sample per frame.
8726      */
8727
8728     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8729     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8730       gint i;
8731
8732       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8733         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8734
8735         if (tmp->subtype == FOURCC_vide) {
8736           fps_stream = tmp;
8737           break;
8738         }
8739       }
8740
8741       if (fps_stream) {
8742         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8743         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8744         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8745       }
8746     } else {
8747       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8748       fps_stream = stream;
8749     }
8750
8751     CUR_STREAM (stream)->caps =
8752         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8753
8754     /* set framerate if calculated framerate is reliable */
8755     if (fps_available) {
8756       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8757           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8758           CUR_STREAM (stream)->fps_d, NULL);
8759     }
8760   }
8761
8762   if (stream->pad) {
8763     GstCaps *prev_caps = NULL;
8764
8765     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8766     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8767     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8768     gst_pad_set_active (stream->pad, TRUE);
8769
8770     gst_pad_use_fixed_caps (stream->pad);
8771
8772     if (stream->protected) {
8773       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8774         GST_ERROR_OBJECT (qtdemux,
8775             "Failed to configure protected stream caps.");
8776         return FALSE;
8777       }
8778     }
8779
8780     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8781         CUR_STREAM (stream)->caps);
8782     if (stream->new_stream) {
8783       GstEvent *event;
8784       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8785
8786       event =
8787           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8788           0);
8789       if (event) {
8790         gst_event_parse_stream_flags (event, &stream_flags);
8791         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8792           qtdemux->have_group_id = TRUE;
8793         else
8794           qtdemux->have_group_id = FALSE;
8795         gst_event_unref (event);
8796       } else if (!qtdemux->have_group_id) {
8797         qtdemux->have_group_id = TRUE;
8798         qtdemux->group_id = gst_util_group_id_next ();
8799       }
8800
8801       stream->new_stream = FALSE;
8802       event = gst_event_new_stream_start (stream->stream_id);
8803       if (qtdemux->have_group_id)
8804         gst_event_set_group_id (event, qtdemux->group_id);
8805       if (stream->disabled)
8806         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8807       if (CUR_STREAM (stream)->sparse) {
8808         stream_flags |= GST_STREAM_FLAG_SPARSE;
8809       } else {
8810         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8811       }
8812       gst_event_set_stream_flags (event, stream_flags);
8813       gst_pad_push_event (stream->pad, event);
8814     }
8815
8816     prev_caps = gst_pad_get_current_caps (stream->pad);
8817
8818     if (CUR_STREAM (stream)->caps) {
8819       if (!prev_caps
8820           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8821         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8822             CUR_STREAM (stream)->caps);
8823         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8824       } else {
8825         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8826       }
8827     } else {
8828       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8829     }
8830
8831     if (prev_caps)
8832       gst_caps_unref (prev_caps);
8833     stream->new_caps = FALSE;
8834   }
8835   return TRUE;
8836 }
8837
8838 static void
8839 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8840     QtDemuxStream * stream)
8841 {
8842   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8843     return;
8844
8845   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8846       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8847   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8848           stream->stsd_entries_length)) {
8849     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8850         (_("This file is invalid and cannot be played.")),
8851         ("New sample description id is out of bounds (%d >= %d)",
8852             stream->stsd_sample_description_id, stream->stsd_entries_length));
8853   } else {
8854     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8855     stream->new_caps = TRUE;
8856   }
8857 }
8858
8859 static gboolean
8860 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8861     QtDemuxStream * stream, GstTagList * list)
8862 {
8863   gboolean ret = TRUE;
8864
8865   if (stream->subtype == FOURCC_vide) {
8866     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8867
8868     stream->pad =
8869         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8870     g_free (name);
8871
8872     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8873       gst_object_unref (stream->pad);
8874       stream->pad = NULL;
8875       ret = FALSE;
8876       goto done;
8877     }
8878
8879     qtdemux->n_video_streams++;
8880   } else if (stream->subtype == FOURCC_soun) {
8881     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8882
8883     stream->pad =
8884         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8885     g_free (name);
8886     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8887       gst_object_unref (stream->pad);
8888       stream->pad = NULL;
8889       ret = FALSE;
8890       goto done;
8891     }
8892     qtdemux->n_audio_streams++;
8893   } else if (stream->subtype == FOURCC_strm) {
8894     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8895   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8896       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8897       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
8898     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8899
8900     stream->pad =
8901         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8902     g_free (name);
8903     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8904       gst_object_unref (stream->pad);
8905       stream->pad = NULL;
8906       ret = FALSE;
8907       goto done;
8908     }
8909     qtdemux->n_sub_streams++;
8910   } else if (CUR_STREAM (stream)->caps) {
8911     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8912
8913     stream->pad =
8914         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8915     g_free (name);
8916     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8917       gst_object_unref (stream->pad);
8918       stream->pad = NULL;
8919       ret = FALSE;
8920       goto done;
8921     }
8922     qtdemux->n_video_streams++;
8923   } else {
8924     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8925     goto done;
8926   }
8927
8928   if (stream->pad) {
8929     GList *l;
8930
8931     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8932         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8933     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8934     GST_OBJECT_LOCK (qtdemux);
8935     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8936     GST_OBJECT_UNLOCK (qtdemux);
8937
8938     if (stream->stream_tags)
8939       gst_tag_list_unref (stream->stream_tags);
8940     stream->stream_tags = list;
8941     list = NULL;
8942     /* global tags go on each pad anyway */
8943     stream->send_global_tags = TRUE;
8944     /* send upstream GST_EVENT_PROTECTION events that were received before
8945        this source pad was created */
8946     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8947       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8948   }
8949 done:
8950   if (list)
8951     gst_tag_list_unref (list);
8952   return ret;
8953 }
8954
8955 /* find next atom with @fourcc starting at @offset */
8956 static GstFlowReturn
8957 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8958     guint64 * length, guint32 fourcc)
8959 {
8960   GstFlowReturn ret;
8961   guint32 lfourcc;
8962   GstBuffer *buf;
8963
8964   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8965       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8966
8967   while (TRUE) {
8968     GstMapInfo map;
8969
8970     buf = NULL;
8971     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8972     if (G_UNLIKELY (ret != GST_FLOW_OK))
8973       goto locate_failed;
8974     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8975       /* likely EOF */
8976       ret = GST_FLOW_EOS;
8977       gst_buffer_unref (buf);
8978       goto locate_failed;
8979     }
8980     gst_buffer_map (buf, &map, GST_MAP_READ);
8981     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8982     gst_buffer_unmap (buf, &map);
8983     gst_buffer_unref (buf);
8984
8985     if (G_UNLIKELY (*length == 0)) {
8986       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8987       ret = GST_FLOW_ERROR;
8988       goto locate_failed;
8989     }
8990
8991     if (lfourcc == fourcc) {
8992       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
8993           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8994       break;
8995     } else {
8996       GST_LOG_OBJECT (qtdemux,
8997           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8998           GST_FOURCC_ARGS (lfourcc), *offset);
8999       if (*offset == G_MAXUINT64)
9000         goto locate_failed;
9001       *offset += *length;
9002     }
9003   }
9004
9005   return GST_FLOW_OK;
9006
9007 locate_failed:
9008   {
9009     /* might simply have had last one */
9010     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9011     return ret;
9012   }
9013 }
9014
9015 /* should only do something in pull mode */
9016 /* call with OBJECT lock */
9017 static GstFlowReturn
9018 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9019 {
9020   guint64 length, offset;
9021   GstBuffer *buf = NULL;
9022   GstFlowReturn ret = GST_FLOW_OK;
9023   GstFlowReturn res = GST_FLOW_OK;
9024   GstMapInfo map;
9025
9026   offset = qtdemux->moof_offset;
9027   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9028
9029   if (!offset) {
9030     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9031     return GST_FLOW_EOS;
9032   }
9033
9034   /* best not do pull etc with lock held */
9035   GST_OBJECT_UNLOCK (qtdemux);
9036
9037   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9038   if (ret != GST_FLOW_OK)
9039     goto flow_failed;
9040
9041   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9042   if (G_UNLIKELY (ret != GST_FLOW_OK))
9043     goto flow_failed;
9044   gst_buffer_map (buf, &map, GST_MAP_READ);
9045   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9046     gst_buffer_unmap (buf, &map);
9047     gst_buffer_unref (buf);
9048     buf = NULL;
9049     goto parse_failed;
9050   }
9051
9052   gst_buffer_unmap (buf, &map);
9053   gst_buffer_unref (buf);
9054   buf = NULL;
9055
9056   offset += length;
9057   /* look for next moof */
9058   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9059   if (G_UNLIKELY (ret != GST_FLOW_OK))
9060     goto flow_failed;
9061
9062 exit:
9063   GST_OBJECT_LOCK (qtdemux);
9064
9065   qtdemux->moof_offset = offset;
9066
9067   return res;
9068
9069 parse_failed:
9070   {
9071     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9072     offset = 0;
9073     res = GST_FLOW_ERROR;
9074     goto exit;
9075   }
9076 flow_failed:
9077   {
9078     /* maybe upstream temporarily flushing */
9079     if (ret != GST_FLOW_FLUSHING) {
9080       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9081       offset = 0;
9082     } else {
9083       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9084       /* resume at current position next time */
9085     }
9086     res = ret;
9087     goto exit;
9088   }
9089 }
9090
9091 static void
9092 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9093 {
9094   guint i;
9095   guint32 num_chunks;
9096   gint32 stts_duration;
9097   GstByteWriter stsc, stts, stsz;
9098
9099   /* Each sample has a different size, which we don't support for merging */
9100   if (stream->sample_size == 0) {
9101     GST_DEBUG_OBJECT (qtdemux,
9102         "Not all samples have the same size, not merging");
9103     return;
9104   }
9105
9106   /* The stream has a ctts table, we don't support that */
9107   if (stream->ctts_present) {
9108     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9109     return;
9110   }
9111
9112   /* If there's a sync sample table also ignore this stream */
9113   if (stream->stps_present || stream->stss_present) {
9114     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9115     return;
9116   }
9117
9118   /* If chunks are considered samples already ignore this stream */
9119   if (stream->chunks_are_samples) {
9120     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9121     return;
9122   }
9123
9124   /* Require that all samples have the same duration */
9125   if (stream->n_sample_times > 1) {
9126     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9127     return;
9128   }
9129
9130   /* Parse the stts to get the sample duration and number of samples */
9131   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9132   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9133
9134   /* Parse the number of chunks from the stco manually because the
9135    * reader is already behind that */
9136   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9137
9138   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9139       num_chunks);
9140
9141   /* Now parse stsc, convert chunks into single samples and generate a
9142    * new stsc, stts and stsz from this information */
9143   gst_byte_writer_init (&stsc);
9144   gst_byte_writer_init (&stts);
9145   gst_byte_writer_init (&stsz);
9146
9147   /* Note: we skip fourccs, size, version, flags and other fields of the new
9148    * atoms as the byte readers with them are already behind that position
9149    * anyway and only update the values of those inside the stream directly.
9150    */
9151   stream->n_sample_times = 0;
9152   stream->n_samples = 0;
9153   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9154     guint j;
9155     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9156
9157     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9158     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9159     sample_description_id =
9160         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9161
9162     if (i == stream->n_samples_per_chunk - 1) {
9163       /* +1 because first_chunk is 1-based */
9164       last_chunk = num_chunks + 1;
9165     } else {
9166       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9167     }
9168
9169     GST_DEBUG_OBJECT (qtdemux,
9170         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9171         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9172
9173     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9174     /* One sample in this chunk */
9175     gst_byte_writer_put_uint32_be (&stsc, 1);
9176     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9177
9178     /* For each chunk write a stts and stsz entry now */
9179     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9180     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9181     for (j = first_chunk; j < last_chunk; j++) {
9182       gst_byte_writer_put_uint32_be (&stsz,
9183           stream->sample_size * samples_per_chunk);
9184     }
9185
9186     stream->n_sample_times += 1;
9187     stream->n_samples += last_chunk - first_chunk;
9188   }
9189
9190   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9191
9192   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9193       stream->n_samples, stream->n_sample_times);
9194
9195   /* We don't have a fixed sample size anymore */
9196   stream->sample_size = 0;
9197
9198   /* Free old data for the atoms */
9199   g_free ((gpointer) stream->stsz.data);
9200   stream->stsz.data = NULL;
9201   g_free ((gpointer) stream->stsc.data);
9202   stream->stsc.data = NULL;
9203   g_free ((gpointer) stream->stts.data);
9204   stream->stts.data = NULL;
9205
9206   /* Store new data and replace byte readers */
9207   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9208   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9209   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9210   stream->stts.size = gst_byte_writer_get_size (&stts);
9211   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9212   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9213   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9214   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9215   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9216 }
9217
9218 /* initialise bytereaders for stbl sub-atoms */
9219 static gboolean
9220 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9221 {
9222   stream->stbl_index = -1;      /* no samples have yet been parsed */
9223   stream->sample_index = -1;
9224
9225   /* time-to-sample atom */
9226   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9227     goto corrupt_file;
9228
9229   /* copy atom data into a new buffer for later use */
9230   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9231
9232   /* skip version + flags */
9233   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9234       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9235     goto corrupt_file;
9236   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9237
9238   /* make sure there's enough data */
9239   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9240     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9241     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9242         stream->n_sample_times);
9243     if (!stream->n_sample_times)
9244       goto corrupt_file;
9245   }
9246
9247   /* sync sample atom */
9248   stream->stps_present = FALSE;
9249   if ((stream->stss_present =
9250           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9251               &stream->stss) ? TRUE : FALSE) == TRUE) {
9252     /* copy atom data into a new buffer for later use */
9253     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9254
9255     /* skip version + flags */
9256     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9257         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9258       goto corrupt_file;
9259
9260     if (stream->n_sample_syncs) {
9261       /* make sure there's enough data */
9262       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9263         goto corrupt_file;
9264     }
9265
9266     /* partial sync sample atom */
9267     if ((stream->stps_present =
9268             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9269                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9270       /* copy atom data into a new buffer for later use */
9271       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9272
9273       /* skip version + flags */
9274       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9275           !gst_byte_reader_get_uint32_be (&stream->stps,
9276               &stream->n_sample_partial_syncs))
9277         goto corrupt_file;
9278
9279       /* if there are no entries, the stss table contains the real
9280        * sync samples */
9281       if (stream->n_sample_partial_syncs) {
9282         /* make sure there's enough data */
9283         if (!qt_atom_parser_has_chunks (&stream->stps,
9284                 stream->n_sample_partial_syncs, 4))
9285           goto corrupt_file;
9286       }
9287     }
9288   }
9289
9290   /* sample size */
9291   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9292     goto no_samples;
9293
9294   /* copy atom data into a new buffer for later use */
9295   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9296
9297   /* skip version + flags */
9298   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9299       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9300     goto corrupt_file;
9301
9302   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9303     goto corrupt_file;
9304
9305   if (!stream->n_samples)
9306     goto no_samples;
9307
9308   /* sample-to-chunk atom */
9309   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9310     goto corrupt_file;
9311
9312   /* copy atom data into a new buffer for later use */
9313   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9314
9315   /* skip version + flags */
9316   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9317       !gst_byte_reader_get_uint32_be (&stream->stsc,
9318           &stream->n_samples_per_chunk))
9319     goto corrupt_file;
9320
9321   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9322       stream->n_samples_per_chunk);
9323
9324   /* make sure there's enough data */
9325   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9326           12))
9327     goto corrupt_file;
9328
9329
9330   /* chunk offset */
9331   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9332     stream->co_size = sizeof (guint32);
9333   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9334           &stream->stco))
9335     stream->co_size = sizeof (guint64);
9336   else
9337     goto corrupt_file;
9338
9339   /* copy atom data into a new buffer for later use */
9340   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9341
9342   /* skip version + flags */
9343   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9344     goto corrupt_file;
9345
9346   /* chunks_are_samples == TRUE means treat chunks as samples */
9347   stream->chunks_are_samples = stream->sample_size
9348       && !CUR_STREAM (stream)->sampled;
9349   if (stream->chunks_are_samples) {
9350     /* treat chunks as samples */
9351     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9352       goto corrupt_file;
9353   } else {
9354     /* skip number of entries */
9355     if (!gst_byte_reader_skip (&stream->stco, 4))
9356       goto corrupt_file;
9357
9358     /* make sure there are enough data in the stsz atom */
9359     if (!stream->sample_size) {
9360       /* different sizes for each sample */
9361       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9362         goto corrupt_file;
9363     }
9364   }
9365
9366   /* composition time-to-sample */
9367   if ((stream->ctts_present =
9368           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9369               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9370     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9371
9372     /* copy atom data into a new buffer for later use */
9373     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9374
9375     /* skip version + flags */
9376     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9377         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9378             &stream->n_composition_times))
9379       goto corrupt_file;
9380
9381     /* make sure there's enough data */
9382     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9383             4 + 4))
9384       goto corrupt_file;
9385
9386     /* This is optional, if missing we iterate the ctts */
9387     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9388       guint8 cslg_version;
9389
9390       /* cslg version 1 has 64 bit fields */
9391       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9392         goto corrupt_file;
9393
9394       /* skip flags */
9395       if (!gst_byte_reader_skip (&cslg, 3))
9396         goto corrupt_file;
9397
9398       if (cslg_version == 0) {
9399         gint32 composition_to_dts_shift;
9400
9401         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9402           goto corrupt_file;
9403
9404         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9405       } else {
9406         gint64 composition_to_dts_shift;
9407
9408         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9409           goto corrupt_file;
9410
9411         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9412       }
9413     } else {
9414       gint32 cslg_least = 0;
9415       guint num_entries, pos;
9416       gint i;
9417
9418       pos = gst_byte_reader_get_pos (&stream->ctts);
9419       num_entries = stream->n_composition_times;
9420
9421       stream->cslg_shift = 0;
9422
9423       for (i = 0; i < num_entries; i++) {
9424         gint32 offset;
9425
9426         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9427         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9428         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9429          * slightly inaccurate PTS could be more usable than corrupted one */
9430         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9431           GST_WARNING_OBJECT (qtdemux,
9432               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9433               " larger than duration %" G_GUINT64_FORMAT,
9434               offset, stream->duration);
9435
9436           stream->cslg_shift = 0;
9437           stream->ctts_present = FALSE;
9438           goto done;
9439         }
9440
9441         if (offset < cslg_least)
9442           cslg_least = offset;
9443       }
9444
9445       if (cslg_least < 0)
9446         stream->cslg_shift = ABS (cslg_least);
9447       else
9448         stream->cslg_shift = 0;
9449
9450       /* reset the reader so we can generate sample table */
9451       gst_byte_reader_set_pos (&stream->ctts, pos);
9452     }
9453   } else {
9454     /* Ensure the cslg_shift value is consistent so we can use it
9455      * unconditionally to produce TS and Segment */
9456     stream->cslg_shift = 0;
9457   }
9458
9459   /* For raw audio streams especially we might want to merge the samples
9460    * to not output one audio sample per buffer. We're doing this here
9461    * before allocating the sample tables so that from this point onwards
9462    * the number of container samples are static */
9463   if (stream->min_buffer_size > 0) {
9464     qtdemux_merge_sample_table (qtdemux, stream);
9465   }
9466
9467 done:
9468   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9469       stream->n_samples, (guint) sizeof (QtDemuxSample),
9470       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9471
9472   if (stream->n_samples >=
9473       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9474     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9475         "be larger than %uMB (broken file?)", stream->n_samples,
9476         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9477     return FALSE;
9478   }
9479
9480   g_assert (stream->samples == NULL);
9481   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9482   if (!stream->samples) {
9483     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9484         stream->n_samples);
9485     return FALSE;
9486   }
9487
9488   return TRUE;
9489
9490 corrupt_file:
9491   {
9492     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9493         (_("This file is corrupt and cannot be played.")), (NULL));
9494     return FALSE;
9495   }
9496 no_samples:
9497   {
9498     gst_qtdemux_stbl_free (stream);
9499     if (!qtdemux->fragmented) {
9500       /* not quite good */
9501       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9502       return FALSE;
9503     } else {
9504       /* may pick up samples elsewhere */
9505       return TRUE;
9506     }
9507   }
9508 }
9509
9510 /* collect samples from the next sample to be parsed up to sample @n for @stream
9511  * by reading the info from @stbl
9512  *
9513  * This code can be executed from both the streaming thread and the seeking
9514  * thread so it takes the object lock to protect itself
9515  */
9516 static gboolean
9517 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9518 {
9519   gint i, j, k;
9520   QtDemuxSample *samples, *first, *cur, *last;
9521   guint32 n_samples_per_chunk;
9522   guint32 n_samples;
9523
9524   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9525       GST_FOURCC_FORMAT ", pad %s",
9526       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9527       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9528
9529   n_samples = stream->n_samples;
9530
9531   if (n >= n_samples)
9532     goto out_of_samples;
9533
9534   GST_OBJECT_LOCK (qtdemux);
9535   if (n <= stream->stbl_index)
9536     goto already_parsed;
9537
9538   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9539
9540   if (!stream->stsz.data) {
9541     /* so we already parsed and passed all the moov samples;
9542      * onto fragmented ones */
9543     g_assert (qtdemux->fragmented);
9544     goto done;
9545   }
9546
9547   /* pointer to the sample table */
9548   samples = stream->samples;
9549
9550   /* starts from -1, moves to the next sample index to parse */
9551   stream->stbl_index++;
9552
9553   /* keep track of the first and last sample to fill */
9554   first = &samples[stream->stbl_index];
9555   last = &samples[n];
9556
9557   if (!stream->chunks_are_samples) {
9558     /* set the sample sizes */
9559     if (stream->sample_size == 0) {
9560       /* different sizes for each sample */
9561       for (cur = first; cur <= last; cur++) {
9562         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9563         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9564             (guint) (cur - samples), cur->size);
9565       }
9566     } else {
9567       /* samples have the same size */
9568       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9569       for (cur = first; cur <= last; cur++)
9570         cur->size = stream->sample_size;
9571     }
9572   }
9573
9574   n_samples_per_chunk = stream->n_samples_per_chunk;
9575   cur = first;
9576
9577   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9578     guint32 last_chunk;
9579
9580     if (stream->stsc_chunk_index >= stream->last_chunk
9581         || stream->stsc_chunk_index < stream->first_chunk) {
9582       stream->first_chunk =
9583           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9584       stream->samples_per_chunk =
9585           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9586       /* starts from 1 */
9587       stream->stsd_sample_description_id =
9588           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9589
9590       /* chunk numbers are counted from 1 it seems */
9591       if (G_UNLIKELY (stream->first_chunk == 0))
9592         goto corrupt_file;
9593
9594       --stream->first_chunk;
9595
9596       /* the last chunk of each entry is calculated by taking the first chunk
9597        * of the next entry; except if there is no next, where we fake it with
9598        * INT_MAX */
9599       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9600         stream->last_chunk = G_MAXUINT32;
9601       } else {
9602         stream->last_chunk =
9603             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9604         if (G_UNLIKELY (stream->last_chunk == 0))
9605           goto corrupt_file;
9606
9607         --stream->last_chunk;
9608       }
9609
9610       GST_LOG_OBJECT (qtdemux,
9611           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9612           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9613           stream->samples_per_chunk, stream->stsd_sample_description_id);
9614
9615       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9616         goto corrupt_file;
9617
9618       if (stream->last_chunk != G_MAXUINT32) {
9619         if (!qt_atom_parser_peek_sub (&stream->stco,
9620                 stream->first_chunk * stream->co_size,
9621                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9622                 &stream->co_chunk))
9623           goto corrupt_file;
9624
9625       } else {
9626         stream->co_chunk = stream->stco;
9627         if (!gst_byte_reader_skip (&stream->co_chunk,
9628                 stream->first_chunk * stream->co_size))
9629           goto corrupt_file;
9630       }
9631
9632       stream->stsc_chunk_index = stream->first_chunk;
9633     }
9634
9635     last_chunk = stream->last_chunk;
9636
9637     if (stream->chunks_are_samples) {
9638       cur = &samples[stream->stsc_chunk_index];
9639
9640       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9641         if (j > n) {
9642           /* save state */
9643           stream->stsc_chunk_index = j;
9644           goto done;
9645         }
9646
9647         cur->offset =
9648             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9649             stream->co_size);
9650
9651         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9652             "%" G_GUINT64_FORMAT, j, cur->offset);
9653
9654         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9655             CUR_STREAM (stream)->bytes_per_frame > 0) {
9656           cur->size =
9657               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9658               CUR_STREAM (stream)->samples_per_frame *
9659               CUR_STREAM (stream)->bytes_per_frame;
9660         } else {
9661           cur->size = stream->samples_per_chunk;
9662         }
9663
9664         GST_DEBUG_OBJECT (qtdemux,
9665             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9666             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9667                     stream->stco_sample_index)), cur->size);
9668
9669         cur->timestamp = stream->stco_sample_index;
9670         cur->duration = stream->samples_per_chunk;
9671         cur->keyframe = TRUE;
9672         cur++;
9673
9674         stream->stco_sample_index += stream->samples_per_chunk;
9675       }
9676       stream->stsc_chunk_index = j;
9677     } else {
9678       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9679         guint32 samples_per_chunk;
9680         guint64 chunk_offset;
9681
9682         if (!stream->stsc_sample_index
9683             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9684                 &stream->chunk_offset))
9685           goto corrupt_file;
9686
9687         samples_per_chunk = stream->samples_per_chunk;
9688         chunk_offset = stream->chunk_offset;
9689
9690         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9691           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9692               G_GUINT64_FORMAT " and size %d",
9693               (guint) (cur - samples), chunk_offset, cur->size);
9694
9695           cur->offset = chunk_offset;
9696           chunk_offset += cur->size;
9697           cur++;
9698
9699           if (G_UNLIKELY (cur > last)) {
9700             /* save state */
9701             stream->stsc_sample_index = k + 1;
9702             stream->chunk_offset = chunk_offset;
9703             stream->stsc_chunk_index = j;
9704             goto done2;
9705           }
9706         }
9707         stream->stsc_sample_index = 0;
9708       }
9709       stream->stsc_chunk_index = j;
9710     }
9711     stream->stsc_index++;
9712   }
9713
9714   if (stream->chunks_are_samples)
9715     goto ctts;
9716 done2:
9717   {
9718     guint32 n_sample_times;
9719
9720     n_sample_times = stream->n_sample_times;
9721     cur = first;
9722
9723     for (i = stream->stts_index; i < n_sample_times; i++) {
9724       guint32 stts_samples;
9725       gint32 stts_duration;
9726       gint64 stts_time;
9727
9728       if (stream->stts_sample_index >= stream->stts_samples
9729           || !stream->stts_sample_index) {
9730
9731         stream->stts_samples =
9732             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9733         stream->stts_duration =
9734             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9735
9736         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9737             i, stream->stts_samples, stream->stts_duration);
9738
9739         stream->stts_sample_index = 0;
9740       }
9741
9742       stts_samples = stream->stts_samples;
9743       stts_duration = stream->stts_duration;
9744       stts_time = stream->stts_time;
9745
9746       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9747         GST_DEBUG_OBJECT (qtdemux,
9748             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9749             (guint) (cur - samples), j,
9750             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9751
9752         cur->timestamp = stts_time;
9753         cur->duration = stts_duration;
9754
9755         /* avoid 32-bit wrap-around,
9756          * but still mind possible 'negative' duration */
9757         stts_time += (gint64) stts_duration;
9758         cur++;
9759
9760         if (G_UNLIKELY (cur > last)) {
9761           /* save values */
9762           stream->stts_time = stts_time;
9763           stream->stts_sample_index = j + 1;
9764           if (stream->stts_sample_index >= stream->stts_samples)
9765             stream->stts_index++;
9766           goto done3;
9767         }
9768       }
9769       stream->stts_sample_index = 0;
9770       stream->stts_time = stts_time;
9771       stream->stts_index++;
9772     }
9773     /* fill up empty timestamps with the last timestamp, this can happen when
9774      * the last samples do not decode and so we don't have timestamps for them.
9775      * We however look at the last timestamp to estimate the track length so we
9776      * need something in here. */
9777     for (; cur < last; cur++) {
9778       GST_DEBUG_OBJECT (qtdemux,
9779           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9780           (guint) (cur - samples),
9781           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9782       cur->timestamp = stream->stts_time;
9783       cur->duration = -1;
9784     }
9785   }
9786 done3:
9787   {
9788     /* sample sync, can be NULL */
9789     if (stream->stss_present == TRUE) {
9790       guint32 n_sample_syncs;
9791
9792       n_sample_syncs = stream->n_sample_syncs;
9793
9794       if (!n_sample_syncs) {
9795         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9796         stream->all_keyframe = TRUE;
9797       } else {
9798         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9799           /* note that the first sample is index 1, not 0 */
9800           guint32 index;
9801
9802           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9803
9804           if (G_LIKELY (index > 0 && index <= n_samples)) {
9805             index -= 1;
9806             samples[index].keyframe = TRUE;
9807             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9808             /* and exit if we have enough samples */
9809             if (G_UNLIKELY (index >= n)) {
9810               i++;
9811               break;
9812             }
9813           }
9814         }
9815         /* save state */
9816         stream->stss_index = i;
9817       }
9818
9819       /* stps marks partial sync frames like open GOP I-Frames */
9820       if (stream->stps_present == TRUE) {
9821         guint32 n_sample_partial_syncs;
9822
9823         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9824
9825         /* if there are no entries, the stss table contains the real
9826          * sync samples */
9827         if (n_sample_partial_syncs) {
9828           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9829             /* note that the first sample is index 1, not 0 */
9830             guint32 index;
9831
9832             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9833
9834             if (G_LIKELY (index > 0 && index <= n_samples)) {
9835               index -= 1;
9836               samples[index].keyframe = TRUE;
9837               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9838               /* and exit if we have enough samples */
9839               if (G_UNLIKELY (index >= n)) {
9840                 i++;
9841                 break;
9842               }
9843             }
9844           }
9845           /* save state */
9846           stream->stps_index = i;
9847         }
9848       }
9849     } else {
9850       /* no stss, all samples are keyframes */
9851       stream->all_keyframe = TRUE;
9852       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9853     }
9854   }
9855
9856 ctts:
9857   /* composition time to sample */
9858   if (stream->ctts_present == TRUE) {
9859     guint32 n_composition_times;
9860     guint32 ctts_count;
9861     gint32 ctts_soffset;
9862
9863     /* Fill in the pts_offsets */
9864     cur = first;
9865     n_composition_times = stream->n_composition_times;
9866
9867     for (i = stream->ctts_index; i < n_composition_times; i++) {
9868       if (stream->ctts_sample_index >= stream->ctts_count
9869           || !stream->ctts_sample_index) {
9870         stream->ctts_count =
9871             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9872         stream->ctts_soffset =
9873             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9874         stream->ctts_sample_index = 0;
9875       }
9876
9877       ctts_count = stream->ctts_count;
9878       ctts_soffset = stream->ctts_soffset;
9879
9880       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9881         cur->pts_offset = ctts_soffset;
9882         cur++;
9883
9884         if (G_UNLIKELY (cur > last)) {
9885           /* save state */
9886           stream->ctts_sample_index = j + 1;
9887           goto done;
9888         }
9889       }
9890       stream->ctts_sample_index = 0;
9891       stream->ctts_index++;
9892     }
9893   }
9894 done:
9895   stream->stbl_index = n;
9896   /* if index has been completely parsed, free data that is no-longer needed */
9897   if (n + 1 == stream->n_samples) {
9898     gst_qtdemux_stbl_free (stream);
9899     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9900     if (qtdemux->pullbased) {
9901       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9902       while (n + 1 == stream->n_samples)
9903         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9904           break;
9905     }
9906   }
9907   GST_OBJECT_UNLOCK (qtdemux);
9908
9909   return TRUE;
9910
9911   /* SUCCESS */
9912 already_parsed:
9913   {
9914     GST_LOG_OBJECT (qtdemux,
9915         "Tried to parse up to sample %u but this sample has already been parsed",
9916         n);
9917     /* if fragmented, there may be more */
9918     if (qtdemux->fragmented && n == stream->stbl_index)
9919       goto done;
9920     GST_OBJECT_UNLOCK (qtdemux);
9921     return TRUE;
9922   }
9923   /* ERRORS */
9924 out_of_samples:
9925   {
9926     GST_LOG_OBJECT (qtdemux,
9927         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9928         stream->n_samples);
9929     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9930         (_("This file is corrupt and cannot be played.")), (NULL));
9931     return FALSE;
9932   }
9933 corrupt_file:
9934   {
9935     GST_OBJECT_UNLOCK (qtdemux);
9936     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9937         (_("This file is corrupt and cannot be played.")), (NULL));
9938     return FALSE;
9939   }
9940 }
9941
9942 /* collect all segment info for @stream.
9943  */
9944 static gboolean
9945 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9946     GNode * trak)
9947 {
9948   GNode *edts;
9949   /* accept edts if they contain gaps at start and there is only
9950    * one media segment */
9951   gboolean allow_pushbased_edts = TRUE;
9952   gint media_segments_count = 0;
9953
9954   /* parse and prepare segment info from the edit list */
9955   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9956   stream->n_segments = 0;
9957   stream->segments = NULL;
9958   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9959     GNode *elst;
9960     gint n_segments;
9961     gint segment_number, entry_size;
9962     guint64 time;
9963     GstClockTime stime;
9964     const guint8 *buffer;
9965     guint8 version;
9966     guint32 size;
9967
9968     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9969     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9970       goto done;
9971
9972     buffer = elst->data;
9973
9974     size = QT_UINT32 (buffer);
9975     /* version, flags, n_segments */
9976     if (size < 16) {
9977       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9978       goto done;
9979     }
9980     version = QT_UINT8 (buffer + 8);
9981     entry_size = (version == 1) ? 20 : 12;
9982
9983     n_segments = QT_UINT32 (buffer + 12);
9984
9985     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9986       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9987       goto done;
9988     }
9989
9990     /* we might allocate a bit too much, at least allocate 1 segment */
9991     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9992
9993     /* segments always start from 0 */
9994     time = 0;
9995     stime = 0;
9996     buffer += 16;
9997     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9998       guint64 duration;
9999       guint64 media_time;
10000       gboolean empty_edit = FALSE;
10001       QtDemuxSegment *segment;
10002       guint32 rate_int;
10003       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10004
10005       if (version == 1) {
10006         media_time = QT_UINT64 (buffer + 8);
10007         duration = QT_UINT64 (buffer);
10008         if (media_time == G_MAXUINT64)
10009           empty_edit = TRUE;
10010       } else {
10011         media_time = QT_UINT32 (buffer + 4);
10012         duration = QT_UINT32 (buffer);
10013         if (media_time == G_MAXUINT32)
10014           empty_edit = TRUE;
10015       }
10016
10017       if (!empty_edit)
10018         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10019
10020       segment = &stream->segments[segment_number];
10021
10022       /* time and duration expressed in global timescale */
10023       segment->time = stime;
10024       if (duration != 0 || empty_edit) {
10025         /* edge case: empty edits with duration=zero are treated here.
10026          * (files should not have these anyway). */
10027
10028         /* add non scaled values so we don't cause roundoff errors */
10029         time += duration;
10030         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10031         segment->duration = stime - segment->time;
10032       } else {
10033         /* zero duration does not imply media_start == media_stop
10034          * but, only specify media_start. The edit ends with the track. */
10035         stime = segment->duration = GST_CLOCK_TIME_NONE;
10036         /* Don't allow more edits after this one. */
10037         n_segments = segment_number + 1;
10038       }
10039       segment->stop_time = stime;
10040
10041       segment->trak_media_start = media_time;
10042       /* media_time expressed in stream timescale */
10043       if (!empty_edit) {
10044         segment->media_start = media_start;
10045         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10046             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10047         media_segments_count++;
10048       } else {
10049         segment->media_start = GST_CLOCK_TIME_NONE;
10050         segment->media_stop = GST_CLOCK_TIME_NONE;
10051       }
10052       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10053
10054       if (rate_int <= 1) {
10055         /* 0 is not allowed, some programs write 1 instead of the floating point
10056          * value */
10057         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10058             rate_int);
10059         segment->rate = 1;
10060       } else {
10061         segment->rate = rate_int / 65536.0;
10062       }
10063
10064       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10065           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10066           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10067           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10068           segment_number, GST_TIME_ARGS (segment->time),
10069           GST_TIME_ARGS (segment->duration),
10070           GST_TIME_ARGS (segment->media_start), media_time,
10071           GST_TIME_ARGS (segment->media_stop),
10072           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10073           stream->timescale);
10074       if (segment->stop_time > qtdemux->segment.stop &&
10075           !qtdemux->upstream_format_is_time) {
10076         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10077             " extends to %" GST_TIME_FORMAT
10078             " past the end of the declared movie duration %" GST_TIME_FORMAT
10079             " movie segment will be extended", segment_number,
10080             GST_TIME_ARGS (segment->stop_time),
10081             GST_TIME_ARGS (qtdemux->segment.stop));
10082         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10083       }
10084
10085       buffer += entry_size;
10086     }
10087     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10088     stream->n_segments = n_segments;
10089     if (media_segments_count != 1)
10090       allow_pushbased_edts = FALSE;
10091   }
10092 done:
10093
10094   /* push based does not handle segments, so act accordingly here,
10095    * and warn if applicable */
10096   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10097     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10098     /* remove and use default one below, we stream like it anyway */
10099     g_free (stream->segments);
10100     stream->segments = NULL;
10101     stream->n_segments = 0;
10102   }
10103
10104   /* no segments, create one to play the complete trak */
10105   if (stream->n_segments == 0) {
10106     GstClockTime stream_duration =
10107         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10108
10109     if (stream->segments == NULL)
10110       stream->segments = g_new (QtDemuxSegment, 1);
10111
10112     /* represent unknown our way */
10113     if (stream_duration == 0)
10114       stream_duration = GST_CLOCK_TIME_NONE;
10115
10116     stream->segments[0].time = 0;
10117     stream->segments[0].stop_time = stream_duration;
10118     stream->segments[0].duration = stream_duration;
10119     stream->segments[0].media_start = 0;
10120     stream->segments[0].media_stop = stream_duration;
10121     stream->segments[0].rate = 1.0;
10122     stream->segments[0].trak_media_start = 0;
10123
10124     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10125         GST_TIME_ARGS (stream_duration));
10126     stream->n_segments = 1;
10127     stream->dummy_segment = TRUE;
10128   }
10129   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10130
10131   return TRUE;
10132 }
10133
10134 /*
10135  * Parses the stsd atom of a svq3 trak looking for
10136  * the SMI and gama atoms.
10137  */
10138 static void
10139 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10140     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10141 {
10142   const guint8 *_gamma = NULL;
10143   GstBuffer *_seqh = NULL;
10144   const guint8 *stsd_data = stsd_entry_data;
10145   guint32 length = QT_UINT32 (stsd_data);
10146   guint16 version;
10147
10148   if (length < 32) {
10149     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10150     goto end;
10151   }
10152
10153   stsd_data += 16;
10154   length -= 16;
10155   version = QT_UINT16 (stsd_data);
10156   if (version == 3) {
10157     if (length >= 70) {
10158       length -= 70;
10159       stsd_data += 70;
10160       while (length > 8) {
10161         guint32 fourcc, size;
10162         const guint8 *data;
10163         size = QT_UINT32 (stsd_data);
10164         fourcc = QT_FOURCC (stsd_data + 4);
10165         data = stsd_data + 8;
10166
10167         if (size == 0) {
10168           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10169               "svq3 atom parsing");
10170           goto end;
10171         }
10172
10173         switch (fourcc) {
10174           case FOURCC_gama:{
10175             if (size == 12) {
10176               _gamma = data;
10177             } else {
10178               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10179                   " for gama atom, expected 12", size);
10180             }
10181             break;
10182           }
10183           case FOURCC_SMI_:{
10184             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10185               guint32 seqh_size;
10186               if (_seqh != NULL) {
10187                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10188                     " found, ignoring");
10189               } else {
10190                 seqh_size = QT_UINT32 (data + 4);
10191                 if (seqh_size > 0) {
10192                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10193                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10194                 }
10195               }
10196             }
10197             break;
10198           }
10199           default:{
10200             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10201                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10202           }
10203         }
10204
10205         if (size <= length) {
10206           length -= size;
10207           stsd_data += size;
10208         }
10209       }
10210     } else {
10211       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10212     }
10213   } else {
10214     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10215         G_GUINT16_FORMAT, version);
10216     goto end;
10217   }
10218
10219 end:
10220   if (gamma) {
10221     *gamma = _gamma;
10222   }
10223   if (seqh) {
10224     *seqh = _seqh;
10225   } else if (_seqh) {
10226     gst_buffer_unref (_seqh);
10227   }
10228 }
10229
10230 static gchar *
10231 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10232 {
10233   GNode *dinf;
10234   GstByteReader dref;
10235   gchar *uri = NULL;
10236
10237   /*
10238    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10239    * atom that might contain a 'data' atom with the rtsp uri.
10240    * This case was reported in bug #597497, some info about
10241    * the hndl atom can be found in TN1195
10242    */
10243   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10244   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10245
10246   if (dinf) {
10247     guint32 dref_num_entries = 0;
10248     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10249         gst_byte_reader_skip (&dref, 4) &&
10250         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10251       gint i;
10252
10253       /* search dref entries for hndl atom */
10254       for (i = 0; i < dref_num_entries; i++) {
10255         guint32 size = 0, type;
10256         guint8 string_len = 0;
10257         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10258             qt_atom_parser_get_fourcc (&dref, &type)) {
10259           if (type == FOURCC_hndl) {
10260             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10261
10262             /* skip data reference handle bytes and the
10263              * following pascal string and some extra 4
10264              * bytes I have no idea what are */
10265             if (!gst_byte_reader_skip (&dref, 4) ||
10266                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10267                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10268               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10269               break;
10270             }
10271
10272             /* iterate over the atoms to find the data atom */
10273             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10274               guint32 atom_size;
10275               guint32 atom_type;
10276
10277               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10278                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10279                 if (atom_type == FOURCC_data) {
10280                   const guint8 *uri_aux = NULL;
10281
10282                   /* found the data atom that might contain the rtsp uri */
10283                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10284                       "hndl atom, interpreting it as an URI");
10285                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10286                           &uri_aux)) {
10287                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10288                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10289                     else
10290                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10291                           "didn't contain a rtsp address");
10292                   } else {
10293                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10294                         "atom contents");
10295                   }
10296                   break;
10297                 }
10298                 /* skipping to the next entry */
10299                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10300                   break;
10301               } else {
10302                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10303                     "atom header");
10304                 break;
10305               }
10306             }
10307             break;
10308           }
10309           /* skip to the next entry */
10310           if (!gst_byte_reader_skip (&dref, size - 8))
10311             break;
10312         } else {
10313           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10314         }
10315       }
10316       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10317     }
10318   }
10319   return uri;
10320 }
10321
10322 #define AMR_NB_ALL_MODES        0x81ff
10323 #define AMR_WB_ALL_MODES        0x83ff
10324 static guint
10325 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10326 {
10327   /* The 'damr' atom is of the form:
10328    *
10329    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10330    *    32 b       8 b          16 b           8 b                 8 b
10331    *
10332    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10333    * represents the highest mode used in the stream (and thus the maximum
10334    * bitrate), with a couple of special cases as seen below.
10335    */
10336
10337   /* Map of frame type ID -> bitrate */
10338   static const guint nb_bitrates[] = {
10339     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10340   };
10341   static const guint wb_bitrates[] = {
10342     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10343   };
10344   GstMapInfo map;
10345   gsize max_mode;
10346   guint16 mode_set;
10347
10348   gst_buffer_map (buf, &map, GST_MAP_READ);
10349
10350   if (map.size != 0x11) {
10351     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10352     goto bad_data;
10353   }
10354
10355   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10356     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10357         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10358     goto bad_data;
10359   }
10360
10361   mode_set = QT_UINT16 (map.data + 13);
10362
10363   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10364     max_mode = 7 + (wb ? 1 : 0);
10365   else
10366     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10367     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10368
10369   if (max_mode == -1) {
10370     GST_DEBUG ("No mode indication was found (mode set) = %x",
10371         (guint) mode_set);
10372     goto bad_data;
10373   }
10374
10375   gst_buffer_unmap (buf, &map);
10376   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10377
10378 bad_data:
10379   gst_buffer_unmap (buf, &map);
10380   return 0;
10381 }
10382
10383 static gboolean
10384 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10385     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10386 {
10387   /*
10388    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10389    * [0 1 2]
10390    * [3 4 5]
10391    * [6 7 8]
10392    */
10393
10394   if (gst_byte_reader_get_remaining (reader) < 36)
10395     return FALSE;
10396
10397   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10398   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10399   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10400   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10401   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10402   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10403   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10404   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10405   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10406
10407   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10408   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10409       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10410       matrix[2] & 0xFF);
10411   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10412       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10413       matrix[5] & 0xFF);
10414   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10415       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10416       matrix[8] & 0xFF);
10417
10418   return TRUE;
10419 }
10420
10421 static void
10422 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10423     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10424 {
10425
10426 /* [a b c]
10427  * [d e f]
10428  * [g h i]
10429  *
10430  * This macro will only compare value abdegh, it expects cfi to have already
10431  * been checked
10432  */
10433 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10434                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10435
10436   /* only handle the cases where the last column has standard values */
10437   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10438     const gchar *rotation_tag = NULL;
10439
10440     /* no rotation needed */
10441     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10442       /* NOP */
10443     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10444       rotation_tag = "rotate-90";
10445     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10446       rotation_tag = "rotate-180";
10447     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10448       rotation_tag = "rotate-270";
10449     } else {
10450       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10451     }
10452
10453     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10454         GST_STR_NULL (rotation_tag));
10455     if (rotation_tag != NULL) {
10456       if (*taglist == NULL)
10457         *taglist = gst_tag_list_new_empty ();
10458       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10459           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10460     }
10461   } else {
10462     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10463   }
10464 }
10465
10466 static gboolean
10467 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10468     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10469 {
10470   GNode *adrm;
10471   guint32 adrm_size;
10472   GstBuffer *adrm_buf = NULL;
10473   QtDemuxAavdEncryptionInfo *info;
10474
10475   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10476   if (G_UNLIKELY (!adrm)) {
10477     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10478     return FALSE;
10479   }
10480   adrm_size = QT_UINT32 (adrm->data);
10481   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10482
10483   stream->protection_scheme_type = FOURCC_aavd;
10484
10485   if (!stream->protection_scheme_info)
10486     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10487
10488   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10489
10490   if (info->default_properties)
10491     gst_structure_free (info->default_properties);
10492   info->default_properties = gst_structure_new ("application/x-aavd",
10493       "encrypted", G_TYPE_BOOLEAN, TRUE,
10494       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10495   gst_buffer_unref (adrm_buf);
10496
10497   *original_fmt = FOURCC_mp4a;
10498   return TRUE;
10499 }
10500
10501 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10502  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10503  * Common Encryption (cenc), the function will also parse the tenc box (defined
10504  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10505  * (typically an enc[v|a|t|s] sample entry); the function will set
10506  * @original_fmt to the fourcc of the original unencrypted stream format.
10507  * Returns TRUE if successful; FALSE otherwise. */
10508 static gboolean
10509 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10510     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10511 {
10512   GNode *sinf;
10513   GNode *frma;
10514   GNode *schm;
10515   GNode *schi;
10516   QtDemuxCencSampleSetInfo *info;
10517   GNode *tenc;
10518   const guint8 *tenc_data;
10519
10520   g_return_val_if_fail (qtdemux != NULL, FALSE);
10521   g_return_val_if_fail (stream != NULL, FALSE);
10522   g_return_val_if_fail (container != NULL, FALSE);
10523   g_return_val_if_fail (original_fmt != NULL, FALSE);
10524
10525   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10526   if (G_UNLIKELY (!sinf)) {
10527     if (stream->protection_scheme_type == FOURCC_cenc
10528         || stream->protection_scheme_type == FOURCC_cbcs) {
10529       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10530           "mandatory for Common Encryption");
10531       return FALSE;
10532     }
10533     return TRUE;
10534   }
10535
10536   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10537   if (G_UNLIKELY (!frma)) {
10538     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10539     return FALSE;
10540   }
10541
10542   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10543   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10544       GST_FOURCC_ARGS (*original_fmt));
10545
10546   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10547   if (!schm) {
10548     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10549     return FALSE;
10550   }
10551   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10552   stream->protection_scheme_version =
10553       QT_UINT32 ((const guint8 *) schm->data + 16);
10554
10555   GST_DEBUG_OBJECT (qtdemux,
10556       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10557       "protection_scheme_version: %#010x",
10558       GST_FOURCC_ARGS (stream->protection_scheme_type),
10559       stream->protection_scheme_version);
10560
10561   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10562   if (!schi) {
10563     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10564     return FALSE;
10565   }
10566   if (stream->protection_scheme_type != FOURCC_cenc &&
10567       stream->protection_scheme_type != FOURCC_piff &&
10568       stream->protection_scheme_type != FOURCC_cbcs) {
10569     GST_ERROR_OBJECT (qtdemux,
10570         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10571         GST_FOURCC_ARGS (stream->protection_scheme_type));
10572     return FALSE;
10573   }
10574
10575   if (G_UNLIKELY (!stream->protection_scheme_info))
10576     stream->protection_scheme_info =
10577         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10578
10579   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10580
10581   if (stream->protection_scheme_type == FOURCC_cenc
10582       || stream->protection_scheme_type == FOURCC_cbcs) {
10583     guint8 is_encrypted;
10584     guint8 iv_size;
10585     guint8 constant_iv_size = 0;
10586     const guint8 *default_kid;
10587     guint8 crypt_byte_block = 0;
10588     guint8 skip_byte_block = 0;
10589     const guint8 *constant_iv = NULL;
10590
10591     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10592     if (!tenc) {
10593       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10594           "which is mandatory for Common Encryption");
10595       return FALSE;
10596     }
10597     tenc_data = (const guint8 *) tenc->data + 12;
10598     is_encrypted = QT_UINT8 (tenc_data + 2);
10599     iv_size = QT_UINT8 (tenc_data + 3);
10600     default_kid = (tenc_data + 4);
10601     if (stream->protection_scheme_type == FOURCC_cbcs) {
10602       guint8 possible_pattern_info;
10603       if (iv_size == 0) {
10604         constant_iv_size = QT_UINT8 (tenc_data + 20);
10605         if (constant_iv_size != 8 && constant_iv_size != 16) {
10606           GST_ERROR_OBJECT (qtdemux,
10607               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10608           return FALSE;
10609         }
10610         constant_iv = (tenc_data + 21);
10611       }
10612       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10613       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10614       skip_byte_block = possible_pattern_info & 0x0f;
10615     }
10616     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10617         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10618         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10619   } else if (stream->protection_scheme_type == FOURCC_piff) {
10620     GstByteReader br;
10621     static const guint8 piff_track_encryption_uuid[] = {
10622       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10623       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10624     };
10625
10626     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10627     if (!tenc) {
10628       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10629           "which is mandatory for Common Encryption");
10630       return FALSE;
10631     }
10632
10633     tenc_data = (const guint8 *) tenc->data + 8;
10634     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10635       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10636       GST_ERROR_OBJECT (qtdemux,
10637           "Unsupported track encryption box with uuid: %s", box_uuid);
10638       g_free (box_uuid);
10639       return FALSE;
10640     }
10641     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10642     gst_byte_reader_init (&br, tenc_data, 20);
10643     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10644       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10645       return FALSE;
10646     }
10647     stream->protection_scheme_type = FOURCC_cenc;
10648   }
10649
10650   return TRUE;
10651 }
10652
10653 static gint
10654 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10655     QtDemuxStream ** stream2)
10656 {
10657   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10658 }
10659
10660 static gboolean
10661 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10662     GNode * stbl)
10663 {
10664   GNode *svmi;
10665
10666   /*parse svmi header if existing */
10667   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10668   if (svmi) {
10669     guint len = QT_UINT32 ((guint8 *) svmi->data);
10670     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10671     if (!version) {
10672       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10673       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10674       guint8 frame_type, frame_layout;
10675       guint32 stereo_mono_change_count;
10676
10677       if (len < 18)
10678         return FALSE;
10679
10680       /* MPEG-A stereo video */
10681       if (qtdemux->major_brand == FOURCC_ss02)
10682         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10683
10684       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10685       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10686       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10687
10688       switch (frame_type) {
10689         case 0:
10690           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10691           break;
10692         case 1:
10693           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10694           break;
10695         case 2:
10696           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10697           break;
10698         case 3:
10699           /* mode 3 is primary/secondary view sequence, ie
10700            * left/right views in separate tracks. See section 7.2
10701            * of ISO/IEC 23000-11:2009 */
10702           /* In the future this might be supported using related
10703            * streams, like an enhancement track - if files like this
10704            * ever exist */
10705           GST_FIXME_OBJECT (qtdemux,
10706               "Implement stereo video in separate streams");
10707       }
10708
10709       if ((frame_layout & 0x1) == 0)
10710         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10711
10712       GST_LOG_OBJECT (qtdemux,
10713           "StereoVideo: composition type: %u, is_left_first: %u",
10714           frame_type, frame_layout);
10715
10716       if (stereo_mono_change_count > 1) {
10717         GST_FIXME_OBJECT (qtdemux,
10718             "Mixed-mono flags are not yet supported in qtdemux.");
10719       }
10720
10721       stream->multiview_mode = mode;
10722       stream->multiview_flags = flags;
10723     }
10724   }
10725
10726   return TRUE;
10727 }
10728
10729 /* parse the traks.
10730  * With each track we associate a new QtDemuxStream that contains all the info
10731  * about the trak.
10732  * traks that do not decode to something (like strm traks) will not have a pad.
10733  */
10734 static gboolean
10735 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10736 {
10737   GstByteReader tkhd;
10738   int offset;
10739   GNode *mdia;
10740   GNode *mdhd;
10741   GNode *hdlr;
10742   GNode *minf;
10743   GNode *stbl;
10744   GNode *stsd;
10745   GNode *mp4a;
10746   GNode *mp4v;
10747   GNode *esds;
10748   GNode *tref;
10749   GNode *udta;
10750
10751   QtDemuxStream *stream = NULL;
10752   const guint8 *stsd_data;
10753   const guint8 *stsd_entry_data;
10754   guint remaining_stsd_len;
10755   guint stsd_entry_count;
10756   guint stsd_index;
10757   guint16 lang_code;            /* quicktime lang code or packed iso code */
10758   guint32 version;
10759   guint32 tkhd_flags = 0;
10760   guint8 tkhd_version = 0;
10761   guint32 w = 0, h = 0;
10762   guint value_size, stsd_len, len;
10763   guint32 track_id;
10764   guint32 dummy;
10765
10766   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10767
10768   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10769       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10770       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10771     goto corrupt_file;
10772
10773   /* pick between 64 or 32 bits */
10774   value_size = tkhd_version == 1 ? 8 : 4;
10775   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10776       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10777     goto corrupt_file;
10778
10779   /* Check if current moov has duplicated track_id */
10780   if (qtdemux_find_stream (qtdemux, track_id))
10781     goto existing_stream;
10782
10783   stream = _create_stream (qtdemux, track_id);
10784   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10785
10786   /* need defaults for fragments */
10787   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10788
10789   if ((tkhd_flags & 1) == 0)
10790     stream->disabled = TRUE;
10791
10792   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10793       tkhd_version, tkhd_flags, stream->track_id);
10794
10795   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10796     goto corrupt_file;
10797
10798   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10799     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10800     if (qtdemux->major_brand != FOURCC_mjp2 ||
10801         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10802       goto corrupt_file;
10803   }
10804
10805   len = QT_UINT32 ((guint8 *) mdhd->data);
10806   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10807   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10808   if (version == 0x01000000) {
10809     if (len < 42)
10810       goto corrupt_file;
10811     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10812     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10813     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10814   } else {
10815     if (len < 30)
10816       goto corrupt_file;
10817     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10818     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10819     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10820   }
10821
10822   if (lang_code < 0x400) {
10823     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10824   } else if (lang_code == 0x7fff) {
10825     stream->lang_id[0] = 0;     /* unspecified */
10826   } else {
10827     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10828     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10829     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10830     stream->lang_id[3] = 0;
10831   }
10832
10833   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10834       stream->timescale);
10835   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10836       stream->duration);
10837   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10838       lang_code, stream->lang_id);
10839
10840   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10841     goto corrupt_file;
10842
10843   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10844     /* chapters track reference */
10845     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10846     if (chap) {
10847       gsize length = GST_READ_UINT32_BE (chap->data);
10848       if (qtdemux->chapters_track_id)
10849         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10850
10851       if (length >= 12) {
10852         qtdemux->chapters_track_id =
10853             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10854       }
10855     }
10856   }
10857
10858   /* fragmented files may have bogus duration in moov */
10859   if (!qtdemux->fragmented &&
10860       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10861     guint64 tdur1, tdur2;
10862
10863     /* don't overflow */
10864     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10865     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10866
10867     /* HACK:
10868      * some of those trailers, nowadays, have prologue images that are
10869      * themselves video tracks as well. I haven't really found a way to
10870      * identify those yet, except for just looking at their duration. */
10871     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10872       GST_WARNING_OBJECT (qtdemux,
10873           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10874           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10875           "found, assuming preview image or something; skipping track",
10876           stream->duration, stream->timescale, qtdemux->duration,
10877           qtdemux->timescale);
10878       gst_qtdemux_stream_unref (stream);
10879       return TRUE;
10880     }
10881   }
10882
10883   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10884     goto corrupt_file;
10885
10886   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10887       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10888
10889   len = QT_UINT32 ((guint8 *) hdlr->data);
10890   if (len >= 20)
10891     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10892   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10893       GST_FOURCC_ARGS (stream->subtype));
10894
10895   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10896     goto corrupt_file;
10897
10898   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10899     goto corrupt_file;
10900
10901   /* Parse out svmi (and later st3d/sv3d) atoms */
10902   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10903     goto corrupt_file;
10904
10905   /* parse rest of tkhd */
10906   if (stream->subtype == FOURCC_vide) {
10907     guint32 matrix[9];
10908
10909     /* version 1 uses some 64-bit ints */
10910     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10911       goto corrupt_file;
10912
10913     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10914       goto corrupt_file;
10915
10916     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10917         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10918       goto corrupt_file;
10919
10920     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10921         &stream->stream_tags);
10922   }
10923
10924   /* parse stsd */
10925   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10926     goto corrupt_file;
10927   stsd_data = (const guint8 *) stsd->data;
10928
10929   /* stsd should at least have one entry */
10930   stsd_len = QT_UINT32 (stsd_data);
10931   if (stsd_len < 24) {
10932     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10933     if (stream->subtype == FOURCC_vivo) {
10934       gst_qtdemux_stream_unref (stream);
10935       return TRUE;
10936     } else {
10937       goto corrupt_file;
10938     }
10939   }
10940
10941   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10942   /* each stsd entry must contain at least 8 bytes */
10943   if (stream->stsd_entries_length == 0
10944       || stream->stsd_entries_length > stsd_len / 8) {
10945     stream->stsd_entries_length = 0;
10946     goto corrupt_file;
10947   }
10948   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10949   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10950   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10951
10952   stsd_entry_data = stsd_data + 16;
10953   remaining_stsd_len = stsd_len - 16;
10954   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10955     guint32 fourcc;
10956     gchar *codec = NULL;
10957     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10958
10959     /* and that entry should fit within stsd */
10960     len = QT_UINT32 (stsd_entry_data);
10961     if (len > remaining_stsd_len)
10962       goto corrupt_file;
10963
10964     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10965     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10966         GST_FOURCC_ARGS (entry->fourcc));
10967     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10968
10969     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10970       goto error_encrypted;
10971
10972     if (fourcc == FOURCC_aavd) {
10973       if (stream->subtype != FOURCC_soun) {
10974         GST_ERROR_OBJECT (qtdemux,
10975             "Unexpeced stsd type 'aavd' outside 'soun' track");
10976       } else {
10977         /* encrypted audio with sound sample description v0 */
10978         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10979         stream->protected = TRUE;
10980         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
10981           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10982       }
10983     }
10984
10985     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10986       /* FIXME this looks wrong, there might be multiple children
10987        * with the same type */
10988       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10989       stream->protected = TRUE;
10990       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10991         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10992     }
10993
10994     if (stream->subtype == FOURCC_vide) {
10995       GNode *colr;
10996       GNode *fiel;
10997       GNode *pasp;
10998       gboolean gray;
10999       gint depth, palette_size, palette_count;
11000       guint32 *palette_data = NULL;
11001
11002       entry->sampled = TRUE;
11003
11004       stream->display_width = w >> 16;
11005       stream->display_height = h >> 16;
11006
11007       offset = 16;
11008       if (len < 86)             /* TODO verify */
11009         goto corrupt_file;
11010
11011       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11012       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11013       entry->fps_n = 0;         /* this is filled in later */
11014       entry->fps_d = 0;         /* this is filled in later */
11015       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11016       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11017
11018       /* if color_table_id is 0, ctab atom must follow; however some files
11019        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11020        * if color table is not present we'll correct the value */
11021       if (entry->color_table_id == 0 &&
11022           (len < 90
11023               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11024         entry->color_table_id = -1;
11025       }
11026
11027       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11028           entry->width, entry->height, entry->bits_per_sample,
11029           entry->color_table_id);
11030
11031       depth = entry->bits_per_sample;
11032
11033       /* more than 32 bits means grayscale */
11034       gray = (depth > 32);
11035       /* low 32 bits specify the depth  */
11036       depth &= 0x1F;
11037
11038       /* different number of palette entries is determined by depth. */
11039       palette_count = 0;
11040       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11041         palette_count = (1 << depth);
11042       palette_size = palette_count * 4;
11043
11044       if (entry->color_table_id) {
11045         switch (palette_count) {
11046           case 0:
11047             break;
11048           case 2:
11049             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11050             break;
11051           case 4:
11052             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11053             break;
11054           case 16:
11055             if (gray)
11056               palette_data =
11057                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11058             else
11059               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11060             break;
11061           case 256:
11062             if (gray)
11063               palette_data =
11064                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11065             else
11066               palette_data =
11067                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11068             break;
11069           default:
11070             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11071                 (_("The video in this file might not play correctly.")),
11072                 ("unsupported palette depth %d", depth));
11073             break;
11074         }
11075       } else {
11076         gint i, j, start, end;
11077
11078         if (len < 94)
11079           goto corrupt_file;
11080
11081         /* read table */
11082         start = QT_UINT32 (stsd_entry_data + offset + 70);
11083         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11084         end = QT_UINT16 (stsd_entry_data + offset + 76);
11085
11086         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11087             start, end, palette_count);
11088
11089         if (end > 255)
11090           end = 255;
11091         if (start > end)
11092           start = end;
11093
11094         if (len < 94 + (end - start) * 8)
11095           goto corrupt_file;
11096
11097         /* palette is always the same size */
11098         palette_data = g_malloc0 (256 * 4);
11099         palette_size = 256 * 4;
11100
11101         for (j = 0, i = start; i <= end; j++, i++) {
11102           guint32 a, r, g, b;
11103
11104           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11105           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11106           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11107           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11108
11109           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11110               (g & 0xff00) | (b >> 8);
11111         }
11112       }
11113
11114       if (entry->caps)
11115         gst_caps_unref (entry->caps);
11116
11117       entry->caps =
11118           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11119           &codec);
11120       if (G_UNLIKELY (!entry->caps)) {
11121         g_free (palette_data);
11122         goto unknown_stream;
11123       }
11124
11125       if (codec) {
11126         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11127             GST_TAG_VIDEO_CODEC, codec, NULL);
11128         g_free (codec);
11129         codec = NULL;
11130       }
11131
11132       if (palette_data) {
11133         GstStructure *s;
11134
11135         if (entry->rgb8_palette)
11136           gst_memory_unref (entry->rgb8_palette);
11137         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11138             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11139
11140         s = gst_caps_get_structure (entry->caps, 0);
11141
11142         /* non-raw video has a palette_data property. raw video has the palette as
11143          * an extra plane that we append to the output buffers before we push
11144          * them*/
11145         if (!gst_structure_has_name (s, "video/x-raw")) {
11146           GstBuffer *palette;
11147
11148           palette = gst_buffer_new ();
11149           gst_buffer_append_memory (palette, entry->rgb8_palette);
11150           entry->rgb8_palette = NULL;
11151
11152           gst_caps_set_simple (entry->caps, "palette_data",
11153               GST_TYPE_BUFFER, palette, NULL);
11154           gst_buffer_unref (palette);
11155         }
11156       } else if (palette_count != 0) {
11157         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11158             (NULL), ("Unsupported palette depth %d", depth));
11159       }
11160
11161       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11162           QT_UINT16 (stsd_entry_data + offset + 32));
11163
11164       esds = NULL;
11165       pasp = NULL;
11166       colr = NULL;
11167       fiel = NULL;
11168       /* pick 'the' stsd child */
11169       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11170       // We should skip parsing the stsd for non-protected streams if
11171       // the entry doesn't match the fourcc, since they don't change
11172       // format. However, for protected streams we can have partial
11173       // encryption, where parts of the stream are encrypted and parts
11174       // not. For both parts of such streams, we should ensure the
11175       // esds overrides are parsed for both from the stsd.
11176       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11177         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11178           mp4v = NULL;
11179         else if (!stream->protected)
11180           mp4v = NULL;
11181       }
11182
11183       if (mp4v) {
11184         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11185         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11186         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11187         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11188       }
11189
11190       if (pasp) {
11191         const guint8 *pasp_data = (const guint8 *) pasp->data;
11192         gint len = QT_UINT32 (pasp_data);
11193
11194         if (len == 16) {
11195           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11196           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11197         } else {
11198           CUR_STREAM (stream)->par_w = 0;
11199           CUR_STREAM (stream)->par_h = 0;
11200         }
11201       } else {
11202         CUR_STREAM (stream)->par_w = 0;
11203         CUR_STREAM (stream)->par_h = 0;
11204       }
11205
11206       if (fiel) {
11207         const guint8 *fiel_data = (const guint8 *) fiel->data;
11208         gint len = QT_UINT32 (fiel_data);
11209
11210         if (len == 10) {
11211           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11212           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11213         }
11214       }
11215
11216       if (colr) {
11217         const guint8 *colr_data = (const guint8 *) colr->data;
11218         gint len = QT_UINT32 (colr_data);
11219
11220         if (len == 19 || len == 18) {
11221           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11222
11223           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11224             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11225             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11226             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11227             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11228
11229             CUR_STREAM (stream)->colorimetry.primaries =
11230                 gst_video_color_primaries_from_iso (primaries);
11231             CUR_STREAM (stream)->colorimetry.transfer =
11232                 gst_video_transfer_function_from_iso (transfer_function);
11233             CUR_STREAM (stream)->colorimetry.matrix =
11234                 gst_video_color_matrix_from_iso (matrix);
11235             CUR_STREAM (stream)->colorimetry.range =
11236                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11237                 GST_VIDEO_COLOR_RANGE_16_235;
11238           } else {
11239             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11240           }
11241         } else {
11242           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11243         }
11244       }
11245
11246       if (esds) {
11247         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11248             stream->stream_tags);
11249       } else {
11250         switch (fourcc) {
11251           case FOURCC_H264:
11252           case FOURCC_avc1:
11253           case FOURCC_avc3:
11254           {
11255             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11256             const guint8 *avc_data = stsd_entry_data + 0x56;
11257
11258             /* find avcC */
11259             while (len >= 0x8) {
11260               gint size;
11261
11262               if (QT_UINT32 (avc_data) <= len)
11263                 size = QT_UINT32 (avc_data) - 0x8;
11264               else
11265                 size = len - 0x8;
11266
11267               if (size < 1)
11268                 /* No real data, so break out */
11269                 break;
11270
11271               switch (QT_FOURCC (avc_data + 0x4)) {
11272                 case FOURCC_avcC:
11273                 {
11274                   /* parse, if found */
11275                   GstBuffer *buf;
11276
11277                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11278
11279                   /* First 4 bytes are the length of the atom, the next 4 bytes
11280                    * are the fourcc, the next 1 byte is the version, and the
11281                    * subsequent bytes are profile_tier_level structure like data. */
11282                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11283                       avc_data + 8 + 1, size - 1);
11284                   buf = gst_buffer_new_and_alloc (size);
11285                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11286                   gst_caps_set_simple (entry->caps,
11287                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11288                   gst_buffer_unref (buf);
11289
11290                   break;
11291                 }
11292                 case FOURCC_strf:
11293                 {
11294                   GstBuffer *buf;
11295
11296                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11297
11298                   /* First 4 bytes are the length of the atom, the next 4 bytes
11299                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11300                    * next 1 byte is the version, and the
11301                    * subsequent bytes are sequence parameter set like data. */
11302
11303                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11304                   if (size > 1) {
11305                     gst_codec_utils_h264_caps_set_level_and_profile
11306                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11307
11308                     buf = gst_buffer_new_and_alloc (size);
11309                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11310                     gst_caps_set_simple (entry->caps,
11311                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11312                     gst_buffer_unref (buf);
11313                   }
11314                   break;
11315                 }
11316                 case FOURCC_btrt:
11317                 {
11318                   guint avg_bitrate, max_bitrate;
11319
11320                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11321                   if (size < 12)
11322                     break;
11323
11324                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11325                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11326
11327                   if (!max_bitrate && !avg_bitrate)
11328                     break;
11329
11330                   /* Some muxers seem to swap the average and maximum bitrates
11331                    * (I'm looking at you, YouTube), so we swap for sanity. */
11332                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11333                     guint temp = avg_bitrate;
11334
11335                     avg_bitrate = max_bitrate;
11336                     max_bitrate = temp;
11337                   }
11338
11339                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11340                     gst_tag_list_add (stream->stream_tags,
11341                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11342                         max_bitrate, NULL);
11343                   }
11344                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11345                     gst_tag_list_add (stream->stream_tags,
11346                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11347                         NULL);
11348                   }
11349
11350                   break;
11351                 }
11352
11353                 default:
11354                   break;
11355               }
11356
11357               len -= size + 8;
11358               avc_data += size + 8;
11359             }
11360
11361             break;
11362           }
11363           case FOURCC_H265:
11364           case FOURCC_hvc1:
11365           case FOURCC_hev1:
11366           case FOURCC_dvh1:
11367           case FOURCC_dvhe:
11368           {
11369             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11370             const guint8 *hevc_data = stsd_entry_data + 0x56;
11371
11372             /* find hevc */
11373             while (len >= 0x8) {
11374               gint size;
11375
11376               if (QT_UINT32 (hevc_data) <= len)
11377                 size = QT_UINT32 (hevc_data) - 0x8;
11378               else
11379                 size = len - 0x8;
11380
11381               if (size < 1)
11382                 /* No real data, so break out */
11383                 break;
11384
11385               switch (QT_FOURCC (hevc_data + 0x4)) {
11386                 case FOURCC_hvcC:
11387                 {
11388                   /* parse, if found */
11389                   GstBuffer *buf;
11390
11391                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11392
11393                   /* First 4 bytes are the length of the atom, the next 4 bytes
11394                    * are the fourcc, the next 1 byte is the version, and the
11395                    * subsequent bytes are sequence parameter set like data. */
11396                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11397                       (entry->caps, hevc_data + 8 + 1, size - 1);
11398
11399                   buf = gst_buffer_new_and_alloc (size);
11400                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11401                   gst_caps_set_simple (entry->caps,
11402                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11403                   gst_buffer_unref (buf);
11404                   break;
11405                 }
11406                 default:
11407                   break;
11408               }
11409               len -= size + 8;
11410               hevc_data += size + 8;
11411             }
11412             break;
11413           }
11414           case FOURCC_mp4v:
11415           case FOURCC_MP4V:
11416           case FOURCC_fmp4:
11417           case FOURCC_FMP4:
11418           case FOURCC_xvid:
11419           case FOURCC_XVID:
11420           {
11421             GNode *glbl;
11422
11423             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11424                 GST_FOURCC_ARGS (fourcc));
11425
11426             /* codec data might be in glbl extension atom */
11427             glbl = mp4v ?
11428                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11429             if (glbl) {
11430               guint8 *data;
11431               GstBuffer *buf;
11432               gint len;
11433
11434               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11435               data = glbl->data;
11436               len = QT_UINT32 (data);
11437               if (len > 0x8) {
11438                 len -= 0x8;
11439                 buf = gst_buffer_new_and_alloc (len);
11440                 gst_buffer_fill (buf, 0, data + 8, len);
11441                 gst_caps_set_simple (entry->caps,
11442                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11443                 gst_buffer_unref (buf);
11444               }
11445             }
11446             break;
11447           }
11448           case FOURCC_mjp2:
11449           {
11450             /* see annex I of the jpeg2000 spec */
11451             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11452             const guint8 *data;
11453             const gchar *colorspace = NULL;
11454             gint ncomp = 0;
11455             guint32 ncomp_map = 0;
11456             gint32 *comp_map = NULL;
11457             guint32 nchan_def = 0;
11458             gint32 *chan_def = NULL;
11459
11460             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11461             /* some required atoms */
11462             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11463             if (!mjp2)
11464               break;
11465             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11466             if (!jp2h)
11467               break;
11468
11469             /* number of components; redundant with info in codestream, but useful
11470                to a muxer */
11471             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11472             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11473               break;
11474             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11475
11476             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11477             if (!colr)
11478               break;
11479             GST_DEBUG_OBJECT (qtdemux, "found colr");
11480             /* extract colour space info */
11481             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11482               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11483                 case 16:
11484                   colorspace = "sRGB";
11485                   break;
11486                 case 17:
11487                   colorspace = "GRAY";
11488                   break;
11489                 case 18:
11490                   colorspace = "sYUV";
11491                   break;
11492                 default:
11493                   colorspace = NULL;
11494                   break;
11495               }
11496             }
11497             if (!colorspace)
11498               /* colr is required, and only values 16, 17, and 18 are specified,
11499                  so error if we have no colorspace */
11500               break;
11501
11502             /* extract component mapping */
11503             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11504             if (cmap) {
11505               guint32 cmap_len = 0;
11506               int i;
11507               cmap_len = QT_UINT32 (cmap->data);
11508               if (cmap_len >= 8) {
11509                 /* normal box, subtract off header */
11510                 cmap_len -= 8;
11511                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11512                 if (cmap_len % 4 == 0) {
11513                   ncomp_map = (cmap_len / 4);
11514                   comp_map = g_new0 (gint32, ncomp_map);
11515                   for (i = 0; i < ncomp_map; i++) {
11516                     guint16 cmp;
11517                     guint8 mtyp, pcol;
11518                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11519                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11520                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11521                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11522                   }
11523                 }
11524               }
11525             }
11526             /* extract channel definitions */
11527             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11528             if (cdef) {
11529               guint32 cdef_len = 0;
11530               int i;
11531               cdef_len = QT_UINT32 (cdef->data);
11532               if (cdef_len >= 10) {
11533                 /* normal box, subtract off header and len */
11534                 cdef_len -= 10;
11535                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11536                 if (cdef_len % 6 == 0) {
11537                   nchan_def = (cdef_len / 6);
11538                   chan_def = g_new0 (gint32, nchan_def);
11539                   for (i = 0; i < nchan_def; i++)
11540                     chan_def[i] = -1;
11541                   for (i = 0; i < nchan_def; i++) {
11542                     guint16 cn, typ, asoc;
11543                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11544                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11545                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11546                     if (cn < nchan_def) {
11547                       switch (typ) {
11548                         case 0:
11549                           chan_def[cn] = asoc;
11550                           break;
11551                         case 1:
11552                           chan_def[cn] = 0;     /* alpha */
11553                           break;
11554                         default:
11555                           chan_def[cn] = -typ;
11556                       }
11557                     }
11558                   }
11559                 }
11560               }
11561             }
11562
11563             gst_caps_set_simple (entry->caps,
11564                 "num-components", G_TYPE_INT, ncomp, NULL);
11565             gst_caps_set_simple (entry->caps,
11566                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11567
11568             if (comp_map) {
11569               GValue arr = { 0, };
11570               GValue elt = { 0, };
11571               int i;
11572               g_value_init (&arr, GST_TYPE_ARRAY);
11573               g_value_init (&elt, G_TYPE_INT);
11574               for (i = 0; i < ncomp_map; i++) {
11575                 g_value_set_int (&elt, comp_map[i]);
11576                 gst_value_array_append_value (&arr, &elt);
11577               }
11578               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11579                   "component-map", &arr);
11580               g_value_unset (&elt);
11581               g_value_unset (&arr);
11582               g_free (comp_map);
11583             }
11584
11585             if (chan_def) {
11586               GValue arr = { 0, };
11587               GValue elt = { 0, };
11588               int i;
11589               g_value_init (&arr, GST_TYPE_ARRAY);
11590               g_value_init (&elt, G_TYPE_INT);
11591               for (i = 0; i < nchan_def; i++) {
11592                 g_value_set_int (&elt, chan_def[i]);
11593                 gst_value_array_append_value (&arr, &elt);
11594               }
11595               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11596                   "channel-definitions", &arr);
11597               g_value_unset (&elt);
11598               g_value_unset (&arr);
11599               g_free (chan_def);
11600             }
11601
11602             /* some optional atoms */
11603             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11604             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11605
11606             /* indicate possible fields in caps */
11607             if (field) {
11608               data = (guint8 *) field->data + 8;
11609               if (*data != 1)
11610                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11611                     (gint) * data, NULL);
11612             }
11613             /* add codec_data if provided */
11614             if (prefix) {
11615               GstBuffer *buf;
11616               gint len;
11617
11618               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11619               data = prefix->data;
11620               len = QT_UINT32 (data);
11621               if (len > 0x8) {
11622                 len -= 0x8;
11623                 buf = gst_buffer_new_and_alloc (len);
11624                 gst_buffer_fill (buf, 0, data + 8, len);
11625                 gst_caps_set_simple (entry->caps,
11626                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11627                 gst_buffer_unref (buf);
11628               }
11629             }
11630             break;
11631           }
11632           case FOURCC_SVQ3:
11633           case FOURCC_VP31:
11634           {
11635             GstBuffer *buf;
11636             GstBuffer *seqh = NULL;
11637             const guint8 *gamma_data = NULL;
11638             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11639
11640             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11641                 &seqh);
11642             if (gamma_data) {
11643               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11644                   QT_FP32 (gamma_data), NULL);
11645             }
11646             if (seqh) {
11647               /* sorry for the bad name, but we don't know what this is, other
11648                * than its own fourcc */
11649               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11650                   NULL);
11651               gst_buffer_unref (seqh);
11652             }
11653
11654             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11655             buf = gst_buffer_new_and_alloc (len);
11656             gst_buffer_fill (buf, 0, stsd_data, len);
11657             gst_caps_set_simple (entry->caps,
11658                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11659             gst_buffer_unref (buf);
11660             break;
11661           }
11662           case FOURCC_jpeg:
11663           {
11664             /* https://developer.apple.com/standards/qtff-2001.pdf,
11665              * page 92, "Video Sample Description", under table 3.1 */
11666             GstByteReader br;
11667
11668             const gint compressor_offset =
11669                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11670             const gint min_size = compressor_offset + 32 + 2 + 2;
11671             GNode *jpeg;
11672             guint32 len;
11673             guint16 color_table_id = 0;
11674             gboolean ok;
11675
11676             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11677
11678             /* recover information on interlaced/progressive */
11679             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11680             if (!jpeg)
11681               break;
11682
11683             len = QT_UINT32 (jpeg->data);
11684             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11685                 min_size);
11686             if (len >= min_size) {
11687               gst_byte_reader_init (&br, jpeg->data, len);
11688
11689               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11690               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11691               if (color_table_id != 0) {
11692                 /* the spec says there can be concatenated chunks in the data, and we want
11693                  * to find one called field. Walk through them. */
11694                 gint offset = min_size;
11695                 while (offset + 8 < len) {
11696                   guint32 size = 0, tag;
11697                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11698                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11699                   if (!ok || size < 8) {
11700                     GST_WARNING_OBJECT (qtdemux,
11701                         "Failed to walk optional chunk list");
11702                     break;
11703                   }
11704                   GST_DEBUG_OBJECT (qtdemux,
11705                       "Found optional %4.4s chunk, size %u",
11706                       (const char *) &tag, size);
11707                   if (tag == FOURCC_fiel) {
11708                     guint8 n_fields = 0, ordering = 0;
11709                     gst_byte_reader_get_uint8 (&br, &n_fields);
11710                     gst_byte_reader_get_uint8 (&br, &ordering);
11711                     if (n_fields == 1 || n_fields == 2) {
11712                       GST_DEBUG_OBJECT (qtdemux,
11713                           "Found fiel tag with %u fields, ordering %u",
11714                           n_fields, ordering);
11715                       if (n_fields == 2)
11716                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11717                             "interlace-mode", G_TYPE_STRING, "interleaved",
11718                             NULL);
11719                     } else {
11720                       GST_WARNING_OBJECT (qtdemux,
11721                           "Found fiel tag with invalid fields (%u)", n_fields);
11722                     }
11723                   }
11724                   offset += size;
11725                 }
11726               } else {
11727                 GST_DEBUG_OBJECT (qtdemux,
11728                     "Color table ID is 0, not trying to get interlacedness");
11729               }
11730             } else {
11731               GST_WARNING_OBJECT (qtdemux,
11732                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11733             }
11734
11735             break;
11736           }
11737           case FOURCC_rle_:
11738           case FOURCC_WRLE:
11739           {
11740             gst_caps_set_simple (entry->caps,
11741                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11742                 NULL);
11743             break;
11744           }
11745           case FOURCC_XiTh:
11746           {
11747             GNode *xith, *xdxt;
11748
11749             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11750             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11751             if (!xith)
11752               break;
11753
11754             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11755             if (!xdxt)
11756               break;
11757
11758             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11759             /* collect the headers and store them in a stream list so that we can
11760              * send them out first */
11761             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11762             break;
11763           }
11764           case FOURCC_ovc1:
11765           {
11766             GNode *ovc1;
11767             guint8 *ovc1_data;
11768             guint ovc1_len;
11769             GstBuffer *buf;
11770
11771             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11772             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11773             if (!ovc1)
11774               break;
11775             ovc1_data = ovc1->data;
11776             ovc1_len = QT_UINT32 (ovc1_data);
11777             if (ovc1_len <= 198) {
11778               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11779               break;
11780             }
11781             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11782             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11783             gst_caps_set_simple (entry->caps,
11784                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11785             gst_buffer_unref (buf);
11786             break;
11787           }
11788           case FOURCC_vc_1:
11789           {
11790             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11791             const guint8 *vc1_data = stsd_entry_data + 0x56;
11792
11793             /* find dvc1 */
11794             while (len >= 8) {
11795               gint size;
11796
11797               if (QT_UINT32 (vc1_data) <= len)
11798                 size = QT_UINT32 (vc1_data) - 8;
11799               else
11800                 size = len - 8;
11801
11802               if (size < 1)
11803                 /* No real data, so break out */
11804                 break;
11805
11806               switch (QT_FOURCC (vc1_data + 0x4)) {
11807                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11808                 {
11809                   GstBuffer *buf;
11810
11811                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11812                   buf = gst_buffer_new_and_alloc (size);
11813                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11814                   gst_caps_set_simple (entry->caps,
11815                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11816                   gst_buffer_unref (buf);
11817                   break;
11818                 }
11819                 default:
11820                   break;
11821               }
11822               len -= size + 8;
11823               vc1_data += size + 8;
11824             }
11825             break;
11826           }
11827           case FOURCC_av01:
11828           {
11829             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11830             const guint8 *av1_data = stsd_entry_data + 0x56;
11831
11832             /* find av1C */
11833             while (len >= 0x8) {
11834               gint size;
11835
11836               if (QT_UINT32 (av1_data) <= len)
11837                 size = QT_UINT32 (av1_data) - 0x8;
11838               else
11839                 size = len - 0x8;
11840
11841               if (size < 1)
11842                 /* No real data, so break out */
11843                 break;
11844
11845               switch (QT_FOURCC (av1_data + 0x4)) {
11846                 case FOURCC_av1C:
11847                 {
11848                   /* parse, if found */
11849                   GstBuffer *buf;
11850                   guint8 pres_delay_field;
11851
11852                   GST_DEBUG_OBJECT (qtdemux,
11853                       "found av1C codec_data in stsd of size %d", size);
11854
11855                   /* not enough data, just ignore and hope for the best */
11856                   if (size < 5)
11857                     break;
11858
11859                   /* Content is:
11860                    * 4 bytes: atom length
11861                    * 4 bytes: fourcc
11862                    * 1 byte: version
11863                    * 3 bytes: flags
11864                    * 3 bits: reserved
11865                    * 1 bits:  initial_presentation_delay_present
11866                    * 4 bits: initial_presentation_delay (if present else reserved
11867                    * rest: OBUs.
11868                    */
11869
11870                   if (av1_data[9] != 0) {
11871                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11872                     break;
11873                   }
11874
11875                   /* We skip initial_presentation_delay* for now */
11876                   pres_delay_field = *(av1_data + 12);
11877                   if (pres_delay_field & (1 << 5)) {
11878                     gst_caps_set_simple (entry->caps,
11879                         "presentation-delay", G_TYPE_INT,
11880                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11881                   }
11882                   if (size > 5) {
11883                     buf = gst_buffer_new_and_alloc (size - 5);
11884                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11885                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11886                     gst_caps_set_simple (entry->caps,
11887                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11888                     gst_buffer_unref (buf);
11889                   }
11890                   break;
11891                 }
11892                 default:
11893                   break;
11894               }
11895
11896               len -= size + 8;
11897               av1_data += size + 8;
11898             }
11899
11900             break;
11901           }
11902
11903             /* TODO: Need to parse vpcC for VP8 codec too.
11904              * Note that VPCodecConfigurationBox (vpcC) is defined for
11905              * vp08, vp09, and vp10 fourcc. */
11906           case FOURCC_vp09:
11907           {
11908             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11909             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11910
11911             /* find vpcC */
11912             while (len >= 0x8) {
11913               gint size;
11914
11915               if (QT_UINT32 (vpcc_data) <= len)
11916                 size = QT_UINT32 (vpcc_data) - 0x8;
11917               else
11918                 size = len - 0x8;
11919
11920               if (size < 1)
11921                 /* No real data, so break out */
11922                 break;
11923
11924               switch (QT_FOURCC (vpcc_data + 0x4)) {
11925                 case FOURCC_vpcC:
11926                 {
11927                   const gchar *profile_str = NULL;
11928                   const gchar *chroma_format_str = NULL;
11929                   guint8 profile;
11930                   guint8 bitdepth;
11931                   guint8 chroma_format;
11932                   GstVideoColorimetry cinfo;
11933
11934                   /* parse, if found */
11935                   GST_DEBUG_OBJECT (qtdemux,
11936                       "found vp codec_data in stsd of size %d", size);
11937
11938                   /* the meaning of "size" is length of the atom body, excluding
11939                    * atom length and fourcc fields */
11940                   if (size < 12)
11941                     break;
11942
11943                   /* Content is:
11944                    * 4 bytes: atom length
11945                    * 4 bytes: fourcc
11946                    * 1 byte: version
11947                    * 3 bytes: flags
11948                    * 1 byte: profile
11949                    * 1 byte: level
11950                    * 4 bits: bitDepth
11951                    * 3 bits: chromaSubsampling
11952                    * 1 bit: videoFullRangeFlag
11953                    * 1 byte: colourPrimaries
11954                    * 1 byte: transferCharacteristics
11955                    * 1 byte: matrixCoefficients
11956                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11957                    * rest: codecIntializationData (not used for vp8 and vp9)
11958                    */
11959
11960                   if (vpcc_data[8] != 1) {
11961                     GST_WARNING_OBJECT (qtdemux,
11962                         "unknown vpcC version %d", vpcc_data[8]);
11963                     break;
11964                   }
11965
11966                   profile = vpcc_data[12];
11967                   switch (profile) {
11968                     case 0:
11969                       profile_str = "0";
11970                       break;
11971                     case 1:
11972                       profile_str = "1";
11973                       break;
11974                     case 2:
11975                       profile_str = "2";
11976                       break;
11977                     case 3:
11978                       profile_str = "3";
11979                       break;
11980                     default:
11981                       break;
11982                   }
11983
11984                   if (profile_str) {
11985                     gst_caps_set_simple (entry->caps,
11986                         "profile", G_TYPE_STRING, profile_str, NULL);
11987                   }
11988
11989                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11990                    * but webm spec define various ones. Add level to caps
11991                    * if we really need it then */
11992
11993                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11994                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11995                     gst_caps_set_simple (entry->caps,
11996                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11997                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11998                   }
11999
12000                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12001                   switch (chroma_format) {
12002                     case 0:
12003                     case 1:
12004                       chroma_format_str = "4:2:0";
12005                       break;
12006                     case 2:
12007                       chroma_format_str = "4:2:2";
12008                       break;
12009                     case 3:
12010                       chroma_format_str = "4:4:4";
12011                       break;
12012                     default:
12013                       break;
12014                   }
12015
12016                   if (chroma_format_str) {
12017                     gst_caps_set_simple (entry->caps,
12018                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12019                         NULL);
12020                   }
12021
12022                   if ((vpcc_data[14] & 0x1) != 0)
12023                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12024                   else
12025                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12026                   cinfo.primaries =
12027                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12028                   cinfo.transfer =
12029                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12030                   cinfo.matrix =
12031                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12032
12033                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12034                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12035                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12036                     /* set this only if all values are known, otherwise this
12037                      * might overwrite valid ones parsed from other color box */
12038                     CUR_STREAM (stream)->colorimetry = cinfo;
12039                   }
12040                   break;
12041                 }
12042                 default:
12043                   break;
12044               }
12045
12046               len -= size + 8;
12047               vpcc_data += size + 8;
12048             }
12049
12050             break;
12051           }
12052           default:
12053             break;
12054         }
12055       }
12056
12057       GST_INFO_OBJECT (qtdemux,
12058           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12059           GST_FOURCC_ARGS (fourcc), entry->caps);
12060
12061     } else if (stream->subtype == FOURCC_soun) {
12062       GNode *wave;
12063       int version, samplesize;
12064       guint16 compression_id;
12065       gboolean amrwb = FALSE;
12066
12067       offset = 16;
12068       /* sample description entry (16) + sound sample description v0 (20) */
12069       if (len < 36)
12070         goto corrupt_file;
12071
12072       version = QT_UINT32 (stsd_entry_data + offset);
12073       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12074       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12075       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12076       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12077
12078       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12079       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12080           QT_UINT32 (stsd_entry_data + offset + 4));
12081       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12082       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12083       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12084       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12085           QT_UINT16 (stsd_entry_data + offset + 14));
12086       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12087
12088       if (compression_id == 0xfffe)
12089         entry->sampled = TRUE;
12090
12091       /* first assume uncompressed audio */
12092       entry->bytes_per_sample = samplesize / 8;
12093       entry->samples_per_frame = entry->n_channels;
12094       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12095       entry->samples_per_packet = entry->samples_per_frame;
12096       entry->bytes_per_packet = entry->bytes_per_sample;
12097
12098       offset = 36;
12099
12100       if (version == 0x00010000) {
12101         /* sample description entry (16) + sound sample description v1 (20+16) */
12102         if (len < 52)
12103           goto corrupt_file;
12104
12105         /* take information from here over the normal sample description */
12106         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12107         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12108         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12109         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12110
12111         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12112         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12113             entry->samples_per_packet);
12114         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12115             entry->bytes_per_packet);
12116         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12117             entry->bytes_per_frame);
12118         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12119             entry->bytes_per_sample);
12120
12121         if (!entry->sampled && entry->bytes_per_packet) {
12122           entry->samples_per_frame = (entry->bytes_per_frame /
12123               entry->bytes_per_packet) * entry->samples_per_packet;
12124           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12125               entry->samples_per_frame);
12126         }
12127       } else if (version == 0x00020000) {
12128         /* sample description entry (16) + sound sample description v2 (56) */
12129         if (len < 72)
12130           goto corrupt_file;
12131
12132         /* take information from here over the normal sample description */
12133         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12134         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12135         entry->samples_per_frame = entry->n_channels;
12136         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12137         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12138         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12139         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12140
12141         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12142         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12143         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12144         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12145             entry->bytes_per_sample * 8);
12146         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12147             QT_UINT32 (stsd_entry_data + offset + 24));
12148         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12149             entry->bytes_per_packet);
12150         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12151             entry->samples_per_packet);
12152       } else if (version != 0x00000) {
12153         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12154             version);
12155       }
12156
12157       switch (fourcc) {
12158           /* Yes, these have to be hard-coded */
12159         case FOURCC_MAC6:
12160         {
12161           entry->samples_per_packet = 6;
12162           entry->bytes_per_packet = 1;
12163           entry->bytes_per_frame = 1 * entry->n_channels;
12164           entry->bytes_per_sample = 1;
12165           entry->samples_per_frame = 6 * entry->n_channels;
12166           break;
12167         }
12168         case FOURCC_MAC3:
12169         {
12170           entry->samples_per_packet = 3;
12171           entry->bytes_per_packet = 1;
12172           entry->bytes_per_frame = 1 * entry->n_channels;
12173           entry->bytes_per_sample = 1;
12174           entry->samples_per_frame = 3 * entry->n_channels;
12175           break;
12176         }
12177         case FOURCC_ima4:
12178         {
12179           entry->samples_per_packet = 64;
12180           entry->bytes_per_packet = 34;
12181           entry->bytes_per_frame = 34 * entry->n_channels;
12182           entry->bytes_per_sample = 2;
12183           entry->samples_per_frame = 64 * entry->n_channels;
12184           break;
12185         }
12186         case FOURCC_ulaw:
12187         case FOURCC_alaw:
12188         {
12189           entry->samples_per_packet = 1;
12190           entry->bytes_per_packet = 1;
12191           entry->bytes_per_frame = 1 * entry->n_channels;
12192           entry->bytes_per_sample = 1;
12193           entry->samples_per_frame = 1 * entry->n_channels;
12194           break;
12195         }
12196         case FOURCC_agsm:
12197         {
12198           entry->samples_per_packet = 160;
12199           entry->bytes_per_packet = 33;
12200           entry->bytes_per_frame = 33 * entry->n_channels;
12201           entry->bytes_per_sample = 2;
12202           entry->samples_per_frame = 160 * entry->n_channels;
12203           break;
12204         }
12205           /* fix up any invalid header information from above */
12206         case FOURCC_twos:
12207         case FOURCC_sowt:
12208         case FOURCC_raw_:
12209         case FOURCC_lpcm:
12210           /* Sometimes these are set to 0 in the sound sample descriptions so
12211            * let's try to infer useful values from the other information we
12212            * have available */
12213           if (entry->bytes_per_sample == 0)
12214             entry->bytes_per_sample =
12215                 entry->bytes_per_frame / entry->n_channels;
12216           if (entry->bytes_per_sample == 0)
12217             entry->bytes_per_sample = samplesize / 8;
12218
12219           if (entry->bytes_per_frame == 0)
12220             entry->bytes_per_frame =
12221                 entry->bytes_per_sample * entry->n_channels;
12222
12223           if (entry->bytes_per_packet == 0)
12224             entry->bytes_per_packet = entry->bytes_per_sample;
12225
12226           if (entry->samples_per_frame == 0)
12227             entry->samples_per_frame = entry->n_channels;
12228
12229           if (entry->samples_per_packet == 0)
12230             entry->samples_per_packet = entry->samples_per_frame;
12231
12232           break;
12233         case FOURCC_in24:
12234         case FOURCC_in32:
12235         case FOURCC_fl32:
12236         case FOURCC_fl64:
12237         case FOURCC_s16l:{
12238           switch (fourcc) {
12239             case FOURCC_in24:
12240               entry->bytes_per_sample = 3;
12241               break;
12242             case FOURCC_in32:
12243             case FOURCC_fl32:
12244               entry->bytes_per_sample = 4;
12245               break;
12246             case FOURCC_fl64:
12247               entry->bytes_per_sample = 8;
12248               break;
12249             case FOURCC_s16l:
12250               entry->bytes_per_sample = 2;
12251               break;
12252             default:
12253               g_assert_not_reached ();
12254               break;
12255           }
12256           entry->samples_per_frame = entry->n_channels;
12257           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12258           entry->samples_per_packet = entry->samples_per_frame;
12259           entry->bytes_per_packet = entry->bytes_per_sample;
12260           break;
12261         }
12262         default:
12263           break;
12264       }
12265
12266       if (entry->caps)
12267         gst_caps_unref (entry->caps);
12268
12269       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12270           stsd_entry_data + 32, len - 16, &codec);
12271
12272       switch (fourcc) {
12273         case FOURCC_in24:
12274         case FOURCC_in32:
12275         case FOURCC_fl32:
12276         case FOURCC_fl64:
12277         {
12278           GNode *enda;
12279           GNode *fmt;
12280
12281           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12282
12283           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12284           if (!enda) {
12285             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12286             if (wave)
12287               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12288           }
12289           if (enda) {
12290             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12291             const gchar *format_str;
12292
12293             switch (fourcc) {
12294               case FOURCC_in24:
12295                 format_str = (enda_value) ? "S24LE" : "S24BE";
12296                 break;
12297               case FOURCC_in32:
12298                 format_str = (enda_value) ? "S32LE" : "S32BE";
12299                 break;
12300               case FOURCC_fl32:
12301                 format_str = (enda_value) ? "F32LE" : "F32BE";
12302                 break;
12303               case FOURCC_fl64:
12304                 format_str = (enda_value) ? "F64LE" : "F64BE";
12305                 break;
12306               default:
12307                 g_assert_not_reached ();
12308                 break;
12309             }
12310             gst_caps_set_simple (entry->caps,
12311                 "format", G_TYPE_STRING, format_str, NULL);
12312           }
12313           break;
12314         }
12315         case FOURCC_owma:
12316         {
12317           const guint8 *owma_data;
12318           const gchar *codec_name = NULL;
12319           guint owma_len;
12320           GstBuffer *buf;
12321           gint version = 1;
12322           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12323           /* FIXME this should also be gst_riff_strf_auds,
12324            * but the latter one is actually missing bits-per-sample :( */
12325           typedef struct
12326           {
12327             gint16 wFormatTag;
12328             gint16 nChannels;
12329             gint32 nSamplesPerSec;
12330             gint32 nAvgBytesPerSec;
12331             gint16 nBlockAlign;
12332             gint16 wBitsPerSample;
12333             gint16 cbSize;
12334           } WAVEFORMATEX;
12335           WAVEFORMATEX *wfex;
12336
12337           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12338           owma_data = stsd_entry_data;
12339           owma_len = QT_UINT32 (owma_data);
12340           if (owma_len <= 54) {
12341             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12342             break;
12343           }
12344           wfex = (WAVEFORMATEX *) (owma_data + 36);
12345           buf = gst_buffer_new_and_alloc (owma_len - 54);
12346           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12347           if (wfex->wFormatTag == 0x0161) {
12348             codec_name = "Windows Media Audio";
12349             version = 2;
12350           } else if (wfex->wFormatTag == 0x0162) {
12351             codec_name = "Windows Media Audio 9 Pro";
12352             version = 3;
12353           } else if (wfex->wFormatTag == 0x0163) {
12354             codec_name = "Windows Media Audio 9 Lossless";
12355             /* is that correct? gstffmpegcodecmap.c is missing it, but
12356              * fluendo codec seems to support it */
12357             version = 4;
12358           }
12359
12360           gst_caps_set_simple (entry->caps,
12361               "codec_data", GST_TYPE_BUFFER, buf,
12362               "wmaversion", G_TYPE_INT, version,
12363               "block_align", G_TYPE_INT,
12364               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12365               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12366               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12367               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12368           gst_buffer_unref (buf);
12369
12370           if (codec_name) {
12371             g_free (codec);
12372             codec = g_strdup (codec_name);
12373           }
12374           break;
12375         }
12376         case FOURCC_wma_:
12377         {
12378           gint len = QT_UINT32 (stsd_entry_data) - offset;
12379           const guint8 *wfex_data = stsd_entry_data + offset;
12380           const gchar *codec_name = NULL;
12381           gint version = 1;
12382           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12383           /* FIXME this should also be gst_riff_strf_auds,
12384            * but the latter one is actually missing bits-per-sample :( */
12385           typedef struct
12386           {
12387             gint16 wFormatTag;
12388             gint16 nChannels;
12389             gint32 nSamplesPerSec;
12390             gint32 nAvgBytesPerSec;
12391             gint16 nBlockAlign;
12392             gint16 wBitsPerSample;
12393             gint16 cbSize;
12394           } WAVEFORMATEX;
12395           WAVEFORMATEX wfex;
12396
12397           /* FIXME: unify with similar wavformatex parsing code above */
12398           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12399
12400           /* find wfex */
12401           while (len >= 8) {
12402             gint size;
12403
12404             if (QT_UINT32 (wfex_data) <= len)
12405               size = QT_UINT32 (wfex_data) - 8;
12406             else
12407               size = len - 8;
12408
12409             if (size < 1)
12410               /* No real data, so break out */
12411               break;
12412
12413             switch (QT_FOURCC (wfex_data + 4)) {
12414               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12415               {
12416                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12417
12418                 if (size < 8 + 18)
12419                   break;
12420
12421                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12422                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12423                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12424                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12425                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12426                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12427                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12428
12429                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12430                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12431                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12432                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12433                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12434                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12435
12436                 if (wfex.wFormatTag == 0x0161) {
12437                   codec_name = "Windows Media Audio";
12438                   version = 2;
12439                 } else if (wfex.wFormatTag == 0x0162) {
12440                   codec_name = "Windows Media Audio 9 Pro";
12441                   version = 3;
12442                 } else if (wfex.wFormatTag == 0x0163) {
12443                   codec_name = "Windows Media Audio 9 Lossless";
12444                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12445                    * fluendo codec seems to support it */
12446                   version = 4;
12447                 }
12448
12449                 gst_caps_set_simple (entry->caps,
12450                     "wmaversion", G_TYPE_INT, version,
12451                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12452                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12453                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12454                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12455
12456                 if (size > wfex.cbSize) {
12457                   GstBuffer *buf;
12458
12459                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12460                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12461                       size - wfex.cbSize);
12462                   gst_caps_set_simple (entry->caps,
12463                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12464                   gst_buffer_unref (buf);
12465                 } else {
12466                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12467                 }
12468
12469                 if (codec_name) {
12470                   g_free (codec);
12471                   codec = g_strdup (codec_name);
12472                 }
12473                 break;
12474               }
12475               default:
12476                 break;
12477             }
12478             len -= size + 8;
12479             wfex_data += size + 8;
12480           }
12481           break;
12482         }
12483         case FOURCC_opus:
12484         {
12485           const guint8 *dops_data;
12486           guint8 *channel_mapping = NULL;
12487           guint32 rate;
12488           guint8 channels;
12489           guint8 channel_mapping_family;
12490           guint8 stream_count;
12491           guint8 coupled_count;
12492           guint8 i;
12493
12494           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12495           if (version == 1)
12496             dops_data = stsd_entry_data + 51;
12497           else
12498             dops_data = stsd_entry_data + 35;
12499
12500           channels = GST_READ_UINT8 (dops_data + 10);
12501           rate = GST_READ_UINT32_LE (dops_data + 13);
12502           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12503           stream_count = GST_READ_UINT8 (dops_data + 20);
12504           coupled_count = GST_READ_UINT8 (dops_data + 21);
12505
12506           if (channels > 0) {
12507             channel_mapping = g_malloc (channels * sizeof (guint8));
12508             for (i = 0; i < channels; i++)
12509               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12510           }
12511
12512           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12513               channel_mapping_family, stream_count, coupled_count,
12514               channel_mapping);
12515           break;
12516         }
12517         default:
12518           break;
12519       }
12520
12521       if (codec) {
12522         GstStructure *s;
12523         gint bitrate = 0;
12524
12525         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12526             GST_TAG_AUDIO_CODEC, codec, NULL);
12527         g_free (codec);
12528         codec = NULL;
12529
12530         /* some bitrate info may have ended up in caps */
12531         s = gst_caps_get_structure (entry->caps, 0);
12532         gst_structure_get_int (s, "bitrate", &bitrate);
12533         if (bitrate > 0)
12534           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12535               GST_TAG_BITRATE, bitrate, NULL);
12536       }
12537
12538       esds = NULL;
12539       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12540       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12541         if (stream->protected) {
12542           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12543             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12544           }
12545           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12546             mp4a = NULL;
12547           }
12548         } else {
12549           mp4a = NULL;
12550         }
12551       }
12552
12553       wave = NULL;
12554       if (mp4a) {
12555         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12556         if (wave)
12557           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12558         if (!esds)
12559           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12560       }
12561
12562
12563       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12564          16 bits is a byte-swapped wave-style codec identifier,
12565          and we can find a WAVE header internally to a 'wave' atom here.
12566          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12567          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12568          is big-endian).
12569        */
12570       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12571         if (len < offset + 20) {
12572           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12573         } else {
12574           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12575           const guint8 *data = stsd_entry_data + offset + 16;
12576           GNode *wavenode;
12577           GNode *waveheadernode;
12578
12579           wavenode = g_node_new ((guint8 *) data);
12580           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12581             const guint8 *waveheader;
12582             guint32 headerlen;
12583
12584             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12585             if (waveheadernode) {
12586               waveheader = (const guint8 *) waveheadernode->data;
12587               headerlen = QT_UINT32 (waveheader);
12588
12589               if (headerlen > 8) {
12590                 gst_riff_strf_auds *header = NULL;
12591                 GstBuffer *headerbuf;
12592                 GstBuffer *extra;
12593
12594                 waveheader += 8;
12595                 headerlen -= 8;
12596
12597                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12598                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12599
12600                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12601                         headerbuf, &header, &extra)) {
12602                   gst_caps_unref (entry->caps);
12603                   /* FIXME: Need to do something with the channel reorder map */
12604                   entry->caps =
12605                       gst_riff_create_audio_caps (header->format, NULL, header,
12606                       extra, NULL, NULL, NULL);
12607
12608                   if (extra)
12609                     gst_buffer_unref (extra);
12610                   g_free (header);
12611                 }
12612               }
12613             } else
12614               GST_DEBUG ("Didn't find waveheadernode for this codec");
12615           }
12616           g_node_destroy (wavenode);
12617         }
12618       } else if (esds) {
12619         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12620             stream->stream_tags);
12621       } else {
12622         switch (fourcc) {
12623 #if 0
12624             /* FIXME: what is in the chunk? */
12625           case FOURCC_QDMC:
12626           {
12627             gint len = QT_UINT32 (stsd_data);
12628
12629             /* seems to be always = 116 = 0x74 */
12630             break;
12631           }
12632 #endif
12633           case FOURCC_QDM2:
12634           {
12635             gint len = QT_UINT32 (stsd_entry_data);
12636
12637             if (len > 0x3C) {
12638               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12639
12640               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12641               gst_caps_set_simple (entry->caps,
12642                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12643               gst_buffer_unref (buf);
12644             }
12645             gst_caps_set_simple (entry->caps,
12646                 "samplesize", G_TYPE_INT, samplesize, NULL);
12647             break;
12648           }
12649           case FOURCC_alac:
12650           {
12651             GNode *alac, *wave = NULL;
12652
12653             /* apparently, m4a has this atom appended directly in the stsd entry,
12654              * while mov has it in a wave atom */
12655             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12656             if (alac) {
12657               /* alac now refers to stsd entry atom */
12658               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12659               if (wave)
12660                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12661               else
12662                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12663             }
12664             if (alac) {
12665               const guint8 *alac_data = alac->data;
12666               gint len = QT_UINT32 (alac->data);
12667               GstBuffer *buf;
12668
12669               if (len < 36) {
12670                 GST_DEBUG_OBJECT (qtdemux,
12671                     "discarding alac atom with unexpected len %d", len);
12672               } else {
12673                 /* codec-data contains alac atom size and prefix,
12674                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12675                 buf = gst_buffer_new_and_alloc (len);
12676                 gst_buffer_fill (buf, 0, alac->data, len);
12677                 gst_caps_set_simple (entry->caps,
12678                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12679                 gst_buffer_unref (buf);
12680
12681                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12682                 entry->n_channels = QT_UINT8 (alac_data + 21);
12683                 entry->rate = QT_UINT32 (alac_data + 32);
12684                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12685               }
12686             }
12687             gst_caps_set_simple (entry->caps,
12688                 "samplesize", G_TYPE_INT, samplesize, NULL);
12689             break;
12690           }
12691           case FOURCC_fLaC:
12692           {
12693             /* The codingname of the sample entry is 'fLaC' */
12694             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12695
12696             if (flac) {
12697               /* The 'dfLa' box is added to the sample entry to convey
12698                  initializing information for the decoder. */
12699               const GNode *dfla =
12700                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12701
12702               if (dfla) {
12703                 const guint32 len = QT_UINT32 (dfla->data);
12704
12705                 /* Must contain at least dfLa box header (12),
12706                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12707                 if (len < 50) {
12708                   GST_DEBUG_OBJECT (qtdemux,
12709                       "discarding dfla atom with unexpected len %d", len);
12710                 } else {
12711                   /* skip dfLa header to get the METADATA_BLOCKs */
12712                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12713                   const guint32 metadata_blocks_len = len - 12;
12714
12715                   gchar *stream_marker = g_strdup ("fLaC");
12716                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12717                       strlen (stream_marker));
12718
12719                   guint32 index = 0;
12720                   guint32 remainder = 0;
12721                   guint32 block_size = 0;
12722                   gboolean is_last = FALSE;
12723
12724                   GValue array = G_VALUE_INIT;
12725                   GValue value = G_VALUE_INIT;
12726
12727                   g_value_init (&array, GST_TYPE_ARRAY);
12728                   g_value_init (&value, GST_TYPE_BUFFER);
12729
12730                   gst_value_set_buffer (&value, block);
12731                   gst_value_array_append_value (&array, &value);
12732                   g_value_reset (&value);
12733
12734                   gst_buffer_unref (block);
12735
12736                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12737                    * of data, and we haven't already finished parsing */
12738                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12739                     remainder = metadata_blocks_len - index;
12740
12741                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12742                     block_size = 4 +
12743                         (metadata_blocks[index + 1] << 16) +
12744                         (metadata_blocks[index + 2] << 8) +
12745                         metadata_blocks[index + 3];
12746
12747                     /* be careful not to read off end of box */
12748                     if (block_size > remainder) {
12749                       break;
12750                     }
12751
12752                     is_last = metadata_blocks[index] >> 7;
12753
12754                     block = gst_buffer_new_and_alloc (block_size);
12755
12756                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12757                         block_size);
12758
12759                     gst_value_set_buffer (&value, block);
12760                     gst_value_array_append_value (&array, &value);
12761                     g_value_reset (&value);
12762
12763                     gst_buffer_unref (block);
12764
12765                     index += block_size;
12766                   }
12767
12768                   /* only append the metadata if we successfully read all of it */
12769                   if (is_last) {
12770                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12771                             (stream)->caps, 0), "streamheader", &array);
12772                   } else {
12773                     GST_WARNING_OBJECT (qtdemux,
12774                         "discarding all METADATA_BLOCKs due to invalid "
12775                         "block_size %d at idx %d, rem %d", block_size, index,
12776                         remainder);
12777                   }
12778
12779                   g_value_unset (&value);
12780                   g_value_unset (&array);
12781
12782                   /* The sample rate obtained from the stsd may not be accurate
12783                    * since it cannot represent rates greater than 65535Hz, so
12784                    * override that value with the sample rate from the
12785                    * METADATA_BLOCK_STREAMINFO block */
12786                   CUR_STREAM (stream)->rate =
12787                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12788                 }
12789               }
12790             }
12791             break;
12792           }
12793           case FOURCC_sawb:
12794             /* Fallthrough! */
12795             amrwb = TRUE;
12796           case FOURCC_samr:
12797           {
12798             gint len = QT_UINT32 (stsd_entry_data);
12799
12800             if (len > 0x24) {
12801               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12802               guint bitrate;
12803
12804               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12805
12806               /* If we have enough data, let's try to get the 'damr' atom. See
12807                * the 3GPP container spec (26.244) for more details. */
12808               if ((len - 0x34) > 8 &&
12809                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12810                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12811                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12812               }
12813
12814               gst_caps_set_simple (entry->caps,
12815                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12816               gst_buffer_unref (buf);
12817             }
12818             break;
12819           }
12820           case FOURCC_mp4a:
12821           {
12822             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12823             gint len = QT_UINT32 (stsd_entry_data);
12824             guint16 sound_version = 0;
12825             /* FIXME: Can this be determined somehow? There doesn't seem to be
12826              * anything in mp4a atom that specifis compression */
12827             gint profile = 2;
12828             guint16 channels = entry->n_channels;
12829             guint32 time_scale = (guint32) entry->rate;
12830             gint sample_rate_index = -1;
12831
12832             if (len >= 34) {
12833               sound_version = QT_UINT16 (stsd_entry_data + 16);
12834
12835               if (sound_version == 1) {
12836                 channels = QT_UINT16 (stsd_entry_data + 24);
12837                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12838               } else {
12839                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12840                     sound_version);
12841               }
12842             } else {
12843               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12844                   len);
12845             }
12846
12847             sample_rate_index =
12848                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12849             if (sample_rate_index >= 0 && channels > 0) {
12850               guint8 codec_data[2];
12851               GstBuffer *buf;
12852
12853               /* build AAC codec data */
12854               codec_data[0] = profile << 3;
12855               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12856               codec_data[1] = (sample_rate_index & 0x01) << 7;
12857               codec_data[1] |= (channels & 0xF) << 3;
12858
12859               buf = gst_buffer_new_and_alloc (2);
12860               gst_buffer_fill (buf, 0, codec_data, 2);
12861               gst_caps_set_simple (entry->caps,
12862                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12863               gst_buffer_unref (buf);
12864             }
12865             break;
12866           }
12867           case FOURCC_lpcm:
12868           case FOURCC_in24:
12869           case FOURCC_in32:
12870           case FOURCC_fl32:
12871           case FOURCC_fl64:
12872           case FOURCC_s16l:
12873             /* Fully handled elsewhere */
12874             break;
12875           default:
12876             GST_INFO_OBJECT (qtdemux,
12877                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12878             break;
12879         }
12880       }
12881       GST_INFO_OBJECT (qtdemux,
12882           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12883           GST_FOURCC_ARGS (fourcc), entry->caps);
12884
12885     } else if (stream->subtype == FOURCC_strm) {
12886       if (fourcc == FOURCC_rtsp) {
12887         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12888       } else {
12889         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12890             GST_FOURCC_ARGS (fourcc));
12891         goto unknown_stream;
12892       }
12893       entry->sampled = TRUE;
12894     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12895         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12896         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
12897
12898       entry->sampled = TRUE;
12899       entry->sparse = TRUE;
12900
12901       entry->caps =
12902           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12903           &codec);
12904       if (codec) {
12905         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12906             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12907         g_free (codec);
12908         codec = NULL;
12909       }
12910
12911       /* hunt for sort-of codec data */
12912       switch (fourcc) {
12913         case FOURCC_mp4s:
12914         {
12915           GNode *mp4s = NULL;
12916           GNode *esds = NULL;
12917
12918           /* look for palette in a stsd->mp4s->esds sub-atom */
12919           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12920           if (mp4s)
12921             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12922           if (esds == NULL) {
12923             /* Invalid STSD */
12924             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12925             break;
12926           }
12927
12928           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12929               stream->stream_tags);
12930           break;
12931         }
12932         default:
12933           GST_INFO_OBJECT (qtdemux,
12934               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12935           break;
12936       }
12937       GST_INFO_OBJECT (qtdemux,
12938           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12939           GST_FOURCC_ARGS (fourcc), entry->caps);
12940     } else {
12941       /* everything in 1 sample */
12942       entry->sampled = TRUE;
12943
12944       entry->caps =
12945           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12946           &codec);
12947
12948       if (entry->caps == NULL)
12949         goto unknown_stream;
12950
12951       if (codec) {
12952         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12953             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12954         g_free (codec);
12955         codec = NULL;
12956       }
12957     }
12958
12959     /* promote to sampled format */
12960     if (entry->fourcc == FOURCC_samr) {
12961       /* force mono 8000 Hz for AMR */
12962       entry->sampled = TRUE;
12963       entry->n_channels = 1;
12964       entry->rate = 8000;
12965     } else if (entry->fourcc == FOURCC_sawb) {
12966       /* force mono 16000 Hz for AMR-WB */
12967       entry->sampled = TRUE;
12968       entry->n_channels = 1;
12969       entry->rate = 16000;
12970     } else if (entry->fourcc == FOURCC_mp4a) {
12971       entry->sampled = TRUE;
12972     }
12973
12974
12975     stsd_entry_data += len;
12976     remaining_stsd_len -= len;
12977
12978   }
12979
12980   /* collect sample information */
12981   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12982     goto samples_failed;
12983
12984   if (qtdemux->fragmented) {
12985     guint64 offset;
12986
12987     /* need all moov samples as basis; probably not many if any at all */
12988     /* prevent moof parsing taking of at this time */
12989     offset = qtdemux->moof_offset;
12990     qtdemux->moof_offset = 0;
12991     if (stream->n_samples &&
12992         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12993       qtdemux->moof_offset = offset;
12994       goto samples_failed;
12995     }
12996     qtdemux->moof_offset = offset;
12997     /* movie duration more reliable in this case (e.g. mehd) */
12998     if (qtdemux->segment.duration &&
12999         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13000       stream->duration =
13001           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13002   }
13003
13004   /* configure segments */
13005   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13006     goto segments_failed;
13007
13008   /* add some language tag, if useful */
13009   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13010       strcmp (stream->lang_id, "und")) {
13011     const gchar *lang_code;
13012
13013     /* convert ISO 639-2 code to ISO 639-1 */
13014     lang_code = gst_tag_get_language_code (stream->lang_id);
13015     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13016         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13017   }
13018
13019   /* Check for UDTA tags */
13020   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13021     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13022   }
13023
13024   /* Insert and sort new stream in track-id order.
13025    * This will help in comparing old/new streams during stream update check */
13026   g_ptr_array_add (qtdemux->active_streams, stream);
13027   g_ptr_array_sort (qtdemux->active_streams,
13028       (GCompareFunc) qtdemux_track_id_compare_func);
13029   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13030       QTDEMUX_N_STREAMS (qtdemux));
13031
13032   return TRUE;
13033
13034 /* ERRORS */
13035 corrupt_file:
13036   {
13037     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13038         (_("This file is corrupt and cannot be played.")), (NULL));
13039     if (stream)
13040       gst_qtdemux_stream_unref (stream);
13041     return FALSE;
13042   }
13043 error_encrypted:
13044   {
13045     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13046     gst_qtdemux_stream_unref (stream);
13047     return FALSE;
13048   }
13049 samples_failed:
13050 segments_failed:
13051   {
13052     /* we posted an error already */
13053     /* free stbl sub-atoms */
13054     gst_qtdemux_stbl_free (stream);
13055     gst_qtdemux_stream_unref (stream);
13056     return FALSE;
13057   }
13058 existing_stream:
13059   {
13060     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13061         track_id);
13062     return TRUE;
13063   }
13064 unknown_stream:
13065   {
13066     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13067         GST_FOURCC_ARGS (stream->subtype));
13068     gst_qtdemux_stream_unref (stream);
13069     return TRUE;
13070   }
13071 }
13072
13073 /* If we can estimate the overall bitrate, and don't have information about the
13074  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13075  * the overall bitrate minus the sum of the bitrates of all other streams. This
13076  * should be useful for the common case where we have one audio and one video
13077  * stream and can estimate the bitrate of one, but not the other. */
13078 static void
13079 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13080 {
13081   QtDemuxStream *stream = NULL;
13082   gint64 size, sys_bitrate, sum_bitrate = 0;
13083   GstClockTime duration;
13084   guint bitrate;
13085   gint i;
13086
13087   if (qtdemux->fragmented)
13088     return;
13089
13090   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13091
13092   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13093       || size <= 0) {
13094     GST_DEBUG_OBJECT (qtdemux,
13095         "Size in bytes of the stream not known - bailing");
13096     return;
13097   }
13098
13099   /* Subtract the header size */
13100   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13101       size, qtdemux->header_size);
13102
13103   if (size < qtdemux->header_size)
13104     return;
13105
13106   size = size - qtdemux->header_size;
13107
13108   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13109     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13110     return;
13111   }
13112
13113   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13114     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13115     switch (str->subtype) {
13116       case FOURCC_soun:
13117       case FOURCC_vide:
13118         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13119             CUR_STREAM (str)->caps);
13120         /* retrieve bitrate, prefer avg then max */
13121         bitrate = 0;
13122         if (str->stream_tags) {
13123           if (gst_tag_list_get_uint (str->stream_tags,
13124                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13125             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13126           if (gst_tag_list_get_uint (str->stream_tags,
13127                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13128             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13129           if (gst_tag_list_get_uint (str->stream_tags,
13130                   GST_TAG_BITRATE, &bitrate))
13131             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13132         }
13133         if (bitrate)
13134           sum_bitrate += bitrate;
13135         else {
13136           if (stream) {
13137             GST_DEBUG_OBJECT (qtdemux,
13138                 ">1 stream with unknown bitrate - bailing");
13139             return;
13140           } else
13141             stream = str;
13142         }
13143
13144       default:
13145         /* For other subtypes, we assume no significant impact on bitrate */
13146         break;
13147     }
13148   }
13149
13150   if (!stream) {
13151     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13152     return;
13153   }
13154
13155   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13156
13157   if (sys_bitrate < sum_bitrate) {
13158     /* This can happen, since sum_bitrate might be derived from maximum
13159      * bitrates and not average bitrates */
13160     GST_DEBUG_OBJECT (qtdemux,
13161         "System bitrate less than sum bitrate - bailing");
13162     return;
13163   }
13164
13165   bitrate = sys_bitrate - sum_bitrate;
13166   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13167       ", Stream bitrate = %u", sys_bitrate, bitrate);
13168
13169   if (!stream->stream_tags)
13170     stream->stream_tags = gst_tag_list_new_empty ();
13171   else
13172     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13173
13174   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13175       GST_TAG_BITRATE, bitrate, NULL);
13176 }
13177
13178 static GstFlowReturn
13179 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13180 {
13181   GstFlowReturn ret = GST_FLOW_OK;
13182   gint i;
13183
13184   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13185
13186   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13187     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13188     guint32 sample_num = 0;
13189
13190     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13191         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13192
13193     if (qtdemux->fragmented && qtdemux->pullbased) {
13194       /* need all moov samples first */
13195       GST_OBJECT_LOCK (qtdemux);
13196       while (stream->n_samples == 0)
13197         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13198           break;
13199       GST_OBJECT_UNLOCK (qtdemux);
13200     } else {
13201       /* discard any stray moof */
13202       qtdemux->moof_offset = 0;
13203     }
13204
13205     /* prepare braking */
13206     if (ret != GST_FLOW_ERROR)
13207       ret = GST_FLOW_OK;
13208
13209     /* in pull mode, we should have parsed some sample info by now;
13210      * and quite some code will not handle no samples.
13211      * in push mode, we'll just have to deal with it */
13212     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13213       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13214       g_ptr_array_remove_index (qtdemux->active_streams, i);
13215       i--;
13216       continue;
13217     } else if (stream->track_id == qtdemux->chapters_track_id &&
13218         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13219       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13220          so that it doesn't look like a subtitle track */
13221       g_ptr_array_remove_index (qtdemux->active_streams, i);
13222       i--;
13223       continue;
13224     }
13225
13226     /* parse the initial sample for use in setting the frame rate cap */
13227     while (sample_num == 0 && sample_num < stream->n_samples) {
13228       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13229         break;
13230       ++sample_num;
13231     }
13232   }
13233
13234   return ret;
13235 }
13236
13237 static gboolean
13238 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13239 {
13240   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13241 }
13242
13243 static gboolean
13244 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13245 {
13246   gint i;
13247
13248   /* Different length, updated */
13249   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13250     return TRUE;
13251
13252   /* streams in list are sorted in track-id order */
13253   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13254     /* Different stream-id, updated */
13255     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13256             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13257       return TRUE;
13258   }
13259
13260   return FALSE;
13261 }
13262
13263 static gboolean
13264 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13265     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13266 {
13267   /* Connect old stream's srcpad to new stream */
13268   newstream->pad = oldstream->pad;
13269   oldstream->pad = NULL;
13270
13271   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13272    * case we need to force one through */
13273   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13274
13275   return gst_qtdemux_configure_stream (qtdemux, newstream);
13276 }
13277
13278 static gboolean
13279 qtdemux_update_streams (GstQTDemux * qtdemux)
13280 {
13281   gint i;
13282   g_assert (qtdemux->streams_aware);
13283
13284   /* At below, figure out which stream in active_streams has identical stream-id
13285    * with that of in old_streams. If there is matching stream-id,
13286    * corresponding newstream will not be exposed again,
13287    * but demux will reuse srcpad of matched old stream
13288    *
13289    * active_streams : newly created streams from the latest moov
13290    * old_streams : existing streams (belong to previous moov)
13291    */
13292
13293   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13294     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13295     QtDemuxStream *oldstream = NULL;
13296     guint target;
13297
13298     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13299         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13300
13301     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13302             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13303       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13304
13305       /* null pad stream cannot be reused */
13306       if (oldstream->pad == NULL)
13307         oldstream = NULL;
13308     }
13309
13310     if (oldstream) {
13311       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13312
13313       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13314         return FALSE;
13315
13316       /* we don't need to preserve order of old streams */
13317       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13318     } else {
13319       GstTagList *list;
13320
13321       /* now we have all info and can expose */
13322       list = stream->stream_tags;
13323       stream->stream_tags = NULL;
13324       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13325         return FALSE;
13326     }
13327   }
13328
13329   return TRUE;
13330 }
13331
13332 /* Must be called with expose lock */
13333 static GstFlowReturn
13334 qtdemux_expose_streams (GstQTDemux * qtdemux)
13335 {
13336   gint i;
13337
13338   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13339
13340   if (!qtdemux_is_streams_update (qtdemux)) {
13341     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13342     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13343       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13344       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13345       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13346         return GST_FLOW_ERROR;
13347     }
13348
13349     g_ptr_array_set_size (qtdemux->old_streams, 0);
13350     qtdemux->need_segment = TRUE;
13351
13352     return GST_FLOW_OK;
13353   }
13354
13355   if (qtdemux->streams_aware) {
13356     if (!qtdemux_update_streams (qtdemux))
13357       return GST_FLOW_ERROR;
13358   } else {
13359     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13360       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13361       GstTagList *list;
13362
13363       /* now we have all info and can expose */
13364       list = stream->stream_tags;
13365       stream->stream_tags = NULL;
13366       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13367         return GST_FLOW_ERROR;
13368
13369     }
13370   }
13371
13372   gst_qtdemux_guess_bitrate (qtdemux);
13373
13374   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13375
13376   /* If we have still old_streams, it's no more used stream */
13377   for (i = 0; i < qtdemux->old_streams->len; i++) {
13378     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13379
13380     if (stream->pad) {
13381       GstEvent *event;
13382
13383       event = gst_event_new_eos ();
13384       if (qtdemux->segment_seqnum)
13385         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13386
13387       gst_pad_push_event (stream->pad, event);
13388     }
13389   }
13390
13391   g_ptr_array_set_size (qtdemux->old_streams, 0);
13392
13393   /* check if we should post a redirect in case there is a single trak
13394    * and it is a redirecting trak */
13395   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13396       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13397     GstMessage *m;
13398
13399     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13400         "an external content");
13401     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13402         gst_structure_new ("redirect",
13403             "new-location", G_TYPE_STRING,
13404             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13405     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13406     g_free (qtdemux->redirect_location);
13407     qtdemux->redirect_location =
13408         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13409   }
13410
13411   g_ptr_array_foreach (qtdemux->active_streams,
13412       (GFunc) qtdemux_do_allocation, qtdemux);
13413
13414   qtdemux->need_segment = TRUE;
13415
13416   qtdemux->exposed = TRUE;
13417   return GST_FLOW_OK;
13418 }
13419
13420 typedef struct
13421 {
13422   GstStructure *structure;      /* helper for sort function */
13423   gchar *location;
13424   guint min_req_bitrate;
13425   guint min_req_qt_version;
13426 } GstQtReference;
13427
13428 static gint
13429 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13430 {
13431   GstQtReference *ref_a = (GstQtReference *) a;
13432   GstQtReference *ref_b = (GstQtReference *) b;
13433
13434   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13435     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13436
13437   /* known bitrates go before unknown; higher bitrates go first */
13438   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13439 }
13440
13441 /* sort the redirects and post a message for the application.
13442  */
13443 static void
13444 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13445 {
13446   GstQtReference *best;
13447   GstStructure *s;
13448   GstMessage *msg;
13449   GValue list_val = { 0, };
13450   GList *l;
13451
13452   g_assert (references != NULL);
13453
13454   references = g_list_sort (references, qtdemux_redirects_sort_func);
13455
13456   best = (GstQtReference *) references->data;
13457
13458   g_value_init (&list_val, GST_TYPE_LIST);
13459
13460   for (l = references; l != NULL; l = l->next) {
13461     GstQtReference *ref = (GstQtReference *) l->data;
13462     GValue struct_val = { 0, };
13463
13464     ref->structure = gst_structure_new ("redirect",
13465         "new-location", G_TYPE_STRING, ref->location, NULL);
13466
13467     if (ref->min_req_bitrate > 0) {
13468       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13469           ref->min_req_bitrate, NULL);
13470     }
13471
13472     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13473     g_value_set_boxed (&struct_val, ref->structure);
13474     gst_value_list_append_value (&list_val, &struct_val);
13475     g_value_unset (&struct_val);
13476     /* don't free anything here yet, since we need best->structure below */
13477   }
13478
13479   g_assert (best != NULL);
13480   s = gst_structure_copy (best->structure);
13481
13482   if (g_list_length (references) > 1) {
13483     gst_structure_set_value (s, "locations", &list_val);
13484   }
13485
13486   g_value_unset (&list_val);
13487
13488   for (l = references; l != NULL; l = l->next) {
13489     GstQtReference *ref = (GstQtReference *) l->data;
13490
13491     gst_structure_free (ref->structure);
13492     g_free (ref->location);
13493     g_free (ref);
13494   }
13495   g_list_free (references);
13496
13497   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13498   g_free (qtdemux->redirect_location);
13499   qtdemux->redirect_location =
13500       g_strdup (gst_structure_get_string (s, "new-location"));
13501   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13502   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13503 }
13504
13505 /* look for redirect nodes, collect all redirect information and
13506  * process it.
13507  */
13508 static gboolean
13509 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13510 {
13511   GNode *rmra, *rmda, *rdrf;
13512
13513   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13514   if (rmra) {
13515     GList *redirects = NULL;
13516
13517     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13518     while (rmda) {
13519       GstQtReference ref = { NULL, NULL, 0, 0 };
13520       GNode *rmdr, *rmvc;
13521
13522       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13523         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13524         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13525             ref.min_req_bitrate);
13526       }
13527
13528       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13529         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13530         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13531
13532 #ifndef GST_DISABLE_GST_DEBUG
13533         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13534 #endif
13535         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13536
13537         GST_LOG_OBJECT (qtdemux,
13538             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13539             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13540             bitmask, check_type);
13541         if (package == FOURCC_qtim && check_type == 0) {
13542           ref.min_req_qt_version = version;
13543         }
13544       }
13545
13546       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13547       if (rdrf) {
13548         guint32 ref_type;
13549         guint8 *ref_data;
13550         guint ref_len;
13551
13552         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13553         if (ref_len > 20) {
13554           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13555           ref_data = (guint8 *) rdrf->data + 20;
13556           if (ref_type == FOURCC_alis) {
13557             guint record_len, record_version, fn_len;
13558
13559             if (ref_len > 70) {
13560               /* MacOSX alias record, google for alias-layout.txt */
13561               record_len = QT_UINT16 (ref_data + 4);
13562               record_version = QT_UINT16 (ref_data + 4 + 2);
13563               fn_len = QT_UINT8 (ref_data + 50);
13564               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13565                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13566               }
13567             } else {
13568               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13569                   ref_len);
13570             }
13571           } else if (ref_type == FOURCC_url_) {
13572             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13573           } else {
13574             GST_DEBUG_OBJECT (qtdemux,
13575                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13576                 GST_FOURCC_ARGS (ref_type));
13577           }
13578           if (ref.location != NULL) {
13579             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13580             redirects =
13581                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13582           } else {
13583             GST_WARNING_OBJECT (qtdemux,
13584                 "Failed to extract redirect location from rdrf atom");
13585           }
13586         } else {
13587           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13588         }
13589       }
13590
13591       /* look for others */
13592       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13593     }
13594
13595     if (redirects != NULL) {
13596       qtdemux_process_redirects (qtdemux, redirects);
13597     }
13598   }
13599   return TRUE;
13600 }
13601
13602 static GstTagList *
13603 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13604 {
13605   const gchar *fmt;
13606
13607   if (tags == NULL) {
13608     tags = gst_tag_list_new_empty ();
13609     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13610   }
13611
13612   if (qtdemux->major_brand == FOURCC_mjp2)
13613     fmt = "Motion JPEG 2000";
13614   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13615     fmt = "3GP";
13616   else if (qtdemux->major_brand == FOURCC_qt__)
13617     fmt = "Quicktime";
13618   else if (qtdemux->fragmented)
13619     fmt = "ISO fMP4";
13620   else
13621     fmt = "ISO MP4/M4A";
13622
13623   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13624       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13625
13626   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13627       fmt, NULL);
13628
13629   return tags;
13630 }
13631
13632 /* we have read the complete moov node now.
13633  * This function parses all of the relevant info, creates the traks and
13634  * prepares all data structures for playback
13635  */
13636 static gboolean
13637 qtdemux_parse_tree (GstQTDemux * qtdemux)
13638 {
13639   GNode *mvhd;
13640   GNode *trak;
13641   GNode *udta;
13642   GNode *mvex;
13643   GNode *pssh;
13644   guint64 creation_time;
13645   GstDateTime *datetime = NULL;
13646   gint version;
13647
13648   /* make sure we have a usable taglist */
13649   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13650
13651   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13652   if (mvhd == NULL) {
13653     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13654     return qtdemux_parse_redirects (qtdemux);
13655   }
13656
13657   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13658   if (version == 1) {
13659     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13660     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13661     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13662   } else if (version == 0) {
13663     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13664     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13665     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13666   } else {
13667     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13668     return FALSE;
13669   }
13670
13671   /* Moving qt creation time (secs since 1904) to unix time */
13672   if (creation_time != 0) {
13673     /* Try to use epoch first as it should be faster and more commonly found */
13674     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13675       gint64 now_s;
13676
13677       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13678       /* some data cleansing sanity */
13679       now_s = g_get_real_time () / G_USEC_PER_SEC;
13680       if (now_s + 24 * 3600 < creation_time) {
13681         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13682       } else {
13683         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13684       }
13685     } else {
13686       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13687       GDateTime *dt, *dt_local;
13688
13689       dt = g_date_time_add_seconds (base_dt, creation_time);
13690       dt_local = g_date_time_to_local (dt);
13691       datetime = gst_date_time_new_from_g_date_time (dt_local);
13692
13693       g_date_time_unref (base_dt);
13694       g_date_time_unref (dt);
13695     }
13696   }
13697   if (datetime) {
13698     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13699     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13700         datetime, NULL);
13701     gst_date_time_unref (datetime);
13702   }
13703
13704   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13705   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13706
13707   /* check for fragmented file and get some (default) data */
13708   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13709   if (mvex) {
13710     GNode *mehd;
13711     GstByteReader mehd_data;
13712
13713     /* let track parsing or anyone know weird stuff might happen ... */
13714     qtdemux->fragmented = TRUE;
13715
13716     /* compensate for total duration */
13717     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13718     if (mehd)
13719       qtdemux_parse_mehd (qtdemux, &mehd_data);
13720   }
13721
13722   /* Update the movie segment duration, unless it was directly given to us
13723    * by upstream. Otherwise let it as is, as we don't want to mangle the
13724    * duration provided by upstream that may come e.g. from a MPD file. */
13725   if (!qtdemux->upstream_format_is_time) {
13726     GstClockTime duration;
13727     /* set duration in the segment info */
13728     gst_qtdemux_get_duration (qtdemux, &duration);
13729     qtdemux->segment.duration = duration;
13730     /* also do not exceed duration; stop is set that way post seek anyway,
13731      * and segment activation falls back to duration,
13732      * whereas loop only checks stop, so let's align this here as well */
13733     qtdemux->segment.stop = duration;
13734   }
13735
13736   /* parse all traks */
13737   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13738   while (trak) {
13739     qtdemux_parse_trak (qtdemux, trak);
13740     /* iterate all siblings */
13741     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13742   }
13743
13744   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13745
13746   /* find tags */
13747   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13748   if (udta) {
13749     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13750   } else {
13751     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13752   }
13753
13754   /* maybe also some tags in meta box */
13755   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13756   if (udta) {
13757     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13758     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13759   } else {
13760     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13761   }
13762
13763   /* parse any protection system info */
13764   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13765   while (pssh) {
13766     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13767     qtdemux_parse_pssh (qtdemux, pssh);
13768     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13769   }
13770
13771   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13772
13773   return TRUE;
13774 }
13775
13776 /* taken from ffmpeg */
13777 static int
13778 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13779 {
13780   int count = 4;
13781   int len = 0;
13782
13783   while (count--) {
13784     int c;
13785
13786     if (ptr >= end)
13787       return -1;
13788
13789     c = *ptr++;
13790     len = (len << 7) | (c & 0x7f);
13791     if (!(c & 0x80))
13792       break;
13793   }
13794   *end_out = ptr;
13795   return len;
13796 }
13797
13798 static GList *
13799 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13800     gsize codec_data_size)
13801 {
13802   GList *list = NULL;
13803   guint8 *p = codec_data;
13804   gint i, offset, num_packets;
13805   guint *length, last;
13806
13807   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13808
13809   if (codec_data == NULL || codec_data_size == 0)
13810     goto error;
13811
13812   /* start of the stream and vorbis audio or theora video, need to
13813    * send the codec_priv data as first three packets */
13814   num_packets = p[0] + 1;
13815   GST_DEBUG_OBJECT (qtdemux,
13816       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13817       (guint) num_packets, codec_data_size);
13818
13819   /* Let's put some limits, Don't think there even is a xiph codec
13820    * with more than 3-4 headers */
13821   if (G_UNLIKELY (num_packets > 16)) {
13822     GST_WARNING_OBJECT (qtdemux,
13823         "Unlikely number of xiph headers, most likely not valid");
13824     goto error;
13825   }
13826
13827   length = g_alloca (num_packets * sizeof (guint));
13828   last = 0;
13829   offset = 1;
13830
13831   /* first packets, read length values */
13832   for (i = 0; i < num_packets - 1; i++) {
13833     length[i] = 0;
13834     while (offset < codec_data_size) {
13835       length[i] += p[offset];
13836       if (p[offset++] != 0xff)
13837         break;
13838     }
13839     last += length[i];
13840   }
13841   if (offset + last > codec_data_size)
13842     goto error;
13843
13844   /* last packet is the remaining size */
13845   length[i] = codec_data_size - offset - last;
13846
13847   for (i = 0; i < num_packets; i++) {
13848     GstBuffer *hdr;
13849
13850     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13851
13852     if (offset + length[i] > codec_data_size)
13853       goto error;
13854
13855     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13856     list = g_list_append (list, hdr);
13857
13858     offset += length[i];
13859   }
13860
13861   return list;
13862
13863   /* ERRORS */
13864 error:
13865   {
13866     if (list != NULL)
13867       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13868     return NULL;
13869   }
13870
13871 }
13872
13873 /* this can change the codec originally present in @list */
13874 static void
13875 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13876     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13877 {
13878   int len = QT_UINT32 (esds->data);
13879   guint8 *ptr = esds->data;
13880   guint8 *end = ptr + len;
13881   int tag;
13882   guint8 *data_ptr = NULL;
13883   int data_len = 0;
13884   guint8 object_type_id = 0;
13885   guint8 stream_type = 0;
13886   const char *codec_name = NULL;
13887   GstCaps *caps = NULL;
13888
13889   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13890   ptr += 8;
13891   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13892   ptr += 4;
13893   while (ptr + 1 < end) {
13894     tag = QT_UINT8 (ptr);
13895     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13896     ptr++;
13897     len = read_descr_size (ptr, end, &ptr);
13898     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13899
13900     /* Check the stated amount of data is available for reading */
13901     if (len < 0 || ptr + len > end)
13902       break;
13903
13904     switch (tag) {
13905       case ES_DESCRIPTOR_TAG:
13906         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13907         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13908         ptr += 3;
13909         break;
13910       case DECODER_CONFIG_DESC_TAG:{
13911         guint max_bitrate, avg_bitrate;
13912
13913         object_type_id = QT_UINT8 (ptr);
13914         stream_type = QT_UINT8 (ptr + 1) >> 2;
13915         max_bitrate = QT_UINT32 (ptr + 5);
13916         avg_bitrate = QT_UINT32 (ptr + 9);
13917         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13918         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13919         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13920         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13921         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13922         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13923           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13924               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13925         }
13926         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13927           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13928               avg_bitrate, NULL);
13929         }
13930         ptr += 13;
13931         break;
13932       }
13933       case DECODER_SPECIFIC_INFO_TAG:
13934         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13935         if (object_type_id == 0xe0 && len == 0x40) {
13936           guint8 *data;
13937           GstStructure *s;
13938           guint32 clut[16];
13939           gint i;
13940
13941           GST_DEBUG_OBJECT (qtdemux,
13942               "Have VOBSUB palette. Creating palette event");
13943           /* move to decConfigDescr data and read palette */
13944           data = ptr;
13945           for (i = 0; i < 16; i++) {
13946             clut[i] = QT_UINT32 (data);
13947             data += 4;
13948           }
13949
13950           s = gst_structure_new ("application/x-gst-dvd", "event",
13951               G_TYPE_STRING, "dvd-spu-clut-change",
13952               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13953               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13954               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13955               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13956               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13957               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13958               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13959               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13960               NULL);
13961
13962           /* store event and trigger custom processing */
13963           stream->pending_event =
13964               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13965         } else {
13966           /* Generic codec_data handler puts it on the caps */
13967           data_ptr = ptr;
13968           data_len = len;
13969         }
13970
13971         ptr += len;
13972         break;
13973       case SL_CONFIG_DESC_TAG:
13974         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13975         ptr += 1;
13976         break;
13977       default:
13978         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13979             tag);
13980         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13981         ptr += len;
13982         break;
13983     }
13984   }
13985
13986   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13987    * in use, and should also be used to override some other parameters for some
13988    * codecs. */
13989   switch (object_type_id) {
13990     case 0x20:                 /* MPEG-4 */
13991       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13992        * profile_and_level_indication */
13993       if (data_ptr != NULL && data_len >= 5 &&
13994           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13995         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13996             data_ptr + 4, data_len - 4);
13997       }
13998       break;                    /* Nothing special needed here */
13999     case 0x21:                 /* H.264 */
14000       codec_name = "H.264 / AVC";
14001       caps = gst_caps_new_simple ("video/x-h264",
14002           "stream-format", G_TYPE_STRING, "avc",
14003           "alignment", G_TYPE_STRING, "au", NULL);
14004       break;
14005     case 0x40:                 /* AAC (any) */
14006     case 0x66:                 /* AAC Main */
14007     case 0x67:                 /* AAC LC */
14008     case 0x68:                 /* AAC SSR */
14009       /* Override channels and rate based on the codec_data, as it's often
14010        * wrong. */
14011       /* Only do so for basic setup without HE-AAC extension */
14012       if (data_ptr && data_len == 2) {
14013         guint channels, rate;
14014
14015         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14016         if (channels > 0)
14017           entry->n_channels = channels;
14018
14019         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14020         if (rate > 0)
14021           entry->rate = rate;
14022       }
14023
14024       /* Set level and profile if possible */
14025       if (data_ptr != NULL && data_len >= 2) {
14026         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14027             data_ptr, data_len);
14028       } else {
14029         const gchar *profile_str = NULL;
14030         GstBuffer *buffer;
14031         GstMapInfo map;
14032         guint8 *codec_data;
14033         gint rate_idx, profile;
14034
14035         /* No codec_data, let's invent something.
14036          * FIXME: This is wrong for SBR! */
14037
14038         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14039
14040         buffer = gst_buffer_new_and_alloc (2);
14041         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14042         codec_data = map.data;
14043
14044         rate_idx =
14045             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14046             (stream)->rate);
14047
14048         switch (object_type_id) {
14049           case 0x66:
14050             profile_str = "main";
14051             profile = 0;
14052             break;
14053           case 0x67:
14054             profile_str = "lc";
14055             profile = 1;
14056             break;
14057           case 0x68:
14058             profile_str = "ssr";
14059             profile = 2;
14060             break;
14061           default:
14062             profile = 3;
14063             break;
14064         }
14065
14066         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14067         codec_data[1] =
14068             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14069
14070         gst_buffer_unmap (buffer, &map);
14071         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14072             GST_TYPE_BUFFER, buffer, NULL);
14073         gst_buffer_unref (buffer);
14074
14075         if (profile_str) {
14076           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14077               G_TYPE_STRING, profile_str, NULL);
14078         }
14079       }
14080       break;
14081     case 0x60:                 /* MPEG-2, various profiles */
14082     case 0x61:
14083     case 0x62:
14084     case 0x63:
14085     case 0x64:
14086     case 0x65:
14087       codec_name = "MPEG-2 video";
14088       caps = gst_caps_new_simple ("video/mpeg",
14089           "mpegversion", G_TYPE_INT, 2,
14090           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14091       break;
14092     case 0x69:                 /* MPEG-2 BC audio */
14093     case 0x6B:                 /* MPEG-1 audio */
14094       caps = gst_caps_new_simple ("audio/mpeg",
14095           "mpegversion", G_TYPE_INT, 1, NULL);
14096       codec_name = "MPEG-1 audio";
14097       break;
14098     case 0x6A:                 /* MPEG-1 */
14099       codec_name = "MPEG-1 video";
14100       caps = gst_caps_new_simple ("video/mpeg",
14101           "mpegversion", G_TYPE_INT, 1,
14102           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14103       break;
14104     case 0x6C:                 /* MJPEG */
14105       caps =
14106           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14107           NULL);
14108       codec_name = "Motion-JPEG";
14109       break;
14110     case 0x6D:                 /* PNG */
14111       caps =
14112           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14113           NULL);
14114       codec_name = "PNG still images";
14115       break;
14116     case 0x6E:                 /* JPEG2000 */
14117       codec_name = "JPEG-2000";
14118       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14119       break;
14120     case 0xA4:                 /* Dirac */
14121       codec_name = "Dirac";
14122       caps = gst_caps_new_empty_simple ("video/x-dirac");
14123       break;
14124     case 0xA5:                 /* AC3 */
14125       codec_name = "AC-3 audio";
14126       caps = gst_caps_new_simple ("audio/x-ac3",
14127           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14128       break;
14129     case 0xA9:                 /* AC3 */
14130       codec_name = "DTS audio";
14131       caps = gst_caps_new_simple ("audio/x-dts",
14132           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14133       break;
14134     case 0xDD:
14135       if (stream_type == 0x05 && data_ptr) {
14136         GList *headers =
14137             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14138         if (headers) {
14139           GList *tmp;
14140           GValue arr_val = G_VALUE_INIT;
14141           GValue buf_val = G_VALUE_INIT;
14142           GstStructure *s;
14143
14144           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14145           codec_name = "Vorbis";
14146           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14147           g_value_init (&arr_val, GST_TYPE_ARRAY);
14148           g_value_init (&buf_val, GST_TYPE_BUFFER);
14149           for (tmp = headers; tmp; tmp = tmp->next) {
14150             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14151             gst_value_array_append_value (&arr_val, &buf_val);
14152           }
14153           s = gst_caps_get_structure (caps, 0);
14154           gst_structure_take_value (s, "streamheader", &arr_val);
14155           g_value_unset (&buf_val);
14156           g_list_free (headers);
14157
14158           data_ptr = NULL;
14159           data_len = 0;
14160         }
14161       }
14162       break;
14163     case 0xE1:                 /* QCELP */
14164       /* QCELP, the codec_data is a riff tag (little endian) with
14165        * 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). */
14166       caps = gst_caps_new_empty_simple ("audio/qcelp");
14167       codec_name = "QCELP";
14168       break;
14169     default:
14170       break;
14171   }
14172
14173   /* If we have a replacement caps, then change our caps for this stream */
14174   if (caps) {
14175     gst_caps_unref (entry->caps);
14176     entry->caps = caps;
14177   }
14178
14179   if (codec_name && list)
14180     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14181         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14182
14183   /* Add the codec_data attribute to caps, if we have it */
14184   if (data_ptr) {
14185     GstBuffer *buffer;
14186
14187     buffer = gst_buffer_new_and_alloc (data_len);
14188     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14189
14190     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14191     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14192
14193     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14194         buffer, NULL);
14195     gst_buffer_unref (buffer);
14196   }
14197
14198 }
14199
14200 static inline GstCaps *
14201 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14202 {
14203   GstCaps *caps;
14204   guint i;
14205   char *s, fourstr[5];
14206
14207   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14208   for (i = 0; i < 4; i++) {
14209     if (!g_ascii_isalnum (fourstr[i]))
14210       fourstr[i] = '_';
14211   }
14212   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14213   caps = gst_caps_new_empty_simple (s);
14214   g_free (s);
14215   return caps;
14216 }
14217
14218 #define _codec(name) \
14219   do { \
14220     if (codec_name) { \
14221       *codec_name = g_strdup (name); \
14222     } \
14223   } while (0)
14224
14225 static GstCaps *
14226 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14227     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14228     const guint8 * stsd_entry_data, gchar ** codec_name)
14229 {
14230   GstCaps *caps = NULL;
14231   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14232
14233   switch (fourcc) {
14234     case FOURCC_png:
14235       _codec ("PNG still images");
14236       caps = gst_caps_new_empty_simple ("image/png");
14237       break;
14238     case FOURCC_jpeg:
14239       _codec ("JPEG still images");
14240       caps =
14241           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14242           NULL);
14243       break;
14244     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14245     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14246     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14247     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14248       _codec ("Motion-JPEG");
14249       caps =
14250           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14251           NULL);
14252       break;
14253     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14254       _codec ("Motion-JPEG format B");
14255       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14256       break;
14257     case FOURCC_mjp2:
14258       _codec ("JPEG-2000");
14259       /* override to what it should be according to spec, avoid palette_data */
14260       entry->bits_per_sample = 24;
14261       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14262       break;
14263     case FOURCC_SVQ3:
14264       _codec ("Sorensen video v.3");
14265       caps = gst_caps_new_simple ("video/x-svq",
14266           "svqversion", G_TYPE_INT, 3, NULL);
14267       break;
14268     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14269     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14270       _codec ("Sorensen video v.1");
14271       caps = gst_caps_new_simple ("video/x-svq",
14272           "svqversion", G_TYPE_INT, 1, NULL);
14273       break;
14274     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14275       caps = gst_caps_new_empty_simple ("video/x-raw");
14276       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14277       _codec ("Windows Raw RGB");
14278       stream->alignment = 32;
14279       break;
14280     case FOURCC_raw_:
14281     {
14282       guint16 bps;
14283
14284       bps = QT_UINT16 (stsd_entry_data + 82);
14285       switch (bps) {
14286         case 15:
14287           format = GST_VIDEO_FORMAT_RGB15;
14288           break;
14289         case 16:
14290           format = GST_VIDEO_FORMAT_RGB16;
14291           break;
14292         case 24:
14293           format = GST_VIDEO_FORMAT_RGB;
14294           break;
14295         case 32:
14296           format = GST_VIDEO_FORMAT_ARGB;
14297           break;
14298         default:
14299           /* unknown */
14300           break;
14301       }
14302       break;
14303     }
14304     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14305       format = GST_VIDEO_FORMAT_I420;
14306       break;
14307     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14308     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14309       format = GST_VIDEO_FORMAT_I420;
14310       break;
14311     case FOURCC_2vuy:
14312     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14313       format = GST_VIDEO_FORMAT_UYVY;
14314       break;
14315     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14316       format = GST_VIDEO_FORMAT_v308;
14317       break;
14318     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14319       format = GST_VIDEO_FORMAT_v216;
14320       break;
14321     case FOURCC_v210:
14322       format = GST_VIDEO_FORMAT_v210;
14323       break;
14324     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14325       format = GST_VIDEO_FORMAT_r210;
14326       break;
14327       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14328          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14329          format = GST_VIDEO_FORMAT_v410;
14330          break;
14331        */
14332       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14333        * but different order than AYUV
14334        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14335        format = GST_VIDEO_FORMAT_v408;
14336        break;
14337        */
14338     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14339     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14340       _codec ("MPEG-1 video");
14341       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14342           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14343       break;
14344     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14345     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14346     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14347     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14348     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14349     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14350     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14351     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14352     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14353     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14354     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14355     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14356     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14357     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14358     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14359     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14360     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14361     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14362     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14363     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14364     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14365     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14366     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14367     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14368     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14369     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14370     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14371     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14372     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14373     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14374     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14375     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14376     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14377     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14378     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14379     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14380     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14381     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14382     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14383     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14384     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14385     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14386     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14387     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14388     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14389     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14390     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14391       _codec ("MPEG-2 video");
14392       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14393           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14394       break;
14395     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14396       _codec ("GIF still images");
14397       caps = gst_caps_new_empty_simple ("image/gif");
14398       break;
14399     case FOURCC_h263:
14400     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14401     case FOURCC_s263:
14402     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14403       _codec ("H.263");
14404       /* ffmpeg uses the height/width props, don't know why */
14405       caps = gst_caps_new_simple ("video/x-h263",
14406           "variant", G_TYPE_STRING, "itu", NULL);
14407       break;
14408     case FOURCC_mp4v:
14409     case FOURCC_MP4V:
14410       _codec ("MPEG-4 video");
14411       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14412           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14413       break;
14414     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14415     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14416       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14417       caps = gst_caps_new_simple ("video/x-msmpeg",
14418           "msmpegversion", G_TYPE_INT, 43, NULL);
14419       break;
14420     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14421       _codec ("DivX 3");
14422       caps = gst_caps_new_simple ("video/x-divx",
14423           "divxversion", G_TYPE_INT, 3, NULL);
14424       break;
14425     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14426     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14427       _codec ("DivX 4");
14428       caps = gst_caps_new_simple ("video/x-divx",
14429           "divxversion", G_TYPE_INT, 4, NULL);
14430       break;
14431     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14432       _codec ("DivX 5");
14433       caps = gst_caps_new_simple ("video/x-divx",
14434           "divxversion", G_TYPE_INT, 5, NULL);
14435       break;
14436
14437     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14438       _codec ("FFV1");
14439       caps = gst_caps_new_simple ("video/x-ffv",
14440           "ffvversion", G_TYPE_INT, 1, NULL);
14441       break;
14442
14443     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14444     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14445     case FOURCC_XVID:
14446     case FOURCC_xvid:
14447     case FOURCC_FMP4:
14448     case FOURCC_fmp4:
14449     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14450       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14451           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14452       _codec ("MPEG-4");
14453       break;
14454
14455     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14456       _codec ("Cinepak");
14457       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14458       break;
14459     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14460       _codec ("Apple QuickDraw");
14461       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14462       break;
14463     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14464       _codec ("Apple video");
14465       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14466       break;
14467     case FOURCC_H264:
14468     case FOURCC_avc1:
14469     case FOURCC_dva1:
14470       _codec ("H.264 / AVC");
14471       caps = gst_caps_new_simple ("video/x-h264",
14472           "stream-format", G_TYPE_STRING, "avc",
14473           "alignment", G_TYPE_STRING, "au", NULL);
14474       break;
14475     case FOURCC_avc3:
14476     case FOURCC_dvav:
14477       _codec ("H.264 / AVC");
14478       caps = gst_caps_new_simple ("video/x-h264",
14479           "stream-format", G_TYPE_STRING, "avc3",
14480           "alignment", G_TYPE_STRING, "au", NULL);
14481       break;
14482     case FOURCC_H265:
14483     case FOURCC_hvc1:
14484     case FOURCC_dvh1:
14485       _codec ("H.265 / HEVC");
14486       caps = gst_caps_new_simple ("video/x-h265",
14487           "stream-format", G_TYPE_STRING, "hvc1",
14488           "alignment", G_TYPE_STRING, "au", NULL);
14489       break;
14490     case FOURCC_hev1:
14491     case FOURCC_dvhe:
14492       _codec ("H.265 / HEVC");
14493       caps = gst_caps_new_simple ("video/x-h265",
14494           "stream-format", G_TYPE_STRING, "hev1",
14495           "alignment", G_TYPE_STRING, "au", NULL);
14496       break;
14497     case FOURCC_rle_:
14498       _codec ("Run-length encoding");
14499       caps = gst_caps_new_simple ("video/x-rle",
14500           "layout", G_TYPE_STRING, "quicktime", NULL);
14501       break;
14502     case FOURCC_WRLE:
14503       _codec ("Run-length encoding");
14504       caps = gst_caps_new_simple ("video/x-rle",
14505           "layout", G_TYPE_STRING, "microsoft", NULL);
14506       break;
14507     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14508     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14509       _codec ("Indeo Video 3");
14510       caps = gst_caps_new_simple ("video/x-indeo",
14511           "indeoversion", G_TYPE_INT, 3, NULL);
14512       break;
14513     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14514     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14515       _codec ("Intel Video 4");
14516       caps = gst_caps_new_simple ("video/x-indeo",
14517           "indeoversion", G_TYPE_INT, 4, NULL);
14518       break;
14519     case FOURCC_dvcp:
14520     case FOURCC_dvc_:
14521     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14522     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14523     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14524     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14525     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14526     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14527       _codec ("DV Video");
14528       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14529           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14530       break;
14531     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14532     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14533       _codec ("DVCPro50 Video");
14534       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14535           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14536       break;
14537     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14538     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14539       _codec ("DVCProHD Video");
14540       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14541           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14542       break;
14543     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14544       _codec ("Apple Graphics (SMC)");
14545       caps = gst_caps_new_empty_simple ("video/x-smc");
14546       break;
14547     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14548       _codec ("VP3");
14549       caps = gst_caps_new_empty_simple ("video/x-vp3");
14550       break;
14551     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14552       _codec ("VP6 Flash");
14553       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14554       break;
14555     case FOURCC_XiTh:
14556       _codec ("Theora");
14557       caps = gst_caps_new_empty_simple ("video/x-theora");
14558       /* theora uses one byte of padding in the data stream because it does not
14559        * allow 0 sized packets while theora does */
14560       entry->padding = 1;
14561       break;
14562     case FOURCC_drac:
14563       _codec ("Dirac");
14564       caps = gst_caps_new_empty_simple ("video/x-dirac");
14565       break;
14566     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14567       _codec ("TIFF still images");
14568       caps = gst_caps_new_empty_simple ("image/tiff");
14569       break;
14570     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14571       _codec ("Apple Intermediate Codec");
14572       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14573       break;
14574     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14575       _codec ("AVID DNxHD");
14576       caps = gst_caps_from_string ("video/x-dnxhd");
14577       break;
14578     case FOURCC_VP80:
14579     case FOURCC_vp08:
14580       _codec ("On2 VP8");
14581       caps = gst_caps_from_string ("video/x-vp8");
14582       break;
14583     case FOURCC_vp09:
14584       _codec ("Google VP9");
14585       caps = gst_caps_from_string ("video/x-vp9");
14586       break;
14587     case FOURCC_apcs:
14588       _codec ("Apple ProRes LT");
14589       caps =
14590           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14591           NULL);
14592       break;
14593     case FOURCC_apch:
14594       _codec ("Apple ProRes HQ");
14595       caps =
14596           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14597           NULL);
14598       break;
14599     case FOURCC_apcn:
14600       _codec ("Apple ProRes");
14601       caps =
14602           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14603           "standard", NULL);
14604       break;
14605     case FOURCC_apco:
14606       _codec ("Apple ProRes Proxy");
14607       caps =
14608           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14609           "proxy", NULL);
14610       break;
14611     case FOURCC_ap4h:
14612       _codec ("Apple ProRes 4444");
14613       caps =
14614           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14615           "4444", NULL);
14616
14617       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14618       if (entry->bits_per_sample > 0) {
14619         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14620             NULL);
14621       }
14622       break;
14623     case FOURCC_ap4x:
14624       _codec ("Apple ProRes 4444 XQ");
14625       caps =
14626           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14627           "4444xq", NULL);
14628
14629       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14630       if (entry->bits_per_sample > 0) {
14631         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14632             NULL);
14633       }
14634       break;
14635     case FOURCC_cfhd:
14636       _codec ("GoPro CineForm");
14637       caps = gst_caps_from_string ("video/x-cineform");
14638       break;
14639     case FOURCC_vc_1:
14640     case FOURCC_ovc1:
14641       _codec ("VC-1");
14642       caps = gst_caps_new_simple ("video/x-wmv",
14643           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14644       break;
14645     case FOURCC_av01:
14646       _codec ("AV1");
14647       caps = gst_caps_new_empty_simple ("video/x-av1");
14648       break;
14649     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14650     default:
14651     {
14652       caps = _get_unknown_codec_name ("video", fourcc);
14653       break;
14654     }
14655   }
14656
14657   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14658     GstVideoInfo info;
14659
14660     gst_video_info_init (&info);
14661     gst_video_info_set_format (&info, format, entry->width, entry->height);
14662
14663     caps = gst_video_info_to_caps (&info);
14664     *codec_name = gst_pb_utils_get_codec_description (caps);
14665
14666     /* enable clipping for raw video streams */
14667     stream->need_clip = TRUE;
14668     stream->alignment = 32;
14669   }
14670
14671   return caps;
14672 }
14673
14674 static guint
14675 round_up_pow2 (guint n)
14676 {
14677   n = n - 1;
14678   n = n | (n >> 1);
14679   n = n | (n >> 2);
14680   n = n | (n >> 4);
14681   n = n | (n >> 8);
14682   n = n | (n >> 16);
14683   return n + 1;
14684 }
14685
14686 static GstCaps *
14687 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14688     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14689     int len, gchar ** codec_name)
14690 {
14691   GstCaps *caps;
14692   const GstStructure *s;
14693   const gchar *name;
14694   gint endian = 0;
14695   GstAudioFormat format = 0;
14696   gint depth;
14697
14698   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14699
14700   depth = entry->bytes_per_packet * 8;
14701
14702   switch (fourcc) {
14703     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14704     case FOURCC_raw_:
14705       /* 8-bit audio is unsigned */
14706       if (depth == 8)
14707         format = GST_AUDIO_FORMAT_U8;
14708       /* otherwise it's signed and big-endian just like 'twos' */
14709     case FOURCC_twos:
14710       endian = G_BIG_ENDIAN;
14711       /* fall-through */
14712     case FOURCC_sowt:
14713     {
14714       gchar *str;
14715
14716       if (!endian)
14717         endian = G_LITTLE_ENDIAN;
14718
14719       if (!format)
14720         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14721
14722       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14723       _codec (str);
14724       g_free (str);
14725
14726       caps = gst_caps_new_simple ("audio/x-raw",
14727           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14728           "layout", G_TYPE_STRING, "interleaved", NULL);
14729       stream->alignment = GST_ROUND_UP_8 (depth);
14730       stream->alignment = round_up_pow2 (stream->alignment);
14731       break;
14732     }
14733     case FOURCC_fl64:
14734       _codec ("Raw 64-bit floating-point audio");
14735       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14736        * endian later */
14737       caps = gst_caps_new_simple ("audio/x-raw",
14738           "format", G_TYPE_STRING, "F64BE",
14739           "layout", G_TYPE_STRING, "interleaved", NULL);
14740       stream->alignment = 8;
14741       break;
14742     case FOURCC_fl32:
14743       _codec ("Raw 32-bit floating-point audio");
14744       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14745        * endian later */
14746       caps = gst_caps_new_simple ("audio/x-raw",
14747           "format", G_TYPE_STRING, "F32BE",
14748           "layout", G_TYPE_STRING, "interleaved", NULL);
14749       stream->alignment = 4;
14750       break;
14751     case FOURCC_in24:
14752       _codec ("Raw 24-bit PCM audio");
14753       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14754        * endian later */
14755       caps = gst_caps_new_simple ("audio/x-raw",
14756           "format", G_TYPE_STRING, "S24BE",
14757           "layout", G_TYPE_STRING, "interleaved", NULL);
14758       stream->alignment = 4;
14759       break;
14760     case FOURCC_in32:
14761       _codec ("Raw 32-bit PCM audio");
14762       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14763        * endian later */
14764       caps = gst_caps_new_simple ("audio/x-raw",
14765           "format", G_TYPE_STRING, "S32BE",
14766           "layout", G_TYPE_STRING, "interleaved", NULL);
14767       stream->alignment = 4;
14768       break;
14769     case FOURCC_s16l:
14770       _codec ("Raw 16-bit PCM audio");
14771       caps = gst_caps_new_simple ("audio/x-raw",
14772           "format", G_TYPE_STRING, "S16LE",
14773           "layout", G_TYPE_STRING, "interleaved", NULL);
14774       stream->alignment = 2;
14775       break;
14776     case FOURCC_ulaw:
14777       _codec ("Mu-law audio");
14778       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14779       break;
14780     case FOURCC_alaw:
14781       _codec ("A-law audio");
14782       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14783       break;
14784     case 0x0200736d:
14785     case 0x6d730002:
14786       _codec ("Microsoft ADPCM");
14787       /* Microsoft ADPCM-ACM code 2 */
14788       caps = gst_caps_new_simple ("audio/x-adpcm",
14789           "layout", G_TYPE_STRING, "microsoft", NULL);
14790       break;
14791     case 0x1100736d:
14792     case 0x6d730011:
14793       _codec ("DVI/IMA ADPCM");
14794       caps = gst_caps_new_simple ("audio/x-adpcm",
14795           "layout", G_TYPE_STRING, "dvi", NULL);
14796       break;
14797     case 0x1700736d:
14798     case 0x6d730017:
14799       _codec ("DVI/Intel IMA ADPCM");
14800       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14801       caps = gst_caps_new_simple ("audio/x-adpcm",
14802           "layout", G_TYPE_STRING, "quicktime", NULL);
14803       break;
14804     case 0x5500736d:
14805     case 0x6d730055:
14806       /* MPEG layer 3, CBR only (pre QT4.1) */
14807     case FOURCC__mp3:
14808     case FOURCC_mp3_:
14809       _codec ("MPEG-1 layer 3");
14810       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14811       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14812           "mpegversion", G_TYPE_INT, 1, NULL);
14813       break;
14814     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14815       _codec ("MPEG-1 layer 2");
14816       /* MPEG layer 2 */
14817       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14818           "mpegversion", G_TYPE_INT, 1, NULL);
14819       break;
14820     case 0x20736d:
14821     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14822       _codec ("EAC-3 audio");
14823       caps = gst_caps_new_simple ("audio/x-eac3",
14824           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14825       entry->sampled = TRUE;
14826       break;
14827     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14828     case FOURCC_ac_3:
14829       _codec ("AC-3 audio");
14830       caps = gst_caps_new_simple ("audio/x-ac3",
14831           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14832       entry->sampled = TRUE;
14833       break;
14834     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14835     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14836       _codec ("DTS audio");
14837       caps = gst_caps_new_simple ("audio/x-dts",
14838           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14839       entry->sampled = TRUE;
14840       break;
14841     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14842     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14843       _codec ("DTS-HD audio");
14844       caps = gst_caps_new_simple ("audio/x-dts",
14845           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14846       entry->sampled = TRUE;
14847       break;
14848     case FOURCC_MAC3:
14849       _codec ("MACE-3");
14850       caps = gst_caps_new_simple ("audio/x-mace",
14851           "maceversion", G_TYPE_INT, 3, NULL);
14852       break;
14853     case FOURCC_MAC6:
14854       _codec ("MACE-6");
14855       caps = gst_caps_new_simple ("audio/x-mace",
14856           "maceversion", G_TYPE_INT, 6, NULL);
14857       break;
14858     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14859       /* ogg/vorbis */
14860       caps = gst_caps_new_empty_simple ("application/ogg");
14861       break;
14862     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14863       _codec ("DV audio");
14864       caps = gst_caps_new_empty_simple ("audio/x-dv");
14865       break;
14866     case FOURCC_mp4a:
14867       _codec ("MPEG-4 AAC audio");
14868       caps = gst_caps_new_simple ("audio/mpeg",
14869           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14870           "stream-format", G_TYPE_STRING, "raw", NULL);
14871       break;
14872     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14873       _codec ("QDesign Music");
14874       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14875       break;
14876     case FOURCC_QDM2:
14877       _codec ("QDesign Music v.2");
14878       /* FIXME: QDesign music version 2 (no constant) */
14879       if (FALSE && data) {
14880         caps = gst_caps_new_simple ("audio/x-qdm2",
14881             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14882             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14883             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14884       } else {
14885         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14886       }
14887       break;
14888     case FOURCC_agsm:
14889       _codec ("GSM audio");
14890       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14891       break;
14892     case FOURCC_samr:
14893       _codec ("AMR audio");
14894       caps = gst_caps_new_empty_simple ("audio/AMR");
14895       break;
14896     case FOURCC_sawb:
14897       _codec ("AMR-WB audio");
14898       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14899       break;
14900     case FOURCC_ima4:
14901       _codec ("Quicktime IMA ADPCM");
14902       caps = gst_caps_new_simple ("audio/x-adpcm",
14903           "layout", G_TYPE_STRING, "quicktime", NULL);
14904       break;
14905     case FOURCC_alac:
14906       _codec ("Apple lossless audio");
14907       caps = gst_caps_new_empty_simple ("audio/x-alac");
14908       break;
14909     case FOURCC_fLaC:
14910       _codec ("Free Lossless Audio Codec");
14911       caps = gst_caps_new_simple ("audio/x-flac",
14912           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14913       break;
14914     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14915       _codec ("QualComm PureVoice");
14916       caps = gst_caps_from_string ("audio/qcelp");
14917       break;
14918     case FOURCC_wma_:
14919     case FOURCC_owma:
14920       _codec ("WMA");
14921       caps = gst_caps_new_empty_simple ("audio/x-wma");
14922       break;
14923     case FOURCC_opus:
14924       _codec ("Opus");
14925       caps = gst_caps_new_empty_simple ("audio/x-opus");
14926       break;
14927     case FOURCC_lpcm:
14928     {
14929       guint32 flags = 0;
14930       guint32 depth = 0;
14931       guint32 width = 0;
14932       GstAudioFormat format;
14933       enum
14934       {
14935         FLAG_IS_FLOAT = 0x1,
14936         FLAG_IS_BIG_ENDIAN = 0x2,
14937         FLAG_IS_SIGNED = 0x4,
14938         FLAG_IS_PACKED = 0x8,
14939         FLAG_IS_ALIGNED_HIGH = 0x10,
14940         FLAG_IS_NON_INTERLEAVED = 0x20
14941       };
14942       _codec ("Raw LPCM audio");
14943
14944       if (data && len >= 36) {
14945         depth = QT_UINT32 (data + 24);
14946         flags = QT_UINT32 (data + 28);
14947         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14948       }
14949       if ((flags & FLAG_IS_FLOAT) == 0) {
14950         if (depth == 0)
14951           depth = 16;
14952         if (width == 0)
14953           width = 16;
14954         if ((flags & FLAG_IS_ALIGNED_HIGH))
14955           depth = width;
14956
14957         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14958             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14959             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14960         caps = gst_caps_new_simple ("audio/x-raw",
14961             "format", G_TYPE_STRING,
14962             format !=
14963             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14964             "UNKNOWN", "layout", G_TYPE_STRING,
14965             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14966             "interleaved", NULL);
14967         stream->alignment = GST_ROUND_UP_8 (depth);
14968         stream->alignment = round_up_pow2 (stream->alignment);
14969       } else {
14970         if (width == 0)
14971           width = 32;
14972         if (width == 64) {
14973           if (flags & FLAG_IS_BIG_ENDIAN)
14974             format = GST_AUDIO_FORMAT_F64BE;
14975           else
14976             format = GST_AUDIO_FORMAT_F64LE;
14977         } else {
14978           if (flags & FLAG_IS_BIG_ENDIAN)
14979             format = GST_AUDIO_FORMAT_F32BE;
14980           else
14981             format = GST_AUDIO_FORMAT_F32LE;
14982         }
14983         caps = gst_caps_new_simple ("audio/x-raw",
14984             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14985             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14986             "non-interleaved" : "interleaved", NULL);
14987         stream->alignment = width / 8;
14988       }
14989       break;
14990     }
14991     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14992     {
14993       _codec ("AC4");
14994       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14995       break;
14996     }
14997     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14998       /* ? */
14999     default:
15000     {
15001       caps = _get_unknown_codec_name ("audio", fourcc);
15002       break;
15003     }
15004   }
15005
15006   if (caps) {
15007     GstCaps *templ_caps =
15008         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15009     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15010     gst_caps_unref (caps);
15011     gst_caps_unref (templ_caps);
15012     caps = intersection;
15013   }
15014
15015   /* enable clipping for raw audio streams */
15016   s = gst_caps_get_structure (caps, 0);
15017   name = gst_structure_get_name (s);
15018   if (g_str_has_prefix (name, "audio/x-raw")) {
15019     stream->need_clip = TRUE;
15020     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15021     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15022     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15023         stream->max_buffer_size);
15024   }
15025   return caps;
15026 }
15027
15028 static GstCaps *
15029 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15030     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15031     const guint8 * stsd_entry_data, gchar ** codec_name)
15032 {
15033   GstCaps *caps;
15034
15035   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15036
15037   switch (fourcc) {
15038     case FOURCC_mp4s:
15039       _codec ("DVD subtitle");
15040       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15041       stream->process_func = gst_qtdemux_process_buffer_dvd;
15042       break;
15043     case FOURCC_text:
15044       _codec ("Quicktime timed text");
15045       goto text;
15046     case FOURCC_tx3g:
15047       _codec ("3GPP timed text");
15048     text:
15049       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15050           "utf8", NULL);
15051       /* actual text piece needs to be extracted */
15052       stream->process_func = gst_qtdemux_process_buffer_text;
15053       break;
15054     case FOURCC_stpp:
15055       _codec ("XML subtitles");
15056       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15057       break;
15058     case FOURCC_wvtt:
15059     {
15060       GstBuffer *buffer;
15061       const gchar *buf = "WEBVTT\n\n";
15062
15063       _codec ("WebVTT subtitles");
15064       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15065       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15066
15067       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15068       buffer = gst_buffer_new_and_alloc (8);
15069       gst_buffer_fill (buffer, 0, buf, 8);
15070       stream->buffers = g_slist_append (stream->buffers, buffer);
15071
15072       break;
15073     }
15074     case FOURCC_c608:
15075       _codec ("CEA 608 Closed Caption");
15076       caps =
15077           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15078           G_TYPE_STRING, "s334-1a", NULL);
15079       stream->process_func = gst_qtdemux_process_buffer_clcp;
15080       stream->need_split = TRUE;
15081       break;
15082     case FOURCC_c708:
15083       _codec ("CEA 708 Closed Caption");
15084       caps =
15085           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15086           G_TYPE_STRING, "cdp", NULL);
15087       stream->process_func = gst_qtdemux_process_buffer_clcp;
15088       break;
15089
15090     default:
15091     {
15092       caps = _get_unknown_codec_name ("text", fourcc);
15093       break;
15094     }
15095   }
15096   return caps;
15097 }
15098
15099 static GstCaps *
15100 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15101     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15102     const guint8 * stsd_entry_data, gchar ** codec_name)
15103 {
15104   GstCaps *caps;
15105
15106   switch (fourcc) {
15107     case FOURCC_m1v:
15108       _codec ("MPEG 1 video");
15109       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15110           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15111       break;
15112     default:
15113       caps = NULL;
15114       break;
15115   }
15116   return caps;
15117 }
15118
15119 static void
15120 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15121     const gchar * system_id)
15122 {
15123   gint i;
15124
15125   if (!qtdemux->protection_system_ids)
15126     qtdemux->protection_system_ids =
15127         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15128   /* Check whether we already have an entry for this system ID. */
15129   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15130     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15131     if (g_ascii_strcasecmp (system_id, id) == 0) {
15132       return;
15133     }
15134   }
15135   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15136   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15137           -1));
15138 }