isomp4: Split buffer process functions.
[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
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
97
98 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
99
100 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
101
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
104 #define QTDEMUX_NTH_STREAM(demux,idx) \
105    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
106 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
107    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
108
109 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
110
111 GST_DEBUG_CATEGORY (qtdemux_debug);
112 #define GST_CAT_DEFAULT qtdemux_debug
113
114 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
115 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
116
117 /* Macros for converting to/from timescale */
118 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
119 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
120
121 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
122 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
123
124 /* timestamp is the DTS */
125 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
126 /* timestamp + offset + cslg_shift is the outgoing PTS */
127 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
128 /* timestamp + offset is the PTS used for internal seek calculations */
129 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
130 /* timestamp + duration - dts is the duration */
131 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
132
133 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
134
135 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
136 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
137     GST_TRACE("Locking from thread %p", g_thread_self()); \
138     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
139     GST_TRACE("Locked from thread %p", g_thread_self()); \
140  } G_STMT_END
141
142 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
143     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
144     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
145  } G_STMT_END
146
147 /*
148  * Quicktime has tracks and segments. A track is a continuous piece of
149  * multimedia content. The track is not always played from start to finish but
150  * instead, pieces of the track are 'cut out' and played in sequence. This is
151  * what the segments do.
152  *
153  * Inside the track we have keyframes (K) and delta frames. The track has its
154  * own timing, which starts from 0 and extends to end. The position in the track
155  * is called the media_time.
156  *
157  * The segments now describe the pieces that should be played from this track
158  * and are basically tuples of media_time/duration/rate entries. We can have
159  * multiple segments and they are all played after one another. An example:
160  *
161  * segment 1: media_time: 1 second, duration: 1 second, rate 1
162  * segment 2: media_time: 3 second, duration: 2 second, rate 2
163  *
164  * To correctly play back this track, one must play: 1 second of media starting
165  * from media_time 1 followed by 2 seconds of media starting from media_time 3
166  * at a rate of 2.
167  *
168  * Each of the segments will be played at a specific time, the first segment at
169  * time 0, the second one after the duration of the first one, etc.. Note that
170  * the time in resulting playback is not identical to the media_time of the
171  * track anymore.
172  *
173  * Visually, assuming the track has 4 second of media_time:
174  *
175  *                (a)                   (b)          (c)              (d)
176  *         .-----------------------------------------------------------.
177  * track:  | K.....K.........K........K.......K.......K...........K... |
178  *         '-----------------------------------------------------------'
179  *         0              1              2              3              4
180  *           .------------^              ^   .----------^              ^
181  *          /              .-------------'  /       .------------------'
182  *         /              /          .-----'       /
183  *         .--------------.         .--------------.
184  *         | segment 1    |         | segment 2    |
185  *         '--------------'         '--------------'
186  *
187  * The challenge here is to cut out the right pieces of the track for each of
188  * the playback segments. This fortunately can easily be done with the SEGMENT
189  * events of GStreamer.
190  *
191  * For playback of segment 1, we need to provide the decoder with the keyframe
192  * (a), in the above figure, but we must instruct it only to output the decoded
193  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
194  * position set to the time of the segment: 0.
195  *
196  * We then proceed to push data from keyframe (a) to frame (b). The decoder
197  * decodes but clips all before media_time 1.
198  *
199  * After finishing a segment, we push out a new SEGMENT event with the clipping
200  * boundaries of the new data.
201  *
202  * This is a good usecase for the GStreamer accumulated SEGMENT events.
203  */
204
205 struct _QtDemuxSegment
206 {
207   /* global time and duration, all gst time */
208   GstClockTime time;
209   GstClockTime stop_time;
210   GstClockTime duration;
211   /* media time of trak, all gst time */
212   GstClockTime media_start;
213   GstClockTime media_stop;
214   gdouble rate;
215   /* Media start time in trak timescale units */
216   guint32 trak_media_start;
217 };
218
219 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
220
221 /* Used with fragmented MP4 files (mfra atom) */
222 struct _QtDemuxRandomAccessEntry
223 {
224   GstClockTime ts;
225   guint64 moof_offset;
226 };
227
228
229 /* Contains properties and cryptographic info for a set of samples from a
230  * track protected using Common Encryption (cenc) */
231 struct _QtDemuxCencSampleSetInfo
232 {
233   GstStructure *default_properties;
234
235   /* @crypto_info holds one GstStructure per sample */
236   GPtrArray *crypto_info;
237 };
238
239 struct _QtDemuxAavdEncryptionInfo
240 {
241   GstStructure *default_properties;
242 };
243
244 static const gchar *
245 qt_demux_state_string (enum QtDemuxState state)
246 {
247   switch (state) {
248     case QTDEMUX_STATE_INITIAL:
249       return "<INITIAL>";
250     case QTDEMUX_STATE_HEADER:
251       return "<HEADER>";
252     case QTDEMUX_STATE_MOVIE:
253       return "<MOVIE>";
254     case QTDEMUX_STATE_BUFFER_MDAT:
255       return "<BUFFER_MDAT>";
256     default:
257       return "<UNKNOWN>";
258   }
259 }
260
261 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
262
263 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
264
265 static GstStaticPadTemplate gst_qtdemux_sink_template =
266     GST_STATIC_PAD_TEMPLATE ("sink",
267     GST_PAD_SINK,
268     GST_PAD_ALWAYS,
269     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
270         "application/x-3gp")
271     );
272
273 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
274 GST_STATIC_PAD_TEMPLATE ("video_%u",
275     GST_PAD_SRC,
276     GST_PAD_SOMETIMES,
277     GST_STATIC_CAPS_ANY);
278
279 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
280 GST_STATIC_PAD_TEMPLATE ("audio_%u",
281     GST_PAD_SRC,
282     GST_PAD_SOMETIMES,
283     GST_STATIC_CAPS_ANY);
284
285 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
286 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
287     GST_PAD_SRC,
288     GST_PAD_SOMETIMES,
289     GST_STATIC_CAPS_ANY);
290
291 #define gst_qtdemux_parent_class parent_class
292 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
293 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
294     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
295
296 static void gst_qtdemux_dispose (GObject * object);
297 static void gst_qtdemux_finalize (GObject * object);
298
299 static guint32
300 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
301     GstClockTime media_time);
302 static guint32
303 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
304     QtDemuxStream * str, gint64 media_offset);
305
306 #if 0
307 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
308 static GstIndex *gst_qtdemux_get_index (GstElement * element);
309 #endif
310 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
311     GstStateChange transition);
312 static void gst_qtdemux_set_context (GstElement * element,
313     GstContext * context);
314 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
315 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
316     GstObject * parent, GstPadMode mode, gboolean active);
317
318 static void gst_qtdemux_loop (GstPad * pad);
319 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
320     GstBuffer * inbuf);
321 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
322     GstEvent * event);
323 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
324     GstQuery * query);
325 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
326 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
327     QtDemuxStream * stream);
328 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
329     QtDemuxStream * stream);
330 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
331     gboolean force);
332
333 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
334
335 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
336     const guint8 * buffer, guint length);
337 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
338     const guint8 * buffer, guint length);
339 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
340
341 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
342     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
343     GstTagList * list);
344 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
345     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
346     const guint8 * stsd_entry_data, gchar ** codec_name);
347 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
348     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
349     const guint8 * data, int len, gchar ** codec_name);
350 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
351     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
352     gchar ** codec_name);
353 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
354     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
355     const guint8 * stsd_entry_data, gchar ** codec_name);
356
357 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
358     QtDemuxStream * stream, guint32 n);
359 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
360 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
361 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
363 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
364 static void qtdemux_do_allocation (QtDemuxStream * stream,
365     GstQTDemux * qtdemux);
366 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
367     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
368 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
369     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
370     GstClockTime * _start, GstClockTime * _stop);
371 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
372     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
373
374 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
375 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
376
377 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
378
379 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
380     QtDemuxStream * stream, guint sample_index);
381 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
382     const gchar * id);
383 static void qtdemux_gst_structure_free (GstStructure * gststructure);
384 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
385
386 static void
387 gst_qtdemux_class_init (GstQTDemuxClass * klass)
388 {
389   GObjectClass *gobject_class;
390   GstElementClass *gstelement_class;
391
392   gobject_class = (GObjectClass *) klass;
393   gstelement_class = (GstElementClass *) klass;
394
395   parent_class = g_type_class_peek_parent (klass);
396
397   gobject_class->dispose = gst_qtdemux_dispose;
398   gobject_class->finalize = gst_qtdemux_finalize;
399
400   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
401 #if 0
402   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
403   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
404 #endif
405   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
406
407   gst_tag_register_musicbrainz_tags ();
408
409   gst_element_class_add_static_pad_template (gstelement_class,
410       &gst_qtdemux_sink_template);
411   gst_element_class_add_static_pad_template (gstelement_class,
412       &gst_qtdemux_videosrc_template);
413   gst_element_class_add_static_pad_template (gstelement_class,
414       &gst_qtdemux_audiosrc_template);
415   gst_element_class_add_static_pad_template (gstelement_class,
416       &gst_qtdemux_subsrc_template);
417   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
418       "Codec/Demuxer",
419       "Demultiplex a QuickTime file into audio and video streams",
420       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
421
422   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
423   gst_riff_init ();
424 }
425
426 static void
427 gst_qtdemux_init (GstQTDemux * qtdemux)
428 {
429   qtdemux->sinkpad =
430       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
431   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
432   gst_pad_set_activatemode_function (qtdemux->sinkpad,
433       qtdemux_sink_activate_mode);
434   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
435   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
436   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
437   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
438
439   qtdemux->adapter = gst_adapter_new ();
440   g_queue_init (&qtdemux->protection_event_queue);
441   qtdemux->flowcombiner = gst_flow_combiner_new ();
442   g_mutex_init (&qtdemux->expose_lock);
443
444   qtdemux->active_streams = g_ptr_array_new_with_free_func
445       ((GDestroyNotify) gst_qtdemux_stream_unref);
446   qtdemux->old_streams = g_ptr_array_new_with_free_func
447       ((GDestroyNotify) gst_qtdemux_stream_unref);
448
449   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
450
451   gst_qtdemux_reset (qtdemux, TRUE);
452 }
453
454 static void
455 gst_qtdemux_finalize (GObject * object)
456 {
457   GstQTDemux *qtdemux = GST_QTDEMUX (object);
458
459   g_free (qtdemux->redirect_location);
460
461   G_OBJECT_CLASS (parent_class)->finalize (object);
462 }
463
464 static void
465 gst_qtdemux_dispose (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   if (qtdemux->adapter) {
470     g_object_unref (G_OBJECT (qtdemux->adapter));
471     qtdemux->adapter = NULL;
472   }
473   gst_tag_list_unref (qtdemux->tag_list);
474   gst_flow_combiner_free (qtdemux->flowcombiner);
475   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
476       NULL);
477   g_queue_clear (&qtdemux->protection_event_queue);
478
479   g_free (qtdemux->cenc_aux_info_sizes);
480   qtdemux->cenc_aux_info_sizes = NULL;
481   g_mutex_clear (&qtdemux->expose_lock);
482
483   g_ptr_array_free (qtdemux->active_streams, TRUE);
484   g_ptr_array_free (qtdemux->old_streams, TRUE);
485
486   G_OBJECT_CLASS (parent_class)->dispose (object);
487 }
488
489 static void
490 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
491 {
492   if (qtdemux->redirect_location) {
493     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
494         (_("This file contains no playable streams.")),
495         ("no known streams found, a redirect message has been posted"),
496         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
497   } else {
498     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
499         (_("This file contains no playable streams.")),
500         ("no known streams found"));
501   }
502 }
503
504 static GstBuffer *
505 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
506 {
507   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
508       mem, size, 0, size, mem, free_func);
509 }
510
511 static GstFlowReturn
512 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
513     GstBuffer ** buf)
514 {
515   GstFlowReturn flow;
516   GstMapInfo map;
517   gsize bsize;
518
519   if (G_UNLIKELY (size == 0)) {
520     GstFlowReturn ret;
521     GstBuffer *tmp = NULL;
522
523     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
524     if (ret != GST_FLOW_OK)
525       return ret;
526
527     gst_buffer_map (tmp, &map, GST_MAP_READ);
528     size = QT_UINT32 (map.data);
529     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
530
531     gst_buffer_unmap (tmp, &map);
532     gst_buffer_unref (tmp);
533   }
534
535   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
536   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
537     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
538       /* we're pulling header but already got most interesting bits,
539        * so never mind the rest (e.g. tags) (that much) */
540       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
541           size);
542       return GST_FLOW_EOS;
543     } else {
544       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
545           (_("This file is invalid and cannot be played.")),
546           ("atom has bogus size %" G_GUINT64_FORMAT, size));
547       return GST_FLOW_ERROR;
548     }
549   }
550
551   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
552
553   if (G_UNLIKELY (flow != GST_FLOW_OK))
554     return flow;
555
556   bsize = gst_buffer_get_size (*buf);
557   /* Catch short reads - we don't want any partial atoms */
558   if (G_UNLIKELY (bsize < size)) {
559     GST_WARNING_OBJECT (qtdemux,
560         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
561     gst_buffer_unref (*buf);
562     *buf = NULL;
563     return GST_FLOW_EOS;
564   }
565
566   return flow;
567 }
568
569 #if 1
570 static gboolean
571 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
572     GstFormat src_format, gint64 src_value, GstFormat dest_format,
573     gint64 * dest_value)
574 {
575   gboolean res = TRUE;
576   QtDemuxStream *stream = gst_pad_get_element_private (pad);
577   gint32 index;
578
579   if (stream->subtype != FOURCC_vide) {
580     res = FALSE;
581     goto done;
582   }
583
584   switch (src_format) {
585     case GST_FORMAT_TIME:
586       switch (dest_format) {
587         case GST_FORMAT_BYTES:{
588           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
589           if (-1 == index) {
590             res = FALSE;
591             goto done;
592           }
593
594           *dest_value = stream->samples[index].offset;
595
596           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
597               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
598               GST_TIME_ARGS (src_value), *dest_value);
599           break;
600         }
601         default:
602           res = FALSE;
603           break;
604       }
605       break;
606     case GST_FORMAT_BYTES:
607       switch (dest_format) {
608         case GST_FORMAT_TIME:{
609           index =
610               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
611               stream, src_value);
612
613           if (-1 == index) {
614             res = FALSE;
615             goto done;
616           }
617
618           *dest_value =
619               QTSTREAMTIME_TO_GSTTIME (stream,
620               stream->samples[index].timestamp);
621           GST_DEBUG_OBJECT (qtdemux,
622               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
623               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
624           break;
625         }
626         default:
627           res = FALSE;
628           break;
629       }
630       break;
631     default:
632       res = FALSE;
633       break;
634   }
635
636 done:
637   return res;
638 }
639 #endif
640
641 static gboolean
642 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
643 {
644   gboolean res = FALSE;
645
646   *duration = GST_CLOCK_TIME_NONE;
647
648   if (qtdemux->duration != 0 &&
649       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
650     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
651     res = TRUE;
652   } else {
653     *duration = GST_CLOCK_TIME_NONE;
654   }
655
656   return res;
657 }
658
659 static gboolean
660 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
661     GstQuery * query)
662 {
663   gboolean res = FALSE;
664   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
665
666   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
667
668   switch (GST_QUERY_TYPE (query)) {
669     case GST_QUERY_POSITION:{
670       GstFormat fmt;
671
672       gst_query_parse_position (query, &fmt, NULL);
673       if (fmt == GST_FORMAT_TIME
674           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
675         gst_query_set_position (query, GST_FORMAT_TIME,
676             qtdemux->segment.position);
677         res = TRUE;
678       }
679     }
680       break;
681     case GST_QUERY_DURATION:{
682       GstFormat fmt;
683
684       gst_query_parse_duration (query, &fmt, NULL);
685       if (fmt == GST_FORMAT_TIME) {
686         /* First try to query upstream */
687         res = gst_pad_query_default (pad, parent, query);
688         if (!res) {
689           GstClockTime duration;
690           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
691             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
692             res = TRUE;
693           }
694         }
695       }
696       break;
697     }
698     case GST_QUERY_CONVERT:{
699       GstFormat src_fmt, dest_fmt;
700       gint64 src_value, dest_value = 0;
701
702       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
703
704       res = gst_qtdemux_src_convert (qtdemux, pad,
705           src_fmt, src_value, dest_fmt, &dest_value);
706       if (res)
707         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
708
709       break;
710     }
711     case GST_QUERY_FORMATS:
712       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
713       res = TRUE;
714       break;
715     case GST_QUERY_SEEKING:{
716       GstFormat fmt;
717       gboolean seekable;
718
719       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
720
721       if (fmt == GST_FORMAT_BYTES) {
722         /* We always refuse BYTES seeks from downstream */
723         break;
724       }
725
726       /* try upstream first */
727       res = gst_pad_query_default (pad, parent, query);
728
729       if (!res) {
730         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
731         if (fmt == GST_FORMAT_TIME) {
732           GstClockTime duration;
733
734           gst_qtdemux_get_duration (qtdemux, &duration);
735           seekable = TRUE;
736           if (!qtdemux->pullbased) {
737             GstQuery *q;
738
739             /* we might be able with help from upstream */
740             seekable = FALSE;
741             q = gst_query_new_seeking (GST_FORMAT_BYTES);
742             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
743               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
744               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
745             }
746             gst_query_unref (q);
747           }
748           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
749           res = TRUE;
750         }
751       }
752       break;
753     }
754     case GST_QUERY_SEGMENT:
755     {
756       GstFormat format;
757       gint64 start, stop;
758
759       format = qtdemux->segment.format;
760
761       start =
762           gst_segment_to_stream_time (&qtdemux->segment, format,
763           qtdemux->segment.start);
764       if ((stop = qtdemux->segment.stop) == -1)
765         stop = qtdemux->segment.duration;
766       else
767         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
768
769       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
770       res = TRUE;
771       break;
772     }
773     default:
774       res = gst_pad_query_default (pad, parent, query);
775       break;
776   }
777
778   return res;
779 }
780
781 static void
782 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
783 {
784   if (G_LIKELY (stream->pad)) {
785     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
786         GST_DEBUG_PAD_NAME (stream->pad));
787
788     if (!gst_tag_list_is_empty (stream->stream_tags)) {
789       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
790           stream->stream_tags);
791       gst_pad_push_event (stream->pad,
792           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
793     }
794
795     if (G_UNLIKELY (stream->send_global_tags)) {
796       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
797           qtdemux->tag_list);
798       gst_pad_push_event (stream->pad,
799           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
800       stream->send_global_tags = FALSE;
801     }
802   }
803 }
804
805 /* push event on all source pads; takes ownership of the event */
806 static void
807 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
808 {
809   gboolean has_valid_stream = FALSE;
810   GstEventType etype = GST_EVENT_TYPE (event);
811   guint i;
812
813   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
814       GST_EVENT_TYPE_NAME (event));
815
816   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
817     GstPad *pad;
818     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
819     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
820
821     if ((pad = stream->pad)) {
822       has_valid_stream = TRUE;
823
824       if (etype == GST_EVENT_EOS) {
825         /* let's not send twice */
826         if (stream->sent_eos)
827           continue;
828         stream->sent_eos = TRUE;
829       }
830
831       gst_pad_push_event (pad, gst_event_ref (event));
832     }
833   }
834
835   gst_event_unref (event);
836
837   /* if it is EOS and there are no pads, post an error */
838   if (!has_valid_stream && etype == GST_EVENT_EOS) {
839     gst_qtdemux_post_no_playable_stream_error (qtdemux);
840   }
841 }
842
843 typedef struct
844 {
845   guint64 media_time;
846 } FindData;
847
848 static gint
849 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
850 {
851   if ((gint64) s1->timestamp > *media_time)
852     return 1;
853   if ((gint64) s1->timestamp == *media_time)
854     return 0;
855
856   return -1;
857 }
858
859 /* find the index of the sample that includes the data for @media_time using a
860  * binary search.  Only to be called in optimized cases of linear search below.
861  *
862  * Returns the index of the sample with the corresponding *DTS*.
863  */
864 static guint32
865 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
866     guint64 media_time)
867 {
868   QtDemuxSample *result;
869   guint32 index;
870
871   /* convert media_time to mov format */
872   media_time =
873       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
874
875   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
876       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
877       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
878
879   if (G_LIKELY (result))
880     index = result - str->samples;
881   else
882     index = 0;
883
884   return index;
885 }
886
887
888
889 /* find the index of the sample that includes the data for @media_offset using a
890  * linear search
891  *
892  * Returns the index of the sample.
893  */
894 static guint32
895 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
896     QtDemuxStream * str, gint64 media_offset)
897 {
898   QtDemuxSample *result = str->samples;
899   guint32 index = 0;
900
901   if (result == NULL || str->n_samples == 0)
902     return -1;
903
904   if (media_offset == result->offset)
905     return index;
906
907   result++;
908   while (index < str->n_samples - 1) {
909     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
910       goto parse_failed;
911
912     if (media_offset < result->offset)
913       break;
914
915     index++;
916     result++;
917   }
918   return index;
919
920   /* ERRORS */
921 parse_failed:
922   {
923     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
924     return -1;
925   }
926 }
927
928 /* find the index of the sample that includes the data for @media_time using a
929  * linear search, and keeping in mind that not all samples may have been parsed
930  * yet.  If possible, it will delegate to binary search.
931  *
932  * Returns the index of the sample.
933  */
934 static guint32
935 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
936     GstClockTime media_time)
937 {
938   guint32 index = 0;
939   guint64 mov_time;
940   QtDemuxSample *sample;
941
942   /* convert media_time to mov format */
943   mov_time =
944       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
945
946   sample = str->samples;
947   if (mov_time == sample->timestamp + sample->pts_offset)
948     return index;
949
950   /* use faster search if requested time in already parsed range */
951   sample = str->samples + str->stbl_index;
952   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
953     index = gst_qtdemux_find_index (qtdemux, str, media_time);
954     sample = str->samples + index;
955   } else {
956     while (index < str->n_samples - 1) {
957       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
958         goto parse_failed;
959
960       sample = str->samples + index + 1;
961       if (mov_time < sample->timestamp) {
962         sample = str->samples + index;
963         break;
964       }
965
966       index++;
967     }
968   }
969
970   /* sample->timestamp is now <= media_time, need to find the corresponding
971    * PTS now by looking backwards */
972   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
973     index--;
974     sample = str->samples + index;
975   }
976
977   return index;
978
979   /* ERRORS */
980 parse_failed:
981   {
982     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
983     return -1;
984   }
985 }
986
987 /* find the index of the keyframe needed to decode the sample at @index
988  * of stream @str, or of a subsequent keyframe (depending on @next)
989  *
990  * Returns the index of the keyframe.
991  */
992 static guint32
993 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
994     guint32 index, gboolean next)
995 {
996   guint32 new_index = index;
997
998   if (index >= str->n_samples) {
999     new_index = str->n_samples;
1000     goto beach;
1001   }
1002
1003   /* all keyframes, return index */
1004   if (str->all_keyframe) {
1005     new_index = index;
1006     goto beach;
1007   }
1008
1009   /* else search until we have a keyframe */
1010   while (new_index < str->n_samples) {
1011     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1012       goto parse_failed;
1013
1014     if (str->samples[new_index].keyframe)
1015       break;
1016
1017     if (new_index == 0)
1018       break;
1019
1020     if (next)
1021       new_index++;
1022     else
1023       new_index--;
1024   }
1025
1026   if (new_index == str->n_samples) {
1027     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1028     new_index = -1;
1029   }
1030
1031 beach:
1032   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1033       "gave %u", next ? "after" : "before", index, new_index);
1034
1035   return new_index;
1036
1037   /* ERRORS */
1038 parse_failed:
1039   {
1040     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1041     return -1;
1042   }
1043 }
1044
1045 /* find the segment for @time_position for @stream
1046  *
1047  * Returns the index of the segment containing @time_position.
1048  * Returns the last segment and sets the @eos variable to TRUE
1049  * if the time is beyond the end. @eos may be NULL
1050  */
1051 static guint32
1052 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1053     GstClockTime time_position)
1054 {
1055   gint i;
1056   guint32 seg_idx;
1057
1058   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1059       GST_TIME_ARGS (time_position));
1060
1061   seg_idx = -1;
1062   for (i = 0; i < stream->n_segments; i++) {
1063     QtDemuxSegment *segment = &stream->segments[i];
1064
1065     GST_LOG_OBJECT (stream->pad,
1066         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1067         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1068
1069     /* For the last segment we include stop_time in the last segment */
1070     if (i < stream->n_segments - 1) {
1071       if (segment->time <= time_position && time_position < segment->stop_time) {
1072         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1073         seg_idx = i;
1074         break;
1075       }
1076     } else {
1077       /* Last segment always matches */
1078       seg_idx = i;
1079       break;
1080     }
1081   }
1082   return seg_idx;
1083 }
1084
1085 /* move the stream @str to the sample position @index.
1086  *
1087  * Updates @str->sample_index and marks discontinuity if needed.
1088  */
1089 static void
1090 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1091     guint32 index)
1092 {
1093   /* no change needed */
1094   if (index == str->sample_index)
1095     return;
1096
1097   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1098       str->n_samples);
1099
1100   /* position changed, we have a discont */
1101   str->sample_index = index;
1102   str->offset_in_sample = 0;
1103   /* Each time we move in the stream we store the position where we are
1104    * starting from */
1105   str->from_sample = index;
1106   str->discont = TRUE;
1107 }
1108
1109 static void
1110 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1111     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1112 {
1113   guint64 min_offset;
1114   gint64 min_byte_offset = -1;
1115   guint i;
1116
1117   min_offset = desired_time;
1118
1119   /* for each stream, find the index of the sample in the segment
1120    * and move back to the previous keyframe. */
1121   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1122     QtDemuxStream *str;
1123     guint32 index, kindex;
1124     guint32 seg_idx;
1125     GstClockTime media_start;
1126     GstClockTime media_time;
1127     GstClockTime seg_time;
1128     QtDemuxSegment *seg;
1129     gboolean empty_segment = FALSE;
1130
1131     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1132
1133     if (CUR_STREAM (str)->sparse && !use_sparse)
1134       continue;
1135
1136     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1137     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1138
1139     /* get segment and time in the segment */
1140     seg = &str->segments[seg_idx];
1141     seg_time = (desired_time - seg->time) * seg->rate;
1142
1143     while (QTSEGMENT_IS_EMPTY (seg)) {
1144       seg_time = 0;
1145       empty_segment = TRUE;
1146       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1147           seg_idx);
1148       seg_idx++;
1149       if (seg_idx == str->n_segments)
1150         break;
1151       seg = &str->segments[seg_idx];
1152     }
1153
1154     if (seg_idx == str->n_segments) {
1155       /* FIXME track shouldn't have the last segment as empty, but if it
1156        * happens we better handle it */
1157       continue;
1158     }
1159
1160     /* get the media time in the segment */
1161     media_start = seg->media_start + seg_time;
1162
1163     /* get the index of the sample with media time */
1164     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1165     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1166         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1167         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1168         empty_segment);
1169
1170     /* shift to next frame if we are looking for next keyframe */
1171     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1172         && index < str->stbl_index)
1173       index++;
1174
1175     if (!empty_segment) {
1176       /* find previous keyframe */
1177       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1178
1179       /* we will settle for one before if none found after */
1180       if (next && kindex == -1)
1181         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1182
1183       /* Update the requested time whenever a keyframe was found, to make it
1184        * accurate and avoid having the first buffer fall outside of the segment
1185        */
1186       if (kindex != -1) {
1187         index = kindex;
1188
1189         /* get timestamp of keyframe */
1190         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1191         GST_DEBUG_OBJECT (qtdemux,
1192             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1193             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1194             str->samples[kindex].offset);
1195
1196         /* keyframes in the segment get a chance to change the
1197          * desired_offset. keyframes out of the segment are
1198          * ignored. */
1199         if (media_time >= seg->media_start) {
1200           GstClockTime seg_time;
1201
1202           /* this keyframe is inside the segment, convert back to
1203            * segment time */
1204           seg_time = (media_time - seg->media_start) + seg->time;
1205           if ((!next && (seg_time < min_offset)) ||
1206               (next && (seg_time > min_offset)))
1207             min_offset = seg_time;
1208         }
1209       }
1210     }
1211
1212     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1213       min_byte_offset = str->samples[index].offset;
1214   }
1215
1216   if (key_time)
1217     *key_time = min_offset;
1218   if (key_offset)
1219     *key_offset = min_byte_offset;
1220 }
1221
1222 static gboolean
1223 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1224     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1225 {
1226   gboolean res;
1227
1228   g_return_val_if_fail (format != NULL, FALSE);
1229   g_return_val_if_fail (cur != NULL, FALSE);
1230   g_return_val_if_fail (stop != NULL, FALSE);
1231
1232   if (*format == GST_FORMAT_TIME)
1233     return TRUE;
1234
1235   res = TRUE;
1236   if (cur_type != GST_SEEK_TYPE_NONE)
1237     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1238   if (res && stop_type != GST_SEEK_TYPE_NONE)
1239     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1240
1241   if (res)
1242     *format = GST_FORMAT_TIME;
1243
1244   return res;
1245 }
1246
1247 /* perform seek in push based mode:
1248    find BYTE position to move to based on time and delegate to upstream
1249 */
1250 static gboolean
1251 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1252 {
1253   gdouble rate;
1254   GstFormat format;
1255   GstSeekFlags flags;
1256   GstSeekType cur_type, stop_type;
1257   gint64 cur, stop, key_cur;
1258   gboolean res;
1259   gint64 byte_cur;
1260   gint64 original_stop;
1261   guint32 seqnum;
1262
1263   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1264
1265   gst_event_parse_seek (event, &rate, &format, &flags,
1266       &cur_type, &cur, &stop_type, &stop);
1267   seqnum = gst_event_get_seqnum (event);
1268
1269   /* Directly send the instant-rate-change event here before taking the
1270    * stream-lock so that it can be applied as soon as possible */
1271   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1272     GstEvent *ev;
1273
1274     /* instant rate change only supported if direction does not change. All
1275      * other requirements are already checked before creating the seek event
1276      * but let's double-check here to be sure */
1277     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1278         (qtdemux->segment.rate < 0 && rate > 0) ||
1279         cur_type != GST_SEEK_TYPE_NONE ||
1280         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1281       GST_ERROR_OBJECT (qtdemux,
1282           "Instant rate change seeks only supported in the "
1283           "same direction, without flushing and position change");
1284       return FALSE;
1285     }
1286
1287     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1288         (GstSegmentFlags) flags);
1289     gst_event_set_seqnum (ev, seqnum);
1290     gst_qtdemux_push_event (qtdemux, ev);
1291     return TRUE;
1292   }
1293
1294   /* only forward streaming and seeking is possible */
1295   if (rate <= 0)
1296     goto unsupported_seek;
1297
1298   /* convert to TIME if needed and possible */
1299   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1300           stop_type, &stop))
1301     goto no_format;
1302
1303   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1304    * the original stop position to use when upstream pushes the new segment
1305    * for this seek */
1306   original_stop = stop;
1307   stop = -1;
1308
1309   /* find reasonable corresponding BYTE position,
1310    * also try to mind about keyframes, since we can not go back a bit for them
1311    * later on */
1312   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1313    * mostly just work, but let's not yet boldly go there  ... */
1314   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1315
1316   if (byte_cur == -1)
1317     goto abort_seek;
1318
1319   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1320       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1321       stop);
1322
1323   GST_OBJECT_LOCK (qtdemux);
1324   qtdemux->seek_offset = byte_cur;
1325   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1326     qtdemux->push_seek_start = cur;
1327   } else {
1328     qtdemux->push_seek_start = key_cur;
1329   }
1330
1331   if (stop_type == GST_SEEK_TYPE_NONE) {
1332     qtdemux->push_seek_stop = qtdemux->segment.stop;
1333   } else {
1334     qtdemux->push_seek_stop = original_stop;
1335   }
1336   GST_OBJECT_UNLOCK (qtdemux);
1337
1338   qtdemux->segment_seqnum = seqnum;
1339   /* BYTE seek event */
1340   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1341       stop_type, stop);
1342   gst_event_set_seqnum (event, seqnum);
1343   res = gst_pad_push_event (qtdemux->sinkpad, event);
1344
1345   return res;
1346
1347   /* ERRORS */
1348 abort_seek:
1349   {
1350     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1351         "seek aborted.");
1352     return FALSE;
1353   }
1354 unsupported_seek:
1355   {
1356     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1357     return FALSE;
1358   }
1359 no_format:
1360   {
1361     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1362     return FALSE;
1363   }
1364 }
1365
1366 /* perform the seek.
1367  *
1368  * We set all segment_indexes in the streams to unknown and
1369  * adjust the time_position to the desired position. this is enough
1370  * to trigger a segment switch in the streaming thread to start
1371  * streaming from the desired position.
1372  *
1373  * Keyframe seeking is a little more complicated when dealing with
1374  * segments. Ideally we want to move to the previous keyframe in
1375  * the segment but there might not be a keyframe in the segment. In
1376  * fact, none of the segments could contain a keyframe. We take a
1377  * practical approach: seek to the previous keyframe in the segment,
1378  * if there is none, seek to the beginning of the segment.
1379  *
1380  * Called with STREAM_LOCK
1381  */
1382 static gboolean
1383 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1384     guint32 seqnum, GstSeekFlags flags)
1385 {
1386   gint64 desired_offset;
1387   guint i;
1388
1389   desired_offset = segment->position;
1390
1391   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1392       GST_TIME_ARGS (desired_offset));
1393
1394   /* may not have enough fragmented info to do this adjustment,
1395    * and we can't scan (and probably should not) at this time with
1396    * possibly flushing upstream */
1397   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1398     gint64 min_offset;
1399     gboolean next, before, after;
1400
1401     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1402     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1403     next = after && !before;
1404     if (segment->rate < 0)
1405       next = !next;
1406
1407     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1408         NULL);
1409     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1410         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1411     desired_offset = min_offset;
1412   }
1413
1414   /* and set all streams to the final position */
1415   GST_OBJECT_LOCK (qtdemux);
1416   gst_flow_combiner_reset (qtdemux->flowcombiner);
1417   GST_OBJECT_UNLOCK (qtdemux);
1418   qtdemux->segment_seqnum = seqnum;
1419   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1420     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1421
1422     stream->time_position = desired_offset;
1423     stream->accumulated_base = 0;
1424     stream->sample_index = -1;
1425     stream->offset_in_sample = 0;
1426     stream->segment_index = -1;
1427     stream->sent_eos = FALSE;
1428     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1429
1430     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1431       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1432   }
1433   segment->position = desired_offset;
1434   if (segment->rate >= 0) {
1435     segment->start = desired_offset;
1436     /* We need to update time as we update start in that direction */
1437     segment->time = desired_offset;
1438
1439     /* we stop at the end */
1440     if (segment->stop == -1)
1441       segment->stop = segment->duration;
1442   } else {
1443     segment->stop = desired_offset;
1444   }
1445
1446   if (qtdemux->fragmented)
1447     qtdemux->fragmented_seek_pending = TRUE;
1448
1449   return TRUE;
1450 }
1451
1452 /* do a seek in pull based mode */
1453 static gboolean
1454 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1455 {
1456   gdouble rate = 1.0;
1457   GstFormat format;
1458   GstSeekFlags flags;
1459   GstSeekType cur_type, stop_type;
1460   gint64 cur, stop;
1461   gboolean flush, instant_rate_change;
1462   gboolean update;
1463   GstSegment seeksegment;
1464   guint32 seqnum = GST_SEQNUM_INVALID;
1465   GstEvent *flush_event;
1466   gboolean ret;
1467
1468   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1469
1470   gst_event_parse_seek (event, &rate, &format, &flags,
1471       &cur_type, &cur, &stop_type, &stop);
1472   seqnum = gst_event_get_seqnum (event);
1473
1474   /* we have to have a format as the segment format. Try to convert
1475    * if not. */
1476   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1477           stop_type, &stop))
1478     goto no_format;
1479
1480   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1481
1482   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1483   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1484
1485   /* Directly send the instant-rate-change event here before taking the
1486    * stream-lock so that it can be applied as soon as possible */
1487   if (instant_rate_change) {
1488     GstEvent *ev;
1489
1490     /* instant rate change only supported if direction does not change. All
1491      * other requirements are already checked before creating the seek event
1492      * but let's double-check here to be sure */
1493     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1494         (qtdemux->segment.rate < 0 && rate > 0) ||
1495         cur_type != GST_SEEK_TYPE_NONE ||
1496         stop_type != GST_SEEK_TYPE_NONE || flush) {
1497       GST_ERROR_OBJECT (qtdemux,
1498           "Instant rate change seeks only supported in the "
1499           "same direction, without flushing and position change");
1500       return FALSE;
1501     }
1502
1503     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1504         (GstSegmentFlags) flags);
1505     gst_event_set_seqnum (ev, seqnum);
1506     gst_qtdemux_push_event (qtdemux, ev);
1507     return TRUE;
1508   }
1509
1510   /* stop streaming, either by flushing or by pausing the task */
1511   if (flush) {
1512     flush_event = gst_event_new_flush_start ();
1513     if (seqnum != GST_SEQNUM_INVALID)
1514       gst_event_set_seqnum (flush_event, seqnum);
1515     /* unlock upstream pull_range */
1516     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1517     /* make sure out loop function exits */
1518     gst_qtdemux_push_event (qtdemux, flush_event);
1519   } else {
1520     /* non flushing seek, pause the task */
1521     gst_pad_pause_task (qtdemux->sinkpad);
1522   }
1523
1524   /* wait for streaming to finish */
1525   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1526
1527   /* copy segment, we need this because we still need the old
1528    * segment when we close the current segment. */
1529   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1530
1531   /* configure the segment with the seek variables */
1532   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1533   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1534           cur_type, cur, stop_type, stop, &update)) {
1535     ret = FALSE;
1536     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1537   } else {
1538     /* now do the seek */
1539     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1540   }
1541
1542   /* prepare for streaming again */
1543   if (flush) {
1544     flush_event = gst_event_new_flush_stop (TRUE);
1545     if (seqnum != GST_SEQNUM_INVALID)
1546       gst_event_set_seqnum (flush_event, seqnum);
1547
1548     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1549     gst_qtdemux_push_event (qtdemux, flush_event);
1550   }
1551
1552   /* commit the new segment */
1553   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1554
1555   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1556     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1557         qtdemux->segment.format, qtdemux->segment.position);
1558     if (seqnum != GST_SEQNUM_INVALID)
1559       gst_message_set_seqnum (msg, seqnum);
1560     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1561   }
1562
1563   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1564   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1565       qtdemux->sinkpad, NULL);
1566
1567   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1568
1569   return ret;
1570
1571   /* ERRORS */
1572 no_format:
1573   {
1574     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1575     return FALSE;
1576   }
1577 }
1578
1579 static gboolean
1580 qtdemux_ensure_index (GstQTDemux * qtdemux)
1581 {
1582   guint i;
1583
1584   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1585
1586   /* Build complete index */
1587   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1588     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1589
1590     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1591       GST_LOG_OBJECT (qtdemux,
1592           "Building complete index of track-id %u for seeking failed!",
1593           stream->track_id);
1594       return FALSE;
1595     }
1596   }
1597
1598   return TRUE;
1599 }
1600
1601 static gboolean
1602 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1603     GstEvent * event)
1604 {
1605   gboolean res = TRUE;
1606   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1607
1608   switch (GST_EVENT_TYPE (event)) {
1609     case GST_EVENT_RECONFIGURE:
1610       GST_OBJECT_LOCK (qtdemux);
1611       gst_flow_combiner_reset (qtdemux->flowcombiner);
1612       GST_OBJECT_UNLOCK (qtdemux);
1613       res = gst_pad_event_default (pad, parent, event);
1614       break;
1615     case GST_EVENT_SEEK:
1616     {
1617       GstSeekFlags flags = 0;
1618       GstFormat seek_format;
1619       gboolean instant_rate_change;
1620
1621 #ifndef GST_DISABLE_GST_DEBUG
1622       GstClockTime ts = gst_util_get_timestamp ();
1623 #endif
1624       guint32 seqnum = gst_event_get_seqnum (event);
1625
1626       qtdemux->received_seek = TRUE;
1627
1628       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1629           NULL);
1630       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1631
1632       if (seqnum == qtdemux->segment_seqnum) {
1633         GST_LOG_OBJECT (pad,
1634             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1635         gst_event_unref (event);
1636         return TRUE;
1637       }
1638
1639       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1640         /* seek should be handled by upstream, we might need to re-download fragments */
1641         GST_DEBUG_OBJECT (qtdemux,
1642             "let upstream handle seek for fragmented playback");
1643         goto upstream;
1644       }
1645
1646       if (seek_format == GST_FORMAT_BYTES) {
1647         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1648         gst_event_unref (event);
1649         return FALSE;
1650       }
1651
1652       gst_event_parse_seek_trickmode_interval (event,
1653           &qtdemux->trickmode_interval);
1654
1655       /* Build complete index for seeking;
1656        * if not a fragmented file at least and we're really doing a seek,
1657        * not just an instant-rate-change */
1658       if (!qtdemux->fragmented && !instant_rate_change) {
1659         if (!qtdemux_ensure_index (qtdemux))
1660           goto index_failed;
1661       }
1662 #ifndef GST_DISABLE_GST_DEBUG
1663       ts = gst_util_get_timestamp () - ts;
1664       GST_INFO_OBJECT (qtdemux,
1665           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1666 #endif
1667       if (qtdemux->pullbased) {
1668         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1669       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1670         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1671         res = TRUE;
1672       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1673           && QTDEMUX_N_STREAMS (qtdemux)
1674           && !qtdemux->fragmented) {
1675         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1676       } else {
1677         GST_DEBUG_OBJECT (qtdemux,
1678             "ignoring seek in push mode in current state");
1679         res = FALSE;
1680       }
1681       gst_event_unref (event);
1682     }
1683       break;
1684     default:
1685     upstream:
1686       res = gst_pad_event_default (pad, parent, event);
1687       break;
1688   }
1689
1690 done:
1691   return res;
1692
1693   /* ERRORS */
1694 index_failed:
1695   {
1696     GST_ERROR_OBJECT (qtdemux, "Index failed");
1697     gst_event_unref (event);
1698     res = FALSE;
1699     goto done;
1700   }
1701 }
1702
1703 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1704  *
1705  * If @fw is false, the coding order is explored backwards.
1706  *
1707  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1708  * sample is found for that track.
1709  *
1710  * The stream and sample index of the sample with the minimum offset in the direction explored
1711  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1712  *
1713  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1714  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1715  * @_stream and @_index. */
1716 static void
1717 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1718     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1719 {
1720   gint i, index;
1721   gint64 time, min_time;
1722   QtDemuxStream *stream;
1723   gint iter;
1724
1725   min_time = -1;
1726   stream = NULL;
1727   index = -1;
1728
1729   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1730     QtDemuxStream *str;
1731     gint inc;
1732     gboolean set_sample;
1733
1734     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1735     set_sample = !set;
1736
1737     if (fw) {
1738       i = 0;
1739       inc = 1;
1740     } else {
1741       i = str->n_samples - 1;
1742       inc = -1;
1743     }
1744
1745     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1746       if (str->samples[i].size == 0)
1747         continue;
1748
1749       if (fw && (str->samples[i].offset < byte_pos))
1750         continue;
1751
1752       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1753         continue;
1754
1755       /* move stream to first available sample */
1756       if (set) {
1757         gst_qtdemux_move_stream (qtdemux, str, i);
1758         set_sample = TRUE;
1759       }
1760
1761       /* avoid index from sparse streams since they might be far away */
1762       if (!CUR_STREAM (str)->sparse) {
1763         /* determine min/max time */
1764         time = QTSAMPLE_PTS (str, &str->samples[i]);
1765         if (min_time == -1 || (!fw && time > min_time) ||
1766             (fw && time < min_time)) {
1767           min_time = time;
1768         }
1769
1770         /* determine stream with leading sample, to get its position */
1771         if (!stream ||
1772             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1773             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1774           stream = str;
1775           index = i;
1776         }
1777       }
1778       break;
1779     }
1780
1781     /* no sample for this stream, mark eos */
1782     if (!set_sample)
1783       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1784   }
1785
1786   if (_time)
1787     *_time = min_time;
1788   if (_stream)
1789     *_stream = stream;
1790   if (_index)
1791     *_index = index;
1792 }
1793
1794 /* Copied from mpegtsbase code */
1795 /* FIXME: replace this function when we add new util function for stream-id creation */
1796 static gchar *
1797 _get_upstream_id (GstQTDemux * demux)
1798 {
1799   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1800
1801   if (!upstream_id) {
1802     /* Try to create one from the upstream URI, else use a randome number */
1803     GstQuery *query;
1804     gchar *uri = NULL;
1805
1806     /* Try to generate one from the URI query and
1807      * if it fails take a random number instead */
1808     query = gst_query_new_uri ();
1809     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1810       gst_query_parse_uri (query, &uri);
1811     }
1812
1813     if (uri) {
1814       GChecksum *cs;
1815
1816       /* And then generate an SHA256 sum of the URI */
1817       cs = g_checksum_new (G_CHECKSUM_SHA256);
1818       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1819       g_free (uri);
1820       upstream_id = g_strdup (g_checksum_get_string (cs));
1821       g_checksum_free (cs);
1822     } else {
1823       /* Just get some random number if the URI query fails */
1824       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1825           "implementing a deterministic way of creating a stream-id");
1826       upstream_id =
1827           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1828           g_random_int (), g_random_int ());
1829     }
1830
1831     gst_query_unref (query);
1832   }
1833   return upstream_id;
1834 }
1835
1836 static QtDemuxStream *
1837 _create_stream (GstQTDemux * demux, guint32 track_id)
1838 {
1839   QtDemuxStream *stream;
1840   gchar *upstream_id;
1841
1842   stream = g_new0 (QtDemuxStream, 1);
1843   stream->demux = demux;
1844   stream->track_id = track_id;
1845   upstream_id = _get_upstream_id (demux);
1846   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1847   g_free (upstream_id);
1848   /* new streams always need a discont */
1849   stream->discont = TRUE;
1850   /* we enable clipping for raw audio/video streams */
1851   stream->need_clip = FALSE;
1852   stream->process_func = NULL;
1853   stream->segment_index = -1;
1854   stream->time_position = 0;
1855   stream->sample_index = -1;
1856   stream->offset_in_sample = 0;
1857   stream->new_stream = TRUE;
1858   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1859   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1860   stream->protected = FALSE;
1861   stream->protection_scheme_type = 0;
1862   stream->protection_scheme_version = 0;
1863   stream->protection_scheme_info = NULL;
1864   stream->n_samples_moof = 0;
1865   stream->duration_moof = 0;
1866   stream->duration_last_moof = 0;
1867   stream->alignment = 1;
1868   stream->stream_tags = gst_tag_list_new_empty ();
1869   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1870   g_queue_init (&stream->protection_scheme_event_queue);
1871   stream->ref_count = 1;
1872   /* consistent default for push based mode */
1873   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1874   return stream;
1875 }
1876
1877 static gboolean
1878 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1879 {
1880   GstStructure *structure;
1881   const gchar *variant;
1882   const GstCaps *mediacaps = NULL;
1883
1884   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1885
1886   structure = gst_caps_get_structure (caps, 0);
1887   variant = gst_structure_get_string (structure, "variant");
1888
1889   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1890     QtDemuxStream *stream;
1891     const GValue *value;
1892
1893     demux->fragmented = TRUE;
1894     demux->mss_mode = TRUE;
1895
1896     if (QTDEMUX_N_STREAMS (demux) > 1) {
1897       /* can't do this, we can only renegotiate for another mss format */
1898       return FALSE;
1899     }
1900
1901     value = gst_structure_get_value (structure, "media-caps");
1902     /* create stream */
1903     if (value) {
1904       const GValue *timescale_v;
1905
1906       /* TODO update when stream changes during playback */
1907
1908       if (QTDEMUX_N_STREAMS (demux) == 0) {
1909         stream = _create_stream (demux, 1);
1910         g_ptr_array_add (demux->active_streams, stream);
1911         /* mss has no stsd/stsd entry, use id 0 as default */
1912         stream->stsd_entries_length = 1;
1913         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1914         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1915       } else {
1916         stream = QTDEMUX_NTH_STREAM (demux, 0);
1917       }
1918
1919       timescale_v = gst_structure_get_value (structure, "timescale");
1920       if (timescale_v) {
1921         stream->timescale = g_value_get_uint64 (timescale_v);
1922       } else {
1923         /* default mss timescale */
1924         stream->timescale = 10000000;
1925       }
1926       demux->timescale = stream->timescale;
1927
1928       mediacaps = gst_value_get_caps (value);
1929       if (!CUR_STREAM (stream)->caps
1930           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1931         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1932             mediacaps);
1933         stream->new_caps = TRUE;
1934       }
1935       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1936       structure = gst_caps_get_structure (mediacaps, 0);
1937       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1938         stream->subtype = FOURCC_vide;
1939
1940         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1941         gst_structure_get_int (structure, "height",
1942             &CUR_STREAM (stream)->height);
1943         gst_structure_get_fraction (structure, "framerate",
1944             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1945       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1946         gint rate = 0;
1947         stream->subtype = FOURCC_soun;
1948         gst_structure_get_int (structure, "channels",
1949             &CUR_STREAM (stream)->n_channels);
1950         gst_structure_get_int (structure, "rate", &rate);
1951         CUR_STREAM (stream)->rate = rate;
1952       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1953         if (gst_structure_has_field (structure, "original-media-type")) {
1954           const gchar *media_type =
1955               gst_structure_get_string (structure, "original-media-type");
1956           if (g_str_has_prefix (media_type, "video")) {
1957             stream->subtype = FOURCC_vide;
1958           } else if (g_str_has_prefix (media_type, "audio")) {
1959             stream->subtype = FOURCC_soun;
1960           }
1961         }
1962       }
1963     }
1964     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1965   } else {
1966     demux->mss_mode = FALSE;
1967   }
1968
1969   return TRUE;
1970 }
1971
1972 static void
1973 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1974 {
1975   gint i;
1976
1977   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1978   gst_pad_stop_task (qtdemux->sinkpad);
1979
1980   if (hard || qtdemux->upstream_format_is_time) {
1981     qtdemux->state = QTDEMUX_STATE_INITIAL;
1982     qtdemux->neededbytes = 16;
1983     qtdemux->todrop = 0;
1984     qtdemux->pullbased = FALSE;
1985     g_clear_pointer (&qtdemux->redirect_location, g_free);
1986     qtdemux->first_mdat = -1;
1987     qtdemux->header_size = 0;
1988     qtdemux->mdatoffset = -1;
1989     qtdemux->restoredata_offset = -1;
1990     if (qtdemux->mdatbuffer)
1991       gst_buffer_unref (qtdemux->mdatbuffer);
1992     if (qtdemux->restoredata_buffer)
1993       gst_buffer_unref (qtdemux->restoredata_buffer);
1994     qtdemux->mdatbuffer = NULL;
1995     qtdemux->restoredata_buffer = NULL;
1996     qtdemux->mdatleft = 0;
1997     qtdemux->mdatsize = 0;
1998     if (qtdemux->comp_brands)
1999       gst_buffer_unref (qtdemux->comp_brands);
2000     qtdemux->comp_brands = NULL;
2001     qtdemux->last_moov_offset = -1;
2002     if (qtdemux->moov_node_compressed) {
2003       g_node_destroy (qtdemux->moov_node_compressed);
2004       if (qtdemux->moov_node)
2005         g_free (qtdemux->moov_node->data);
2006     }
2007     qtdemux->moov_node_compressed = NULL;
2008     if (qtdemux->moov_node)
2009       g_node_destroy (qtdemux->moov_node);
2010     qtdemux->moov_node = NULL;
2011     if (qtdemux->tag_list)
2012       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2013     qtdemux->tag_list = gst_tag_list_new_empty ();
2014     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2015 #if 0
2016     if (qtdemux->element_index)
2017       gst_object_unref (qtdemux->element_index);
2018     qtdemux->element_index = NULL;
2019 #endif
2020     qtdemux->major_brand = 0;
2021     qtdemux->upstream_format_is_time = FALSE;
2022     qtdemux->upstream_seekable = FALSE;
2023     qtdemux->upstream_size = 0;
2024
2025     qtdemux->fragment_start = -1;
2026     qtdemux->fragment_start_offset = -1;
2027     qtdemux->duration = 0;
2028     qtdemux->moof_offset = 0;
2029     qtdemux->chapters_track_id = 0;
2030     qtdemux->have_group_id = FALSE;
2031     qtdemux->group_id = G_MAXUINT;
2032
2033     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2034         NULL);
2035     g_queue_clear (&qtdemux->protection_event_queue);
2036
2037     qtdemux->received_seek = FALSE;
2038     qtdemux->first_moof_already_parsed = FALSE;
2039   }
2040   qtdemux->offset = 0;
2041   gst_adapter_clear (qtdemux->adapter);
2042   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2043   qtdemux->need_segment = TRUE;
2044
2045   if (hard) {
2046     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2047     qtdemux->trickmode_interval = 0;
2048     g_ptr_array_set_size (qtdemux->active_streams, 0);
2049     g_ptr_array_set_size (qtdemux->old_streams, 0);
2050     qtdemux->n_video_streams = 0;
2051     qtdemux->n_audio_streams = 0;
2052     qtdemux->n_sub_streams = 0;
2053     qtdemux->exposed = FALSE;
2054     qtdemux->fragmented = FALSE;
2055     qtdemux->mss_mode = FALSE;
2056     gst_caps_replace (&qtdemux->media_caps, NULL);
2057     qtdemux->timescale = 0;
2058     qtdemux->got_moov = FALSE;
2059     qtdemux->cenc_aux_info_offset = 0;
2060     qtdemux->cenc_aux_info_sizes = NULL;
2061     qtdemux->cenc_aux_sample_count = 0;
2062     if (qtdemux->protection_system_ids) {
2063       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2064       qtdemux->protection_system_ids = NULL;
2065     }
2066     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2067         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2068         GST_BIN_FLAG_STREAMS_AWARE);
2069
2070     if (qtdemux->preferred_protection_system_id) {
2071       g_free (qtdemux->preferred_protection_system_id);
2072       qtdemux->preferred_protection_system_id = NULL;
2073     }
2074   } else if (qtdemux->mss_mode) {
2075     gst_flow_combiner_reset (qtdemux->flowcombiner);
2076     g_ptr_array_foreach (qtdemux->active_streams,
2077         (GFunc) gst_qtdemux_stream_clear, NULL);
2078   } else {
2079     gst_flow_combiner_reset (qtdemux->flowcombiner);
2080     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2081       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2082       stream->sent_eos = FALSE;
2083       stream->time_position = 0;
2084       stream->accumulated_base = 0;
2085       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2086     }
2087   }
2088 }
2089
2090
2091 /* Maps the @segment to the qt edts internal segments and pushes
2092  * the corresponding segment event.
2093  *
2094  * If it ends up being at a empty segment, a gap will be pushed and the next
2095  * edts segment will be activated in sequence.
2096  *
2097  * To be used in push-mode only */
2098 static void
2099 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2100 {
2101   gint i, iter;
2102
2103   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2104     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2105
2106     stream->time_position = segment->start;
2107
2108     /* in push mode we should be guaranteed that we will have empty segments
2109      * at the beginning and then one segment after, other scenarios are not
2110      * supported and are discarded when parsing the edts */
2111     for (i = 0; i < stream->n_segments; i++) {
2112       if (stream->segments[i].stop_time > segment->start) {
2113         /* push the empty segment and move to the next one */
2114         gst_qtdemux_activate_segment (qtdemux, stream, i,
2115             stream->time_position);
2116         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2117           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2118               stream->time_position);
2119
2120           /* accumulate previous segments */
2121           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2122             stream->accumulated_base +=
2123                 (stream->segment.stop -
2124                 stream->segment.start) / ABS (stream->segment.rate);
2125           continue;
2126         }
2127
2128         g_assert (i == stream->n_segments - 1);
2129       }
2130     }
2131   }
2132 }
2133
2134 static void
2135 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2136     GPtrArray * src)
2137 {
2138   guint i;
2139   guint len;
2140
2141   len = src->len;
2142
2143   if (len == 0)
2144     return;
2145
2146   for (i = 0; i < len; i++) {
2147     QtDemuxStream *stream = g_ptr_array_index (src, i);
2148
2149 #ifndef GST_DISABLE_GST_DEBUG
2150     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2151         stream, GST_STR_NULL (stream->stream_id), dest);
2152 #endif
2153     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2154   }
2155
2156   g_ptr_array_set_size (src, 0);
2157 }
2158
2159 static gboolean
2160 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2161     GstEvent * event)
2162 {
2163   GstQTDemux *demux = GST_QTDEMUX (parent);
2164   gboolean res = TRUE;
2165
2166   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2167
2168   switch (GST_EVENT_TYPE (event)) {
2169     case GST_EVENT_SEGMENT:
2170     {
2171       gint64 offset = 0;
2172       QtDemuxStream *stream;
2173       gint idx;
2174       GstSegment segment;
2175
2176       /* some debug output */
2177       gst_event_copy_segment (event, &segment);
2178       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2179           &segment);
2180
2181       if (segment.format == GST_FORMAT_TIME) {
2182         demux->upstream_format_is_time = TRUE;
2183         demux->segment_seqnum = gst_event_get_seqnum (event);
2184       } else {
2185         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2186             "not in time format");
2187
2188         /* chain will send initial newsegment after pads have been added */
2189         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2190           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2191           goto exit;
2192         }
2193       }
2194
2195       /* check if this matches a time seek we received previously
2196        * FIXME for backwards compatibility reasons we use the
2197        * seek_offset here to compare. In the future we might want to
2198        * change this to use the seqnum as it uniquely should identify
2199        * the segment that corresponds to the seek. */
2200       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2201           ", received segment offset %" G_GINT64_FORMAT,
2202           demux->seek_offset, segment.start);
2203       if (segment.format == GST_FORMAT_BYTES
2204           && demux->seek_offset == segment.start) {
2205         GST_OBJECT_LOCK (demux);
2206         offset = segment.start;
2207
2208         segment.format = GST_FORMAT_TIME;
2209         segment.start = demux->push_seek_start;
2210         segment.stop = demux->push_seek_stop;
2211         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2212             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2213             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2214         GST_OBJECT_UNLOCK (demux);
2215       }
2216
2217       /* we only expect a BYTE segment, e.g. following a seek */
2218       if (segment.format == GST_FORMAT_BYTES) {
2219         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2220           offset = segment.start;
2221
2222           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2223               NULL, (gint64 *) & segment.start);
2224           if ((gint64) segment.start < 0)
2225             segment.start = 0;
2226         }
2227         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2228           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2229               NULL, (gint64 *) & segment.stop);
2230           /* keyframe seeking should already arrange for start >= stop,
2231            * but make sure in other rare cases */
2232           segment.stop = MAX (segment.stop, segment.start);
2233         }
2234       } else if (segment.format == GST_FORMAT_TIME) {
2235         /* push all data on the adapter before starting this
2236          * new segment */
2237         gst_qtdemux_process_adapter (demux, TRUE);
2238       } else {
2239         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2240         goto exit;
2241       }
2242
2243       /* We shouldn't modify upstream driven TIME FORMAT segment */
2244       if (!demux->upstream_format_is_time) {
2245         /* accept upstream's notion of segment and distribute along */
2246         segment.format = GST_FORMAT_TIME;
2247         segment.position = segment.time = segment.start;
2248         segment.duration = demux->segment.duration;
2249         segment.base = gst_segment_to_running_time (&demux->segment,
2250             GST_FORMAT_TIME, demux->segment.position);
2251       }
2252
2253       gst_segment_copy_into (&segment, &demux->segment);
2254       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2255
2256       /* map segment to internal qt segments and push on each stream */
2257       if (QTDEMUX_N_STREAMS (demux)) {
2258         demux->need_segment = TRUE;
2259         gst_qtdemux_check_send_pending_segment (demux);
2260       }
2261
2262       /* clear leftover in current segment, if any */
2263       gst_adapter_clear (demux->adapter);
2264
2265       /* set up streaming thread */
2266       demux->offset = offset;
2267       if (demux->upstream_format_is_time) {
2268         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2269             "set values to restart reading from a new atom");
2270         demux->neededbytes = 16;
2271         demux->todrop = 0;
2272       } else {
2273         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2274             NULL);
2275         if (stream) {
2276           demux->todrop = stream->samples[idx].offset - offset;
2277           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2278         } else {
2279           /* set up for EOS */
2280           demux->neededbytes = -1;
2281           demux->todrop = 0;
2282         }
2283       }
2284     exit:
2285       gst_event_unref (event);
2286       res = TRUE;
2287       goto drop;
2288     }
2289     case GST_EVENT_FLUSH_START:
2290     {
2291       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2292         gst_event_unref (event);
2293         goto drop;
2294       }
2295       QTDEMUX_EXPOSE_LOCK (demux);
2296       res = gst_pad_event_default (demux->sinkpad, parent, event);
2297       QTDEMUX_EXPOSE_UNLOCK (demux);
2298       goto drop;
2299     }
2300     case GST_EVENT_FLUSH_STOP:
2301     {
2302       guint64 dur;
2303
2304       dur = demux->segment.duration;
2305       gst_qtdemux_reset (demux, FALSE);
2306       demux->segment.duration = dur;
2307
2308       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2309         gst_event_unref (event);
2310         goto drop;
2311       }
2312       break;
2313     }
2314     case GST_EVENT_EOS:
2315       /* If we are in push mode, and get an EOS before we've seen any streams,
2316        * then error out - we have nowhere to send the EOS */
2317       if (!demux->pullbased) {
2318         gint i;
2319         gboolean has_valid_stream = FALSE;
2320         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2321           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2322             has_valid_stream = TRUE;
2323             break;
2324           }
2325         }
2326         if (!has_valid_stream)
2327           gst_qtdemux_post_no_playable_stream_error (demux);
2328         else {
2329           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2330               (guint) gst_adapter_available (demux->adapter));
2331           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2332             res = FALSE;
2333           }
2334         }
2335       }
2336       break;
2337     case GST_EVENT_CAPS:{
2338       GstCaps *caps = NULL;
2339
2340       gst_event_parse_caps (event, &caps);
2341       gst_qtdemux_setcaps (demux, caps);
2342       res = TRUE;
2343       gst_event_unref (event);
2344       goto drop;
2345     }
2346     case GST_EVENT_PROTECTION:
2347     {
2348       const gchar *system_id = NULL;
2349
2350       gst_event_parse_protection (event, &system_id, NULL, NULL);
2351       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2352           system_id);
2353       gst_qtdemux_append_protection_system_id (demux, system_id);
2354       /* save the event for later, for source pads that have not been created */
2355       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2356       /* send it to all pads that already exist */
2357       gst_qtdemux_push_event (demux, event);
2358       res = TRUE;
2359       goto drop;
2360     }
2361     case GST_EVENT_STREAM_START:
2362     {
2363       res = TRUE;
2364       gst_event_unref (event);
2365
2366       /* Drain all the buffers */
2367       gst_qtdemux_process_adapter (demux, TRUE);
2368       gst_qtdemux_reset (demux, FALSE);
2369       /* We expect new moov box after new stream-start event */
2370       if (demux->exposed) {
2371         gst_qtdemux_stream_concat (demux,
2372             demux->old_streams, demux->active_streams);
2373       }
2374
2375       goto drop;
2376     }
2377     default:
2378       break;
2379   }
2380
2381   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2382
2383 drop:
2384   return res;
2385 }
2386
2387 static gboolean
2388 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2389     GstQuery * query)
2390 {
2391   GstQTDemux *demux = GST_QTDEMUX (parent);
2392   gboolean res = FALSE;
2393
2394   switch (GST_QUERY_TYPE (query)) {
2395     case GST_QUERY_BITRATE:
2396     {
2397       GstClockTime duration;
2398
2399       /* populate demux->upstream_size if not done yet */
2400       gst_qtdemux_check_seekability (demux);
2401
2402       if (demux->upstream_size != -1
2403           && gst_qtdemux_get_duration (demux, &duration)) {
2404         guint bitrate =
2405             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2406             duration);
2407
2408         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2409             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2410             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2411
2412         /* TODO: better results based on ranges/index tables */
2413         gst_query_set_bitrate (query, bitrate);
2414         res = TRUE;
2415       }
2416       break;
2417     }
2418     default:
2419       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2420       break;
2421   }
2422
2423   return res;
2424 }
2425
2426
2427 #if 0
2428 static void
2429 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2430 {
2431   GstQTDemux *demux = GST_QTDEMUX (element);
2432
2433   GST_OBJECT_LOCK (demux);
2434   if (demux->element_index)
2435     gst_object_unref (demux->element_index);
2436   if (index) {
2437     demux->element_index = gst_object_ref (index);
2438   } else {
2439     demux->element_index = NULL;
2440   }
2441   GST_OBJECT_UNLOCK (demux);
2442   /* object lock might be taken again */
2443   if (index)
2444     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2445   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2446       demux->element_index, demux->index_id);
2447 }
2448
2449 static GstIndex *
2450 gst_qtdemux_get_index (GstElement * element)
2451 {
2452   GstIndex *result = NULL;
2453   GstQTDemux *demux = GST_QTDEMUX (element);
2454
2455   GST_OBJECT_LOCK (demux);
2456   if (demux->element_index)
2457     result = gst_object_ref (demux->element_index);
2458   GST_OBJECT_UNLOCK (demux);
2459
2460   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2461
2462   return result;
2463 }
2464 #endif
2465
2466 static void
2467 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2468 {
2469   g_free ((gpointer) stream->stco.data);
2470   stream->stco.data = NULL;
2471   g_free ((gpointer) stream->stsz.data);
2472   stream->stsz.data = NULL;
2473   g_free ((gpointer) stream->stsc.data);
2474   stream->stsc.data = NULL;
2475   g_free ((gpointer) stream->stts.data);
2476   stream->stts.data = NULL;
2477   g_free ((gpointer) stream->stss.data);
2478   stream->stss.data = NULL;
2479   g_free ((gpointer) stream->stps.data);
2480   stream->stps.data = NULL;
2481   g_free ((gpointer) stream->ctts.data);
2482   stream->ctts.data = NULL;
2483 }
2484
2485 static void
2486 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2487 {
2488   g_free (stream->segments);
2489   stream->segments = NULL;
2490   stream->segment_index = -1;
2491   stream->accumulated_base = 0;
2492 }
2493
2494 static void
2495 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2496 {
2497   g_free (stream->samples);
2498   stream->samples = NULL;
2499   gst_qtdemux_stbl_free (stream);
2500
2501   /* fragments */
2502   g_free (stream->ra_entries);
2503   stream->ra_entries = NULL;
2504   stream->n_ra_entries = 0;
2505
2506   stream->sample_index = -1;
2507   stream->stbl_index = -1;
2508   stream->n_samples = 0;
2509   stream->time_position = 0;
2510
2511   stream->n_samples_moof = 0;
2512   stream->duration_moof = 0;
2513   stream->duration_last_moof = 0;
2514 }
2515
2516 static void
2517 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2518 {
2519   gint i;
2520   if (stream->allocator)
2521     gst_object_unref (stream->allocator);
2522   while (stream->buffers) {
2523     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2524     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2525   }
2526   for (i = 0; i < stream->stsd_entries_length; i++) {
2527     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2528     if (entry->rgb8_palette) {
2529       gst_memory_unref (entry->rgb8_palette);
2530       entry->rgb8_palette = NULL;
2531     }
2532     entry->sparse = FALSE;
2533   }
2534
2535   if (stream->stream_tags)
2536     gst_tag_list_unref (stream->stream_tags);
2537
2538   stream->stream_tags = gst_tag_list_new_empty ();
2539   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2540   g_free (stream->redirect_uri);
2541   stream->redirect_uri = NULL;
2542   stream->sent_eos = FALSE;
2543   stream->protected = FALSE;
2544   if (stream->protection_scheme_info) {
2545     if (stream->protection_scheme_type == FOURCC_cenc
2546         || stream->protection_scheme_type == FOURCC_cbcs) {
2547       QtDemuxCencSampleSetInfo *info =
2548           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2549       if (info->default_properties)
2550         gst_structure_free (info->default_properties);
2551       if (info->crypto_info)
2552         g_ptr_array_free (info->crypto_info, TRUE);
2553     }
2554     if (stream->protection_scheme_type == FOURCC_aavd) {
2555       QtDemuxAavdEncryptionInfo *info =
2556           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2557       if (info->default_properties)
2558         gst_structure_free (info->default_properties);
2559     }
2560     g_free (stream->protection_scheme_info);
2561     stream->protection_scheme_info = NULL;
2562   }
2563   stream->protection_scheme_type = 0;
2564   stream->protection_scheme_version = 0;
2565   g_queue_foreach (&stream->protection_scheme_event_queue,
2566       (GFunc) gst_event_unref, NULL);
2567   g_queue_clear (&stream->protection_scheme_event_queue);
2568   gst_qtdemux_stream_flush_segments_data (stream);
2569   gst_qtdemux_stream_flush_samples_data (stream);
2570 }
2571
2572 static void
2573 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2574 {
2575   gint i;
2576   gst_qtdemux_stream_clear (stream);
2577   for (i = 0; i < stream->stsd_entries_length; i++) {
2578     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2579     if (entry->caps) {
2580       gst_caps_unref (entry->caps);
2581       entry->caps = NULL;
2582     }
2583   }
2584   g_free (stream->stsd_entries);
2585   stream->stsd_entries = NULL;
2586   stream->stsd_entries_length = 0;
2587 }
2588
2589 static QtDemuxStream *
2590 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2591 {
2592   g_atomic_int_add (&stream->ref_count, 1);
2593
2594   return stream;
2595 }
2596
2597 static void
2598 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2599 {
2600   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2601     gst_qtdemux_stream_reset (stream);
2602     gst_tag_list_unref (stream->stream_tags);
2603     if (stream->pad) {
2604       GstQTDemux *demux = stream->demux;
2605       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2606       GST_OBJECT_LOCK (demux);
2607       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2608       GST_OBJECT_UNLOCK (demux);
2609     }
2610     g_free (stream->stream_id);
2611     g_free (stream);
2612   }
2613 }
2614
2615 static GstStateChangeReturn
2616 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2617 {
2618   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2619   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2620
2621   switch (transition) {
2622     case GST_STATE_CHANGE_READY_TO_PAUSED:
2623       gst_qtdemux_reset (qtdemux, TRUE);
2624       break;
2625     default:
2626       break;
2627   }
2628
2629   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2630
2631   switch (transition) {
2632     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2633       gst_qtdemux_reset (qtdemux, TRUE);
2634       break;
2635     }
2636     default:
2637       break;
2638   }
2639
2640   return result;
2641 }
2642
2643 static void
2644 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2645 {
2646   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2647
2648   g_return_if_fail (GST_IS_CONTEXT (context));
2649
2650   if (gst_context_has_context_type (context,
2651           "drm-preferred-decryption-system-id")) {
2652     const GstStructure *s;
2653
2654     s = gst_context_get_structure (context);
2655     g_free (qtdemux->preferred_protection_system_id);
2656     qtdemux->preferred_protection_system_id =
2657         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2658     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2659         qtdemux->preferred_protection_system_id);
2660   }
2661
2662   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2663 }
2664
2665 static void
2666 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2667 {
2668   /* counts as header data */
2669   qtdemux->header_size += length;
2670
2671   /* only consider at least a sufficiently complete ftyp atom */
2672   if (length >= 20) {
2673     GstBuffer *buf;
2674
2675     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2676     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2677         GST_FOURCC_ARGS (qtdemux->major_brand));
2678     if (qtdemux->comp_brands)
2679       gst_buffer_unref (qtdemux->comp_brands);
2680     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2681     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2682   }
2683 }
2684
2685 static void
2686 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2687     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2688     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2689     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2690     const guint8 * constant_iv)
2691 {
2692   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2693   gst_buffer_fill (kid_buf, 0, kid, 16);
2694   if (info->default_properties)
2695     gst_structure_free (info->default_properties);
2696   info->default_properties =
2697       gst_structure_new ("application/x-cenc",
2698       "iv_size", G_TYPE_UINT, iv_size,
2699       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2700       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2701   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2702       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2703   gst_buffer_unref (kid_buf);
2704   if (protection_scheme_type == FOURCC_cbcs) {
2705     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2706       gst_structure_set (info->default_properties, "crypt_byte_block",
2707           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2708           skip_byte_block, NULL);
2709     }
2710     if (constant_iv != NULL) {
2711       GstBuffer *constant_iv_buf =
2712           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2713       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2714       gst_structure_set (info->default_properties, "constant_iv_size",
2715           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2716           NULL);
2717       gst_buffer_unref (constant_iv_buf);
2718     }
2719     gst_structure_set (info->default_properties, "cipher-mode",
2720         G_TYPE_STRING, "cbcs", NULL);
2721   } else {
2722     gst_structure_set (info->default_properties, "cipher-mode",
2723         G_TYPE_STRING, "cenc", NULL);
2724   }
2725 }
2726
2727 static gboolean
2728 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2729     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2730 {
2731   guint32 algorithm_id = 0;
2732   const guint8 *kid;
2733   gboolean is_encrypted = TRUE;
2734   guint8 iv_size = 8;
2735
2736   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2737     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2738     return FALSE;
2739   }
2740
2741   algorithm_id >>= 8;
2742   if (algorithm_id == 0) {
2743     is_encrypted = FALSE;
2744   } else if (algorithm_id == 1) {
2745     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2746   } else if (algorithm_id == 2) {
2747     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2748   }
2749
2750   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2751     return FALSE;
2752
2753   if (!gst_byte_reader_get_data (br, 16, &kid))
2754     return FALSE;
2755
2756   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2757       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2758   gst_structure_set (info->default_properties, "piff_algorithm_id",
2759       G_TYPE_UINT, algorithm_id, NULL);
2760   return TRUE;
2761 }
2762
2763
2764 static void
2765 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2766     guint offset)
2767 {
2768   GstByteReader br;
2769   guint8 version;
2770   guint32 flags = 0;
2771   guint i;
2772   guint iv_size = 8;
2773   QtDemuxStream *stream;
2774   GstStructure *structure;
2775   QtDemuxCencSampleSetInfo *ss_info = NULL;
2776   const gchar *system_id;
2777   gboolean uses_sub_sample_encryption = FALSE;
2778   guint32 sample_count;
2779
2780   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2781     return;
2782
2783   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2784
2785   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2786   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2787     GST_WARNING_OBJECT (qtdemux,
2788         "Attempting PIFF box parsing on an unencrypted stream.");
2789     return;
2790   }
2791
2792   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2793       G_TYPE_STRING, &system_id, NULL);
2794   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2795
2796   stream->protected = TRUE;
2797   stream->protection_scheme_type = FOURCC_cenc;
2798
2799   if (!stream->protection_scheme_info)
2800     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2801
2802   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2803   if (!ss_info->default_properties) {
2804     ss_info->default_properties =
2805         gst_structure_new ("application/x-cenc",
2806         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2807         NULL);
2808
2809   }
2810
2811   if (ss_info->crypto_info) {
2812     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2813     g_ptr_array_free (ss_info->crypto_info, TRUE);
2814     ss_info->crypto_info = NULL;
2815   }
2816
2817   /* skip UUID */
2818   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2819
2820   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2821     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2822     return;
2823   }
2824
2825   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2826     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2827     return;
2828   }
2829
2830   if ((flags & 0x000001)) {
2831     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2832             &br))
2833       return;
2834   } else if ((flags & 0x000002)) {
2835     uses_sub_sample_encryption = TRUE;
2836   }
2837
2838   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2839           &iv_size)) {
2840     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2841     return;
2842   }
2843
2844   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2845     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2846     return;
2847   }
2848
2849   ss_info->crypto_info =
2850       g_ptr_array_new_full (sample_count,
2851       (GDestroyNotify) qtdemux_gst_structure_free);
2852
2853   for (i = 0; i < sample_count; ++i) {
2854     GstStructure *properties;
2855     guint8 *data;
2856     GstBuffer *buf;
2857
2858     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2859     if (properties == NULL) {
2860       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2861       qtdemux->cenc_aux_sample_count = i;
2862       return;
2863     }
2864
2865     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2866       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2867       gst_structure_free (properties);
2868       qtdemux->cenc_aux_sample_count = i;
2869       return;
2870     }
2871     buf = gst_buffer_new_wrapped (data, iv_size);
2872     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2873     gst_buffer_unref (buf);
2874
2875     if (uses_sub_sample_encryption) {
2876       guint16 n_subsamples;
2877       const GValue *kid_buf_value;
2878
2879       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2880           || n_subsamples == 0) {
2881         GST_ERROR_OBJECT (qtdemux,
2882             "failed to get subsample count for sample %u", i);
2883         gst_structure_free (properties);
2884         qtdemux->cenc_aux_sample_count = i;
2885         return;
2886       }
2887       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2888       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2889         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2890             i);
2891         gst_structure_free (properties);
2892         qtdemux->cenc_aux_sample_count = i;
2893         return;
2894       }
2895       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2896
2897       kid_buf_value =
2898           gst_structure_get_value (ss_info->default_properties, "kid");
2899
2900       gst_structure_set (properties,
2901           "subsample_count", G_TYPE_UINT, n_subsamples,
2902           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2903       gst_structure_set_value (properties, "kid", kid_buf_value);
2904       gst_buffer_unref (buf);
2905     } else {
2906       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2907     }
2908
2909     g_ptr_array_add (ss_info->crypto_info, properties);
2910   }
2911
2912   qtdemux->cenc_aux_sample_count = sample_count;
2913 }
2914
2915 static void
2916 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2917 {
2918   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2919     0x97, 0xA9, 0x42, 0xE8,
2920     0x9C, 0x71, 0x99, 0x94,
2921     0x91, 0xE3, 0xAF, 0xAC
2922   };
2923   static const guint8 playready_uuid[] = {
2924     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2925     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2926   };
2927
2928   static const guint8 piff_sample_encryption_uuid[] = {
2929     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2930     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2931   };
2932
2933   guint offset;
2934
2935   /* counts as header data */
2936   qtdemux->header_size += length;
2937
2938   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2939
2940   if (length <= offset + 16) {
2941     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2942     return;
2943   }
2944
2945   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2946     GstBuffer *buf;
2947     GstTagList *taglist;
2948
2949     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2950         length - offset - 16, NULL);
2951     taglist = gst_tag_list_from_xmp_buffer (buf);
2952     gst_buffer_unref (buf);
2953
2954     /* make sure we have a usable taglist */
2955     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2956
2957     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2958
2959   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2960     int len;
2961     const gunichar2 *s_utf16;
2962     char *contents;
2963
2964     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2965     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2966     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2967     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2968
2969     g_free (contents);
2970
2971     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2972         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2973         (NULL));
2974   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2975     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2976   } else {
2977     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2978         GST_READ_UINT32_LE (buffer + offset),
2979         GST_READ_UINT32_LE (buffer + offset + 4),
2980         GST_READ_UINT32_LE (buffer + offset + 8),
2981         GST_READ_UINT32_LE (buffer + offset + 12));
2982   }
2983 }
2984
2985 static void
2986 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2987 {
2988   GstSidxParser sidx_parser;
2989   GstIsoffParserResult res;
2990   guint consumed;
2991
2992   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2993
2994   res =
2995       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2996       &consumed);
2997   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2998   if (res == GST_ISOFF_QT_PARSER_DONE) {
2999     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3000   }
3001   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3002 }
3003
3004 /* caller verifies at least 8 bytes in buf */
3005 static void
3006 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3007     guint64 * plength, guint32 * pfourcc)
3008 {
3009   guint64 length;
3010   guint32 fourcc;
3011
3012   length = QT_UINT32 (data);
3013   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3014   fourcc = QT_FOURCC (data + 4);
3015   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3016
3017   if (length == 0) {
3018     length = G_MAXUINT64;
3019   } else if (length == 1 && size >= 16) {
3020     /* this means we have an extended size, which is the 64 bit value of
3021      * the next 8 bytes */
3022     length = QT_UINT64 (data + 8);
3023     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3024   }
3025
3026   if (plength)
3027     *plength = length;
3028   if (pfourcc)
3029     *pfourcc = fourcc;
3030 }
3031
3032 static gboolean
3033 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3034 {
3035   guint32 version = 0;
3036   GstClockTime duration = 0;
3037
3038   if (!gst_byte_reader_get_uint32_be (br, &version))
3039     goto failed;
3040
3041   version >>= 24;
3042   if (version == 1) {
3043     if (!gst_byte_reader_get_uint64_be (br, &duration))
3044       goto failed;
3045   } else {
3046     guint32 dur = 0;
3047
3048     if (!gst_byte_reader_get_uint32_be (br, &dur))
3049       goto failed;
3050     duration = dur;
3051   }
3052
3053   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3054   qtdemux->duration = duration;
3055
3056   return TRUE;
3057
3058 failed:
3059   {
3060     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3061     return FALSE;
3062   }
3063 }
3064
3065 static gboolean
3066 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3067     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3068 {
3069   if (!stream->parsed_trex && qtdemux->moov_node) {
3070     GNode *mvex, *trex;
3071     GstByteReader trex_data;
3072
3073     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3074     if (mvex) {
3075       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3076           &trex_data);
3077       while (trex) {
3078         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3079
3080         /* skip version/flags */
3081         if (!gst_byte_reader_skip (&trex_data, 4))
3082           goto next;
3083         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3084           goto next;
3085         if (id != stream->track_id)
3086           goto next;
3087         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3088           goto next;
3089         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3090           goto next;
3091         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3092           goto next;
3093         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3094           goto next;
3095
3096         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3097             "duration %d,  size %d, flags 0x%x", stream->track_id,
3098             dur, size, flags);
3099
3100         stream->parsed_trex = TRUE;
3101         stream->def_sample_description_index = sdi;
3102         stream->def_sample_duration = dur;
3103         stream->def_sample_size = size;
3104         stream->def_sample_flags = flags;
3105
3106       next:
3107         /* iterate all siblings */
3108         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3109             &trex_data);
3110       }
3111     }
3112   }
3113
3114   *ds_duration = stream->def_sample_duration;
3115   *ds_size = stream->def_sample_size;
3116   *ds_flags = stream->def_sample_flags;
3117
3118   /* even then, above values are better than random ... */
3119   if (G_UNLIKELY (!stream->parsed_trex)) {
3120     GST_WARNING_OBJECT (qtdemux,
3121         "failed to find fragment defaults for stream %d", stream->track_id);
3122     return FALSE;
3123   }
3124
3125   return TRUE;
3126 }
3127
3128 /* This method should be called whenever a more accurate duration might
3129  * have been found. It will update all relevant variables if/where needed
3130  */
3131 static void
3132 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3133 {
3134   guint i;
3135   guint64 movdur;
3136   GstClockTime prevdur;
3137
3138   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3139
3140   if (movdur > qtdemux->duration) {
3141     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3142     GST_DEBUG_OBJECT (qtdemux,
3143         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3144         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3145     qtdemux->duration = movdur;
3146     GST_DEBUG_OBJECT (qtdemux,
3147         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3148         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3149         GST_TIME_ARGS (qtdemux->segment.stop));
3150     if (qtdemux->segment.duration == prevdur) {
3151       /* If the current segment has duration/stop identical to previous duration
3152        * update them also (because they were set at that point in time with
3153        * the wrong duration */
3154       /* We convert the value *from* the timescale version to avoid rounding errors */
3155       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3156       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3157       qtdemux->segment.duration = fixeddur;
3158       qtdemux->segment.stop = fixeddur;
3159     }
3160   }
3161
3162   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3163     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3164
3165     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3166     if (movdur > stream->duration) {
3167       GST_DEBUG_OBJECT (qtdemux,
3168           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3169           GST_TIME_ARGS (duration));
3170       stream->duration = movdur;
3171       /* internal duration tracking state has been updated above, so */
3172       /* preserve an open-ended dummy segment rather than repeatedly updating
3173        * it and spamming downstream accordingly with segment events */
3174       /* also mangle the edit list end time when fragmented with a single edit
3175        * list that may only cover any non-fragmented data */
3176       if ((stream->dummy_segment ||
3177               (qtdemux->fragmented && stream->n_segments == 1)) &&
3178           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3179         /* Update all dummy values to new duration */
3180         stream->segments[0].stop_time = duration;
3181         stream->segments[0].duration = duration;
3182         stream->segments[0].media_stop = duration;
3183
3184         /* let downstream know we possibly have a new stop time */
3185         if (stream->segment_index != -1) {
3186           GstClockTime pos;
3187
3188           if (qtdemux->segment.rate >= 0) {
3189             pos = stream->segment.start;
3190           } else {
3191             pos = stream->segment.stop;
3192           }
3193
3194           gst_qtdemux_stream_update_segment (qtdemux, stream,
3195               stream->segment_index, pos, NULL, NULL);
3196         }
3197       }
3198     }
3199   }
3200 }
3201
3202 static gboolean
3203 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3204     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3205     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3206     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3207     gboolean has_tfdt)
3208 {
3209   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3210   guint64 timestamp;
3211   gint32 data_offset = 0;
3212   guint32 flags = 0, first_flags = 0, samples_count = 0;
3213   gint i;
3214   guint8 *data;
3215   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3216   QtDemuxSample *sample;
3217   gboolean ismv = FALSE;
3218   gint64 initial_offset;
3219
3220   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3221       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3222       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3223       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3224
3225   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3226     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3227     return TRUE;
3228   }
3229
3230   /* presence of stss or not can't really tell us much,
3231    * and flags and so on tend to be marginally reliable in these files */
3232   if (stream->subtype == FOURCC_soun) {
3233     GST_DEBUG_OBJECT (qtdemux,
3234         "sound track in fragmented file; marking all keyframes");
3235     stream->all_keyframe = TRUE;
3236   }
3237
3238   if (!gst_byte_reader_skip (trun, 1) ||
3239       !gst_byte_reader_get_uint24_be (trun, &flags))
3240     goto fail;
3241
3242   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3243     goto fail;
3244
3245   if (flags & TR_DATA_OFFSET) {
3246     /* note this is really signed */
3247     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3248       goto fail;
3249     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3250     /* default base offset = first byte of moof */
3251     if (*base_offset == -1) {
3252       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3253       *base_offset = moof_offset;
3254     }
3255     *running_offset = *base_offset + data_offset;
3256   } else {
3257     /* if no offset at all, that would mean data starts at moof start,
3258      * which is a bit wrong and is ismv crappy way, so compensate
3259      * assuming data is in mdat following moof */
3260     if (*base_offset == -1) {
3261       *base_offset = moof_offset + moof_length + 8;
3262       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3263       ismv = TRUE;
3264     }
3265     if (*running_offset == -1)
3266       *running_offset = *base_offset;
3267   }
3268
3269   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3270       *running_offset);
3271   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3272       data_offset, flags, samples_count);
3273
3274   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3275     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3276       GST_DEBUG_OBJECT (qtdemux,
3277           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3278       flags ^= TR_FIRST_SAMPLE_FLAGS;
3279     } else {
3280       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3281         goto fail;
3282       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3283     }
3284   }
3285
3286   /* FIXME ? spec says other bits should also be checked to determine
3287    * entry size (and prefix size for that matter) */
3288   entry_size = 0;
3289   dur_offset = size_offset = 0;
3290   if (flags & TR_SAMPLE_DURATION) {
3291     GST_LOG_OBJECT (qtdemux, "entry duration present");
3292     dur_offset = entry_size;
3293     entry_size += 4;
3294   }
3295   if (flags & TR_SAMPLE_SIZE) {
3296     GST_LOG_OBJECT (qtdemux, "entry size present");
3297     size_offset = entry_size;
3298     entry_size += 4;
3299   }
3300   if (flags & TR_SAMPLE_FLAGS) {
3301     GST_LOG_OBJECT (qtdemux, "entry flags present");
3302     flags_offset = entry_size;
3303     entry_size += 4;
3304   }
3305   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3306     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3307     ct_offset = entry_size;
3308     entry_size += 4;
3309   }
3310
3311   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3312     goto fail;
3313   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3314
3315   if (stream->n_samples + samples_count >=
3316       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3317     goto index_too_big;
3318
3319   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3320       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3321       (stream->n_samples + samples_count) *
3322       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3323
3324   /* create a new array of samples if it's the first sample parsed */
3325   if (stream->n_samples == 0) {
3326     g_assert (stream->samples == NULL);
3327     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3328     /* or try to reallocate it with space enough to insert the new samples */
3329   } else
3330     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3331         stream->n_samples + samples_count);
3332   if (stream->samples == NULL)
3333     goto out_of_memory;
3334
3335   if (qtdemux->fragment_start != -1) {
3336     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3337     qtdemux->fragment_start = -1;
3338   } else {
3339     if (stream->n_samples == 0) {
3340       if (decode_ts > 0) {
3341         timestamp = decode_ts;
3342       } else if (stream->pending_seek != NULL) {
3343         /* if we don't have a timestamp from a tfdt box, we'll use the one
3344          * from the mfra seek table */
3345         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3346             GST_TIME_ARGS (stream->pending_seek->ts));
3347
3348         /* FIXME: this is not fully correct, the timestamp refers to the random
3349          * access sample refered to in the tfra entry, which may not necessarily
3350          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3351         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3352       } else {
3353         timestamp = 0;
3354       }
3355
3356       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3357       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3358           GST_TIME_ARGS (gst_ts));
3359     } else {
3360       /* subsequent fragments extend stream */
3361       timestamp =
3362           stream->samples[stream->n_samples - 1].timestamp +
3363           stream->samples[stream->n_samples - 1].duration;
3364
3365       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3366        * difference (1 sec.) between decode_ts and timestamp, prefer the
3367        * former */
3368       if (has_tfdt && !qtdemux->upstream_format_is_time
3369           && ABSDIFF (decode_ts, timestamp) >
3370           MAX (stream->duration_last_moof / 2,
3371               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3372         GST_INFO_OBJECT (qtdemux,
3373             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3374             ") are significantly different (more than %" GST_TIME_FORMAT
3375             "), using decode_ts",
3376             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3377             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3378             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3379                     MAX (stream->duration_last_moof / 2,
3380                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3381         timestamp = decode_ts;
3382       }
3383
3384       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3385       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3386           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3387     }
3388   }
3389
3390   initial_offset = *running_offset;
3391
3392   sample = stream->samples + stream->n_samples;
3393   for (i = 0; i < samples_count; i++) {
3394     guint32 dur, size, sflags, ct;
3395
3396     /* first read sample data */
3397     if (flags & TR_SAMPLE_DURATION) {
3398       dur = QT_UINT32 (data + dur_offset);
3399     } else {
3400       dur = d_sample_duration;
3401     }
3402     if (flags & TR_SAMPLE_SIZE) {
3403       size = QT_UINT32 (data + size_offset);
3404     } else {
3405       size = d_sample_size;
3406     }
3407     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3408       if (i == 0) {
3409         sflags = first_flags;
3410       } else {
3411         sflags = d_sample_flags;
3412       }
3413     } else if (flags & TR_SAMPLE_FLAGS) {
3414       sflags = QT_UINT32 (data + flags_offset);
3415     } else {
3416       sflags = d_sample_flags;
3417     }
3418     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3419       ct = QT_UINT32 (data + ct_offset);
3420     } else {
3421       ct = 0;
3422     }
3423     data += entry_size;
3424
3425     /* fill the sample information */
3426     sample->offset = *running_offset;
3427     sample->pts_offset = ct;
3428     sample->size = size;
3429     sample->timestamp = timestamp;
3430     sample->duration = dur;
3431     /* sample-is-difference-sample */
3432     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3433      * now idea how it relates to bitfield other than massive LE/BE confusion */
3434     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3435     *running_offset += size;
3436     timestamp += dur;
3437     stream->duration_moof += dur;
3438     sample++;
3439   }
3440
3441   /* Update total duration if needed */
3442   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3443
3444   /* Pre-emptively figure out size of mdat based on trun information.
3445    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3446    * size, else we will still be able to use this when dealing with gap'ed
3447    * input */
3448   qtdemux->mdatleft = *running_offset - initial_offset;
3449   qtdemux->mdatoffset = initial_offset;
3450   qtdemux->mdatsize = qtdemux->mdatleft;
3451
3452   stream->n_samples += samples_count;
3453   stream->n_samples_moof += samples_count;
3454
3455   if (stream->pending_seek != NULL)
3456     stream->pending_seek = NULL;
3457
3458   return TRUE;
3459
3460 fail:
3461   {
3462     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3463     return FALSE;
3464   }
3465 out_of_memory:
3466   {
3467     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3468         stream->n_samples);
3469     return FALSE;
3470   }
3471 index_too_big:
3472   {
3473     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3474         "be larger than %uMB (broken file?)", stream->n_samples,
3475         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3476     return FALSE;
3477   }
3478 }
3479
3480 /* find stream with @id */
3481 static inline QtDemuxStream *
3482 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3483 {
3484   QtDemuxStream *stream;
3485   gint i;
3486
3487   /* check */
3488   if (G_UNLIKELY (!id)) {
3489     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3490     return NULL;
3491   }
3492
3493   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3494     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3495     if (stream->track_id == id)
3496       return stream;
3497   }
3498   if (qtdemux->mss_mode) {
3499     /* mss should have only 1 stream anyway */
3500     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3501   }
3502
3503   return NULL;
3504 }
3505
3506 static gboolean
3507 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3508     guint32 * fragment_number)
3509 {
3510   if (!gst_byte_reader_skip (mfhd, 4))
3511     goto fail;
3512   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3513     goto fail;
3514   return TRUE;
3515 fail:
3516   {
3517     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3518     return FALSE;
3519   }
3520 }
3521
3522 static gboolean
3523 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3524     QtDemuxStream ** stream, guint32 * default_sample_duration,
3525     guint32 * default_sample_size, guint32 * default_sample_flags,
3526     gint64 * base_offset)
3527 {
3528   guint32 flags = 0;
3529   guint32 track_id = 0;
3530
3531   if (!gst_byte_reader_skip (tfhd, 1) ||
3532       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3533     goto invalid_track;
3534
3535   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3536     goto invalid_track;
3537
3538   *stream = qtdemux_find_stream (qtdemux, track_id);
3539   if (G_UNLIKELY (!*stream))
3540     goto unknown_stream;
3541
3542   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3543     *base_offset = qtdemux->moof_offset;
3544
3545   if (flags & TF_BASE_DATA_OFFSET)
3546     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3547       goto invalid_track;
3548
3549   /* obtain stream defaults */
3550   qtdemux_parse_trex (qtdemux, *stream,
3551       default_sample_duration, default_sample_size, default_sample_flags);
3552
3553   (*stream)->stsd_sample_description_id =
3554       (*stream)->def_sample_description_index - 1;
3555
3556   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3557     guint32 sample_description_index;
3558     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3559       goto invalid_track;
3560     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3561   }
3562
3563   if (qtdemux->mss_mode) {
3564     /* mss has no stsd entry */
3565     (*stream)->stsd_sample_description_id = 0;
3566   }
3567
3568   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3569     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3570       goto invalid_track;
3571
3572   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3573     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3574       goto invalid_track;
3575
3576   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3577     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3578       goto invalid_track;
3579
3580   return TRUE;
3581
3582 invalid_track:
3583   {
3584     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3585     return FALSE;
3586   }
3587 unknown_stream:
3588   {
3589     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3590     return TRUE;
3591   }
3592 }
3593
3594 static gboolean
3595 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3596     guint64 * decode_time)
3597 {
3598   guint32 version = 0;
3599
3600   if (!gst_byte_reader_get_uint32_be (br, &version))
3601     return FALSE;
3602
3603   version >>= 24;
3604   if (version == 1) {
3605     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3606       goto failed;
3607   } else {
3608     guint32 dec_time = 0;
3609     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3610       goto failed;
3611     *decode_time = dec_time;
3612   }
3613
3614   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3615       *decode_time);
3616
3617   return TRUE;
3618
3619 failed:
3620   {
3621     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3622     return FALSE;
3623   }
3624 }
3625
3626 /* Returns a pointer to a GstStructure containing the properties of
3627  * the stream sample identified by @sample_index. The caller must unref
3628  * the returned object after use. Returns NULL if unsuccessful. */
3629 static GstStructure *
3630 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3631     QtDemuxStream * stream, guint sample_index)
3632 {
3633   QtDemuxCencSampleSetInfo *info = NULL;
3634
3635   g_return_val_if_fail (stream != NULL, NULL);
3636   g_return_val_if_fail (stream->protected, NULL);
3637   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3638
3639   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3640
3641   /* Currently, cenc properties for groups of samples are not supported, so
3642    * simply return a copy of the default sample properties */
3643   return gst_structure_copy (info->default_properties);
3644 }
3645
3646 /* Parses the sizes of sample auxiliary information contained within a stream,
3647  * as given in a saiz box. Returns array of sample_count guint8 size values,
3648  * or NULL on failure */
3649 static guint8 *
3650 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3651     GstByteReader * br, guint32 * sample_count)
3652 {
3653   guint32 flags = 0;
3654   guint8 *info_sizes;
3655   guint8 default_info_size;
3656
3657   g_return_val_if_fail (qtdemux != NULL, NULL);
3658   g_return_val_if_fail (stream != NULL, NULL);
3659   g_return_val_if_fail (br != NULL, NULL);
3660   g_return_val_if_fail (sample_count != NULL, NULL);
3661
3662   if (!gst_byte_reader_get_uint32_be (br, &flags))
3663     return NULL;
3664
3665   if (flags & 0x1) {
3666     /* aux_info_type and aux_info_type_parameter are ignored */
3667     if (!gst_byte_reader_skip (br, 8))
3668       return NULL;
3669   }
3670
3671   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3672     return NULL;
3673   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3674
3675   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3676     return NULL;
3677   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3678
3679
3680   if (default_info_size == 0) {
3681     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3682       return NULL;
3683     }
3684   } else {
3685     info_sizes = g_new (guint8, *sample_count);
3686     memset (info_sizes, default_info_size, *sample_count);
3687   }
3688
3689   return info_sizes;
3690 }
3691
3692 /* Parses the offset of sample auxiliary information contained within a stream,
3693  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3694 static gboolean
3695 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3696     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3697     guint64 * offset)
3698 {
3699   guint8 version = 0;
3700   guint32 flags = 0;
3701   guint32 aux_info_type = 0;
3702   guint32 aux_info_type_parameter = 0;
3703   guint32 entry_count;
3704   guint32 off_32;
3705   guint64 off_64;
3706   const guint8 *aux_info_type_data = NULL;
3707
3708   g_return_val_if_fail (qtdemux != NULL, FALSE);
3709   g_return_val_if_fail (stream != NULL, FALSE);
3710   g_return_val_if_fail (br != NULL, FALSE);
3711   g_return_val_if_fail (offset != NULL, FALSE);
3712
3713   if (!gst_byte_reader_get_uint8 (br, &version))
3714     return FALSE;
3715
3716   if (!gst_byte_reader_get_uint24_be (br, &flags))
3717     return FALSE;
3718
3719   if (flags & 0x1) {
3720
3721     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3722       return FALSE;
3723     aux_info_type = QT_FOURCC (aux_info_type_data);
3724
3725     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3726       return FALSE;
3727   } else if (stream->protected) {
3728     aux_info_type = stream->protection_scheme_type;
3729   } else {
3730     aux_info_type = CUR_STREAM (stream)->fourcc;
3731   }
3732
3733   if (info_type)
3734     *info_type = aux_info_type;
3735   if (info_type_parameter)
3736     *info_type_parameter = aux_info_type_parameter;
3737
3738   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3739       "aux_info_type_parameter:  %#06x",
3740       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3741
3742   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3743     return FALSE;
3744
3745   if (entry_count != 1) {
3746     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3747     return FALSE;
3748   }
3749
3750   if (version == 0) {
3751     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3752       return FALSE;
3753     *offset = (guint64) off_32;
3754   } else {
3755     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3756       return FALSE;
3757     *offset = off_64;
3758   }
3759
3760   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3761   return TRUE;
3762 }
3763
3764 static void
3765 qtdemux_gst_structure_free (GstStructure * gststructure)
3766 {
3767   if (gststructure) {
3768     gst_structure_free (gststructure);
3769   }
3770 }
3771
3772 /* Parses auxiliary information relating to samples protected using
3773  * Common Encryption (cenc); the format of this information
3774  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3775  * otherwise. */
3776 static gboolean
3777 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3778     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3779 {
3780   QtDemuxCencSampleSetInfo *ss_info = NULL;
3781   guint8 size;
3782   gint i;
3783   GPtrArray *old_crypto_info = NULL;
3784   guint old_entries = 0;
3785
3786   g_return_val_if_fail (qtdemux != NULL, FALSE);
3787   g_return_val_if_fail (stream != NULL, FALSE);
3788   g_return_val_if_fail (br != NULL, FALSE);
3789   g_return_val_if_fail (stream->protected, FALSE);
3790   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3791
3792   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3793
3794   if (ss_info->crypto_info) {
3795     old_crypto_info = ss_info->crypto_info;
3796     /* Count number of non-null entries remaining at the tail end */
3797     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3798       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3799         break;
3800       old_entries++;
3801     }
3802   }
3803
3804   ss_info->crypto_info =
3805       g_ptr_array_new_full (sample_count + old_entries,
3806       (GDestroyNotify) qtdemux_gst_structure_free);
3807
3808   /* We preserve old entries because we parse the next moof in advance
3809    * of consuming all samples from the previous moof, and otherwise
3810    * we'd discard the corresponding crypto info for the samples
3811    * from the previous fragment. */
3812   if (old_entries) {
3813     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3814         old_entries);
3815     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3816       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3817               i));
3818       g_ptr_array_index (old_crypto_info, i) = NULL;
3819     }
3820   }
3821
3822   if (old_crypto_info) {
3823     /* Everything now belongs to the new array */
3824     g_ptr_array_free (old_crypto_info, TRUE);
3825   }
3826
3827   for (i = 0; i < sample_count; ++i) {
3828     GstStructure *properties;
3829     guint16 n_subsamples = 0;
3830     guint8 *data;
3831     guint iv_size;
3832     GstBuffer *buf;
3833     gboolean could_read_iv;
3834
3835     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3836     if (properties == NULL) {
3837       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3838       return FALSE;
3839     }
3840     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3841       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3842       gst_structure_free (properties);
3843       return FALSE;
3844     }
3845     could_read_iv =
3846         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3847     if (could_read_iv) {
3848       buf = gst_buffer_new_wrapped (data, iv_size);
3849       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3850       gst_buffer_unref (buf);
3851     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3852       const GValue *constant_iv_size_value =
3853           gst_structure_get_value (properties, "constant_iv_size");
3854       const GValue *constant_iv_value =
3855           gst_structure_get_value (properties, "iv");
3856       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3857         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3858         gst_structure_free (properties);
3859         return FALSE;
3860       }
3861       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3862       gst_structure_remove_field (properties, "constant_iv_size");
3863     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3864       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3865       gst_structure_free (properties);
3866       return FALSE;
3867     }
3868     size = info_sizes[i];
3869     if (size > iv_size) {
3870       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3871           || !(n_subsamples > 0)) {
3872         gst_structure_free (properties);
3873         GST_ERROR_OBJECT (qtdemux,
3874             "failed to get subsample count for sample %u", i);
3875         return FALSE;
3876       }
3877       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3878       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3879         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3880             i);
3881         gst_structure_free (properties);
3882         return FALSE;
3883       }
3884       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3885       if (!buf) {
3886         gst_structure_free (properties);
3887         return FALSE;
3888       }
3889       gst_structure_set (properties,
3890           "subsample_count", G_TYPE_UINT, n_subsamples,
3891           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3892       gst_buffer_unref (buf);
3893     } else {
3894       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3895     }
3896     g_ptr_array_add (ss_info->crypto_info, properties);
3897   }
3898   return TRUE;
3899 }
3900
3901 /* Converts a UUID in raw byte form to a string representation, as defined in
3902  * RFC 4122. The caller takes ownership of the returned string and is
3903  * responsible for freeing it after use. */
3904 static gchar *
3905 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3906 {
3907   const guint8 *uuid = (const guint8 *) uuid_bytes;
3908
3909   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3910       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3911       uuid[0], uuid[1], uuid[2], uuid[3],
3912       uuid[4], uuid[5], uuid[6], uuid[7],
3913       uuid[8], uuid[9], uuid[10], uuid[11],
3914       uuid[12], uuid[13], uuid[14], uuid[15]);
3915 }
3916
3917 /* Parses a Protection System Specific Header box (pssh), as defined in the
3918  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3919  * information needed by a specific content protection system in order to
3920  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3921  * otherwise. */
3922 static gboolean
3923 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3924 {
3925   gchar *sysid_string;
3926   guint32 pssh_size = QT_UINT32 (node->data);
3927   GstBuffer *pssh = NULL;
3928   GstEvent *event = NULL;
3929   guint32 parent_box_type;
3930   gint i;
3931
3932   if (G_UNLIKELY (pssh_size < 32U)) {
3933     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3934     return FALSE;
3935   }
3936
3937   sysid_string =
3938       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3939
3940   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3941
3942   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3943   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3944       gst_buffer_get_size (pssh));
3945
3946   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3947
3948   /* Push an event containing the pssh box onto the queues of all streams. */
3949   event = gst_event_new_protection (sysid_string, pssh,
3950       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3951   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3952     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3953     GST_TRACE_OBJECT (qtdemux,
3954         "adding protection event for stream %s and system %s",
3955         stream->stream_id, sysid_string);
3956     g_queue_push_tail (&stream->protection_scheme_event_queue,
3957         gst_event_ref (event));
3958   }
3959   g_free (sysid_string);
3960   gst_event_unref (event);
3961   gst_buffer_unref (pssh);
3962   return TRUE;
3963 }
3964
3965 static gboolean
3966 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3967     guint64 moof_offset, QtDemuxStream * stream)
3968 {
3969   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3970   GNode *uuid_node;
3971   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3972   GNode *saiz_node, *saio_node, *pssh_node;
3973   GstByteReader saiz_data, saio_data;
3974   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3975   gint64 base_offset, running_offset;
3976   guint32 frag_num;
3977   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3978
3979   /* NOTE @stream ignored */
3980
3981   moof_node = g_node_new ((guint8 *) buffer);
3982   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3983   qtdemux_node_dump (qtdemux, moof_node);
3984
3985   /* Get fragment number from mfhd and check it's valid */
3986   mfhd_node =
3987       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3988   if (mfhd_node == NULL)
3989     goto missing_mfhd;
3990   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3991     goto fail;
3992   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3993
3994   /* unknown base_offset to start with */
3995   base_offset = running_offset = -1;
3996   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3997   while (traf_node) {
3998     guint64 decode_time = 0;
3999
4000     /* Fragment Header node */
4001     tfhd_node =
4002         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4003         &tfhd_data);
4004     if (!tfhd_node)
4005       goto missing_tfhd;
4006     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4007             &ds_size, &ds_flags, &base_offset))
4008       goto missing_tfhd;
4009
4010     /* The following code assumes at most a single set of sample auxiliary
4011      * data in the fragment (consisting of a saiz box and a corresponding saio
4012      * box); in theory, however, there could be multiple sets of sample
4013      * auxiliary data in a fragment. */
4014     saiz_node =
4015         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4016         &saiz_data);
4017     if (saiz_node) {
4018       guint32 info_type = 0;
4019       guint64 offset = 0;
4020       guint32 info_type_parameter = 0;
4021
4022       g_free (qtdemux->cenc_aux_info_sizes);
4023
4024       qtdemux->cenc_aux_info_sizes =
4025           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4026           &qtdemux->cenc_aux_sample_count);
4027       if (qtdemux->cenc_aux_info_sizes == NULL) {
4028         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4029         goto fail;
4030       }
4031       saio_node =
4032           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4033           &saio_data);
4034       if (!saio_node) {
4035         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4036         g_free (qtdemux->cenc_aux_info_sizes);
4037         qtdemux->cenc_aux_info_sizes = NULL;
4038         goto fail;
4039       }
4040
4041       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4042                   &info_type, &info_type_parameter, &offset))) {
4043         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4044         g_free (qtdemux->cenc_aux_info_sizes);
4045         qtdemux->cenc_aux_info_sizes = NULL;
4046         goto fail;
4047       }
4048       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4049         offset += (guint64) (base_offset - qtdemux->moof_offset);
4050       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4051           && info_type_parameter == 0U) {
4052         GstByteReader br;
4053         if (offset > length) {
4054           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4055           qtdemux->cenc_aux_info_offset = offset;
4056         } else {
4057           gst_byte_reader_init (&br, buffer + offset, length - offset);
4058           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4059                   qtdemux->cenc_aux_info_sizes,
4060                   qtdemux->cenc_aux_sample_count)) {
4061             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4062             g_free (qtdemux->cenc_aux_info_sizes);
4063             qtdemux->cenc_aux_info_sizes = NULL;
4064             goto fail;
4065           }
4066         }
4067       }
4068     }
4069
4070     tfdt_node =
4071         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4072         &tfdt_data);
4073     if (tfdt_node) {
4074       /* We'll use decode_time to interpolate timestamps
4075        * in case the input timestamps are missing */
4076       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4077
4078       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4079           " (%" GST_TIME_FORMAT ")", decode_time,
4080           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4081                   decode_time) : GST_CLOCK_TIME_NONE));
4082
4083       /* Discard the fragment buffer timestamp info to avoid using it.
4084        * Rely on tfdt instead as it is more accurate than the timestamp
4085        * that is fetched from a manifest/playlist and is usually
4086        * less accurate. */
4087       qtdemux->fragment_start = -1;
4088     }
4089
4090     if (G_UNLIKELY (!stream)) {
4091       /* we lost track of offset, we'll need to regain it,
4092        * but can delay complaining until later or avoid doing so altogether */
4093       base_offset = -2;
4094       goto next;
4095     }
4096     if (G_UNLIKELY (base_offset < -1))
4097       goto lost_offset;
4098
4099     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4100
4101     if (!qtdemux->pullbased) {
4102       /* Sample tables can grow enough to be problematic if the system memory
4103        * is very low (e.g. embedded devices) and the videos very long
4104        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4105        * Fortunately, we can easily discard them for each new fragment when
4106        * we know qtdemux will not receive seeks outside of the current fragment.
4107        * adaptivedemux honors this assumption.
4108        * This optimization is also useful for applications that use qtdemux as
4109        * a push-based simple demuxer, like Media Source Extensions. */
4110       gst_qtdemux_stream_flush_samples_data (stream);
4111     }
4112
4113     /* initialise moof sample data */
4114     stream->n_samples_moof = 0;
4115     stream->duration_last_moof = stream->duration_moof;
4116     stream->duration_moof = 0;
4117
4118     /* Track Run node */
4119     trun_node =
4120         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4121         &trun_data);
4122     while (trun_node) {
4123       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4124           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4125           &running_offset, decode_time, (tfdt_node != NULL));
4126       /* iterate all siblings */
4127       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4128           &trun_data);
4129     }
4130
4131     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4132     if (uuid_node) {
4133       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4134       guint32 box_length = QT_UINT32 (uuid_buffer);
4135
4136       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4137     }
4138
4139     /* if no new base_offset provided for next traf,
4140      * base is end of current traf */
4141     base_offset = running_offset;
4142     running_offset = -1;
4143
4144     if (stream->n_samples_moof && stream->duration_moof)
4145       stream->new_caps = TRUE;
4146
4147   next:
4148     /* iterate all siblings */
4149     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4150   }
4151
4152   /* parse any protection system info */
4153   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4154   while (pssh_node) {
4155     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4156     qtdemux_parse_pssh (qtdemux, pssh_node);
4157     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4158   }
4159
4160   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4161       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4162       && min_dts != 0) {
4163     /* Unless the user has explicitly requested another seek, perform an
4164      * internal seek to the time specified in the tfdt.
4165      *
4166      * This way if the user opens a file where the first tfdt is 1 hour
4167      * into the presentation, they will not have to wait 1 hour for run
4168      * time to catch up and actual playback to start. */
4169     gint i;
4170
4171     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4172         "performing an internal seek to %" GST_TIME_FORMAT,
4173         GST_TIME_ARGS (min_dts));
4174
4175     qtdemux->segment.start = min_dts;
4176     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4177
4178     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4179       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4180       stream->time_position = min_dts;
4181     }
4182
4183     /* Before this code was run a segment was already sent when the moov was
4184      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4185      * be emitted after a moov, and we can emit a second segment anyway for
4186      * special cases like this. */
4187     qtdemux->need_segment = TRUE;
4188   }
4189
4190   qtdemux->first_moof_already_parsed = TRUE;
4191
4192   g_node_destroy (moof_node);
4193   return TRUE;
4194
4195 missing_tfhd:
4196   {
4197     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4198     goto fail;
4199   }
4200 missing_mfhd:
4201   {
4202     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4203     goto fail;
4204   }
4205 lost_offset:
4206   {
4207     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4208     goto fail;
4209   }
4210 fail:
4211   {
4212     g_node_destroy (moof_node);
4213     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4214         (_("This file is corrupt and cannot be played.")), (NULL));
4215     return FALSE;
4216   }
4217 }
4218
4219 #if 0
4220 /* might be used if some day we actually use mfra & co
4221  * for random access to fragments,
4222  * but that will require quite some modifications and much less relying
4223  * on a sample array */
4224 #endif
4225
4226 static gboolean
4227 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4228 {
4229   QtDemuxStream *stream;
4230   guint32 ver_flags, track_id, len, num_entries, i;
4231   guint value_size, traf_size, trun_size, sample_size;
4232   guint64 time = 0, moof_offset = 0;
4233 #if 0
4234   GstBuffer *buf = NULL;
4235   GstFlowReturn ret;
4236 #endif
4237   GstByteReader tfra;
4238
4239   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4240
4241   if (!gst_byte_reader_skip (&tfra, 8))
4242     return FALSE;
4243
4244   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4245     return FALSE;
4246
4247   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4248       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4249       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4250     return FALSE;
4251
4252   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4253
4254   stream = qtdemux_find_stream (qtdemux, track_id);
4255   if (stream == NULL)
4256     goto unknown_trackid;
4257
4258   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4259   sample_size = (len & 3) + 1;
4260   trun_size = ((len & 12) >> 2) + 1;
4261   traf_size = ((len & 48) >> 4) + 1;
4262
4263   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4264       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4265
4266   if (num_entries == 0)
4267     goto no_samples;
4268
4269   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4270           value_size + value_size + traf_size + trun_size + sample_size))
4271     goto corrupt_file;
4272
4273   g_free (stream->ra_entries);
4274   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4275   stream->n_ra_entries = num_entries;
4276
4277   for (i = 0; i < num_entries; i++) {
4278     qt_atom_parser_get_offset (&tfra, value_size, &time);
4279     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4280     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4281     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4282     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4283
4284     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4285
4286     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4287         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4288
4289     stream->ra_entries[i].ts = time;
4290     stream->ra_entries[i].moof_offset = moof_offset;
4291
4292     /* don't want to go through the entire file and read all moofs at startup */
4293 #if 0
4294     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4295     if (ret != GST_FLOW_OK)
4296       goto corrupt_file;
4297     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4298         moof_offset, stream);
4299     gst_buffer_unref (buf);
4300 #endif
4301   }
4302
4303   check_update_duration (qtdemux, time);
4304
4305   return TRUE;
4306
4307 /* ERRORS */
4308 unknown_trackid:
4309   {
4310     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4311     return FALSE;
4312   }
4313 corrupt_file:
4314   {
4315     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4316     return FALSE;
4317   }
4318 no_samples:
4319   {
4320     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4321     return FALSE;
4322   }
4323 }
4324
4325 static gboolean
4326 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4327 {
4328   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4329   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4330   GstBuffer *mfro = NULL, *mfra = NULL;
4331   GstFlowReturn flow;
4332   gboolean ret = FALSE;
4333   GNode *mfra_node, *tfra_node;
4334   guint64 mfra_offset = 0;
4335   guint32 fourcc, mfra_size;
4336   gint64 len;
4337
4338   /* query upstream size in bytes */
4339   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4340     goto size_query_failed;
4341
4342   /* mfro box should be at the very end of the file */
4343   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4344   if (flow != GST_FLOW_OK)
4345     goto exit;
4346
4347   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4348
4349   fourcc = QT_FOURCC (mfro_map.data + 4);
4350   if (fourcc != FOURCC_mfro)
4351     goto exit;
4352
4353   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4354   if (mfro_map.size < 16)
4355     goto invalid_mfro_size;
4356
4357   mfra_size = QT_UINT32 (mfro_map.data + 12);
4358   if (mfra_size >= len)
4359     goto invalid_mfra_size;
4360
4361   mfra_offset = len - mfra_size;
4362
4363   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4364       mfra_offset, mfra_size);
4365
4366   /* now get and parse mfra box */
4367   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4368   if (flow != GST_FLOW_OK)
4369     goto broken_file;
4370
4371   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4372
4373   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4374   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4375
4376   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4377
4378   while (tfra_node) {
4379     qtdemux_parse_tfra (qtdemux, tfra_node);
4380     /* iterate all siblings */
4381     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4382   }
4383   g_node_destroy (mfra_node);
4384
4385   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4386   ret = TRUE;
4387
4388 exit:
4389
4390   if (mfro) {
4391     if (mfro_map.memory != NULL)
4392       gst_buffer_unmap (mfro, &mfro_map);
4393     gst_buffer_unref (mfro);
4394   }
4395   if (mfra) {
4396     if (mfra_map.memory != NULL)
4397       gst_buffer_unmap (mfra, &mfra_map);
4398     gst_buffer_unref (mfra);
4399   }
4400   return ret;
4401
4402 /* ERRORS */
4403 size_query_failed:
4404   {
4405     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4406     goto exit;
4407   }
4408 invalid_mfro_size:
4409   {
4410     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4411     goto exit;
4412   }
4413 invalid_mfra_size:
4414   {
4415     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4416     goto exit;
4417   }
4418 broken_file:
4419   {
4420     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4421     goto exit;
4422   }
4423 }
4424
4425 static guint64
4426 add_offset (guint64 offset, guint64 advance)
4427 {
4428   /* Avoid 64-bit overflow by clamping */
4429   if (offset > G_MAXUINT64 - advance)
4430     return G_MAXUINT64;
4431   return offset + advance;
4432 }
4433
4434 static GstFlowReturn
4435 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4436 {
4437   guint64 length = 0;
4438   guint32 fourcc = 0;
4439   GstBuffer *buf = NULL;
4440   GstFlowReturn ret = GST_FLOW_OK;
4441   guint64 cur_offset = qtdemux->offset;
4442   GstMapInfo map;
4443
4444   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4445   if (G_UNLIKELY (ret != GST_FLOW_OK))
4446     goto beach;
4447   gst_buffer_map (buf, &map, GST_MAP_READ);
4448   if (G_LIKELY (map.size >= 8))
4449     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4450   gst_buffer_unmap (buf, &map);
4451   gst_buffer_unref (buf);
4452
4453   /* maybe we already got most we needed, so only consider this eof */
4454   if (G_UNLIKELY (length == 0)) {
4455     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4456         (_("Invalid atom size.")),
4457         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4458             GST_FOURCC_ARGS (fourcc)));
4459     ret = GST_FLOW_EOS;
4460     goto beach;
4461   }
4462
4463   switch (fourcc) {
4464     case FOURCC_moof:
4465       /* record for later parsing when needed */
4466       if (!qtdemux->moof_offset) {
4467         qtdemux->moof_offset = qtdemux->offset;
4468       }
4469       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4470         /* FIXME */
4471       } else {
4472         qtdemux->offset += length;      /* skip moof and keep going */
4473       }
4474       if (qtdemux->got_moov) {
4475         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4476         ret = GST_FLOW_EOS;
4477         goto beach;
4478       }
4479       break;
4480     case FOURCC_mdat:
4481     case FOURCC_free:
4482     case FOURCC_skip:
4483     case FOURCC_wide:
4484     case FOURCC_PICT:
4485     case FOURCC_pnot:
4486     {
4487       GST_LOG_OBJECT (qtdemux,
4488           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4489           GST_FOURCC_ARGS (fourcc), cur_offset);
4490       qtdemux->offset = add_offset (qtdemux->offset, length);
4491       break;
4492     }
4493     case FOURCC_moov:
4494     {
4495       GstBuffer *moov = NULL;
4496
4497       if (qtdemux->got_moov) {
4498         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4499         qtdemux->offset = add_offset (qtdemux->offset, length);
4500         goto beach;
4501       }
4502
4503       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4504       if (ret != GST_FLOW_OK)
4505         goto beach;
4506       gst_buffer_map (moov, &map, GST_MAP_READ);
4507
4508       if (length != map.size) {
4509         /* Some files have a 'moov' atom at the end of the file which contains
4510          * a terminal 'free' atom where the body of the atom is missing.
4511          * Check for, and permit, this special case.
4512          */
4513         if (map.size >= 8) {
4514           guint8 *final_data = map.data + (map.size - 8);
4515           guint32 final_length = QT_UINT32 (final_data);
4516           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4517
4518           if (final_fourcc == FOURCC_free
4519               && map.size + final_length - 8 == length) {
4520             /* Ok, we've found that special case. Allocate a new buffer with
4521              * that free atom actually present. */
4522             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4523             gst_buffer_fill (newmoov, 0, map.data, map.size);
4524             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4525             gst_buffer_unmap (moov, &map);
4526             gst_buffer_unref (moov);
4527             moov = newmoov;
4528             gst_buffer_map (moov, &map, GST_MAP_READ);
4529           }
4530         }
4531       }
4532
4533       if (length != map.size) {
4534         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4535             (_("This file is incomplete and cannot be played.")),
4536             ("We got less than expected (received %" G_GSIZE_FORMAT
4537                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4538                 (guint) length, cur_offset));
4539         gst_buffer_unmap (moov, &map);
4540         gst_buffer_unref (moov);
4541         ret = GST_FLOW_ERROR;
4542         goto beach;
4543       }
4544       qtdemux->offset += length;
4545
4546       qtdemux_parse_moov (qtdemux, map.data, length);
4547       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4548
4549       qtdemux_parse_tree (qtdemux);
4550       if (qtdemux->moov_node_compressed) {
4551         g_node_destroy (qtdemux->moov_node_compressed);
4552         g_free (qtdemux->moov_node->data);
4553       }
4554       qtdemux->moov_node_compressed = NULL;
4555       g_node_destroy (qtdemux->moov_node);
4556       qtdemux->moov_node = NULL;
4557       gst_buffer_unmap (moov, &map);
4558       gst_buffer_unref (moov);
4559       qtdemux->got_moov = TRUE;
4560
4561       break;
4562     }
4563     case FOURCC_ftyp:
4564     {
4565       GstBuffer *ftyp = NULL;
4566
4567       /* extract major brand; might come in handy for ISO vs QT issues */
4568       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4569       if (ret != GST_FLOW_OK)
4570         goto beach;
4571       qtdemux->offset += length;
4572       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4573       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4574       gst_buffer_unmap (ftyp, &map);
4575       gst_buffer_unref (ftyp);
4576       break;
4577     }
4578     case FOURCC_uuid:
4579     {
4580       GstBuffer *uuid = NULL;
4581
4582       /* uuid are extension atoms */
4583       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4584       if (ret != GST_FLOW_OK)
4585         goto beach;
4586       qtdemux->offset += length;
4587       gst_buffer_map (uuid, &map, GST_MAP_READ);
4588       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4589       gst_buffer_unmap (uuid, &map);
4590       gst_buffer_unref (uuid);
4591       break;
4592     }
4593     case FOURCC_sidx:
4594     {
4595       GstBuffer *sidx = NULL;
4596       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4597       if (ret != GST_FLOW_OK)
4598         goto beach;
4599       qtdemux->offset += length;
4600       gst_buffer_map (sidx, &map, GST_MAP_READ);
4601       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4602       gst_buffer_unmap (sidx, &map);
4603       gst_buffer_unref (sidx);
4604       break;
4605     }
4606     default:
4607     {
4608       GstBuffer *unknown = NULL;
4609
4610       GST_LOG_OBJECT (qtdemux,
4611           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4612           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4613           cur_offset);
4614       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4615       if (ret != GST_FLOW_OK)
4616         goto beach;
4617       gst_buffer_map (unknown, &map, GST_MAP_READ);
4618       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4619       gst_buffer_unmap (unknown, &map);
4620       gst_buffer_unref (unknown);
4621       qtdemux->offset += length;
4622       break;
4623     }
4624   }
4625
4626 beach:
4627   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4628     /* digested all data, show what we have */
4629     qtdemux_prepare_streams (qtdemux);
4630     QTDEMUX_EXPOSE_LOCK (qtdemux);
4631     ret = qtdemux_expose_streams (qtdemux);
4632     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4633
4634     qtdemux->state = QTDEMUX_STATE_MOVIE;
4635     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4636         qtdemux->state);
4637     return ret;
4638   }
4639   return ret;
4640 }
4641
4642 /* Seeks to the previous keyframe of the indexed stream and
4643  * aligns other streams with respect to the keyframe timestamp
4644  * of indexed stream. Only called in case of Reverse Playback
4645  */
4646 static GstFlowReturn
4647 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4648 {
4649   guint32 seg_idx = 0, k_index = 0;
4650   guint32 ref_seg_idx, ref_k_index;
4651   GstClockTime k_pos = 0, last_stop = 0;
4652   QtDemuxSegment *seg = NULL;
4653   QtDemuxStream *ref_str = NULL;
4654   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4655   guint64 target_ts;
4656   gint i;
4657
4658   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4659    * and finally align all the other streams on that timestamp with their
4660    * respective keyframes */
4661   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4662     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4663
4664     /* No candidate yet, take the first stream */
4665     if (!ref_str) {
4666       ref_str = str;
4667       continue;
4668     }
4669
4670     /* So that stream has a segment, we prefer video streams */
4671     if (str->subtype == FOURCC_vide) {
4672       ref_str = str;
4673       break;
4674     }
4675   }
4676
4677   if (G_UNLIKELY (!ref_str)) {
4678     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4679     goto eos;
4680   }
4681
4682   if (G_UNLIKELY (!ref_str->from_sample)) {
4683     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4684     goto eos;
4685   }
4686
4687   /* So that stream has been playing from from_sample to to_sample. We will
4688    * get the timestamp of the previous sample and search for a keyframe before
4689    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4690   if (ref_str->subtype == FOURCC_vide) {
4691     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4692         ref_str->from_sample - 1, FALSE);
4693   } else {
4694     if (ref_str->from_sample >= 10)
4695       k_index = ref_str->from_sample - 10;
4696     else
4697       k_index = 0;
4698   }
4699
4700   target_ts =
4701       ref_str->samples[k_index].timestamp +
4702       ref_str->samples[k_index].pts_offset;
4703
4704   /* get current segment for that stream */
4705   seg = &ref_str->segments[ref_str->segment_index];
4706   /* Use segment start in original timescale for comparisons */
4707   seg_media_start_mov = seg->trak_media_start;
4708
4709   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4710       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4711       k_index, target_ts, seg_media_start_mov,
4712       GST_TIME_ARGS (seg->media_start));
4713
4714   /* Crawl back through segments to find the one containing this I frame */
4715   while (target_ts < seg_media_start_mov) {
4716     GST_DEBUG_OBJECT (qtdemux,
4717         "keyframe position (sample %u) is out of segment %u " " target %"
4718         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4719         ref_str->segment_index, target_ts, seg_media_start_mov);
4720
4721     if (G_UNLIKELY (!ref_str->segment_index)) {
4722       /* Reached first segment, let's consider it's EOS */
4723       goto eos;
4724     }
4725     ref_str->segment_index--;
4726     seg = &ref_str->segments[ref_str->segment_index];
4727     /* Use segment start in original timescale for comparisons */
4728     seg_media_start_mov = seg->trak_media_start;
4729   }
4730   /* Calculate time position of the keyframe and where we should stop */
4731   k_pos =
4732       QTSTREAMTIME_TO_GSTTIME (ref_str,
4733       target_ts - seg->trak_media_start) + seg->time;
4734   last_stop =
4735       QTSTREAMTIME_TO_GSTTIME (ref_str,
4736       ref_str->samples[ref_str->from_sample].timestamp -
4737       seg->trak_media_start) + seg->time;
4738
4739   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4740       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4741       k_index, GST_TIME_ARGS (k_pos));
4742
4743   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4744   qtdemux->segment.position = last_stop;
4745   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4746       GST_TIME_ARGS (last_stop));
4747
4748   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4749     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4750     goto eos;
4751   }
4752
4753   ref_seg_idx = ref_str->segment_index;
4754   ref_k_index = k_index;
4755
4756   /* Align them all on this */
4757   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4758     guint32 index = 0;
4759     GstClockTime seg_time = 0;
4760     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4761
4762     /* aligning reference stream again might lead to backing up to yet another
4763      * keyframe (due to timestamp rounding issues),
4764      * potentially putting more load on downstream; so let's try to avoid */
4765     if (str == ref_str) {
4766       seg_idx = ref_seg_idx;
4767       seg = &str->segments[seg_idx];
4768       k_index = ref_k_index;
4769       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4770           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4771     } else {
4772       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4773       GST_DEBUG_OBJECT (qtdemux,
4774           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4775           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4776
4777       /* get segment and time in the segment */
4778       seg = &str->segments[seg_idx];
4779       seg_time = k_pos - seg->time;
4780
4781       /* get the media time in the segment.
4782        * No adjustment for empty "filler" segments */
4783       if (seg->media_start != GST_CLOCK_TIME_NONE)
4784         seg_time += seg->media_start;
4785
4786       /* get the index of the sample with media time */
4787       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4788       GST_DEBUG_OBJECT (qtdemux,
4789           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4790           GST_TIME_ARGS (seg_time), index);
4791
4792       /* find previous keyframe */
4793       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4794     }
4795
4796     /* Remember until where we want to go */
4797     str->to_sample = str->from_sample - 1;
4798     /* Define our time position */
4799     target_ts =
4800         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4801     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4802     if (seg->media_start != GST_CLOCK_TIME_NONE)
4803       str->time_position -= seg->media_start;
4804
4805     /* Now seek back in time */
4806     gst_qtdemux_move_stream (qtdemux, str, k_index);
4807     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4808         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4809         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4810   }
4811
4812   return GST_FLOW_OK;
4813
4814 eos:
4815   return GST_FLOW_EOS;
4816 }
4817
4818 /*
4819  * Gets the current qt segment start, stop and position for the
4820  * given time offset. This is used in update_segment()
4821  */
4822 static void
4823 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4824     QtDemuxStream * stream, GstClockTime offset,
4825     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4826 {
4827   GstClockTime seg_time;
4828   GstClockTime start, stop, time;
4829   QtDemuxSegment *segment;
4830
4831   segment = &stream->segments[stream->segment_index];
4832
4833   /* get time in this segment */
4834   seg_time = (offset - segment->time) * segment->rate;
4835
4836   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4837       GST_TIME_ARGS (seg_time));
4838
4839   if (G_UNLIKELY (seg_time > segment->duration)) {
4840     GST_LOG_OBJECT (stream->pad,
4841         "seg_time > segment->duration %" GST_TIME_FORMAT,
4842         GST_TIME_ARGS (segment->duration));
4843     seg_time = segment->duration;
4844   }
4845
4846   /* qtdemux->segment.stop is in outside-time-realm, whereas
4847    * segment->media_stop is in track-time-realm.
4848    *
4849    * In order to compare the two, we need to bring segment.stop
4850    * into the track-time-realm
4851    *
4852    * FIXME - does this comment still hold? Don't see any conversion here */
4853
4854   stop = qtdemux->segment.stop;
4855   if (stop == GST_CLOCK_TIME_NONE)
4856     stop = qtdemux->segment.duration;
4857   if (stop == GST_CLOCK_TIME_NONE)
4858     stop = segment->media_stop;
4859   else
4860     stop =
4861         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4862
4863   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4864     start = segment->time + seg_time;
4865     time = offset;
4866     stop = start - seg_time + segment->duration;
4867   } else if (qtdemux->segment.rate >= 0) {
4868     start = MIN (segment->media_start + seg_time, stop);
4869     time = offset;
4870   } else {
4871     if (segment->media_start >= qtdemux->segment.start) {
4872       time = segment->time;
4873     } else {
4874       time = segment->time + (qtdemux->segment.start - segment->media_start);
4875     }
4876
4877     start = MAX (segment->media_start, qtdemux->segment.start);
4878     stop = MIN (segment->media_start + seg_time, stop);
4879   }
4880
4881   *_start = start;
4882   *_stop = stop;
4883   *_time = time;
4884 }
4885
4886 /*
4887  * Updates the qt segment used for the stream and pushes a new segment event
4888  * downstream on this stream's pad.
4889  */
4890 static gboolean
4891 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4892     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4893     GstClockTime * _stop)
4894 {
4895   QtDemuxSegment *segment;
4896   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4897   gdouble rate;
4898   GstEvent *event;
4899
4900   /* update the current segment */
4901   stream->segment_index = seg_idx;
4902
4903   /* get the segment */
4904   segment = &stream->segments[seg_idx];
4905
4906   if (G_UNLIKELY (offset < segment->time)) {
4907     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4908         GST_TIME_ARGS (segment->time));
4909     return FALSE;
4910   }
4911
4912   /* segment lies beyond total indicated duration */
4913   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4914           segment->time > qtdemux->segment.duration)) {
4915     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4916         " < segment->time %" GST_TIME_FORMAT,
4917         GST_TIME_ARGS (qtdemux->segment.duration),
4918         GST_TIME_ARGS (segment->time));
4919     return FALSE;
4920   }
4921
4922   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4923       &start, &stop, &time);
4924
4925   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4926       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4927       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4928
4929   /* combine global rate with that of the segment */
4930   rate = segment->rate * qtdemux->segment.rate;
4931
4932   /* Copy flags from main segment */
4933   stream->segment.flags = qtdemux->segment.flags;
4934
4935   /* update the segment values used for clipping */
4936   stream->segment.offset = qtdemux->segment.offset;
4937   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4938   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4939   stream->segment.rate = rate;
4940   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4941       stream->cslg_shift);
4942   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4943       stream->cslg_shift);
4944   stream->segment.time = time;
4945   stream->segment.position = stream->segment.start;
4946
4947   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4948       &stream->segment);
4949
4950   /* now prepare and send the segment */
4951   if (stream->pad) {
4952     event = gst_event_new_segment (&stream->segment);
4953     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4954       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4955     }
4956     gst_pad_push_event (stream->pad, event);
4957     /* assume we can send more data now */
4958     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4959     /* clear to send tags on this pad now */
4960     gst_qtdemux_push_tags (qtdemux, stream);
4961   }
4962
4963   if (_start)
4964     *_start = start;
4965   if (_stop)
4966     *_stop = stop;
4967
4968   return TRUE;
4969 }
4970
4971 /* activate the given segment number @seg_idx of @stream at time @offset.
4972  * @offset is an absolute global position over all the segments.
4973  *
4974  * This will push out a NEWSEGMENT event with the right values and
4975  * position the stream index to the first decodable sample before
4976  * @offset.
4977  */
4978 static gboolean
4979 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4980     guint32 seg_idx, GstClockTime offset)
4981 {
4982   QtDemuxSegment *segment;
4983   guint32 index, kf_index;
4984   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4985
4986   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4987       seg_idx, GST_TIME_ARGS (offset));
4988
4989   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4990           &start, &stop))
4991     return FALSE;
4992
4993   segment = &stream->segments[stream->segment_index];
4994
4995   /* in the fragmented case, we pick a fragment that starts before our
4996    * desired position and rely on downstream to wait for a keyframe
4997    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4998    * tfra entries tells us which trun/sample the key unit is in, but we don't
4999    * make use of this additional information at the moment) */
5000   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5001     stream->to_sample = G_MAXUINT32;
5002     return TRUE;
5003   } else {
5004     /* well, it will be taken care of below */
5005     qtdemux->fragmented_seek_pending = FALSE;
5006     /* FIXME ideally the do_fragmented_seek can be done right here,
5007      * rather than at loop level
5008      * (which might even allow handling edit lists in a fragmented file) */
5009   }
5010
5011   /* We don't need to look for a sample in push-based */
5012   if (!qtdemux->pullbased)
5013     return TRUE;
5014
5015   /* and move to the keyframe before the indicated media time of the
5016    * segment */
5017   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5018     if (qtdemux->segment.rate >= 0) {
5019       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5020       stream->to_sample = G_MAXUINT32;
5021       GST_DEBUG_OBJECT (stream->pad,
5022           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5023           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5024           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5025     } else {
5026       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5027       stream->to_sample = index;
5028       GST_DEBUG_OBJECT (stream->pad,
5029           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5030           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5031           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5032     }
5033   } else {
5034     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5035         "this is an empty segment");
5036     return TRUE;
5037   }
5038
5039   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5040    * encountered an error and printed a message so we return appropriately */
5041   if (index == -1)
5042     return FALSE;
5043
5044   /* we're at the right spot */
5045   if (index == stream->sample_index) {
5046     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5047     return TRUE;
5048   }
5049
5050   /* find keyframe of the target index */
5051   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5052
5053   /* go back two frames to provide lead-in for non-raw audio decoders */
5054   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5055     guint32 lead_in = 2;
5056     guint32 old_index = kf_index;
5057     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5058
5059     if (gst_structure_has_name (s, "audio/mpeg")) {
5060       gint mpegversion;
5061       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5062           && mpegversion == 1) {
5063         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5064         lead_in = 30;
5065       }
5066     }
5067
5068     kf_index = MAX (kf_index, lead_in) - lead_in;
5069     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5070       GST_DEBUG_OBJECT (stream->pad,
5071           "Moving backwards %u frames to ensure sufficient sound lead-in",
5072           old_index - kf_index);
5073     } else {
5074       kf_index = old_index;
5075     }
5076   }
5077
5078   /* if we move forwards, we don't have to go back to the previous
5079    * keyframe since we already sent that. We can also just jump to
5080    * the keyframe right before the target index if there is one. */
5081   if (index > stream->sample_index) {
5082     /* moving forwards check if we move past a keyframe */
5083     if (kf_index > stream->sample_index) {
5084       GST_DEBUG_OBJECT (stream->pad,
5085           "moving forwards to keyframe at %u "
5086           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5087           kf_index,
5088           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5089           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5090       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5091     } else {
5092       GST_DEBUG_OBJECT (stream->pad,
5093           "moving forwards, keyframe at %u "
5094           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5095           kf_index,
5096           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5097           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5098     }
5099   } else {
5100     GST_DEBUG_OBJECT (stream->pad,
5101         "moving backwards to %sframe at %u "
5102         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5103         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5104         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5105         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5106     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5107   }
5108
5109   return TRUE;
5110 }
5111
5112 /* prepare to get the current sample of @stream, getting essential values.
5113  *
5114  * This function will also prepare and send the segment when needed.
5115  *
5116  * Return FALSE if the stream is EOS.
5117  *
5118  * PULL-BASED
5119  */
5120 static gboolean
5121 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5122     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5123     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5124     gboolean * keyframe)
5125 {
5126   QtDemuxSample *sample;
5127   GstClockTime time_position;
5128   guint32 seg_idx;
5129
5130   g_return_val_if_fail (stream != NULL, FALSE);
5131
5132   time_position = stream->time_position;
5133   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5134     goto eos;
5135
5136   seg_idx = stream->segment_index;
5137   if (G_UNLIKELY (seg_idx == -1)) {
5138     /* find segment corresponding to time_position if we are looking
5139      * for a segment. */
5140     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5141   }
5142
5143   /* different segment, activate it, sample_index will be set. */
5144   if (G_UNLIKELY (stream->segment_index != seg_idx))
5145     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5146
5147   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5148               segments[stream->segment_index]))) {
5149     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5150
5151     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5152         " prepare empty sample");
5153
5154     *empty = TRUE;
5155     *pts = *dts = time_position;
5156     *duration = seg->duration - (time_position - seg->time);
5157
5158     return TRUE;
5159   }
5160
5161   *empty = FALSE;
5162
5163   if (stream->sample_index == -1)
5164     stream->sample_index = 0;
5165
5166   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5167       stream->sample_index, stream->n_samples);
5168
5169   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5170     if (!qtdemux->fragmented)
5171       goto eos;
5172
5173     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5174     do {
5175       GstFlowReturn flow;
5176
5177       GST_OBJECT_LOCK (qtdemux);
5178       flow = qtdemux_add_fragmented_samples (qtdemux);
5179       GST_OBJECT_UNLOCK (qtdemux);
5180
5181       if (flow != GST_FLOW_OK)
5182         goto eos;
5183     }
5184     while (stream->sample_index >= stream->n_samples);
5185   }
5186
5187   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5188     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5189         stream->sample_index);
5190     return FALSE;
5191   }
5192
5193   /* now get the info for the sample we're at */
5194   sample = &stream->samples[stream->sample_index];
5195
5196   *dts = QTSAMPLE_DTS (stream, sample);
5197   *pts = QTSAMPLE_PTS (stream, sample);
5198   *offset = sample->offset;
5199   *size = sample->size;
5200   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5201   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5202
5203   return TRUE;
5204
5205   /* special cases */
5206 eos:
5207   {
5208     stream->time_position = GST_CLOCK_TIME_NONE;
5209     return FALSE;
5210   }
5211 }
5212
5213 /* move to the next sample in @stream.
5214  *
5215  * Moves to the next segment when needed.
5216  */
5217 static void
5218 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5219 {
5220   QtDemuxSample *sample;
5221   QtDemuxSegment *segment;
5222
5223   /* get current segment */
5224   segment = &stream->segments[stream->segment_index];
5225
5226   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5227     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5228     goto next_segment;
5229   }
5230
5231   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5232     /* Mark the stream as EOS */
5233     GST_DEBUG_OBJECT (qtdemux,
5234         "reached max allowed sample %u, mark EOS", stream->to_sample);
5235     stream->time_position = GST_CLOCK_TIME_NONE;
5236     return;
5237   }
5238
5239   /* move to next sample */
5240   stream->sample_index++;
5241   stream->offset_in_sample = 0;
5242
5243   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5244       stream->n_samples);
5245
5246   /* reached the last sample, we need the next segment */
5247   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5248     goto next_segment;
5249
5250   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5251     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5252         stream->sample_index);
5253     return;
5254   }
5255
5256   /* get next sample */
5257   sample = &stream->samples[stream->sample_index];
5258
5259   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5260       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5261       GST_TIME_ARGS (segment->media_stop));
5262
5263   /* see if we are past the segment */
5264   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5265     goto next_segment;
5266
5267   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5268     /* inside the segment, update time_position, looks very familiar to
5269      * GStreamer segments, doesn't it? */
5270     stream->time_position =
5271         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5272   } else {
5273     /* not yet in segment, time does not yet increment. This means
5274      * that we are still prerolling keyframes to the decoder so it can
5275      * decode the first sample of the segment. */
5276     stream->time_position = segment->time;
5277   }
5278   return;
5279
5280   /* move to the next segment */
5281 next_segment:
5282   {
5283     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5284
5285     if (stream->segment_index == stream->n_segments - 1) {
5286       /* are we at the end of the last segment, we're EOS */
5287       stream->time_position = GST_CLOCK_TIME_NONE;
5288     } else {
5289       /* else we're only at the end of the current segment */
5290       stream->time_position = segment->stop_time;
5291     }
5292     /* make sure we select a new segment */
5293
5294     /* accumulate previous segments */
5295     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5296       stream->accumulated_base +=
5297           (stream->segment.stop -
5298           stream->segment.start) / ABS (stream->segment.rate);
5299
5300     stream->segment_index = -1;
5301   }
5302 }
5303
5304 static void
5305 gst_qtdemux_sync_streams (GstQTDemux * demux)
5306 {
5307   gint i;
5308
5309   if (QTDEMUX_N_STREAMS (demux) <= 1)
5310     return;
5311
5312   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5313     QtDemuxStream *stream;
5314     GstClockTime end_time;
5315
5316     stream = QTDEMUX_NTH_STREAM (demux, i);
5317
5318     if (!stream->pad)
5319       continue;
5320
5321     /* TODO advance time on subtitle streams here, if any some day */
5322
5323     /* some clips/trailers may have unbalanced streams at the end,
5324      * so send EOS on shorter stream to prevent stalling others */
5325
5326     /* do not mess with EOS if SEGMENT seeking */
5327     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5328       continue;
5329
5330     if (demux->pullbased) {
5331       /* loop mode is sample time based */
5332       if (!STREAM_IS_EOS (stream))
5333         continue;
5334     } else {
5335       /* push mode is byte position based */
5336       if (stream->n_samples &&
5337           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5338         continue;
5339     }
5340
5341     if (stream->sent_eos)
5342       continue;
5343
5344     /* only act if some gap */
5345     end_time = stream->segments[stream->n_segments - 1].stop_time;
5346     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5347         ", stream end: %" GST_TIME_FORMAT,
5348         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5349     if (GST_CLOCK_TIME_IS_VALID (end_time)
5350         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5351       GstEvent *event;
5352
5353       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5354           GST_PAD_NAME (stream->pad));
5355       stream->sent_eos = TRUE;
5356       event = gst_event_new_eos ();
5357       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5358         gst_event_set_seqnum (event, demux->segment_seqnum);
5359       gst_pad_push_event (stream->pad, event);
5360     }
5361   }
5362 }
5363
5364 /* EOS and NOT_LINKED need to be combined. This means that we return:
5365  *
5366  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5367  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5368  */
5369 static GstFlowReturn
5370 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5371     GstFlowReturn ret)
5372 {
5373   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5374
5375   if (stream->pad)
5376     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5377         ret);
5378   else
5379     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5380
5381   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5382   return ret;
5383 }
5384
5385 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5386  * completely clipped
5387  *
5388  * Should be used only with raw buffers */
5389 static GstBuffer *
5390 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5391     GstBuffer * buf)
5392 {
5393   guint64 start, stop, cstart, cstop, diff;
5394   GstClockTime pts, duration;
5395   gsize size, osize;
5396   gint num_rate, denom_rate;
5397   gint frame_size;
5398   gboolean clip_data;
5399   guint offset;
5400
5401   osize = size = gst_buffer_get_size (buf);
5402   offset = 0;
5403
5404   /* depending on the type, setup the clip parameters */
5405   if (stream->subtype == FOURCC_soun) {
5406     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5407     num_rate = GST_SECOND;
5408     denom_rate = (gint) CUR_STREAM (stream)->rate;
5409     clip_data = TRUE;
5410   } else if (stream->subtype == FOURCC_vide) {
5411     frame_size = size;
5412     num_rate = CUR_STREAM (stream)->fps_n;
5413     denom_rate = CUR_STREAM (stream)->fps_d;
5414     clip_data = FALSE;
5415   } else
5416     goto wrong_type;
5417
5418   if (frame_size <= 0)
5419     goto bad_frame_size;
5420
5421   /* we can only clip if we have a valid pts */
5422   pts = GST_BUFFER_PTS (buf);
5423   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5424     goto no_pts;
5425
5426   duration = GST_BUFFER_DURATION (buf);
5427
5428   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5429     duration =
5430         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5431   }
5432
5433   start = pts;
5434   stop = start + duration;
5435
5436   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5437               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5438     goto clipped;
5439
5440   /* see if some clipping happened */
5441   diff = cstart - start;
5442   if (diff > 0) {
5443     pts += diff;
5444     duration -= diff;
5445
5446     if (clip_data) {
5447       /* bring clipped time to samples and to bytes */
5448       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5449       diff *= frame_size;
5450
5451       GST_DEBUG_OBJECT (qtdemux,
5452           "clipping start to %" GST_TIME_FORMAT " %"
5453           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5454
5455       offset = diff;
5456       size -= diff;
5457     }
5458   }
5459   diff = stop - cstop;
5460   if (diff > 0) {
5461     duration -= diff;
5462
5463     if (clip_data) {
5464       /* bring clipped time to samples and then to bytes */
5465       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5466       diff *= frame_size;
5467       GST_DEBUG_OBJECT (qtdemux,
5468           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5469           " bytes", GST_TIME_ARGS (cstop), diff);
5470       size -= diff;
5471     }
5472   }
5473
5474   if (offset != 0 || size != osize)
5475     gst_buffer_resize (buf, offset, size);
5476
5477   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5478   GST_BUFFER_PTS (buf) = pts;
5479   GST_BUFFER_DURATION (buf) = duration;
5480
5481   return buf;
5482
5483   /* dropped buffer */
5484 wrong_type:
5485   {
5486     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5487     return buf;
5488   }
5489 bad_frame_size:
5490   {
5491     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5492     return buf;
5493   }
5494 no_pts:
5495   {
5496     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5497     return buf;
5498   }
5499 clipped:
5500   {
5501     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5502     gst_buffer_unref (buf);
5503     return NULL;
5504   }
5505 }
5506
5507 static GstBuffer *
5508 gst_qtdemux_align_buffer (GstQTDemux * demux,
5509     GstBuffer * buffer, gsize alignment)
5510 {
5511   GstMapInfo map;
5512
5513   gst_buffer_map (buffer, &map, GST_MAP_READ);
5514
5515   if (map.size < sizeof (guintptr)) {
5516     gst_buffer_unmap (buffer, &map);
5517     return buffer;
5518   }
5519
5520   if (((guintptr) map.data) & (alignment - 1)) {
5521     GstBuffer *new_buffer;
5522     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5523
5524     new_buffer = gst_buffer_new_allocate (NULL,
5525         gst_buffer_get_size (buffer), &params);
5526
5527     /* Copy data "by hand", so ensure alignment is kept: */
5528     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5529
5530     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5531     GST_DEBUG_OBJECT (demux,
5532         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5533         alignment);
5534
5535     gst_buffer_unmap (buffer, &map);
5536     gst_buffer_unref (buffer);
5537
5538     return new_buffer;
5539   }
5540
5541   gst_buffer_unmap (buffer, &map);
5542   return buffer;
5543 }
5544
5545 static guint8 *
5546 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5547     gsize * res)
5548 {
5549   guint8 *storage;
5550   gsize i;
5551
5552   /* We are converting from pairs to triplets */
5553   *res = ccpair_size / 2 * 3;
5554   storage = g_malloc (*res);
5555   for (i = 0; i * 2 < ccpair_size; i += 1) {
5556     /* FIXME: Use line offset 0 as we simply can't know here */
5557     if (field == 1)
5558       storage[i * 3] = 0x80 | 0x00;
5559     else
5560       storage[i * 3] = 0x00 | 0x00;
5561     storage[i * 3 + 1] = ccpair[i * 2];
5562     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5563   }
5564
5565   return storage;
5566 }
5567
5568 static guint8 *
5569 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5570     gsize * cclen)
5571 {
5572   guint8 *res = NULL;
5573   guint32 atom_length, fourcc;
5574   QtDemuxStreamStsdEntry *stsd_entry;
5575
5576   GST_MEMDUMP ("caption atom", data, size);
5577
5578   /* There might be multiple atoms */
5579
5580   *cclen = 0;
5581   if (size < 8)
5582     goto invalid_cdat;
5583   atom_length = QT_UINT32 (data);
5584   fourcc = QT_FOURCC (data + 4);
5585   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5586     goto invalid_cdat;
5587
5588   GST_DEBUG_OBJECT (stream->pad, "here");
5589
5590   /* Check if we have something compatible */
5591   stsd_entry = CUR_STREAM (stream);
5592   switch (stsd_entry->fourcc) {
5593     case FOURCC_c608:{
5594       guint8 *cdat = NULL, *cdt2 = NULL;
5595       gsize cdat_size = 0, cdt2_size = 0;
5596       /* Should be cdat or cdt2 */
5597       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5598         GST_WARNING_OBJECT (stream->pad,
5599             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5600             GST_FOURCC_ARGS (fourcc));
5601         goto invalid_cdat;
5602       }
5603
5604       /* Convert to S334-1 Annex A byte triplet */
5605       if (fourcc == FOURCC_cdat)
5606         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5607       else
5608         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5609       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5610           size, atom_length);
5611
5612       /* Check for another atom ? */
5613       if (size > atom_length + 8) {
5614         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5615         if (size >= atom_length + new_atom_length) {
5616           fourcc = QT_FOURCC (data + atom_length + 4);
5617           if (fourcc == FOURCC_cdat) {
5618             if (cdat == NULL)
5619               cdat =
5620                   convert_to_s334_1a (data + atom_length + 8,
5621                   new_atom_length - 8, 1, &cdat_size);
5622             else
5623               GST_WARNING_OBJECT (stream->pad,
5624                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5625           } else {
5626             if (cdt2 == NULL)
5627               cdt2 =
5628                   convert_to_s334_1a (data + atom_length + 8,
5629                   new_atom_length - 8, 2, &cdt2_size);
5630             else
5631               GST_WARNING_OBJECT (stream->pad,
5632                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5633           }
5634         }
5635       }
5636
5637       *cclen = cdat_size + cdt2_size;
5638       res = g_malloc (*cclen);
5639       if (cdat_size)
5640         memcpy (res, cdat, cdat_size);
5641       if (cdt2_size)
5642         memcpy (res + cdat_size, cdt2, cdt2_size);
5643       g_free (cdat);
5644       g_free (cdt2);
5645     }
5646       break;
5647     case FOURCC_c708:
5648       if (fourcc != FOURCC_ccdp) {
5649         GST_WARNING_OBJECT (stream->pad,
5650             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5651             GST_FOURCC_ARGS (fourcc));
5652         goto invalid_cdat;
5653       }
5654       *cclen = atom_length - 8;
5655       res = g_memdup2 (data + 8, *cclen);
5656       break;
5657     default:
5658       /* Keep this here in case other closed caption formats are added */
5659       g_assert_not_reached ();
5660       break;
5661   }
5662
5663   GST_MEMDUMP ("Output", res, *cclen);
5664   return res;
5665
5666   /* Errors */
5667 invalid_cdat:
5668   GST_WARNING ("[cdat] atom is too small or invalid");
5669   return NULL;
5670 }
5671
5672 /* Handle Closed Caption sample buffers.
5673  * The input buffer metadata must be writable,
5674  * but time/duration etc not yet set and need not be preserved */
5675 static GstBuffer *
5676 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5677     GstBuffer * buf)
5678 {
5679   GstMapInfo map;
5680   guint8 *cc;
5681   gsize cclen = 0;
5682
5683   gst_buffer_map (buf, &map, GST_MAP_READ);
5684
5685   /* empty buffer is sent to terminate previous subtitle */
5686   if (map.size <= 2) {
5687     gst_buffer_unmap (buf, &map);
5688     gst_buffer_unref (buf);
5689     return NULL;
5690   }
5691
5692   /* For closed caption, we need to extract the information from the
5693    * [cdat],[cdt2] or [ccdp] atom */
5694   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5695   gst_buffer_unmap (buf, &map);
5696   gst_buffer_unref (buf);
5697   if (cc) {
5698     buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5699   } else {
5700     /* Conversion failed or there's nothing */
5701     buf = NULL;
5702   }
5703   return buf;
5704 }
5705
5706 /* DVD subpicture specific sample handling.
5707  * the input buffer metadata must be writable,
5708  * but time/duration etc not yet set and need not be preserved */
5709 static GstBuffer *
5710 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5711     GstBuffer * buf)
5712 {
5713   /* send a one time dvd clut event */
5714   if (stream->pending_event && stream->pad)
5715     gst_pad_push_event (stream->pad, stream->pending_event);
5716   stream->pending_event = NULL;
5717
5718   /* empty buffer is sent to terminate previous subtitle */
5719   if (gst_buffer_get_size (buf) <= 2) {
5720     gst_buffer_unref (buf);
5721     return NULL;
5722   }
5723
5724   /* That's all the processing needed for subpictures */
5725   return buf;
5726 }
5727
5728 /* Timed text formats
5729  * the input buffer metadata must be writable,
5730  * but time/duration etc not yet set and need not be preserved */
5731 static GstBuffer *
5732 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5733     GstBuffer * buf)
5734 {
5735   GstMapInfo map;
5736   guint nsize = 0;
5737   gchar *str;
5738
5739   /* not many cases for now */
5740   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5741           stream->subtype != FOURCC_sbtl)) {
5742     return buf;
5743   }
5744
5745   gst_buffer_map (buf, &map, GST_MAP_READ);
5746
5747   /* empty buffer is sent to terminate previous subtitle */
5748   if (map.size <= 2) {
5749     gst_buffer_unmap (buf, &map);
5750     gst_buffer_unref (buf);
5751     return NULL;
5752   }
5753
5754   nsize = GST_READ_UINT16_BE (map.data);
5755   nsize = MIN (nsize, map.size - 2);
5756
5757   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5758       nsize, map.size);
5759
5760   /* takes care of UTF-8 validation or UTF-16 recognition,
5761    * no other encoding expected */
5762   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5763   gst_buffer_unmap (buf, &map);
5764   if (str) {
5765     gst_buffer_unref (buf);
5766     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5767   } else {
5768     /* this should not really happen unless the subtitle is corrupted */
5769     gst_buffer_unref (buf);
5770     buf = NULL;
5771   }
5772
5773   /* FIXME ? convert optional subsequent style info to markup */
5774
5775   return buf;
5776 }
5777
5778 static GstFlowReturn
5779 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5780     GstBuffer * buf)
5781 {
5782   GstFlowReturn ret = GST_FLOW_OK;
5783   GstClockTime pts, duration;
5784
5785   if (stream->need_clip)
5786     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5787
5788   if (G_UNLIKELY (buf == NULL))
5789     goto exit;
5790
5791   if (G_UNLIKELY (stream->discont)) {
5792     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5793     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5794     stream->discont = FALSE;
5795   } else {
5796     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5797   }
5798
5799   GST_LOG_OBJECT (qtdemux,
5800       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5801       ", duration %" GST_TIME_FORMAT " on pad %s",
5802       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5803       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5804       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5805
5806   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5807     GstStructure *crypto_info;
5808     QtDemuxAavdEncryptionInfo *info =
5809         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5810
5811     crypto_info = gst_structure_copy (info->default_properties);
5812     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5813       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5814   }
5815
5816   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5817           || stream->protection_scheme_type == FOURCC_cbcs)) {
5818     GstStructure *crypto_info;
5819     QtDemuxCencSampleSetInfo *info =
5820         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5821     gint index;
5822     GstEvent *event;
5823
5824     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5825       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5826           GST_PTR_FORMAT, event);
5827       gst_pad_push_event (stream->pad, event);
5828     }
5829
5830     if (info->crypto_info == NULL) {
5831       if (stream->protection_scheme_type == FOURCC_cbcs) {
5832         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5833         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5834           GST_ERROR_OBJECT (qtdemux,
5835               "failed to attach cbcs metadata to buffer");
5836           qtdemux_gst_structure_free (crypto_info);
5837         } else {
5838           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5839         }
5840       } else {
5841         GST_DEBUG_OBJECT (qtdemux,
5842             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5843       }
5844     } else {
5845       /* The end of the crypto_info array matches our n_samples position,
5846        * so count backward from there */
5847       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5848       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5849         /* steal structure from array */
5850         crypto_info = g_ptr_array_index (info->crypto_info, index);
5851         g_ptr_array_index (info->crypto_info, index) = NULL;
5852         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5853             info->crypto_info->len);
5854         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5855           GST_ERROR_OBJECT (qtdemux,
5856               "failed to attach cenc metadata to buffer");
5857       } else {
5858         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5859             index, stream->sample_index);
5860       }
5861     }
5862   }
5863
5864   if (stream->alignment > 1)
5865     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5866
5867   pts = GST_BUFFER_PTS (buf);
5868   duration = GST_BUFFER_DURATION (buf);
5869
5870   ret = gst_pad_push (stream->pad, buf);
5871
5872   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5873     /* mark position in stream, we'll need this to know when to send GAP event */
5874     stream->segment.position = pts + duration;
5875   }
5876
5877 exit:
5878
5879   return ret;
5880 }
5881
5882 static GstFlowReturn
5883 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5884     GstBuffer * buf)
5885 {
5886   GstFlowReturn ret = GST_FLOW_OK;
5887
5888   if (stream->subtype == FOURCC_clcp
5889       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5890     GstMapInfo map;
5891     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5892     guint n_triplets, i;
5893     guint field1_off = 0, field2_off = 0;
5894
5895     /* We have to split CEA608 buffers so that each outgoing buffer contains
5896      * one byte pair per field according to the framerate of the video track.
5897      *
5898      * If there is only a single byte pair per field we don't have to do
5899      * anything
5900      */
5901
5902     gst_buffer_map (buf, &map, GST_MAP_READ);
5903
5904     n_triplets = map.size / 3;
5905     for (i = 0; i < n_triplets; i++) {
5906       if (map.data[3 * i] & 0x80)
5907         n_field1++;
5908       else
5909         n_field2++;
5910     }
5911
5912     g_assert (n_field1 || n_field2);
5913
5914     /* If there's more than 1 frame we have to split, otherwise we can just
5915      * pass through */
5916     if (n_field1 > 1 || n_field2 > 1) {
5917       n_output_buffers =
5918           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5919           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5920
5921       for (i = 0; i < n_output_buffers; i++) {
5922         GstBuffer *outbuf =
5923             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5924         GstMapInfo outmap;
5925         guint8 *outptr;
5926
5927         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5928         outptr = outmap.data;
5929
5930         if (n_field1) {
5931           gboolean found = FALSE;
5932
5933           while (map.data + field1_off < map.data + map.size) {
5934             if (map.data[field1_off] & 0x80) {
5935               memcpy (outptr, &map.data[field1_off], 3);
5936               field1_off += 3;
5937               found = TRUE;
5938               break;
5939             }
5940             field1_off += 3;
5941           }
5942
5943           if (!found) {
5944             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5945
5946             memcpy (outptr, empty, 3);
5947           }
5948
5949           outptr += 3;
5950         }
5951
5952         if (n_field2) {
5953           gboolean found = FALSE;
5954
5955           while (map.data + field2_off < map.data + map.size) {
5956             if ((map.data[field2_off] & 0x80) == 0) {
5957               memcpy (outptr, &map.data[field2_off], 3);
5958               field2_off += 3;
5959               found = TRUE;
5960               break;
5961             }
5962             field2_off += 3;
5963           }
5964
5965           if (!found) {
5966             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5967
5968             memcpy (outptr, empty, 3);
5969           }
5970
5971           outptr += 3;
5972         }
5973
5974         gst_buffer_unmap (outbuf, &outmap);
5975
5976         GST_BUFFER_PTS (outbuf) =
5977             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5978             GST_SECOND * CUR_STREAM (stream)->fps_d,
5979             CUR_STREAM (stream)->fps_n);
5980         GST_BUFFER_DURATION (outbuf) =
5981             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5982             CUR_STREAM (stream)->fps_n);
5983         GST_BUFFER_OFFSET (outbuf) = -1;
5984         GST_BUFFER_OFFSET_END (outbuf) = -1;
5985
5986         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
5987
5988         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
5989           break;
5990       }
5991       gst_buffer_unmap (buf, &map);
5992       gst_buffer_unref (buf);
5993     } else {
5994       gst_buffer_unmap (buf, &map);
5995       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5996     }
5997   } else {
5998     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5999   }
6000
6001   return ret;
6002 }
6003
6004 /* Sets a buffer's attributes properly and pushes it downstream.
6005  * Also checks for additional actions and custom processing that may
6006  * need to be done first.
6007  */
6008 static GstFlowReturn
6009 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6010     QtDemuxStream * stream, GstBuffer * buf,
6011     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6012     gboolean keyframe, GstClockTime position, guint64 byte_position)
6013 {
6014   GstFlowReturn ret = GST_FLOW_OK;
6015
6016   /* offset the timestamps according to the edit list */
6017
6018   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6019     gchar *url;
6020     GstMapInfo map;
6021
6022     gst_buffer_map (buf, &map, GST_MAP_READ);
6023     url = g_strndup ((gchar *) map.data, map.size);
6024     gst_buffer_unmap (buf, &map);
6025     if (url != NULL && strlen (url) != 0) {
6026       /* we have RTSP redirect now */
6027       g_free (qtdemux->redirect_location);
6028       qtdemux->redirect_location = g_strdup (url);
6029       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6030           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6031               gst_structure_new ("redirect",
6032                   "new-location", G_TYPE_STRING, url, NULL)));
6033     } else {
6034       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6035           "posting");
6036     }
6037     g_free (url);
6038   }
6039
6040   /* position reporting */
6041   if (qtdemux->segment.rate >= 0) {
6042     qtdemux->segment.position = position;
6043     gst_qtdemux_sync_streams (qtdemux);
6044   }
6045
6046   if (G_UNLIKELY (!stream->pad)) {
6047     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6048     gst_buffer_unref (buf);
6049     goto exit;
6050   }
6051
6052   /* send out pending buffers */
6053   while (stream->buffers) {
6054     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6055
6056     if (G_UNLIKELY (stream->discont)) {
6057       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6058       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6059       stream->discont = FALSE;
6060     } else {
6061       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6062     }
6063
6064     if (stream->alignment > 1)
6065       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6066     gst_pad_push (stream->pad, buffer);
6067
6068     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6069   }
6070
6071   /* we're going to modify the metadata */
6072   buf = gst_buffer_make_writable (buf);
6073
6074   if (G_UNLIKELY (stream->process_func))
6075     buf = stream->process_func (qtdemux, stream, buf);
6076
6077   if (!buf) {
6078     goto exit;
6079   }
6080
6081   GST_BUFFER_DTS (buf) = dts;
6082   GST_BUFFER_PTS (buf) = pts;
6083   GST_BUFFER_DURATION (buf) = duration;
6084   GST_BUFFER_OFFSET (buf) = -1;
6085   GST_BUFFER_OFFSET_END (buf) = -1;
6086
6087   if (!keyframe) {
6088     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6089     stream->on_keyframe = FALSE;
6090   } else {
6091     stream->on_keyframe = TRUE;
6092   }
6093
6094   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6095     gst_buffer_append_memory (buf,
6096         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6097
6098   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6099     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6100   }
6101 #if 0
6102   if (G_UNLIKELY (qtdemux->element_index)) {
6103     GstClockTime stream_time;
6104
6105     stream_time =
6106         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6107         timestamp);
6108     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6109       GST_LOG_OBJECT (qtdemux,
6110           "adding association %" GST_TIME_FORMAT "-> %"
6111           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6112       gst_index_add_association (qtdemux->element_index,
6113           qtdemux->index_id,
6114           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6115           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6116           GST_FORMAT_BYTES, byte_position, NULL);
6117     }
6118   }
6119 #endif
6120
6121   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6122
6123 exit:
6124   return ret;
6125 }
6126
6127 static const QtDemuxRandomAccessEntry *
6128 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6129     GstClockTime pos, gboolean after)
6130 {
6131   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6132   guint n_entries = stream->n_ra_entries;
6133   guint i;
6134
6135   /* we assume the table is sorted */
6136   for (i = 0; i < n_entries; ++i) {
6137     if (entries[i].ts > pos)
6138       break;
6139   }
6140
6141   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6142    * probably okay to assume that the index lists the very first fragment */
6143   if (i == 0)
6144     return &entries[0];
6145
6146   if (after)
6147     return &entries[i];
6148   else
6149     return &entries[i - 1];
6150 }
6151
6152 static gboolean
6153 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6154 {
6155   const QtDemuxRandomAccessEntry *best_entry = NULL;
6156   gint i;
6157
6158   GST_OBJECT_LOCK (qtdemux);
6159
6160   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6161
6162   /* first see if we can determine where to go to using mfra,
6163    * before we start clearing things */
6164   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6165     const QtDemuxRandomAccessEntry *entry;
6166     QtDemuxStream *stream;
6167     gboolean is_audio_or_video;
6168
6169     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6170
6171     if (stream->ra_entries == NULL)
6172       continue;
6173
6174     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6175       is_audio_or_video = TRUE;
6176     else
6177       is_audio_or_video = FALSE;
6178
6179     entry =
6180         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6181         stream->time_position, !is_audio_or_video);
6182
6183     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6184         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6185
6186     stream->pending_seek = entry;
6187
6188     /* decide position to jump to just based on audio/video tracks, not subs */
6189     if (!is_audio_or_video)
6190       continue;
6191
6192     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6193       best_entry = entry;
6194   }
6195
6196   /* no luck, will handle seek otherwise */
6197   if (best_entry == NULL) {
6198     GST_OBJECT_UNLOCK (qtdemux);
6199     return FALSE;
6200   }
6201
6202   /* ok, now we can prepare for processing as of located moof */
6203   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6204     QtDemuxStream *stream;
6205
6206     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6207
6208     g_free (stream->samples);
6209     stream->samples = NULL;
6210     stream->n_samples = 0;
6211     stream->stbl_index = -1;    /* no samples have yet been parsed */
6212     stream->sample_index = -1;
6213
6214     if (stream->protection_scheme_info) {
6215       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6216       if (stream->protection_scheme_type == FOURCC_cenc
6217           || stream->protection_scheme_type == FOURCC_cbcs) {
6218         QtDemuxCencSampleSetInfo *info =
6219             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6220         if (info->crypto_info) {
6221           g_ptr_array_free (info->crypto_info, TRUE);
6222           info->crypto_info = NULL;
6223         }
6224       }
6225     }
6226   }
6227
6228   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6229       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6230       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6231       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6232
6233   qtdemux->moof_offset = best_entry->moof_offset;
6234
6235   qtdemux_add_fragmented_samples (qtdemux);
6236
6237   GST_OBJECT_UNLOCK (qtdemux);
6238   return TRUE;
6239 }
6240
6241 static GstFlowReturn
6242 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6243 {
6244   GstFlowReturn ret = GST_FLOW_OK;
6245   GstBuffer *buf = NULL;
6246   QtDemuxStream *stream, *target_stream = NULL;
6247   GstClockTime min_time;
6248   guint64 offset = 0;
6249   GstClockTime dts = GST_CLOCK_TIME_NONE;
6250   GstClockTime pts = GST_CLOCK_TIME_NONE;
6251   GstClockTime duration = 0;
6252   gboolean keyframe = FALSE;
6253   guint sample_size = 0;
6254   guint num_samples = 1;
6255   gboolean empty = 0;
6256   guint size;
6257   gint i;
6258
6259   if (qtdemux->fragmented_seek_pending) {
6260     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6261     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6262       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6263       qtdemux->fragmented_seek_pending = FALSE;
6264     } else {
6265       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6266     }
6267   }
6268
6269   /* Figure out the next stream sample to output, min_time is expressed in
6270    * global time and runs over the edit list segments. */
6271   min_time = G_MAXUINT64;
6272   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6273     GstClockTime position;
6274
6275     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6276     position = stream->time_position;
6277
6278     if (!GST_CLOCK_TIME_IS_VALID (position))
6279       continue;
6280
6281     if (stream->segment_index != -1) {
6282       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6283       position += segment->media_start;
6284     }
6285
6286     /* position of -1 is EOS */
6287     if (position < min_time) {
6288       min_time = position;
6289       target_stream = stream;
6290     }
6291   }
6292   /* all are EOS */
6293   if (G_UNLIKELY (target_stream == NULL)) {
6294     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6295     goto eos;
6296   }
6297
6298   /* check for segment end */
6299   if (G_UNLIKELY (qtdemux->segment.stop != -1
6300           && qtdemux->segment.rate >= 0
6301           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6302     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6303     target_stream->time_position = GST_CLOCK_TIME_NONE;
6304     goto eos_stream;
6305   }
6306
6307   /* gap events for subtitle streams */
6308   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6309     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6310     if (stream->pad) {
6311       GstClockTime gap_threshold;
6312
6313       /* Only send gap events on non-subtitle streams if lagging way behind. */
6314       if (stream->subtype == FOURCC_subp
6315           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)
6316         gap_threshold = 1 * GST_SECOND;
6317       else
6318         gap_threshold = 3 * GST_SECOND;
6319
6320       /* send gap events until the stream catches up */
6321       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6322       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6323           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6324           stream->segment.position + gap_threshold < min_time) {
6325         GstEvent *gap =
6326             gst_event_new_gap (stream->segment.position, gap_threshold);
6327         gst_pad_push_event (stream->pad, gap);
6328         stream->segment.position += gap_threshold;
6329       }
6330     }
6331   }
6332
6333   stream = target_stream;
6334   /* fetch info for the current sample of this stream */
6335   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6336               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6337     goto eos_stream;
6338
6339   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6340   if (stream->new_caps) {
6341     gst_qtdemux_configure_stream (qtdemux, stream);
6342     qtdemux_do_allocation (stream, qtdemux);
6343   }
6344
6345   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6346   if (G_UNLIKELY (qtdemux->segment.
6347           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6348     if (stream->subtype == FOURCC_vide) {
6349       if (!keyframe) {
6350         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6351             stream->track_id);
6352         goto next;
6353       } else if (qtdemux->trickmode_interval > 0) {
6354         GstClockTimeDiff interval;
6355
6356         if (qtdemux->segment.rate > 0)
6357           interval = stream->time_position - stream->last_keyframe_dts;
6358         else
6359           interval = stream->last_keyframe_dts - stream->time_position;
6360
6361         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6362             && interval < qtdemux->trickmode_interval) {
6363           GST_LOG_OBJECT (qtdemux,
6364               "Skipping keyframe within interval on track-id %u",
6365               stream->track_id);
6366           goto next;
6367         } else {
6368           stream->last_keyframe_dts = stream->time_position;
6369         }
6370       }
6371     }
6372   }
6373
6374   GST_DEBUG_OBJECT (qtdemux,
6375       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6376       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6377       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6378       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6379       GST_TIME_ARGS (duration));
6380
6381   if (G_UNLIKELY (empty)) {
6382     /* empty segment, push a gap if there's a second or more
6383      * difference and move to the next one */
6384     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6385       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6386     stream->segment.position = pts + duration;
6387     goto next;
6388   }
6389
6390   /* hmm, empty sample, skip and move to next sample */
6391   if (G_UNLIKELY (sample_size <= 0))
6392     goto next;
6393
6394   /* last pushed sample was out of boundary, goto next sample */
6395   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6396     goto next;
6397
6398   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6399     GST_DEBUG_OBJECT (qtdemux,
6400         "size %d larger than stream max_buffer_size %d, trimming",
6401         sample_size, stream->max_buffer_size);
6402     size =
6403         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6404   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6405       && sample_size < stream->min_buffer_size) {
6406     guint start_sample_index = stream->sample_index;
6407     guint accumulated_size = sample_size;
6408     guint64 expected_next_offset = offset + sample_size;
6409
6410     GST_DEBUG_OBJECT (qtdemux,
6411         "size %d smaller than stream min_buffer_size %d, combining with the next",
6412         sample_size, stream->min_buffer_size);
6413
6414     while (stream->sample_index < stream->to_sample
6415         && stream->sample_index + 1 < stream->n_samples) {
6416       const QtDemuxSample *next_sample;
6417
6418       /* Increment temporarily */
6419       stream->sample_index++;
6420
6421       /* Failed to parse sample so let's go back to the previous one that was
6422        * still successful */
6423       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6424         stream->sample_index--;
6425         break;
6426       }
6427
6428       next_sample = &stream->samples[stream->sample_index];
6429
6430       /* Not contiguous with the previous sample so let's go back to the
6431        * previous one that was still successful */
6432       if (next_sample->offset != expected_next_offset) {
6433         stream->sample_index--;
6434         break;
6435       }
6436
6437       accumulated_size += next_sample->size;
6438       expected_next_offset += next_sample->size;
6439       if (accumulated_size >= stream->min_buffer_size)
6440         break;
6441     }
6442
6443     num_samples = stream->sample_index + 1 - start_sample_index;
6444     stream->sample_index = start_sample_index;
6445     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6446         num_samples, accumulated_size);
6447     size = accumulated_size;
6448   } else {
6449     size = sample_size;
6450   }
6451
6452   if (qtdemux->cenc_aux_info_offset > 0) {
6453     GstMapInfo map;
6454     GstByteReader br;
6455     GstBuffer *aux_info = NULL;
6456
6457     /* pull the data stored before the sample */
6458     ret =
6459         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6460         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6461     if (G_UNLIKELY (ret != GST_FLOW_OK))
6462       goto beach;
6463     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6464     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6465     gst_byte_reader_init (&br, map.data + 8, map.size);
6466     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6467             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6468       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6469       gst_buffer_unmap (aux_info, &map);
6470       gst_buffer_unref (aux_info);
6471       ret = GST_FLOW_ERROR;
6472       goto beach;
6473     }
6474     gst_buffer_unmap (aux_info, &map);
6475     gst_buffer_unref (aux_info);
6476   }
6477
6478   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6479       offset);
6480
6481   if (stream->use_allocator) {
6482     /* if we have a per-stream allocator, use it */
6483     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6484   }
6485
6486   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6487       size, &buf);
6488   if (G_UNLIKELY (ret != GST_FLOW_OK))
6489     goto beach;
6490
6491   /* Update for both splitting and combining of samples */
6492   if (size != sample_size) {
6493     pts += gst_util_uint64_scale_int (GST_SECOND,
6494         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6495         stream->timescale);
6496     dts +=
6497         gst_util_uint64_scale_int (GST_SECOND,
6498         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6499         stream->timescale);
6500     duration =
6501         gst_util_uint64_scale_int (GST_SECOND,
6502         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6503   }
6504
6505   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6506       dts, pts, duration, keyframe, min_time, offset);
6507
6508   if (size < sample_size) {
6509     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6510     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6511
6512     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6513         sample->timestamp +
6514         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6515     if (time_position >= segment->media_start) {
6516       /* inside the segment, update time_position, looks very familiar to
6517        * GStreamer segments, doesn't it? */
6518       stream->time_position = (time_position - segment->media_start) +
6519           segment->time;
6520     } else {
6521       /* not yet in segment, time does not yet increment. This means
6522        * that we are still prerolling keyframes to the decoder so it can
6523        * decode the first sample of the segment. */
6524       stream->time_position = segment->time;
6525     }
6526   } else if (size > sample_size) {
6527     /* Increase to the last sample we already pulled so that advancing
6528      * below brings us to the next sample we need to pull */
6529     stream->sample_index += num_samples - 1;
6530   }
6531
6532   /* combine flows */
6533   GST_OBJECT_LOCK (qtdemux);
6534   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6535   GST_OBJECT_UNLOCK (qtdemux);
6536   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6537    * we have no more data for the pad to push */
6538   if (ret == GST_FLOW_EOS)
6539     ret = GST_FLOW_OK;
6540
6541   stream->offset_in_sample += size;
6542   if (stream->offset_in_sample >= sample_size) {
6543     gst_qtdemux_advance_sample (qtdemux, stream);
6544   }
6545   goto beach;
6546
6547 next:
6548   gst_qtdemux_advance_sample (qtdemux, stream);
6549
6550 beach:
6551   return ret;
6552
6553   /* special cases */
6554 eos:
6555   {
6556     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6557     ret = GST_FLOW_EOS;
6558     goto beach;
6559   }
6560 eos_stream:
6561   {
6562     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6563     /* EOS will be raised if all are EOS */
6564     ret = GST_FLOW_OK;
6565     goto beach;
6566   }
6567 }
6568
6569 static void
6570 gst_qtdemux_loop (GstPad * pad)
6571 {
6572   GstQTDemux *qtdemux;
6573   guint64 cur_offset;
6574   GstFlowReturn ret;
6575
6576   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6577
6578   cur_offset = qtdemux->offset;
6579   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6580       cur_offset, qt_demux_state_string (qtdemux->state));
6581
6582   switch (qtdemux->state) {
6583     case QTDEMUX_STATE_INITIAL:
6584     case QTDEMUX_STATE_HEADER:
6585       ret = gst_qtdemux_loop_state_header (qtdemux);
6586       break;
6587     case QTDEMUX_STATE_MOVIE:
6588       ret = gst_qtdemux_loop_state_movie (qtdemux);
6589       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6590         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6591       }
6592       break;
6593     default:
6594       /* ouch */
6595       goto invalid_state;
6596   }
6597
6598   /* if something went wrong, pause */
6599   if (ret != GST_FLOW_OK)
6600     goto pause;
6601
6602 done:
6603   gst_object_unref (qtdemux);
6604   return;
6605
6606   /* ERRORS */
6607 invalid_state:
6608   {
6609     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6610         (NULL), ("streaming stopped, invalid state"));
6611     gst_pad_pause_task (pad);
6612     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6613     goto done;
6614   }
6615 pause:
6616   {
6617     const gchar *reason = gst_flow_get_name (ret);
6618
6619     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6620
6621     gst_pad_pause_task (pad);
6622
6623     /* fatal errors need special actions */
6624     /* check EOS */
6625     if (ret == GST_FLOW_EOS) {
6626       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6627         /* we have no streams, post an error */
6628         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6629       }
6630       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6631         gint64 stop;
6632
6633         if ((stop = qtdemux->segment.stop) == -1)
6634           stop = qtdemux->segment.duration;
6635
6636         if (qtdemux->segment.rate >= 0) {
6637           GstMessage *message;
6638           GstEvent *event;
6639
6640           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6641           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6642               GST_FORMAT_TIME, stop);
6643           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6644           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6645             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6646             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6647           }
6648           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6649           gst_qtdemux_push_event (qtdemux, event);
6650         } else {
6651           GstMessage *message;
6652           GstEvent *event;
6653
6654           /*  For Reverse Playback */
6655           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6656           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6657               GST_FORMAT_TIME, qtdemux->segment.start);
6658           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6659               qtdemux->segment.start);
6660           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6661             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6662             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6663           }
6664           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6665           gst_qtdemux_push_event (qtdemux, event);
6666         }
6667       } else {
6668         GstEvent *event;
6669
6670         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6671         event = gst_event_new_eos ();
6672         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6673           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6674         gst_qtdemux_push_event (qtdemux, event);
6675       }
6676     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6677       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6678       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6679     }
6680     goto done;
6681   }
6682 }
6683
6684 /*
6685  * has_next_entry
6686  *
6687  * Returns if there are samples to be played.
6688  */
6689 static gboolean
6690 has_next_entry (GstQTDemux * demux)
6691 {
6692   QtDemuxStream *stream;
6693   gint i;
6694
6695   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6696
6697   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6698     stream = QTDEMUX_NTH_STREAM (demux, i);
6699
6700     if (stream->sample_index == -1) {
6701       stream->sample_index = 0;
6702       stream->offset_in_sample = 0;
6703     }
6704
6705     if (stream->sample_index >= stream->n_samples) {
6706       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6707       continue;
6708     }
6709     GST_DEBUG_OBJECT (demux, "Found a sample");
6710     return TRUE;
6711   }
6712
6713   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6714   return FALSE;
6715 }
6716
6717 /*
6718  * next_entry_size
6719  *
6720  * Returns the size of the first entry at the current offset.
6721  * If -1, there are none (which means EOS or empty file).
6722  */
6723 static guint64
6724 next_entry_size (GstQTDemux * demux)
6725 {
6726   QtDemuxStream *stream, *target_stream = NULL;
6727   guint64 smalloffs = (guint64) - 1;
6728   QtDemuxSample *sample;
6729   gint i;
6730
6731   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6732       demux->offset);
6733
6734   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6735     stream = QTDEMUX_NTH_STREAM (demux, i);
6736
6737     if (stream->sample_index == -1) {
6738       stream->sample_index = 0;
6739       stream->offset_in_sample = 0;
6740     }
6741
6742     if (stream->sample_index >= stream->n_samples) {
6743       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6744       continue;
6745     }
6746
6747     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6748       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6749           stream->sample_index);
6750       return -1;
6751     }
6752
6753     sample = &stream->samples[stream->sample_index];
6754
6755     GST_LOG_OBJECT (demux,
6756         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6757         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6758         stream->sample_index, sample->offset, sample->size);
6759
6760     if (((smalloffs == -1)
6761             || (sample->offset < smalloffs)) && (sample->size)) {
6762       smalloffs = sample->offset;
6763       target_stream = stream;
6764     }
6765   }
6766
6767   if (!target_stream)
6768     return -1;
6769
6770   GST_LOG_OBJECT (demux,
6771       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6772       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6773
6774   stream = target_stream;
6775   sample = &stream->samples[stream->sample_index];
6776
6777   if (sample->offset >= demux->offset) {
6778     demux->todrop = sample->offset - demux->offset;
6779     return sample->size + demux->todrop;
6780   }
6781
6782   GST_DEBUG_OBJECT (demux,
6783       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6784   return -1;
6785 }
6786
6787 static void
6788 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6789 {
6790   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6791
6792   gst_element_post_message (GST_ELEMENT_CAST (demux),
6793       gst_message_new_element (GST_OBJECT_CAST (demux),
6794           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6795 }
6796
6797 static gboolean
6798 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6799 {
6800   GstEvent *event;
6801   gboolean res = 0;
6802
6803   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6804
6805   event =
6806       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6807       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6808       GST_SEEK_TYPE_NONE, -1);
6809
6810   /* store seqnum to drop flush events, they don't need to reach downstream */
6811   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6812   res = gst_pad_push_event (demux->sinkpad, event);
6813   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6814
6815   return res;
6816 }
6817
6818 /* check for seekable upstream, above and beyond a mere query */
6819 static void
6820 gst_qtdemux_check_seekability (GstQTDemux * demux)
6821 {
6822   GstQuery *query;
6823   gboolean seekable = FALSE;
6824   gint64 start = -1, stop = -1;
6825
6826   if (demux->upstream_size)
6827     return;
6828
6829   if (demux->upstream_format_is_time)
6830     return;
6831
6832   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6833   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6834     GST_DEBUG_OBJECT (demux, "seeking query failed");
6835     goto done;
6836   }
6837
6838   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6839
6840   /* try harder to query upstream size if we didn't get it the first time */
6841   if (seekable && stop == -1) {
6842     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6843     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6844   }
6845
6846   /* if upstream doesn't know the size, it's likely that it's not seekable in
6847    * practice even if it technically may be seekable */
6848   if (seekable && (start != 0 || stop <= start)) {
6849     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6850     seekable = FALSE;
6851   }
6852
6853 done:
6854   gst_query_unref (query);
6855
6856   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6857       G_GUINT64_FORMAT ")", seekable, start, stop);
6858   demux->upstream_seekable = seekable;
6859   demux->upstream_size = seekable ? stop : -1;
6860 }
6861
6862 static void
6863 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6864 {
6865   g_return_if_fail (bytes <= demux->todrop);
6866
6867   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6868   gst_adapter_flush (demux->adapter, bytes);
6869   demux->neededbytes -= bytes;
6870   demux->offset += bytes;
6871   demux->todrop -= bytes;
6872 }
6873
6874 /* PUSH-MODE only: Send a segment, if not done already. */
6875 static void
6876 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6877 {
6878   if (G_UNLIKELY (demux->need_segment)) {
6879     gint i;
6880
6881     if (!demux->upstream_format_is_time) {
6882       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6883     } else {
6884       GstEvent *segment_event;
6885       segment_event = gst_event_new_segment (&demux->segment);
6886       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6887         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6888       gst_qtdemux_push_event (demux, segment_event);
6889     }
6890
6891     demux->need_segment = FALSE;
6892
6893     /* clear to send tags on all streams */
6894     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6895       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6896       gst_qtdemux_push_tags (demux, stream);
6897       if (CUR_STREAM (stream)->sparse) {
6898         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6899         gst_pad_push_event (stream->pad,
6900             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6901       }
6902     }
6903   }
6904 }
6905
6906 /* Used for push mode only. */
6907 static void
6908 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6909     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6910 {
6911   GstClockTime ts, dur;
6912
6913   ts = pos;
6914   dur =
6915       stream->segments[segment_index].duration - (pos -
6916       stream->segments[segment_index].time);
6917   stream->time_position += dur;
6918
6919   /* Only gaps with a duration of at least one second are propagated.
6920    * Same workaround as in pull mode.
6921    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6922   if (dur >= GST_SECOND) {
6923     GstEvent *gap;
6924     gap = gst_event_new_gap (ts, dur);
6925
6926     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6927         "segment: %" GST_PTR_FORMAT, gap);
6928     gst_pad_push_event (stream->pad, gap);
6929   }
6930 }
6931
6932 static GstFlowReturn
6933 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6934 {
6935   GstQTDemux *demux;
6936
6937   demux = GST_QTDEMUX (parent);
6938
6939   GST_DEBUG_OBJECT (demux,
6940       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6941       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6942       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6943       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6944       gst_buffer_get_size (inbuf), demux->offset);
6945
6946   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6947     gboolean is_gap_input = FALSE;
6948     gint i;
6949
6950     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6951
6952     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6953       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6954     }
6955
6956     /* Check if we can land back on our feet in the case where upstream is
6957      * handling the seeking/pushing of samples with gaps in between (like
6958      * in the case of trick-mode DASH for example) */
6959     if (demux->upstream_format_is_time
6960         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6961       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6962         guint32 res;
6963         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6964         GST_LOG_OBJECT (demux,
6965             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6966             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6967         res =
6968             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6969             stream, GST_BUFFER_OFFSET (inbuf));
6970         if (res != -1) {
6971           QtDemuxSample *sample = &stream->samples[res];
6972           GST_LOG_OBJECT (demux,
6973               "Checking if sample %d from track-id %u is valid (offset:%"
6974               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6975               stream->track_id, sample->offset, sample->size);
6976           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6977             GST_LOG_OBJECT (demux,
6978                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6979                 res);
6980             is_gap_input = TRUE;
6981             /* We can go back to standard playback mode */
6982             demux->state = QTDEMUX_STATE_MOVIE;
6983             /* Remember which sample this stream is at */
6984             stream->sample_index = res;
6985             /* Finally update all push-based values to the expected values */
6986             demux->neededbytes = stream->samples[res].size;
6987             demux->offset = GST_BUFFER_OFFSET (inbuf);
6988             demux->mdatleft =
6989                 demux->mdatsize - demux->offset + demux->mdatoffset;
6990             demux->todrop = 0;
6991           }
6992         }
6993       }
6994       if (!is_gap_input) {
6995         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6996         /* Reset state if it's a real discont */
6997         demux->neededbytes = 16;
6998         demux->state = QTDEMUX_STATE_INITIAL;
6999         demux->offset = GST_BUFFER_OFFSET (inbuf);
7000         gst_adapter_clear (demux->adapter);
7001       }
7002     }
7003     /* Reverse fragmented playback, need to flush all we have before
7004      * consuming a new fragment.
7005      * The samples array have the timestamps calculated by accumulating the
7006      * durations but this won't work for reverse playback of fragments as
7007      * the timestamps of a subsequent fragment should be smaller than the
7008      * previously received one. */
7009     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7010       gst_qtdemux_process_adapter (demux, TRUE);
7011       g_ptr_array_foreach (demux->active_streams,
7012           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7013     }
7014   }
7015
7016   gst_adapter_push (demux->adapter, inbuf);
7017
7018   GST_DEBUG_OBJECT (demux,
7019       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7020       demux->neededbytes, gst_adapter_available (demux->adapter));
7021
7022   return gst_qtdemux_process_adapter (demux, FALSE);
7023 }
7024
7025 static GstFlowReturn
7026 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7027 {
7028   GstFlowReturn ret = GST_FLOW_OK;
7029
7030   /* we never really mean to buffer that much */
7031   if (demux->neededbytes == -1) {
7032     goto eos;
7033   }
7034
7035   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7036       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7037
7038 #ifndef GST_DISABLE_GST_DEBUG
7039     {
7040       guint64 discont_offset, distance_from_discont;
7041
7042       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7043       distance_from_discont =
7044           gst_adapter_distance_from_discont (demux->adapter);
7045
7046       GST_DEBUG_OBJECT (demux,
7047           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7048           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7049           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7050           demux->offset, discont_offset, distance_from_discont);
7051     }
7052 #endif
7053
7054     switch (demux->state) {
7055       case QTDEMUX_STATE_INITIAL:{
7056         const guint8 *data;
7057         guint32 fourcc;
7058         guint64 size;
7059
7060         gst_qtdemux_check_seekability (demux);
7061
7062         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7063
7064         /* get fourcc/length, set neededbytes */
7065         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7066             &size, &fourcc);
7067         gst_adapter_unmap (demux->adapter);
7068         data = NULL;
7069         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7070             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7071         if (size == 0) {
7072           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7073               (_("This file is invalid and cannot be played.")),
7074               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7075                   GST_FOURCC_ARGS (fourcc)));
7076           ret = GST_FLOW_ERROR;
7077           break;
7078         }
7079         if (fourcc == FOURCC_mdat) {
7080           gint next_entry = next_entry_size (demux);
7081           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7082                   || !demux->fragmented)) {
7083             /* we have the headers, start playback */
7084             demux->state = QTDEMUX_STATE_MOVIE;
7085             demux->neededbytes = next_entry;
7086             demux->mdatleft = size;
7087             demux->mdatsize = demux->mdatleft;
7088           } else {
7089             /* no headers yet, try to get them */
7090             guint bs;
7091             gboolean res;
7092             guint64 old, target;
7093
7094           buffer_data:
7095             old = demux->offset;
7096             target = old + size;
7097
7098             /* try to jump over the atom with a seek */
7099             /* only bother if it seems worth doing so,
7100              * and avoids possible upstream/server problems */
7101             if (demux->upstream_seekable &&
7102                 demux->upstream_size > 4 * (1 << 20)) {
7103               res = qtdemux_seek_offset (demux, target);
7104             } else {
7105               GST_DEBUG_OBJECT (demux, "skipping seek");
7106               res = FALSE;
7107             }
7108
7109             if (res) {
7110               GST_DEBUG_OBJECT (demux, "seek success");
7111               /* remember the offset fo the first mdat so we can seek back to it
7112                * after we have the headers */
7113               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7114                 demux->first_mdat = old;
7115                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7116                     demux->first_mdat);
7117               }
7118               /* seek worked, continue reading */
7119               demux->offset = target;
7120               demux->neededbytes = 16;
7121               demux->state = QTDEMUX_STATE_INITIAL;
7122             } else {
7123               /* seek failed, need to buffer */
7124               demux->offset = old;
7125               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7126               /* there may be multiple mdat (or alike) buffers */
7127               /* sanity check */
7128               if (demux->mdatbuffer)
7129                 bs = gst_buffer_get_size (demux->mdatbuffer);
7130               else
7131                 bs = 0;
7132               if (size + bs > 10 * (1 << 20))
7133                 goto no_moov;
7134               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7135               demux->neededbytes = size;
7136               if (!demux->mdatbuffer)
7137                 demux->mdatoffset = demux->offset;
7138             }
7139           }
7140         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7141           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7142               (_("This file is invalid and cannot be played.")),
7143               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7144                   GST_FOURCC_ARGS (fourcc), size));
7145           ret = GST_FLOW_ERROR;
7146           break;
7147         } else {
7148           /* this means we already started buffering and still no moov header,
7149            * let's continue buffering everything till we get moov */
7150           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7151                   || fourcc == FOURCC_moof))
7152             goto buffer_data;
7153           demux->neededbytes = size;
7154           demux->state = QTDEMUX_STATE_HEADER;
7155         }
7156         break;
7157       }
7158       case QTDEMUX_STATE_HEADER:{
7159         const guint8 *data;
7160         guint32 fourcc;
7161
7162         GST_DEBUG_OBJECT (demux, "In header");
7163
7164         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7165
7166         /* parse the header */
7167         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7168             &fourcc);
7169         if (fourcc == FOURCC_moov) {
7170           /* in usual fragmented setup we could try to scan for more
7171            * and end up at the the moov (after mdat) again */
7172           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7173               (!demux->fragmented
7174                   || demux->last_moov_offset == demux->offset)) {
7175             GST_DEBUG_OBJECT (demux,
7176                 "Skipping moov atom as we have (this) one already");
7177           } else {
7178             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7179
7180             if (demux->got_moov && demux->fragmented) {
7181               GST_DEBUG_OBJECT (demux,
7182                   "Got a second moov, clean up data from old one");
7183               if (demux->moov_node_compressed) {
7184                 g_node_destroy (demux->moov_node_compressed);
7185                 if (demux->moov_node)
7186                   g_free (demux->moov_node->data);
7187               }
7188               demux->moov_node_compressed = NULL;
7189               if (demux->moov_node)
7190                 g_node_destroy (demux->moov_node);
7191               demux->moov_node = NULL;
7192             }
7193
7194             demux->last_moov_offset = demux->offset;
7195
7196             /* Update streams with new moov */
7197             gst_qtdemux_stream_concat (demux,
7198                 demux->old_streams, demux->active_streams);
7199
7200             qtdemux_parse_moov (demux, data, demux->neededbytes);
7201             qtdemux_node_dump (demux, demux->moov_node);
7202             qtdemux_parse_tree (demux);
7203             qtdemux_prepare_streams (demux);
7204             QTDEMUX_EXPOSE_LOCK (demux);
7205             qtdemux_expose_streams (demux);
7206             QTDEMUX_EXPOSE_UNLOCK (demux);
7207
7208             demux->got_moov = TRUE;
7209
7210             gst_qtdemux_check_send_pending_segment (demux);
7211
7212             if (demux->moov_node_compressed) {
7213               g_node_destroy (demux->moov_node_compressed);
7214               g_free (demux->moov_node->data);
7215             }
7216             demux->moov_node_compressed = NULL;
7217             g_node_destroy (demux->moov_node);
7218             demux->moov_node = NULL;
7219             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7220           }
7221         } else if (fourcc == FOURCC_moof) {
7222           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7223             guint64 dist = 0;
7224             GstClockTime prev_pts;
7225             guint64 prev_offset;
7226             guint64 adapter_discont_offset, adapter_discont_dist;
7227
7228             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7229
7230             /*
7231              * The timestamp of the moof buffer is relevant as some scenarios
7232              * won't have the initial timestamp in the atoms. Whenever a new
7233              * buffer has started, we get that buffer's PTS and use it as a base
7234              * timestamp for the trun entries.
7235              *
7236              * To keep track of the current buffer timestamp and starting point
7237              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7238              * from the beginning of the buffer, with the distance and demux->offset
7239              * we know if it is still the same buffer or not.
7240              */
7241             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7242             prev_offset = demux->offset - dist;
7243             if (demux->fragment_start_offset == -1
7244                 || prev_offset > demux->fragment_start_offset) {
7245               demux->fragment_start_offset = prev_offset;
7246               demux->fragment_start = prev_pts;
7247               GST_DEBUG_OBJECT (demux,
7248                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7249                   GST_TIME_FORMAT, demux->fragment_start_offset,
7250                   GST_TIME_ARGS (demux->fragment_start));
7251             }
7252
7253             /* We can't use prev_offset() here because this would require
7254              * upstream to set consistent and correct offsets on all buffers
7255              * since the discont. Nothing ever did that in the past and we
7256              * would break backwards compatibility here then.
7257              * Instead take the offset we had at the last discont and count
7258              * the bytes from there. This works with old code as there would
7259              * be no discont between moov and moof, and also works with
7260              * adaptivedemux which correctly sets offset and will set the
7261              * DISCONT flag accordingly when needed.
7262              *
7263              * We also only do this for upstream TIME segments as otherwise
7264              * there are potential backwards compatibility problems with
7265              * seeking in PUSH mode and upstream providing inconsistent
7266              * timestamps. */
7267             adapter_discont_offset =
7268                 gst_adapter_offset_at_discont (demux->adapter);
7269             adapter_discont_dist =
7270                 gst_adapter_distance_from_discont (demux->adapter);
7271
7272             GST_DEBUG_OBJECT (demux,
7273                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7274                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7275                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7276
7277             if (demux->upstream_format_is_time) {
7278               demux->moof_offset = adapter_discont_offset;
7279               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7280                 demux->moof_offset += adapter_discont_dist;
7281               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7282                 demux->moof_offset = demux->offset;
7283             } else {
7284               demux->moof_offset = demux->offset;
7285             }
7286
7287             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7288                     demux->moof_offset, NULL)) {
7289               gst_adapter_unmap (demux->adapter);
7290               ret = GST_FLOW_ERROR;
7291               goto done;
7292             }
7293
7294             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7295             if (demux->mss_mode && !demux->exposed) {
7296               QTDEMUX_EXPOSE_LOCK (demux);
7297               qtdemux_expose_streams (demux);
7298               QTDEMUX_EXPOSE_UNLOCK (demux);
7299             }
7300
7301             gst_qtdemux_check_send_pending_segment (demux);
7302           } else {
7303             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7304           }
7305         } else if (fourcc == FOURCC_ftyp) {
7306           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7307           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7308         } else if (fourcc == FOURCC_uuid) {
7309           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7310           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7311         } else if (fourcc == FOURCC_sidx) {
7312           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7313           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7314         } else {
7315           switch (fourcc) {
7316             case FOURCC_styp:
7317               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7318                * FALLTHROUGH */
7319             case FOURCC_skip:
7320             case FOURCC_free:
7321               /* [free] and [skip] are padding atoms */
7322               GST_DEBUG_OBJECT (demux,
7323                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7324                   GST_FOURCC_ARGS (fourcc));
7325               break;
7326             default:
7327               GST_WARNING_OBJECT (demux,
7328                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7329                   GST_FOURCC_ARGS (fourcc));
7330               /* Let's jump that one and go back to initial state */
7331               break;
7332           }
7333         }
7334         gst_adapter_unmap (demux->adapter);
7335         data = NULL;
7336
7337         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7338           gsize remaining_data_size = 0;
7339
7340           /* the mdat was before the header */
7341           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7342               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7343           /* restore our adapter/offset view of things with upstream;
7344            * put preceding buffered data ahead of current moov data.
7345            * This should also handle evil mdat, moov, mdat cases and alike */
7346           gst_adapter_flush (demux->adapter, demux->neededbytes);
7347
7348           /* Store any remaining data after the mdat for later usage */
7349           remaining_data_size = gst_adapter_available (demux->adapter);
7350           if (remaining_data_size > 0) {
7351             g_assert (demux->restoredata_buffer == NULL);
7352             demux->restoredata_buffer =
7353                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7354             demux->restoredata_offset = demux->offset + demux->neededbytes;
7355             GST_DEBUG_OBJECT (demux,
7356                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7357                 G_GUINT64_FORMAT, remaining_data_size,
7358                 demux->restoredata_offset);
7359           }
7360
7361           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7362           demux->mdatbuffer = NULL;
7363           demux->offset = demux->mdatoffset;
7364           demux->neededbytes = next_entry_size (demux);
7365           demux->state = QTDEMUX_STATE_MOVIE;
7366           demux->mdatleft = gst_adapter_available (demux->adapter);
7367           demux->mdatsize = demux->mdatleft;
7368         } else {
7369           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7370           gst_adapter_flush (demux->adapter, demux->neededbytes);
7371
7372           /* only go back to the mdat if there are samples to play */
7373           if (demux->got_moov && demux->first_mdat != -1
7374               && has_next_entry (demux)) {
7375             gboolean res;
7376
7377             /* we need to seek back */
7378             res = qtdemux_seek_offset (demux, demux->first_mdat);
7379             if (res) {
7380               demux->offset = demux->first_mdat;
7381             } else {
7382               GST_DEBUG_OBJECT (demux, "Seek back failed");
7383             }
7384           } else {
7385             demux->offset += demux->neededbytes;
7386           }
7387           demux->neededbytes = 16;
7388           demux->state = QTDEMUX_STATE_INITIAL;
7389         }
7390
7391         break;
7392       }
7393       case QTDEMUX_STATE_BUFFER_MDAT:{
7394         GstBuffer *buf;
7395         guint8 fourcc[4];
7396
7397         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7398             demux->offset);
7399         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7400         gst_buffer_extract (buf, 0, fourcc, 4);
7401         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7402             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7403         if (demux->mdatbuffer)
7404           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7405         else
7406           demux->mdatbuffer = buf;
7407         demux->offset += demux->neededbytes;
7408         demux->neededbytes = 16;
7409         demux->state = QTDEMUX_STATE_INITIAL;
7410         gst_qtdemux_post_progress (demux, 1, 1);
7411
7412         break;
7413       }
7414       case QTDEMUX_STATE_MOVIE:{
7415         QtDemuxStream *stream = NULL;
7416         QtDemuxSample *sample;
7417         GstClockTime dts, pts, duration;
7418         gboolean keyframe;
7419         gint i;
7420
7421         GST_DEBUG_OBJECT (demux,
7422             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7423
7424         if (demux->fragmented) {
7425           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7426               demux->mdatleft);
7427           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7428             /* if needed data starts within this atom,
7429              * then it should not exceed this atom */
7430             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7431               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7432                   (_("This file is invalid and cannot be played.")),
7433                   ("sample data crosses atom boundary"));
7434               ret = GST_FLOW_ERROR;
7435               break;
7436             }
7437             demux->mdatleft -= demux->neededbytes;
7438           } else {
7439             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7440             /* so we are dropping more than left in this atom */
7441             gst_qtdemux_drop_data (demux, demux->mdatleft);
7442             demux->mdatleft = 0;
7443
7444             /* need to resume atom parsing so we do not miss any other pieces */
7445             demux->state = QTDEMUX_STATE_INITIAL;
7446             demux->neededbytes = 16;
7447
7448             /* check if there was any stored post mdat data from previous buffers */
7449             if (demux->restoredata_buffer) {
7450               g_assert (gst_adapter_available (demux->adapter) == 0);
7451
7452               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7453               demux->restoredata_buffer = NULL;
7454               demux->offset = demux->restoredata_offset;
7455             }
7456
7457             break;
7458           }
7459         }
7460
7461         if (demux->todrop) {
7462           if (demux->cenc_aux_info_offset > 0) {
7463             GstByteReader br;
7464             const guint8 *data;
7465
7466             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7467             data = gst_adapter_map (demux->adapter, demux->todrop);
7468             gst_byte_reader_init (&br, data + 8, demux->todrop);
7469             if (!qtdemux_parse_cenc_aux_info (demux,
7470                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7471                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7472               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7473               ret = GST_FLOW_ERROR;
7474               gst_adapter_unmap (demux->adapter);
7475               g_free (demux->cenc_aux_info_sizes);
7476               demux->cenc_aux_info_sizes = NULL;
7477               goto done;
7478             }
7479             demux->cenc_aux_info_offset = 0;
7480             g_free (demux->cenc_aux_info_sizes);
7481             demux->cenc_aux_info_sizes = NULL;
7482             gst_adapter_unmap (demux->adapter);
7483           }
7484           gst_qtdemux_drop_data (demux, demux->todrop);
7485         }
7486
7487         /* first buffer? */
7488         /* initial newsegment sent here after having added pads,
7489          * possible others in sink_event */
7490         gst_qtdemux_check_send_pending_segment (demux);
7491
7492         /* Figure out which stream this packet belongs to */
7493         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7494           stream = QTDEMUX_NTH_STREAM (demux, i);
7495           if (stream->sample_index >= stream->n_samples) {
7496             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7497             stream = NULL;
7498             continue;
7499           }
7500           GST_LOG_OBJECT (demux,
7501               "Checking track-id %u (sample_index:%d / offset:%"
7502               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7503               stream->sample_index,
7504               stream->samples[stream->sample_index].offset,
7505               stream->samples[stream->sample_index].size);
7506
7507           if (stream->samples[stream->sample_index].offset == demux->offset)
7508             break;
7509         }
7510
7511         if (G_UNLIKELY (stream == NULL))
7512           goto unknown_stream;
7513
7514         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7515
7516         if (stream->new_caps) {
7517           gst_qtdemux_configure_stream (demux, stream);
7518         }
7519
7520         /* Put data in a buffer, set timestamps, caps, ... */
7521         sample = &stream->samples[stream->sample_index];
7522
7523         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7524           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7525               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7526
7527           dts = QTSAMPLE_DTS (stream, sample);
7528           pts = QTSAMPLE_PTS (stream, sample);
7529           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7530           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7531
7532           /* check for segment end */
7533           if (G_UNLIKELY (demux->segment.stop != -1
7534                   && demux->segment.stop <= pts && stream->on_keyframe)
7535               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7536             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7537             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7538
7539             /* skip this data, stream is EOS */
7540             gst_adapter_flush (demux->adapter, demux->neededbytes);
7541             demux->offset += demux->neededbytes;
7542
7543             /* check if all streams are eos */
7544             ret = GST_FLOW_EOS;
7545             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7546               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7547                 ret = GST_FLOW_OK;
7548                 break;
7549               }
7550             }
7551           } else {
7552             GstBuffer *outbuf;
7553
7554             outbuf =
7555                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7556
7557             /* FIXME: should either be an assert or a plain check */
7558             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7559
7560             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7561                 dts, pts, duration, keyframe, dts, demux->offset);
7562           }
7563
7564           /* combine flows */
7565           GST_OBJECT_LOCK (demux);
7566           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7567           GST_OBJECT_UNLOCK (demux);
7568         } else {
7569           /* skip this data, stream is EOS */
7570           gst_adapter_flush (demux->adapter, demux->neededbytes);
7571         }
7572
7573         stream->sample_index++;
7574         stream->offset_in_sample = 0;
7575
7576         /* update current offset and figure out size of next buffer */
7577         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7578             demux->offset, demux->neededbytes);
7579         demux->offset += demux->neededbytes;
7580         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7581             demux->offset);
7582
7583
7584         if (ret == GST_FLOW_EOS) {
7585           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7586           demux->neededbytes = -1;
7587           goto eos;
7588         }
7589
7590         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7591           if (demux->fragmented) {
7592             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7593             /* there may be more to follow, only finish this atom */
7594             demux->todrop = demux->mdatleft;
7595             demux->neededbytes = demux->todrop;
7596             break;
7597           }
7598           goto eos;
7599         }
7600         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7601           goto non_ok_unlinked_flow;
7602         }
7603         break;
7604       }
7605       default:
7606         goto invalid_state;
7607     }
7608   }
7609
7610   /* when buffering movie data, at least show user something is happening */
7611   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7612       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7613     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7614         demux->neededbytes);
7615   }
7616 done:
7617
7618   return ret;
7619
7620   /* ERRORS */
7621 non_ok_unlinked_flow:
7622   {
7623     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7624         gst_flow_get_name (ret));
7625     return ret;
7626   }
7627 unknown_stream:
7628   {
7629     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7630     ret = GST_FLOW_ERROR;
7631     goto done;
7632   }
7633 eos:
7634   {
7635     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7636     ret = GST_FLOW_EOS;
7637     goto done;
7638   }
7639 invalid_state:
7640   {
7641     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7642         (NULL), ("qtdemuxer invalid state %d", demux->state));
7643     ret = GST_FLOW_ERROR;
7644     goto done;
7645   }
7646 no_moov:
7647   {
7648     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7649         (NULL), ("no 'moov' atom within the first 10 MB"));
7650     ret = GST_FLOW_ERROR;
7651     goto done;
7652   }
7653 }
7654
7655 static gboolean
7656 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7657 {
7658   GstQuery *query;
7659   gboolean pull_mode;
7660
7661   query = gst_query_new_scheduling ();
7662
7663   if (!gst_pad_peer_query (sinkpad, query)) {
7664     gst_query_unref (query);
7665     goto activate_push;
7666   }
7667
7668   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7669       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7670   gst_query_unref (query);
7671
7672   if (!pull_mode)
7673     goto activate_push;
7674
7675   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7676   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7677
7678 activate_push:
7679   {
7680     GST_DEBUG_OBJECT (sinkpad, "activating push");
7681     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7682   }
7683 }
7684
7685 static gboolean
7686 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7687     GstPadMode mode, gboolean active)
7688 {
7689   gboolean res;
7690   GstQTDemux *demux = GST_QTDEMUX (parent);
7691
7692   switch (mode) {
7693     case GST_PAD_MODE_PUSH:
7694       demux->pullbased = FALSE;
7695       res = TRUE;
7696       break;
7697     case GST_PAD_MODE_PULL:
7698       if (active) {
7699         demux->pullbased = TRUE;
7700         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7701             sinkpad, NULL);
7702       } else {
7703         res = gst_pad_stop_task (sinkpad);
7704       }
7705       break;
7706     default:
7707       res = FALSE;
7708       break;
7709   }
7710   return res;
7711 }
7712
7713 #ifdef HAVE_ZLIB
7714 static void *
7715 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7716 {
7717   guint8 *buffer;
7718   z_stream z;
7719   int ret;
7720
7721   memset (&z, 0, sizeof (z));
7722   z.zalloc = NULL;
7723   z.zfree = NULL;
7724   z.opaque = NULL;
7725
7726   if ((ret = inflateInit (&z)) != Z_OK) {
7727     GST_ERROR ("inflateInit() returned %d", ret);
7728     return NULL;
7729   }
7730
7731   z.next_in = z_buffer;
7732   z.avail_in = z_length;
7733
7734   buffer = (guint8 *) g_malloc (*length);
7735   z.avail_out = *length;
7736   z.next_out = (Bytef *) buffer;
7737   do {
7738     ret = inflate (&z, Z_NO_FLUSH);
7739     if (ret == Z_STREAM_END) {
7740       break;
7741     } else if (ret != Z_OK) {
7742       GST_WARNING ("inflate() returned %d", ret);
7743       break;
7744     }
7745
7746     *length += 4096;
7747     buffer = (guint8 *) g_realloc (buffer, *length);
7748     z.next_out = (Bytef *) (buffer + z.total_out);
7749     z.avail_out += 4096;
7750   } while (z.avail_in > 0);
7751
7752   if (ret != Z_STREAM_END) {
7753     g_free (buffer);
7754     buffer = NULL;
7755     *length = 0;
7756   } else {
7757     *length = z.total_out;
7758   }
7759
7760   inflateEnd (&z);
7761
7762   return buffer;
7763 }
7764 #endif /* HAVE_ZLIB */
7765
7766 static gboolean
7767 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7768 {
7769   GNode *cmov;
7770
7771   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7772
7773   /* counts as header data */
7774   qtdemux->header_size += length;
7775
7776   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7777   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7778
7779   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7780   if (cmov) {
7781     guint32 method;
7782     GNode *dcom;
7783     GNode *cmvd;
7784     guint32 dcom_len;
7785
7786     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7787     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7788     if (dcom == NULL || cmvd == NULL)
7789       goto invalid_compression;
7790
7791     dcom_len = QT_UINT32 (dcom->data);
7792     if (dcom_len < 12)
7793       goto invalid_compression;
7794
7795     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7796     switch (method) {
7797 #ifdef HAVE_ZLIB
7798       case FOURCC_zlib:{
7799         guint uncompressed_length;
7800         guint compressed_length;
7801         guint8 *buf;
7802         guint32 cmvd_len;
7803
7804         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7805         if (cmvd_len < 12)
7806           goto invalid_compression;
7807
7808         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7809         compressed_length = cmvd_len - 12;
7810         GST_LOG ("length = %u", uncompressed_length);
7811
7812         buf =
7813             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7814             compressed_length, &uncompressed_length);
7815
7816         if (buf) {
7817           qtdemux->moov_node_compressed = qtdemux->moov_node;
7818           qtdemux->moov_node = g_node_new (buf);
7819
7820           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7821               uncompressed_length);
7822         }
7823         break;
7824       }
7825 #endif /* HAVE_ZLIB */
7826       default:
7827         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7828             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7829         break;
7830     }
7831   }
7832   return TRUE;
7833
7834   /* ERRORS */
7835 invalid_compression:
7836   {
7837     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7838     return FALSE;
7839   }
7840 }
7841
7842 static gboolean
7843 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7844     const guint8 * end)
7845 {
7846   while (G_UNLIKELY (buf < end)) {
7847     GNode *child;
7848     guint32 len;
7849
7850     if (G_UNLIKELY (buf + 4 > end)) {
7851       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7852       break;
7853     }
7854     len = QT_UINT32 (buf);
7855     if (G_UNLIKELY (len == 0)) {
7856       GST_LOG_OBJECT (qtdemux, "empty container");
7857       break;
7858     }
7859     if (G_UNLIKELY (len < 8)) {
7860       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7861       break;
7862     }
7863     if (G_UNLIKELY (len > (end - buf))) {
7864       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7865           (gint) (end - buf));
7866       break;
7867     }
7868
7869     child = g_node_new ((guint8 *) buf);
7870     g_node_append (node, child);
7871     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7872     qtdemux_parse_node (qtdemux, child, buf, len);
7873
7874     buf += len;
7875   }
7876   return TRUE;
7877 }
7878
7879 static gboolean
7880 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7881     GNode * xdxt)
7882 {
7883   int len = QT_UINT32 (xdxt->data);
7884   guint8 *buf = xdxt->data;
7885   guint8 *end = buf + len;
7886   GstBuffer *buffer;
7887
7888   /* skip size and type */
7889   buf += 8;
7890   end -= 8;
7891
7892   while (buf < end) {
7893     gint size;
7894     guint32 type;
7895
7896     size = QT_UINT32 (buf);
7897     type = QT_FOURCC (buf + 4);
7898
7899     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7900
7901     if (buf + size > end || size <= 0)
7902       break;
7903
7904     buf += 8;
7905     size -= 8;
7906
7907     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7908         GST_FOURCC_ARGS (type));
7909
7910     switch (type) {
7911       case FOURCC_tCtH:
7912         buffer = gst_buffer_new_and_alloc (size);
7913         gst_buffer_fill (buffer, 0, buf, size);
7914         stream->buffers = g_slist_append (stream->buffers, buffer);
7915         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7916         break;
7917       case FOURCC_tCt_:
7918         buffer = gst_buffer_new_and_alloc (size);
7919         gst_buffer_fill (buffer, 0, buf, size);
7920         stream->buffers = g_slist_append (stream->buffers, buffer);
7921         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7922         break;
7923       case FOURCC_tCtC:
7924         buffer = gst_buffer_new_and_alloc (size);
7925         gst_buffer_fill (buffer, 0, buf, size);
7926         stream->buffers = g_slist_append (stream->buffers, buffer);
7927         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7928         break;
7929       default:
7930         GST_WARNING_OBJECT (qtdemux,
7931             "unknown theora cookie %" GST_FOURCC_FORMAT,
7932             GST_FOURCC_ARGS (type));
7933         break;
7934     }
7935     buf += size;
7936   }
7937   return TRUE;
7938 }
7939
7940 static gboolean
7941 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7942     guint length)
7943 {
7944   guint32 fourcc = 0;
7945   guint32 node_length = 0;
7946   const QtNodeType *type;
7947   const guint8 *end;
7948
7949   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7950
7951   if (G_UNLIKELY (length < 8))
7952     goto not_enough_data;
7953
7954   node_length = QT_UINT32 (buffer);
7955   fourcc = QT_FOURCC (buffer + 4);
7956
7957   /* ignore empty nodes */
7958   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7959     return TRUE;
7960
7961   type = qtdemux_type_get (fourcc);
7962
7963   end = buffer + length;
7964
7965   GST_LOG_OBJECT (qtdemux,
7966       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7967       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7968
7969   if (node_length > length)
7970     goto broken_atom_size;
7971
7972   if (type->flags & QT_FLAG_CONTAINER) {
7973     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7974   } else {
7975     switch (fourcc) {
7976       case FOURCC_stsd:
7977       {
7978         if (node_length < 20) {
7979           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7980           break;
7981         }
7982         GST_DEBUG_OBJECT (qtdemux,
7983             "parsing stsd (sample table, sample description) atom");
7984         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7985         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7986         break;
7987       }
7988       case FOURCC_mp4a:
7989       case FOURCC_alac:
7990       case FOURCC_fLaC:
7991       case FOURCC_aavd:
7992       {
7993         guint32 version;
7994         guint32 offset;
7995         guint min_size;
7996
7997         /* also read alac (or whatever) in stead of mp4a in the following,
7998          * since a similar layout is used in other cases as well */
7999         if (fourcc == FOURCC_mp4a)
8000           min_size = 20;
8001         else if (fourcc == FOURCC_fLaC)
8002           min_size = 86;
8003         else
8004           min_size = 40;
8005
8006         /* There are two things we might encounter here: a true mp4a atom, and
8007            an mp4a entry in an stsd atom. The latter is what we're interested
8008            in, and it looks like an atom, but isn't really one. The true mp4a
8009            atom is short, so we detect it based on length here. */
8010         if (length < min_size) {
8011           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8012               GST_FOURCC_ARGS (fourcc));
8013           break;
8014         }
8015
8016         /* 'version' here is the sound sample description version. Types 0 and
8017            1 are documented in the QTFF reference, but type 2 is not: it's
8018            described in Apple header files instead (struct SoundDescriptionV2
8019            in Movies.h) */
8020         version = QT_UINT16 (buffer + 16);
8021
8022         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8023             GST_FOURCC_ARGS (fourcc), version);
8024
8025         /* parse any esds descriptors */
8026         switch (version) {
8027           case 0:
8028             offset = 0x24;
8029             break;
8030           case 1:
8031             offset = 0x34;
8032             break;
8033           case 2:
8034             offset = 0x48;
8035             break;
8036           default:
8037             GST_WARNING_OBJECT (qtdemux,
8038                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8039                 GST_FOURCC_ARGS (fourcc), version);
8040             offset = 0;
8041             break;
8042         }
8043         if (offset)
8044           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8045         break;
8046       }
8047       case FOURCC_mp4v:
8048       case FOURCC_MP4V:
8049       case FOURCC_fmp4:
8050       case FOURCC_FMP4:
8051       case FOURCC_apcs:
8052       case FOURCC_apch:
8053       case FOURCC_apcn:
8054       case FOURCC_apco:
8055       case FOURCC_ap4h:
8056       case FOURCC_xvid:
8057       case FOURCC_XVID:
8058       case FOURCC_H264:
8059       case FOURCC_avc1:
8060       case FOURCC_avc3:
8061       case FOURCC_H265:
8062       case FOURCC_hvc1:
8063       case FOURCC_hev1:
8064       case FOURCC_dvh1:
8065       case FOURCC_dvhe:
8066       case FOURCC_mjp2:
8067       case FOURCC_encv:
8068       {
8069         guint32 version;
8070         guint32 str_len;
8071
8072         /* codec_data is contained inside these atoms, which all have
8073          * the same format. */
8074         /* video sample description size is 86 bytes without extension.
8075          * node_length have to be bigger than 86 bytes because video sample
8076          * description can include extensions such as esds, fiel, glbl, etc. */
8077         if (node_length < 86) {
8078           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8079               " sample description length too short (%u < 86)",
8080               GST_FOURCC_ARGS (fourcc), node_length);
8081           break;
8082         }
8083
8084         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8085             GST_FOURCC_ARGS (fourcc));
8086
8087         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8088          *              its data format.
8089          * revision level (2 bytes) : must be set to 0. */
8090         version = QT_UINT32 (buffer + 16);
8091         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8092
8093         /* compressor name : PASCAL string and informative purposes
8094          * first byte : the number of bytes to be displayed.
8095          *              it has to be less than 32 because it is reserved
8096          *              space of 32 bytes total including itself. */
8097         str_len = QT_UINT8 (buffer + 50);
8098         if (str_len < 32)
8099           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8100               (char *) buffer + 51);
8101         else
8102           GST_WARNING_OBJECT (qtdemux,
8103               "compressorname length too big (%u > 31)", str_len);
8104
8105         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8106             end - buffer);
8107         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8108         break;
8109       }
8110       case FOURCC_meta:
8111       {
8112         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8113
8114         /* You are reading this correctly. QTFF specifies that the
8115          * metadata atom is a short atom, whereas ISO BMFF specifies
8116          * it's a full atom. But since so many people are doing things
8117          * differently, we actually peek into the atom to see which
8118          * variant it is */
8119         if (length < 16) {
8120           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8121               GST_FOURCC_ARGS (fourcc));
8122           break;
8123         }
8124         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8125           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8126            * starts with a 'hdlr' atom */
8127           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8128         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8129           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8130            * with version/flags both set to zero */
8131           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8132         } else
8133           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8134         break;
8135       }
8136       case FOURCC_mp4s:
8137       {
8138         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8139         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8140         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8141         break;
8142       }
8143       case FOURCC_XiTh:
8144       {
8145         guint32 version;
8146         guint32 offset;
8147
8148         if (length < 16) {
8149           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8150               GST_FOURCC_ARGS (fourcc));
8151           break;
8152         }
8153
8154         version = QT_UINT32 (buffer + 12);
8155         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8156
8157         switch (version) {
8158           case 0x00000001:
8159             offset = 0x62;
8160             break;
8161           default:
8162             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8163             offset = 0;
8164             break;
8165         }
8166         if (offset) {
8167           if (length < offset) {
8168             GST_WARNING_OBJECT (qtdemux,
8169                 "skipping too small %" GST_FOURCC_FORMAT " box",
8170                 GST_FOURCC_ARGS (fourcc));
8171             break;
8172           }
8173           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8174         }
8175         break;
8176       }
8177       case FOURCC_in24:
8178       {
8179         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8180         break;
8181       }
8182       case FOURCC_uuid:
8183       {
8184         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8185         break;
8186       }
8187       case FOURCC_enca:
8188       {
8189         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8190         break;
8191       }
8192       default:
8193         if (!strcmp (type->name, "unknown"))
8194           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8195         break;
8196     }
8197   }
8198   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8199       GST_FOURCC_ARGS (fourcc));
8200   return TRUE;
8201
8202 /* ERRORS */
8203 not_enough_data:
8204   {
8205     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8206         (_("This file is corrupt and cannot be played.")),
8207         ("Not enough data for an atom header, got only %u bytes", length));
8208     return FALSE;
8209   }
8210 broken_atom_size:
8211   {
8212     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8213         (_("This file is corrupt and cannot be played.")),
8214         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8215             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8216             length));
8217     return FALSE;
8218   }
8219 }
8220
8221 static void
8222 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8223 {
8224 /* FIXME: This can only reliably work if demuxers have a
8225  * separate streaming thread per srcpad. This should be
8226  * done in a demuxer base class, which integrates parts
8227  * of multiqueue
8228  *
8229  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8230  */
8231 #if 0
8232   GstQuery *query;
8233
8234   query = gst_query_new_allocation (stream->caps, FALSE);
8235
8236   if (!gst_pad_peer_query (stream->pad, query)) {
8237     /* not a problem, just debug a little */
8238     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8239   }
8240
8241   if (stream->allocator)
8242     gst_object_unref (stream->allocator);
8243
8244   if (gst_query_get_n_allocation_params (query) > 0) {
8245     /* try the allocator */
8246     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8247         &stream->params);
8248     stream->use_allocator = TRUE;
8249   } else {
8250     stream->allocator = NULL;
8251     gst_allocation_params_init (&stream->params);
8252     stream->use_allocator = FALSE;
8253   }
8254   gst_query_unref (query);
8255 #endif
8256 }
8257
8258 static gboolean
8259 pad_query (const GValue * item, GValue * value, gpointer user_data)
8260 {
8261   GstPad *pad = g_value_get_object (item);
8262   GstQuery *query = user_data;
8263   gboolean res;
8264
8265   res = gst_pad_peer_query (pad, query);
8266
8267   if (res) {
8268     g_value_set_boolean (value, TRUE);
8269     return FALSE;
8270   }
8271
8272   GST_INFO_OBJECT (pad, "pad peer query failed");
8273   return TRUE;
8274 }
8275
8276 static gboolean
8277 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8278     GstPadDirection direction)
8279 {
8280   GstIterator *it;
8281   GstIteratorFoldFunction func = pad_query;
8282   GValue res = { 0, };
8283
8284   g_value_init (&res, G_TYPE_BOOLEAN);
8285   g_value_set_boolean (&res, FALSE);
8286
8287   /* Ask neighbor */
8288   if (direction == GST_PAD_SRC)
8289     it = gst_element_iterate_src_pads (element);
8290   else
8291     it = gst_element_iterate_sink_pads (element);
8292
8293   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8294     gst_iterator_resync (it);
8295
8296   gst_iterator_free (it);
8297
8298   return g_value_get_boolean (&res);
8299 }
8300
8301 static void
8302 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8303     QtDemuxStream * stream)
8304 {
8305   GstQuery *query;
8306   GstContext *ctxt;
8307   GstElement *element = GST_ELEMENT (qtdemux);
8308   GstStructure *st;
8309   gchar **filtered_sys_ids;
8310   GValue event_list = G_VALUE_INIT;
8311   GList *walk;
8312
8313   /* 1. Check if we already have the context. */
8314   if (qtdemux->preferred_protection_system_id != NULL) {
8315     GST_LOG_OBJECT (element,
8316         "already have the protection context, no need to request it again");
8317     return;
8318   }
8319
8320   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8321   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8322       (const gchar **) qtdemux->protection_system_ids->pdata);
8323
8324   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8325       qtdemux->protection_system_ids->len - 1);
8326   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8327       "decryptors for %u of them, running context request",
8328       qtdemux->protection_system_ids->len,
8329       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8330
8331
8332   if (stream->protection_scheme_event_queue.length) {
8333     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8334         stream->protection_scheme_event_queue.length);
8335     walk = stream->protection_scheme_event_queue.tail;
8336   } else {
8337     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8338         qtdemux->protection_event_queue.length);
8339     walk = qtdemux->protection_event_queue.tail;
8340   }
8341
8342   g_value_init (&event_list, GST_TYPE_LIST);
8343   for (; walk; walk = g_list_previous (walk)) {
8344     GValue *event_value = g_new0 (GValue, 1);
8345     g_value_init (event_value, GST_TYPE_EVENT);
8346     g_value_set_boxed (event_value, walk->data);
8347     gst_value_list_append_and_take_value (&event_list, event_value);
8348   }
8349
8350   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8351    *      check if downstream already has a context of the specific type
8352    *  2b) Query upstream as above.
8353    */
8354   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8355   st = gst_query_writable_structure (query);
8356   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8357       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8358       NULL);
8359   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8360   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8361     gst_query_parse_context (query, &ctxt);
8362     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8363     gst_element_set_context (element, ctxt);
8364   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8365     gst_query_parse_context (query, &ctxt);
8366     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8367     gst_element_set_context (element, ctxt);
8368   } else {
8369     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8370      *    the required context type and afterwards check if a
8371      *    usable context was set now as in 1). The message could
8372      *    be handled by the parent bins of the element and the
8373      *    application.
8374      */
8375     GstMessage *msg;
8376
8377     GST_INFO_OBJECT (element, "posting need context message");
8378     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8379         "drm-preferred-decryption-system-id");
8380     st = (GstStructure *) gst_message_get_structure (msg);
8381     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8382         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8383         NULL);
8384
8385     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8386     gst_element_post_message (element, msg);
8387   }
8388
8389   g_strfreev (filtered_sys_ids);
8390   g_value_unset (&event_list);
8391   gst_query_unref (query);
8392 }
8393
8394 static gboolean
8395 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8396     QtDemuxStream * stream)
8397 {
8398   GstStructure *s;
8399   const gchar *selected_system = NULL;
8400
8401   g_return_val_if_fail (qtdemux != NULL, FALSE);
8402   g_return_val_if_fail (stream != NULL, FALSE);
8403   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8404       FALSE);
8405
8406   if (stream->protection_scheme_type == FOURCC_aavd) {
8407     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8408     if (!gst_structure_has_name (s, "application/x-aavd")) {
8409       gst_structure_set (s,
8410           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8411           NULL);
8412       gst_structure_set_name (s, "application/x-aavd");
8413     }
8414     return TRUE;
8415   }
8416
8417   if (stream->protection_scheme_type != FOURCC_cenc
8418       && stream->protection_scheme_type != FOURCC_cbcs) {
8419     GST_ERROR_OBJECT (qtdemux,
8420         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8421         GST_FOURCC_ARGS (stream->protection_scheme_type));
8422     return FALSE;
8423   }
8424
8425   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8426   if (!gst_structure_has_name (s, "application/x-cenc")) {
8427     gst_structure_set (s,
8428         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8429     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8430         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8431         NULL);
8432     gst_structure_set_name (s, "application/x-cenc");
8433   }
8434
8435   if (qtdemux->protection_system_ids == NULL) {
8436     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8437         "cenc protection system information has been found, not setting a "
8438         "protection system UUID");
8439     return TRUE;
8440   }
8441
8442   gst_qtdemux_request_protection_context (qtdemux, stream);
8443   if (qtdemux->preferred_protection_system_id != NULL) {
8444     const gchar *preferred_system_array[] =
8445         { qtdemux->preferred_protection_system_id, NULL };
8446
8447     selected_system = gst_protection_select_system (preferred_system_array);
8448
8449     if (selected_system) {
8450       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8451           qtdemux->preferred_protection_system_id);
8452     } else {
8453       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8454           "because there is no available decryptor",
8455           qtdemux->preferred_protection_system_id);
8456     }
8457   }
8458
8459   if (!selected_system) {
8460     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8461     selected_system = gst_protection_select_system ((const gchar **)
8462         qtdemux->protection_system_ids->pdata);
8463     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8464         qtdemux->protection_system_ids->len - 1);
8465   }
8466
8467   if (!selected_system) {
8468     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8469         "suitable decryptor element has been found");
8470     return FALSE;
8471   }
8472
8473   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8474       selected_system);
8475
8476   gst_structure_set (s,
8477       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8478       NULL);
8479
8480   return TRUE;
8481 }
8482
8483 static gboolean
8484 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8485 {
8486   /* fps is calculated base on the duration of the average framerate since
8487    * qt does not have a fixed framerate. */
8488   gboolean fps_available = TRUE;
8489   guint32 first_duration = 0;
8490
8491   if (stream->n_samples > 0)
8492     first_duration = stream->samples[0].duration;
8493
8494   if ((stream->n_samples == 1 && first_duration == 0)
8495       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8496     /* still frame */
8497     CUR_STREAM (stream)->fps_n = 0;
8498     CUR_STREAM (stream)->fps_d = 1;
8499   } else {
8500     if (stream->duration == 0 || stream->n_samples < 2) {
8501       CUR_STREAM (stream)->fps_n = stream->timescale;
8502       CUR_STREAM (stream)->fps_d = 1;
8503       fps_available = FALSE;
8504     } else {
8505       GstClockTime avg_duration;
8506       guint64 duration;
8507       guint32 n_samples;
8508
8509       /* duration and n_samples can be updated for fragmented format
8510        * so, framerate of fragmented format is calculated using data in a moof */
8511       if (qtdemux->fragmented && stream->n_samples_moof > 0
8512           && stream->duration_moof > 0) {
8513         n_samples = stream->n_samples_moof;
8514         duration = stream->duration_moof;
8515       } else {
8516         n_samples = stream->n_samples;
8517         duration = stream->duration;
8518       }
8519
8520       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8521       /* stream->duration is guint64, timescale, n_samples are guint32 */
8522       avg_duration =
8523           gst_util_uint64_scale_round (duration -
8524           first_duration, GST_SECOND,
8525           (guint64) (stream->timescale) * (n_samples - 1));
8526
8527       GST_LOG_OBJECT (qtdemux,
8528           "Calculating avg sample duration based on stream (or moof) duration %"
8529           G_GUINT64_FORMAT
8530           " minus first sample %u, leaving %d samples gives %"
8531           GST_TIME_FORMAT, duration, first_duration,
8532           n_samples - 1, GST_TIME_ARGS (avg_duration));
8533
8534       fps_available =
8535           gst_video_guess_framerate (avg_duration,
8536           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8537
8538       GST_DEBUG_OBJECT (qtdemux,
8539           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8540           stream->timescale, CUR_STREAM (stream)->fps_n,
8541           CUR_STREAM (stream)->fps_d);
8542     }
8543   }
8544
8545   return fps_available;
8546 }
8547
8548 static gboolean
8549 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8550 {
8551   if (stream->subtype == FOURCC_vide) {
8552     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8553
8554     if (CUR_STREAM (stream)->caps) {
8555       CUR_STREAM (stream)->caps =
8556           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8557
8558       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8559         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8560             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8561             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8562
8563       /* set framerate if calculated framerate is reliable */
8564       if (fps_available) {
8565         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8566             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8567             CUR_STREAM (stream)->fps_d, NULL);
8568       }
8569
8570       /* calculate pixel-aspect-ratio using display width and height */
8571       GST_DEBUG_OBJECT (qtdemux,
8572           "video size %dx%d, target display size %dx%d",
8573           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8574           stream->display_width, stream->display_height);
8575       /* qt file might have pasp atom */
8576       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8577         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8578             CUR_STREAM (stream)->par_h);
8579         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8580             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8581             CUR_STREAM (stream)->par_h, NULL);
8582       } else if (stream->display_width > 0 && stream->display_height > 0
8583           && CUR_STREAM (stream)->width > 0
8584           && CUR_STREAM (stream)->height > 0) {
8585         gint n, d;
8586
8587         /* calculate the pixel aspect ratio using the display and pixel w/h */
8588         n = stream->display_width * CUR_STREAM (stream)->height;
8589         d = stream->display_height * CUR_STREAM (stream)->width;
8590         if (n == d)
8591           n = d = 1;
8592         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8593         CUR_STREAM (stream)->par_w = n;
8594         CUR_STREAM (stream)->par_h = d;
8595         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8596             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8597             CUR_STREAM (stream)->par_h, NULL);
8598       }
8599
8600       if (CUR_STREAM (stream)->interlace_mode > 0) {
8601         if (CUR_STREAM (stream)->interlace_mode == 1) {
8602           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8603               G_TYPE_STRING, "progressive", NULL);
8604         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8605           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8606               G_TYPE_STRING, "interleaved", NULL);
8607           if (CUR_STREAM (stream)->field_order == 9) {
8608             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8609                 G_TYPE_STRING, "top-field-first", NULL);
8610           } else if (CUR_STREAM (stream)->field_order == 14) {
8611             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8612                 G_TYPE_STRING, "bottom-field-first", NULL);
8613           }
8614         }
8615       }
8616
8617       /* Create incomplete colorimetry here if needed */
8618       if (CUR_STREAM (stream)->colorimetry.range ||
8619           CUR_STREAM (stream)->colorimetry.matrix ||
8620           CUR_STREAM (stream)->colorimetry.transfer
8621           || CUR_STREAM (stream)->colorimetry.primaries) {
8622         gchar *colorimetry =
8623             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8624         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8625             G_TYPE_STRING, colorimetry, NULL);
8626         g_free (colorimetry);
8627       }
8628
8629       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8630         guint par_w = 1, par_h = 1;
8631
8632         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8633           par_w = CUR_STREAM (stream)->par_w;
8634           par_h = CUR_STREAM (stream)->par_h;
8635         }
8636
8637         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8638                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8639                 par_h)) {
8640           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8641         }
8642
8643         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8644             "multiview-mode", G_TYPE_STRING,
8645             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8646             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8647             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8648       }
8649     }
8650   }
8651
8652   else if (stream->subtype == FOURCC_soun) {
8653     if (CUR_STREAM (stream)->caps) {
8654       CUR_STREAM (stream)->caps =
8655           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8656       if (CUR_STREAM (stream)->rate > 0)
8657         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8658             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8659       if (CUR_STREAM (stream)->n_channels > 0)
8660         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8661             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8662       if (CUR_STREAM (stream)->n_channels > 2) {
8663         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8664          * correctly; this is just the minimum we can do - assume
8665          * we don't actually have any channel positions. */
8666         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8667             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8668       }
8669     }
8670   }
8671
8672   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8673     const GstStructure *s;
8674     QtDemuxStream *fps_stream = NULL;
8675     gboolean fps_available = FALSE;
8676
8677     /* CEA608 closed caption tracks are a bit special in that each sample
8678      * can contain CCs for multiple frames, and CCs can be omitted and have to
8679      * be inferred from the duration of the sample then.
8680      *
8681      * As such we take the framerate from the (first) video track here for
8682      * CEA608 as there must be one CC byte pair for every video frame
8683      * according to the spec.
8684      *
8685      * For CEA708 all is fine and there is one sample per frame.
8686      */
8687
8688     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8689     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8690       gint i;
8691
8692       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8693         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8694
8695         if (tmp->subtype == FOURCC_vide) {
8696           fps_stream = tmp;
8697           break;
8698         }
8699       }
8700
8701       if (fps_stream) {
8702         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8703         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8704         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8705       }
8706     } else {
8707       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8708       fps_stream = stream;
8709     }
8710
8711     CUR_STREAM (stream)->caps =
8712         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8713
8714     /* set framerate if calculated framerate is reliable */
8715     if (fps_available) {
8716       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8717           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8718           CUR_STREAM (stream)->fps_d, NULL);
8719     }
8720   }
8721
8722   if (stream->pad) {
8723     GstCaps *prev_caps = NULL;
8724
8725     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8726     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8727     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8728     gst_pad_set_active (stream->pad, TRUE);
8729
8730     gst_pad_use_fixed_caps (stream->pad);
8731
8732     if (stream->protected) {
8733       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8734         GST_ERROR_OBJECT (qtdemux,
8735             "Failed to configure protected stream caps.");
8736         return FALSE;
8737       }
8738     }
8739
8740     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8741         CUR_STREAM (stream)->caps);
8742     if (stream->new_stream) {
8743       GstEvent *event;
8744       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8745
8746       event =
8747           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8748           0);
8749       if (event) {
8750         gst_event_parse_stream_flags (event, &stream_flags);
8751         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8752           qtdemux->have_group_id = TRUE;
8753         else
8754           qtdemux->have_group_id = FALSE;
8755         gst_event_unref (event);
8756       } else if (!qtdemux->have_group_id) {
8757         qtdemux->have_group_id = TRUE;
8758         qtdemux->group_id = gst_util_group_id_next ();
8759       }
8760
8761       stream->new_stream = FALSE;
8762       event = gst_event_new_stream_start (stream->stream_id);
8763       if (qtdemux->have_group_id)
8764         gst_event_set_group_id (event, qtdemux->group_id);
8765       if (stream->disabled)
8766         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8767       if (CUR_STREAM (stream)->sparse) {
8768         stream_flags |= GST_STREAM_FLAG_SPARSE;
8769       } else {
8770         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8771       }
8772       gst_event_set_stream_flags (event, stream_flags);
8773       gst_pad_push_event (stream->pad, event);
8774     }
8775
8776     prev_caps = gst_pad_get_current_caps (stream->pad);
8777
8778     if (CUR_STREAM (stream)->caps) {
8779       if (!prev_caps
8780           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8781         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8782             CUR_STREAM (stream)->caps);
8783         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8784       } else {
8785         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8786       }
8787     } else {
8788       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8789     }
8790
8791     if (prev_caps)
8792       gst_caps_unref (prev_caps);
8793     stream->new_caps = FALSE;
8794   }
8795   return TRUE;
8796 }
8797
8798 static void
8799 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8800     QtDemuxStream * stream)
8801 {
8802   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8803     return;
8804
8805   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8806       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8807   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8808           stream->stsd_entries_length)) {
8809     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8810         (_("This file is invalid and cannot be played.")),
8811         ("New sample description id is out of bounds (%d >= %d)",
8812             stream->stsd_sample_description_id, stream->stsd_entries_length));
8813   } else {
8814     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8815     stream->new_caps = TRUE;
8816   }
8817 }
8818
8819 static gboolean
8820 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8821     QtDemuxStream * stream, GstTagList * list)
8822 {
8823   gboolean ret = TRUE;
8824
8825   if (stream->subtype == FOURCC_vide) {
8826     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8827
8828     stream->pad =
8829         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8830     g_free (name);
8831
8832     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8833       gst_object_unref (stream->pad);
8834       stream->pad = NULL;
8835       ret = FALSE;
8836       goto done;
8837     }
8838
8839     qtdemux->n_video_streams++;
8840   } else if (stream->subtype == FOURCC_soun) {
8841     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8842
8843     stream->pad =
8844         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8845     g_free (name);
8846     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8847       gst_object_unref (stream->pad);
8848       stream->pad = NULL;
8849       ret = FALSE;
8850       goto done;
8851     }
8852     qtdemux->n_audio_streams++;
8853   } else if (stream->subtype == FOURCC_strm) {
8854     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8855   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8856       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8857       || stream->subtype == FOURCC_clcp) {
8858     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8859
8860     stream->pad =
8861         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8862     g_free (name);
8863     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8864       gst_object_unref (stream->pad);
8865       stream->pad = NULL;
8866       ret = FALSE;
8867       goto done;
8868     }
8869     qtdemux->n_sub_streams++;
8870   } else if (CUR_STREAM (stream)->caps) {
8871     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8872
8873     stream->pad =
8874         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8875     g_free (name);
8876     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8877       gst_object_unref (stream->pad);
8878       stream->pad = NULL;
8879       ret = FALSE;
8880       goto done;
8881     }
8882     qtdemux->n_video_streams++;
8883   } else {
8884     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8885     goto done;
8886   }
8887
8888   if (stream->pad) {
8889     GList *l;
8890
8891     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8892         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8893     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8894     GST_OBJECT_LOCK (qtdemux);
8895     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8896     GST_OBJECT_UNLOCK (qtdemux);
8897
8898     if (stream->stream_tags)
8899       gst_tag_list_unref (stream->stream_tags);
8900     stream->stream_tags = list;
8901     list = NULL;
8902     /* global tags go on each pad anyway */
8903     stream->send_global_tags = TRUE;
8904     /* send upstream GST_EVENT_PROTECTION events that were received before
8905        this source pad was created */
8906     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8907       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8908   }
8909 done:
8910   if (list)
8911     gst_tag_list_unref (list);
8912   return ret;
8913 }
8914
8915 /* find next atom with @fourcc starting at @offset */
8916 static GstFlowReturn
8917 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8918     guint64 * length, guint32 fourcc)
8919 {
8920   GstFlowReturn ret;
8921   guint32 lfourcc;
8922   GstBuffer *buf;
8923
8924   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8925       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8926
8927   while (TRUE) {
8928     GstMapInfo map;
8929
8930     buf = NULL;
8931     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8932     if (G_UNLIKELY (ret != GST_FLOW_OK))
8933       goto locate_failed;
8934     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8935       /* likely EOF */
8936       ret = GST_FLOW_EOS;
8937       gst_buffer_unref (buf);
8938       goto locate_failed;
8939     }
8940     gst_buffer_map (buf, &map, GST_MAP_READ);
8941     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8942     gst_buffer_unmap (buf, &map);
8943     gst_buffer_unref (buf);
8944
8945     if (G_UNLIKELY (*length == 0)) {
8946       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8947       ret = GST_FLOW_ERROR;
8948       goto locate_failed;
8949     }
8950
8951     if (lfourcc == fourcc) {
8952       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
8953           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8954       break;
8955     } else {
8956       GST_LOG_OBJECT (qtdemux,
8957           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8958           GST_FOURCC_ARGS (lfourcc), *offset);
8959       if (*offset == G_MAXUINT64)
8960         goto locate_failed;
8961       *offset += *length;
8962     }
8963   }
8964
8965   return GST_FLOW_OK;
8966
8967 locate_failed:
8968   {
8969     /* might simply have had last one */
8970     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8971     return ret;
8972   }
8973 }
8974
8975 /* should only do something in pull mode */
8976 /* call with OBJECT lock */
8977 static GstFlowReturn
8978 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8979 {
8980   guint64 length, offset;
8981   GstBuffer *buf = NULL;
8982   GstFlowReturn ret = GST_FLOW_OK;
8983   GstFlowReturn res = GST_FLOW_OK;
8984   GstMapInfo map;
8985
8986   offset = qtdemux->moof_offset;
8987   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8988
8989   if (!offset) {
8990     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8991     return GST_FLOW_EOS;
8992   }
8993
8994   /* best not do pull etc with lock held */
8995   GST_OBJECT_UNLOCK (qtdemux);
8996
8997   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8998   if (ret != GST_FLOW_OK)
8999     goto flow_failed;
9000
9001   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9002   if (G_UNLIKELY (ret != GST_FLOW_OK))
9003     goto flow_failed;
9004   gst_buffer_map (buf, &map, GST_MAP_READ);
9005   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9006     gst_buffer_unmap (buf, &map);
9007     gst_buffer_unref (buf);
9008     buf = NULL;
9009     goto parse_failed;
9010   }
9011
9012   gst_buffer_unmap (buf, &map);
9013   gst_buffer_unref (buf);
9014   buf = NULL;
9015
9016   offset += length;
9017   /* look for next moof */
9018   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9019   if (G_UNLIKELY (ret != GST_FLOW_OK))
9020     goto flow_failed;
9021
9022 exit:
9023   GST_OBJECT_LOCK (qtdemux);
9024
9025   qtdemux->moof_offset = offset;
9026
9027   return res;
9028
9029 parse_failed:
9030   {
9031     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9032     offset = 0;
9033     res = GST_FLOW_ERROR;
9034     goto exit;
9035   }
9036 flow_failed:
9037   {
9038     /* maybe upstream temporarily flushing */
9039     if (ret != GST_FLOW_FLUSHING) {
9040       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9041       offset = 0;
9042     } else {
9043       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9044       /* resume at current position next time */
9045     }
9046     res = ret;
9047     goto exit;
9048   }
9049 }
9050
9051 static void
9052 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9053 {
9054   guint i;
9055   guint32 num_chunks;
9056   gint32 stts_duration;
9057   GstByteWriter stsc, stts, stsz;
9058
9059   /* Each sample has a different size, which we don't support for merging */
9060   if (stream->sample_size == 0) {
9061     GST_DEBUG_OBJECT (qtdemux,
9062         "Not all samples have the same size, not merging");
9063     return;
9064   }
9065
9066   /* The stream has a ctts table, we don't support that */
9067   if (stream->ctts_present) {
9068     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9069     return;
9070   }
9071
9072   /* If there's a sync sample table also ignore this stream */
9073   if (stream->stps_present || stream->stss_present) {
9074     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9075     return;
9076   }
9077
9078   /* If chunks are considered samples already ignore this stream */
9079   if (stream->chunks_are_samples) {
9080     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9081     return;
9082   }
9083
9084   /* Require that all samples have the same duration */
9085   if (stream->n_sample_times > 1) {
9086     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9087     return;
9088   }
9089
9090   /* Parse the stts to get the sample duration and number of samples */
9091   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9092   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9093
9094   /* Parse the number of chunks from the stco manually because the
9095    * reader is already behind that */
9096   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9097
9098   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9099       num_chunks);
9100
9101   /* Now parse stsc, convert chunks into single samples and generate a
9102    * new stsc, stts and stsz from this information */
9103   gst_byte_writer_init (&stsc);
9104   gst_byte_writer_init (&stts);
9105   gst_byte_writer_init (&stsz);
9106
9107   /* Note: we skip fourccs, size, version, flags and other fields of the new
9108    * atoms as the byte readers with them are already behind that position
9109    * anyway and only update the values of those inside the stream directly.
9110    */
9111   stream->n_sample_times = 0;
9112   stream->n_samples = 0;
9113   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9114     guint j;
9115     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9116
9117     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9118     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9119     sample_description_id =
9120         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9121
9122     if (i == stream->n_samples_per_chunk - 1) {
9123       /* +1 because first_chunk is 1-based */
9124       last_chunk = num_chunks + 1;
9125     } else {
9126       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9127     }
9128
9129     GST_DEBUG_OBJECT (qtdemux,
9130         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9131         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9132
9133     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9134     /* One sample in this chunk */
9135     gst_byte_writer_put_uint32_be (&stsc, 1);
9136     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9137
9138     /* For each chunk write a stts and stsz entry now */
9139     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9140     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9141     for (j = first_chunk; j < last_chunk; j++) {
9142       gst_byte_writer_put_uint32_be (&stsz,
9143           stream->sample_size * samples_per_chunk);
9144     }
9145
9146     stream->n_sample_times += 1;
9147     stream->n_samples += last_chunk - first_chunk;
9148   }
9149
9150   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9151
9152   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9153       stream->n_samples, stream->n_sample_times);
9154
9155   /* We don't have a fixed sample size anymore */
9156   stream->sample_size = 0;
9157
9158   /* Free old data for the atoms */
9159   g_free ((gpointer) stream->stsz.data);
9160   stream->stsz.data = NULL;
9161   g_free ((gpointer) stream->stsc.data);
9162   stream->stsc.data = NULL;
9163   g_free ((gpointer) stream->stts.data);
9164   stream->stts.data = NULL;
9165
9166   /* Store new data and replace byte readers */
9167   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9168   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9169   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9170   stream->stts.size = gst_byte_writer_get_size (&stts);
9171   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9172   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9173   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9174   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9175   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9176 }
9177
9178 /* initialise bytereaders for stbl sub-atoms */
9179 static gboolean
9180 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9181 {
9182   stream->stbl_index = -1;      /* no samples have yet been parsed */
9183   stream->sample_index = -1;
9184
9185   /* time-to-sample atom */
9186   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9187     goto corrupt_file;
9188
9189   /* copy atom data into a new buffer for later use */
9190   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9191
9192   /* skip version + flags */
9193   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9194       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9195     goto corrupt_file;
9196   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9197
9198   /* make sure there's enough data */
9199   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9200     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9201     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9202         stream->n_sample_times);
9203     if (!stream->n_sample_times)
9204       goto corrupt_file;
9205   }
9206
9207   /* sync sample atom */
9208   stream->stps_present = FALSE;
9209   if ((stream->stss_present =
9210           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9211               &stream->stss) ? TRUE : FALSE) == TRUE) {
9212     /* copy atom data into a new buffer for later use */
9213     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9214
9215     /* skip version + flags */
9216     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9217         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9218       goto corrupt_file;
9219
9220     if (stream->n_sample_syncs) {
9221       /* make sure there's enough data */
9222       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9223         goto corrupt_file;
9224     }
9225
9226     /* partial sync sample atom */
9227     if ((stream->stps_present =
9228             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9229                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9230       /* copy atom data into a new buffer for later use */
9231       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9232
9233       /* skip version + flags */
9234       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9235           !gst_byte_reader_get_uint32_be (&stream->stps,
9236               &stream->n_sample_partial_syncs))
9237         goto corrupt_file;
9238
9239       /* if there are no entries, the stss table contains the real
9240        * sync samples */
9241       if (stream->n_sample_partial_syncs) {
9242         /* make sure there's enough data */
9243         if (!qt_atom_parser_has_chunks (&stream->stps,
9244                 stream->n_sample_partial_syncs, 4))
9245           goto corrupt_file;
9246       }
9247     }
9248   }
9249
9250   /* sample size */
9251   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9252     goto no_samples;
9253
9254   /* copy atom data into a new buffer for later use */
9255   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9256
9257   /* skip version + flags */
9258   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9259       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9260     goto corrupt_file;
9261
9262   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9263     goto corrupt_file;
9264
9265   if (!stream->n_samples)
9266     goto no_samples;
9267
9268   /* sample-to-chunk atom */
9269   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9270     goto corrupt_file;
9271
9272   /* copy atom data into a new buffer for later use */
9273   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9274
9275   /* skip version + flags */
9276   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9277       !gst_byte_reader_get_uint32_be (&stream->stsc,
9278           &stream->n_samples_per_chunk))
9279     goto corrupt_file;
9280
9281   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9282       stream->n_samples_per_chunk);
9283
9284   /* make sure there's enough data */
9285   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9286           12))
9287     goto corrupt_file;
9288
9289
9290   /* chunk offset */
9291   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9292     stream->co_size = sizeof (guint32);
9293   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9294           &stream->stco))
9295     stream->co_size = sizeof (guint64);
9296   else
9297     goto corrupt_file;
9298
9299   /* copy atom data into a new buffer for later use */
9300   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9301
9302   /* skip version + flags */
9303   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9304     goto corrupt_file;
9305
9306   /* chunks_are_samples == TRUE means treat chunks as samples */
9307   stream->chunks_are_samples = stream->sample_size
9308       && !CUR_STREAM (stream)->sampled;
9309   if (stream->chunks_are_samples) {
9310     /* treat chunks as samples */
9311     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9312       goto corrupt_file;
9313   } else {
9314     /* skip number of entries */
9315     if (!gst_byte_reader_skip (&stream->stco, 4))
9316       goto corrupt_file;
9317
9318     /* make sure there are enough data in the stsz atom */
9319     if (!stream->sample_size) {
9320       /* different sizes for each sample */
9321       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9322         goto corrupt_file;
9323     }
9324   }
9325
9326   /* composition time-to-sample */
9327   if ((stream->ctts_present =
9328           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9329               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9330     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9331
9332     /* copy atom data into a new buffer for later use */
9333     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9334
9335     /* skip version + flags */
9336     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9337         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9338             &stream->n_composition_times))
9339       goto corrupt_file;
9340
9341     /* make sure there's enough data */
9342     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9343             4 + 4))
9344       goto corrupt_file;
9345
9346     /* This is optional, if missing we iterate the ctts */
9347     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9348       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9349           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9350         g_free ((gpointer) cslg.data);
9351         goto corrupt_file;
9352       }
9353     } else {
9354       gint32 cslg_least = 0;
9355       guint num_entries, pos;
9356       gint i;
9357
9358       pos = gst_byte_reader_get_pos (&stream->ctts);
9359       num_entries = stream->n_composition_times;
9360
9361       stream->cslg_shift = 0;
9362
9363       for (i = 0; i < num_entries; i++) {
9364         gint32 offset;
9365
9366         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9367         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9368         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9369          * slightly inaccurate PTS could be more usable than corrupted one */
9370         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9371           GST_WARNING_OBJECT (qtdemux,
9372               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9373               " larger than duration %" G_GUINT64_FORMAT,
9374               offset, stream->duration);
9375
9376           stream->cslg_shift = 0;
9377           stream->ctts_present = FALSE;
9378           goto done;
9379         }
9380
9381         if (offset < cslg_least)
9382           cslg_least = offset;
9383       }
9384
9385       if (cslg_least < 0)
9386         stream->cslg_shift = ABS (cslg_least);
9387       else
9388         stream->cslg_shift = 0;
9389
9390       /* reset the reader so we can generate sample table */
9391       gst_byte_reader_set_pos (&stream->ctts, pos);
9392     }
9393   } else {
9394     /* Ensure the cslg_shift value is consistent so we can use it
9395      * unconditionally to produce TS and Segment */
9396     stream->cslg_shift = 0;
9397   }
9398
9399   /* For raw audio streams especially we might want to merge the samples
9400    * to not output one audio sample per buffer. We're doing this here
9401    * before allocating the sample tables so that from this point onwards
9402    * the number of container samples are static */
9403   if (stream->min_buffer_size > 0) {
9404     qtdemux_merge_sample_table (qtdemux, stream);
9405   }
9406
9407 done:
9408   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9409       stream->n_samples, (guint) sizeof (QtDemuxSample),
9410       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9411
9412   if (stream->n_samples >=
9413       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9414     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9415         "be larger than %uMB (broken file?)", stream->n_samples,
9416         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9417     return FALSE;
9418   }
9419
9420   g_assert (stream->samples == NULL);
9421   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9422   if (!stream->samples) {
9423     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9424         stream->n_samples);
9425     return FALSE;
9426   }
9427
9428   return TRUE;
9429
9430 corrupt_file:
9431   {
9432     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9433         (_("This file is corrupt and cannot be played.")), (NULL));
9434     return FALSE;
9435   }
9436 no_samples:
9437   {
9438     gst_qtdemux_stbl_free (stream);
9439     if (!qtdemux->fragmented) {
9440       /* not quite good */
9441       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9442       return FALSE;
9443     } else {
9444       /* may pick up samples elsewhere */
9445       return TRUE;
9446     }
9447   }
9448 }
9449
9450 /* collect samples from the next sample to be parsed up to sample @n for @stream
9451  * by reading the info from @stbl
9452  *
9453  * This code can be executed from both the streaming thread and the seeking
9454  * thread so it takes the object lock to protect itself
9455  */
9456 static gboolean
9457 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9458 {
9459   gint i, j, k;
9460   QtDemuxSample *samples, *first, *cur, *last;
9461   guint32 n_samples_per_chunk;
9462   guint32 n_samples;
9463
9464   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9465       GST_FOURCC_FORMAT ", pad %s",
9466       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9467       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9468
9469   n_samples = stream->n_samples;
9470
9471   if (n >= n_samples)
9472     goto out_of_samples;
9473
9474   GST_OBJECT_LOCK (qtdemux);
9475   if (n <= stream->stbl_index)
9476     goto already_parsed;
9477
9478   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9479
9480   if (!stream->stsz.data) {
9481     /* so we already parsed and passed all the moov samples;
9482      * onto fragmented ones */
9483     g_assert (qtdemux->fragmented);
9484     goto done;
9485   }
9486
9487   /* pointer to the sample table */
9488   samples = stream->samples;
9489
9490   /* starts from -1, moves to the next sample index to parse */
9491   stream->stbl_index++;
9492
9493   /* keep track of the first and last sample to fill */
9494   first = &samples[stream->stbl_index];
9495   last = &samples[n];
9496
9497   if (!stream->chunks_are_samples) {
9498     /* set the sample sizes */
9499     if (stream->sample_size == 0) {
9500       /* different sizes for each sample */
9501       for (cur = first; cur <= last; cur++) {
9502         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9503         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9504             (guint) (cur - samples), cur->size);
9505       }
9506     } else {
9507       /* samples have the same size */
9508       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9509       for (cur = first; cur <= last; cur++)
9510         cur->size = stream->sample_size;
9511     }
9512   }
9513
9514   n_samples_per_chunk = stream->n_samples_per_chunk;
9515   cur = first;
9516
9517   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9518     guint32 last_chunk;
9519
9520     if (stream->stsc_chunk_index >= stream->last_chunk
9521         || stream->stsc_chunk_index < stream->first_chunk) {
9522       stream->first_chunk =
9523           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9524       stream->samples_per_chunk =
9525           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9526       /* starts from 1 */
9527       stream->stsd_sample_description_id =
9528           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9529
9530       /* chunk numbers are counted from 1 it seems */
9531       if (G_UNLIKELY (stream->first_chunk == 0))
9532         goto corrupt_file;
9533
9534       --stream->first_chunk;
9535
9536       /* the last chunk of each entry is calculated by taking the first chunk
9537        * of the next entry; except if there is no next, where we fake it with
9538        * INT_MAX */
9539       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9540         stream->last_chunk = G_MAXUINT32;
9541       } else {
9542         stream->last_chunk =
9543             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9544         if (G_UNLIKELY (stream->last_chunk == 0))
9545           goto corrupt_file;
9546
9547         --stream->last_chunk;
9548       }
9549
9550       GST_LOG_OBJECT (qtdemux,
9551           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9552           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9553           stream->samples_per_chunk, stream->stsd_sample_description_id);
9554
9555       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9556         goto corrupt_file;
9557
9558       if (stream->last_chunk != G_MAXUINT32) {
9559         if (!qt_atom_parser_peek_sub (&stream->stco,
9560                 stream->first_chunk * stream->co_size,
9561                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9562                 &stream->co_chunk))
9563           goto corrupt_file;
9564
9565       } else {
9566         stream->co_chunk = stream->stco;
9567         if (!gst_byte_reader_skip (&stream->co_chunk,
9568                 stream->first_chunk * stream->co_size))
9569           goto corrupt_file;
9570       }
9571
9572       stream->stsc_chunk_index = stream->first_chunk;
9573     }
9574
9575     last_chunk = stream->last_chunk;
9576
9577     if (stream->chunks_are_samples) {
9578       cur = &samples[stream->stsc_chunk_index];
9579
9580       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9581         if (j > n) {
9582           /* save state */
9583           stream->stsc_chunk_index = j;
9584           goto done;
9585         }
9586
9587         cur->offset =
9588             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9589             stream->co_size);
9590
9591         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9592             "%" G_GUINT64_FORMAT, j, cur->offset);
9593
9594         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9595             CUR_STREAM (stream)->bytes_per_frame > 0) {
9596           cur->size =
9597               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9598               CUR_STREAM (stream)->samples_per_frame *
9599               CUR_STREAM (stream)->bytes_per_frame;
9600         } else {
9601           cur->size = stream->samples_per_chunk;
9602         }
9603
9604         GST_DEBUG_OBJECT (qtdemux,
9605             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9606             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9607                     stream->stco_sample_index)), cur->size);
9608
9609         cur->timestamp = stream->stco_sample_index;
9610         cur->duration = stream->samples_per_chunk;
9611         cur->keyframe = TRUE;
9612         cur++;
9613
9614         stream->stco_sample_index += stream->samples_per_chunk;
9615       }
9616       stream->stsc_chunk_index = j;
9617     } else {
9618       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9619         guint32 samples_per_chunk;
9620         guint64 chunk_offset;
9621
9622         if (!stream->stsc_sample_index
9623             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9624                 &stream->chunk_offset))
9625           goto corrupt_file;
9626
9627         samples_per_chunk = stream->samples_per_chunk;
9628         chunk_offset = stream->chunk_offset;
9629
9630         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9631           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9632               G_GUINT64_FORMAT " and size %d",
9633               (guint) (cur - samples), chunk_offset, cur->size);
9634
9635           cur->offset = chunk_offset;
9636           chunk_offset += cur->size;
9637           cur++;
9638
9639           if (G_UNLIKELY (cur > last)) {
9640             /* save state */
9641             stream->stsc_sample_index = k + 1;
9642             stream->chunk_offset = chunk_offset;
9643             stream->stsc_chunk_index = j;
9644             goto done2;
9645           }
9646         }
9647         stream->stsc_sample_index = 0;
9648       }
9649       stream->stsc_chunk_index = j;
9650     }
9651     stream->stsc_index++;
9652   }
9653
9654   if (stream->chunks_are_samples)
9655     goto ctts;
9656 done2:
9657   {
9658     guint32 n_sample_times;
9659
9660     n_sample_times = stream->n_sample_times;
9661     cur = first;
9662
9663     for (i = stream->stts_index; i < n_sample_times; i++) {
9664       guint32 stts_samples;
9665       gint32 stts_duration;
9666       gint64 stts_time;
9667
9668       if (stream->stts_sample_index >= stream->stts_samples
9669           || !stream->stts_sample_index) {
9670
9671         stream->stts_samples =
9672             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9673         stream->stts_duration =
9674             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9675
9676         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9677             i, stream->stts_samples, stream->stts_duration);
9678
9679         stream->stts_sample_index = 0;
9680       }
9681
9682       stts_samples = stream->stts_samples;
9683       stts_duration = stream->stts_duration;
9684       stts_time = stream->stts_time;
9685
9686       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9687         GST_DEBUG_OBJECT (qtdemux,
9688             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9689             (guint) (cur - samples), j,
9690             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9691
9692         cur->timestamp = stts_time;
9693         cur->duration = stts_duration;
9694
9695         /* avoid 32-bit wrap-around,
9696          * but still mind possible 'negative' duration */
9697         stts_time += (gint64) stts_duration;
9698         cur++;
9699
9700         if (G_UNLIKELY (cur > last)) {
9701           /* save values */
9702           stream->stts_time = stts_time;
9703           stream->stts_sample_index = j + 1;
9704           if (stream->stts_sample_index >= stream->stts_samples)
9705             stream->stts_index++;
9706           goto done3;
9707         }
9708       }
9709       stream->stts_sample_index = 0;
9710       stream->stts_time = stts_time;
9711       stream->stts_index++;
9712     }
9713     /* fill up empty timestamps with the last timestamp, this can happen when
9714      * the last samples do not decode and so we don't have timestamps for them.
9715      * We however look at the last timestamp to estimate the track length so we
9716      * need something in here. */
9717     for (; cur < last; cur++) {
9718       GST_DEBUG_OBJECT (qtdemux,
9719           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9720           (guint) (cur - samples),
9721           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9722       cur->timestamp = stream->stts_time;
9723       cur->duration = -1;
9724     }
9725   }
9726 done3:
9727   {
9728     /* sample sync, can be NULL */
9729     if (stream->stss_present == TRUE) {
9730       guint32 n_sample_syncs;
9731
9732       n_sample_syncs = stream->n_sample_syncs;
9733
9734       if (!n_sample_syncs) {
9735         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9736         stream->all_keyframe = TRUE;
9737       } else {
9738         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9739           /* note that the first sample is index 1, not 0 */
9740           guint32 index;
9741
9742           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9743
9744           if (G_LIKELY (index > 0 && index <= n_samples)) {
9745             index -= 1;
9746             samples[index].keyframe = TRUE;
9747             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9748             /* and exit if we have enough samples */
9749             if (G_UNLIKELY (index >= n)) {
9750               i++;
9751               break;
9752             }
9753           }
9754         }
9755         /* save state */
9756         stream->stss_index = i;
9757       }
9758
9759       /* stps marks partial sync frames like open GOP I-Frames */
9760       if (stream->stps_present == TRUE) {
9761         guint32 n_sample_partial_syncs;
9762
9763         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9764
9765         /* if there are no entries, the stss table contains the real
9766          * sync samples */
9767         if (n_sample_partial_syncs) {
9768           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9769             /* note that the first sample is index 1, not 0 */
9770             guint32 index;
9771
9772             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9773
9774             if (G_LIKELY (index > 0 && index <= n_samples)) {
9775               index -= 1;
9776               samples[index].keyframe = TRUE;
9777               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9778               /* and exit if we have enough samples */
9779               if (G_UNLIKELY (index >= n)) {
9780                 i++;
9781                 break;
9782               }
9783             }
9784           }
9785           /* save state */
9786           stream->stps_index = i;
9787         }
9788       }
9789     } else {
9790       /* no stss, all samples are keyframes */
9791       stream->all_keyframe = TRUE;
9792       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9793     }
9794   }
9795
9796 ctts:
9797   /* composition time to sample */
9798   if (stream->ctts_present == TRUE) {
9799     guint32 n_composition_times;
9800     guint32 ctts_count;
9801     gint32 ctts_soffset;
9802
9803     /* Fill in the pts_offsets */
9804     cur = first;
9805     n_composition_times = stream->n_composition_times;
9806
9807     for (i = stream->ctts_index; i < n_composition_times; i++) {
9808       if (stream->ctts_sample_index >= stream->ctts_count
9809           || !stream->ctts_sample_index) {
9810         stream->ctts_count =
9811             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9812         stream->ctts_soffset =
9813             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9814         stream->ctts_sample_index = 0;
9815       }
9816
9817       ctts_count = stream->ctts_count;
9818       ctts_soffset = stream->ctts_soffset;
9819
9820       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9821         cur->pts_offset = ctts_soffset;
9822         cur++;
9823
9824         if (G_UNLIKELY (cur > last)) {
9825           /* save state */
9826           stream->ctts_sample_index = j + 1;
9827           goto done;
9828         }
9829       }
9830       stream->ctts_sample_index = 0;
9831       stream->ctts_index++;
9832     }
9833   }
9834 done:
9835   stream->stbl_index = n;
9836   /* if index has been completely parsed, free data that is no-longer needed */
9837   if (n + 1 == stream->n_samples) {
9838     gst_qtdemux_stbl_free (stream);
9839     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9840     if (qtdemux->pullbased) {
9841       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9842       while (n + 1 == stream->n_samples)
9843         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9844           break;
9845     }
9846   }
9847   GST_OBJECT_UNLOCK (qtdemux);
9848
9849   return TRUE;
9850
9851   /* SUCCESS */
9852 already_parsed:
9853   {
9854     GST_LOG_OBJECT (qtdemux,
9855         "Tried to parse up to sample %u but this sample has already been parsed",
9856         n);
9857     /* if fragmented, there may be more */
9858     if (qtdemux->fragmented && n == stream->stbl_index)
9859       goto done;
9860     GST_OBJECT_UNLOCK (qtdemux);
9861     return TRUE;
9862   }
9863   /* ERRORS */
9864 out_of_samples:
9865   {
9866     GST_LOG_OBJECT (qtdemux,
9867         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9868         stream->n_samples);
9869     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9870         (_("This file is corrupt and cannot be played.")), (NULL));
9871     return FALSE;
9872   }
9873 corrupt_file:
9874   {
9875     GST_OBJECT_UNLOCK (qtdemux);
9876     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9877         (_("This file is corrupt and cannot be played.")), (NULL));
9878     return FALSE;
9879   }
9880 }
9881
9882 /* collect all segment info for @stream.
9883  */
9884 static gboolean
9885 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9886     GNode * trak)
9887 {
9888   GNode *edts;
9889   /* accept edts if they contain gaps at start and there is only
9890    * one media segment */
9891   gboolean allow_pushbased_edts = TRUE;
9892   gint media_segments_count = 0;
9893
9894   /* parse and prepare segment info from the edit list */
9895   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9896   stream->n_segments = 0;
9897   stream->segments = NULL;
9898   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9899     GNode *elst;
9900     gint n_segments;
9901     gint segment_number, entry_size;
9902     guint64 time;
9903     GstClockTime stime;
9904     const guint8 *buffer;
9905     guint8 version;
9906     guint32 size;
9907
9908     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9909     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9910       goto done;
9911
9912     buffer = elst->data;
9913
9914     size = QT_UINT32 (buffer);
9915     /* version, flags, n_segments */
9916     if (size < 16) {
9917       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9918       goto done;
9919     }
9920     version = QT_UINT8 (buffer + 8);
9921     entry_size = (version == 1) ? 20 : 12;
9922
9923     n_segments = QT_UINT32 (buffer + 12);
9924
9925     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9926       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9927       goto done;
9928     }
9929
9930     /* we might allocate a bit too much, at least allocate 1 segment */
9931     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9932
9933     /* segments always start from 0 */
9934     time = 0;
9935     stime = 0;
9936     buffer += 16;
9937     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9938       guint64 duration;
9939       guint64 media_time;
9940       gboolean empty_edit = FALSE;
9941       QtDemuxSegment *segment;
9942       guint32 rate_int;
9943       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9944
9945       if (version == 1) {
9946         media_time = QT_UINT64 (buffer + 8);
9947         duration = QT_UINT64 (buffer);
9948         if (media_time == G_MAXUINT64)
9949           empty_edit = TRUE;
9950       } else {
9951         media_time = QT_UINT32 (buffer + 4);
9952         duration = QT_UINT32 (buffer);
9953         if (media_time == G_MAXUINT32)
9954           empty_edit = TRUE;
9955       }
9956
9957       if (!empty_edit)
9958         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9959
9960       segment = &stream->segments[segment_number];
9961
9962       /* time and duration expressed in global timescale */
9963       segment->time = stime;
9964       if (duration != 0 || empty_edit) {
9965         /* edge case: empty edits with duration=zero are treated here.
9966          * (files should not have these anyway). */
9967
9968         /* add non scaled values so we don't cause roundoff errors */
9969         time += duration;
9970         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9971         segment->duration = stime - segment->time;
9972       } else {
9973         /* zero duration does not imply media_start == media_stop
9974          * but, only specify media_start. The edit ends with the track. */
9975         stime = segment->duration = GST_CLOCK_TIME_NONE;
9976         /* Don't allow more edits after this one. */
9977         n_segments = segment_number + 1;
9978       }
9979       segment->stop_time = stime;
9980
9981       segment->trak_media_start = media_time;
9982       /* media_time expressed in stream timescale */
9983       if (!empty_edit) {
9984         segment->media_start = media_start;
9985         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9986             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9987         media_segments_count++;
9988       } else {
9989         segment->media_start = GST_CLOCK_TIME_NONE;
9990         segment->media_stop = GST_CLOCK_TIME_NONE;
9991       }
9992       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9993
9994       if (rate_int <= 1) {
9995         /* 0 is not allowed, some programs write 1 instead of the floating point
9996          * value */
9997         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9998             rate_int);
9999         segment->rate = 1;
10000       } else {
10001         segment->rate = rate_int / 65536.0;
10002       }
10003
10004       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10005           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10006           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10007           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10008           segment_number, GST_TIME_ARGS (segment->time),
10009           GST_TIME_ARGS (segment->duration),
10010           GST_TIME_ARGS (segment->media_start), media_time,
10011           GST_TIME_ARGS (segment->media_stop),
10012           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10013           stream->timescale);
10014       if (segment->stop_time > qtdemux->segment.stop &&
10015           !qtdemux->upstream_format_is_time) {
10016         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10017             " extends to %" GST_TIME_FORMAT
10018             " past the end of the declared movie duration %" GST_TIME_FORMAT
10019             " movie segment will be extended", segment_number,
10020             GST_TIME_ARGS (segment->stop_time),
10021             GST_TIME_ARGS (qtdemux->segment.stop));
10022         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10023       }
10024
10025       buffer += entry_size;
10026     }
10027     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10028     stream->n_segments = n_segments;
10029     if (media_segments_count != 1)
10030       allow_pushbased_edts = FALSE;
10031   }
10032 done:
10033
10034   /* push based does not handle segments, so act accordingly here,
10035    * and warn if applicable */
10036   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10037     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10038     /* remove and use default one below, we stream like it anyway */
10039     g_free (stream->segments);
10040     stream->segments = NULL;
10041     stream->n_segments = 0;
10042   }
10043
10044   /* no segments, create one to play the complete trak */
10045   if (stream->n_segments == 0) {
10046     GstClockTime stream_duration =
10047         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10048
10049     if (stream->segments == NULL)
10050       stream->segments = g_new (QtDemuxSegment, 1);
10051
10052     /* represent unknown our way */
10053     if (stream_duration == 0)
10054       stream_duration = GST_CLOCK_TIME_NONE;
10055
10056     stream->segments[0].time = 0;
10057     stream->segments[0].stop_time = stream_duration;
10058     stream->segments[0].duration = stream_duration;
10059     stream->segments[0].media_start = 0;
10060     stream->segments[0].media_stop = stream_duration;
10061     stream->segments[0].rate = 1.0;
10062     stream->segments[0].trak_media_start = 0;
10063
10064     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10065         GST_TIME_ARGS (stream_duration));
10066     stream->n_segments = 1;
10067     stream->dummy_segment = TRUE;
10068   }
10069   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10070
10071   return TRUE;
10072 }
10073
10074 /*
10075  * Parses the stsd atom of a svq3 trak looking for
10076  * the SMI and gama atoms.
10077  */
10078 static void
10079 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10080     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10081 {
10082   const guint8 *_gamma = NULL;
10083   GstBuffer *_seqh = NULL;
10084   const guint8 *stsd_data = stsd_entry_data;
10085   guint32 length = QT_UINT32 (stsd_data);
10086   guint16 version;
10087
10088   if (length < 32) {
10089     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10090     goto end;
10091   }
10092
10093   stsd_data += 16;
10094   length -= 16;
10095   version = QT_UINT16 (stsd_data);
10096   if (version == 3) {
10097     if (length >= 70) {
10098       length -= 70;
10099       stsd_data += 70;
10100       while (length > 8) {
10101         guint32 fourcc, size;
10102         const guint8 *data;
10103         size = QT_UINT32 (stsd_data);
10104         fourcc = QT_FOURCC (stsd_data + 4);
10105         data = stsd_data + 8;
10106
10107         if (size == 0) {
10108           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10109               "svq3 atom parsing");
10110           goto end;
10111         }
10112
10113         switch (fourcc) {
10114           case FOURCC_gama:{
10115             if (size == 12) {
10116               _gamma = data;
10117             } else {
10118               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10119                   " for gama atom, expected 12", size);
10120             }
10121             break;
10122           }
10123           case FOURCC_SMI_:{
10124             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10125               guint32 seqh_size;
10126               if (_seqh != NULL) {
10127                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10128                     " found, ignoring");
10129               } else {
10130                 seqh_size = QT_UINT32 (data + 4);
10131                 if (seqh_size > 0) {
10132                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10133                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10134                 }
10135               }
10136             }
10137             break;
10138           }
10139           default:{
10140             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10141                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10142           }
10143         }
10144
10145         if (size <= length) {
10146           length -= size;
10147           stsd_data += size;
10148         }
10149       }
10150     } else {
10151       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10152     }
10153   } else {
10154     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10155         G_GUINT16_FORMAT, version);
10156     goto end;
10157   }
10158
10159 end:
10160   if (gamma) {
10161     *gamma = _gamma;
10162   }
10163   if (seqh) {
10164     *seqh = _seqh;
10165   } else if (_seqh) {
10166     gst_buffer_unref (_seqh);
10167   }
10168 }
10169
10170 static gchar *
10171 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10172 {
10173   GNode *dinf;
10174   GstByteReader dref;
10175   gchar *uri = NULL;
10176
10177   /*
10178    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10179    * atom that might contain a 'data' atom with the rtsp uri.
10180    * This case was reported in bug #597497, some info about
10181    * the hndl atom can be found in TN1195
10182    */
10183   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10184   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10185
10186   if (dinf) {
10187     guint32 dref_num_entries = 0;
10188     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10189         gst_byte_reader_skip (&dref, 4) &&
10190         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10191       gint i;
10192
10193       /* search dref entries for hndl atom */
10194       for (i = 0; i < dref_num_entries; i++) {
10195         guint32 size = 0, type;
10196         guint8 string_len = 0;
10197         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10198             qt_atom_parser_get_fourcc (&dref, &type)) {
10199           if (type == FOURCC_hndl) {
10200             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10201
10202             /* skip data reference handle bytes and the
10203              * following pascal string and some extra 4
10204              * bytes I have no idea what are */
10205             if (!gst_byte_reader_skip (&dref, 4) ||
10206                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10207                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10208               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10209               break;
10210             }
10211
10212             /* iterate over the atoms to find the data atom */
10213             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10214               guint32 atom_size;
10215               guint32 atom_type;
10216
10217               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10218                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10219                 if (atom_type == FOURCC_data) {
10220                   const guint8 *uri_aux = NULL;
10221
10222                   /* found the data atom that might contain the rtsp uri */
10223                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10224                       "hndl atom, interpreting it as an URI");
10225                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10226                           &uri_aux)) {
10227                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10228                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10229                     else
10230                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10231                           "didn't contain a rtsp address");
10232                   } else {
10233                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10234                         "atom contents");
10235                   }
10236                   break;
10237                 }
10238                 /* skipping to the next entry */
10239                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10240                   break;
10241               } else {
10242                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10243                     "atom header");
10244                 break;
10245               }
10246             }
10247             break;
10248           }
10249           /* skip to the next entry */
10250           if (!gst_byte_reader_skip (&dref, size - 8))
10251             break;
10252         } else {
10253           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10254         }
10255       }
10256       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10257     }
10258   }
10259   return uri;
10260 }
10261
10262 #define AMR_NB_ALL_MODES        0x81ff
10263 #define AMR_WB_ALL_MODES        0x83ff
10264 static guint
10265 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10266 {
10267   /* The 'damr' atom is of the form:
10268    *
10269    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10270    *    32 b       8 b          16 b           8 b                 8 b
10271    *
10272    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10273    * represents the highest mode used in the stream (and thus the maximum
10274    * bitrate), with a couple of special cases as seen below.
10275    */
10276
10277   /* Map of frame type ID -> bitrate */
10278   static const guint nb_bitrates[] = {
10279     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10280   };
10281   static const guint wb_bitrates[] = {
10282     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10283   };
10284   GstMapInfo map;
10285   gsize max_mode;
10286   guint16 mode_set;
10287
10288   gst_buffer_map (buf, &map, GST_MAP_READ);
10289
10290   if (map.size != 0x11) {
10291     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10292     goto bad_data;
10293   }
10294
10295   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10296     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10297         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10298     goto bad_data;
10299   }
10300
10301   mode_set = QT_UINT16 (map.data + 13);
10302
10303   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10304     max_mode = 7 + (wb ? 1 : 0);
10305   else
10306     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10307     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10308
10309   if (max_mode == -1) {
10310     GST_DEBUG ("No mode indication was found (mode set) = %x",
10311         (guint) mode_set);
10312     goto bad_data;
10313   }
10314
10315   gst_buffer_unmap (buf, &map);
10316   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10317
10318 bad_data:
10319   gst_buffer_unmap (buf, &map);
10320   return 0;
10321 }
10322
10323 static gboolean
10324 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10325     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10326 {
10327   /*
10328    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10329    * [0 1 2]
10330    * [3 4 5]
10331    * [6 7 8]
10332    */
10333
10334   if (gst_byte_reader_get_remaining (reader) < 36)
10335     return FALSE;
10336
10337   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10338   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10339   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10340   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10341   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10342   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10343   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10344   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10345   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10346
10347   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10348   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10349       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10350       matrix[2] & 0xFF);
10351   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10352       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10353       matrix[5] & 0xFF);
10354   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10355       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10356       matrix[8] & 0xFF);
10357
10358   return TRUE;
10359 }
10360
10361 static void
10362 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10363     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10364 {
10365
10366 /* [a b c]
10367  * [d e f]
10368  * [g h i]
10369  *
10370  * This macro will only compare value abdegh, it expects cfi to have already
10371  * been checked
10372  */
10373 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10374                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10375
10376   /* only handle the cases where the last column has standard values */
10377   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10378     const gchar *rotation_tag = NULL;
10379
10380     /* no rotation needed */
10381     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10382       /* NOP */
10383     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10384       rotation_tag = "rotate-90";
10385     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10386       rotation_tag = "rotate-180";
10387     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10388       rotation_tag = "rotate-270";
10389     } else {
10390       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10391     }
10392
10393     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10394         GST_STR_NULL (rotation_tag));
10395     if (rotation_tag != NULL) {
10396       if (*taglist == NULL)
10397         *taglist = gst_tag_list_new_empty ();
10398       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10399           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10400     }
10401   } else {
10402     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10403   }
10404 }
10405
10406 static gboolean
10407 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10408     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10409 {
10410   GNode *adrm;
10411   guint32 adrm_size;
10412   GstBuffer *adrm_buf = NULL;
10413   QtDemuxAavdEncryptionInfo *info;
10414
10415   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10416   if (G_UNLIKELY (!adrm)) {
10417     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10418     return FALSE;
10419   }
10420   adrm_size = QT_UINT32 (adrm->data);
10421   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10422
10423   stream->protection_scheme_type = FOURCC_aavd;
10424
10425   if (!stream->protection_scheme_info)
10426     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10427
10428   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10429
10430   if (info->default_properties)
10431     gst_structure_free (info->default_properties);
10432   info->default_properties = gst_structure_new ("application/x-aavd",
10433       "encrypted", G_TYPE_BOOLEAN, TRUE,
10434       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10435   gst_buffer_unref (adrm_buf);
10436
10437   *original_fmt = FOURCC_mp4a;
10438   return TRUE;
10439 }
10440
10441 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10442  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10443  * Common Encryption (cenc), the function will also parse the tenc box (defined
10444  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10445  * (typically an enc[v|a|t|s] sample entry); the function will set
10446  * @original_fmt to the fourcc of the original unencrypted stream format.
10447  * Returns TRUE if successful; FALSE otherwise. */
10448 static gboolean
10449 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10450     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10451 {
10452   GNode *sinf;
10453   GNode *frma;
10454   GNode *schm;
10455   GNode *schi;
10456   QtDemuxCencSampleSetInfo *info;
10457   GNode *tenc;
10458   const guint8 *tenc_data;
10459
10460   g_return_val_if_fail (qtdemux != NULL, FALSE);
10461   g_return_val_if_fail (stream != NULL, FALSE);
10462   g_return_val_if_fail (container != NULL, FALSE);
10463   g_return_val_if_fail (original_fmt != NULL, FALSE);
10464
10465   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10466   if (G_UNLIKELY (!sinf)) {
10467     if (stream->protection_scheme_type == FOURCC_cenc
10468         || stream->protection_scheme_type == FOURCC_cbcs) {
10469       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10470           "mandatory for Common Encryption");
10471       return FALSE;
10472     }
10473     return TRUE;
10474   }
10475
10476   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10477   if (G_UNLIKELY (!frma)) {
10478     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10479     return FALSE;
10480   }
10481
10482   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10483   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10484       GST_FOURCC_ARGS (*original_fmt));
10485
10486   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10487   if (!schm) {
10488     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10489     return FALSE;
10490   }
10491   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10492   stream->protection_scheme_version =
10493       QT_UINT32 ((const guint8 *) schm->data + 16);
10494
10495   GST_DEBUG_OBJECT (qtdemux,
10496       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10497       "protection_scheme_version: %#010x",
10498       GST_FOURCC_ARGS (stream->protection_scheme_type),
10499       stream->protection_scheme_version);
10500
10501   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10502   if (!schi) {
10503     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10504     return FALSE;
10505   }
10506   if (stream->protection_scheme_type != FOURCC_cenc &&
10507       stream->protection_scheme_type != FOURCC_piff &&
10508       stream->protection_scheme_type != FOURCC_cbcs) {
10509     GST_ERROR_OBJECT (qtdemux,
10510         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10511         GST_FOURCC_ARGS (stream->protection_scheme_type));
10512     return FALSE;
10513   }
10514
10515   if (G_UNLIKELY (!stream->protection_scheme_info))
10516     stream->protection_scheme_info =
10517         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10518
10519   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10520
10521   if (stream->protection_scheme_type == FOURCC_cenc
10522       || stream->protection_scheme_type == FOURCC_cbcs) {
10523     guint8 is_encrypted;
10524     guint8 iv_size;
10525     guint8 constant_iv_size = 0;
10526     const guint8 *default_kid;
10527     guint8 crypt_byte_block = 0;
10528     guint8 skip_byte_block = 0;
10529     const guint8 *constant_iv = NULL;
10530
10531     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10532     if (!tenc) {
10533       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10534           "which is mandatory for Common Encryption");
10535       return FALSE;
10536     }
10537     tenc_data = (const guint8 *) tenc->data + 12;
10538     is_encrypted = QT_UINT8 (tenc_data + 2);
10539     iv_size = QT_UINT8 (tenc_data + 3);
10540     default_kid = (tenc_data + 4);
10541     if (stream->protection_scheme_type == FOURCC_cbcs) {
10542       guint8 possible_pattern_info;
10543       if (iv_size == 0) {
10544         constant_iv_size = QT_UINT8 (tenc_data + 20);
10545         if (constant_iv_size != 8 && constant_iv_size != 16) {
10546           GST_ERROR_OBJECT (qtdemux,
10547               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10548           return FALSE;
10549         }
10550         constant_iv = (tenc_data + 21);
10551       }
10552       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10553       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10554       skip_byte_block = possible_pattern_info & 0x0f;
10555     }
10556     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10557         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10558         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10559   } else if (stream->protection_scheme_type == FOURCC_piff) {
10560     GstByteReader br;
10561     static const guint8 piff_track_encryption_uuid[] = {
10562       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10563       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10564     };
10565
10566     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10567     if (!tenc) {
10568       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10569           "which is mandatory for Common Encryption");
10570       return FALSE;
10571     }
10572
10573     tenc_data = (const guint8 *) tenc->data + 8;
10574     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10575       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10576       GST_ERROR_OBJECT (qtdemux,
10577           "Unsupported track encryption box with uuid: %s", box_uuid);
10578       g_free (box_uuid);
10579       return FALSE;
10580     }
10581     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10582     gst_byte_reader_init (&br, tenc_data, 20);
10583     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10584       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10585       return FALSE;
10586     }
10587     stream->protection_scheme_type = FOURCC_cenc;
10588   }
10589
10590   return TRUE;
10591 }
10592
10593 static gint
10594 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10595     QtDemuxStream ** stream2)
10596 {
10597   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10598 }
10599
10600 static gboolean
10601 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10602     GNode * stbl)
10603 {
10604   GNode *svmi;
10605
10606   /*parse svmi header if existing */
10607   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10608   if (svmi) {
10609     guint len = QT_UINT32 ((guint8 *) svmi->data);
10610     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10611     if (!version) {
10612       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10613       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10614       guint8 frame_type, frame_layout;
10615       guint32 stereo_mono_change_count;
10616
10617       if (len < 18)
10618         return FALSE;
10619
10620       /* MPEG-A stereo video */
10621       if (qtdemux->major_brand == FOURCC_ss02)
10622         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10623
10624       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10625       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10626       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10627
10628       switch (frame_type) {
10629         case 0:
10630           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10631           break;
10632         case 1:
10633           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10634           break;
10635         case 2:
10636           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10637           break;
10638         case 3:
10639           /* mode 3 is primary/secondary view sequence, ie
10640            * left/right views in separate tracks. See section 7.2
10641            * of ISO/IEC 23000-11:2009 */
10642           /* In the future this might be supported using related
10643            * streams, like an enhancement track - if files like this
10644            * ever exist */
10645           GST_FIXME_OBJECT (qtdemux,
10646               "Implement stereo video in separate streams");
10647       }
10648
10649       if ((frame_layout & 0x1) == 0)
10650         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10651
10652       GST_LOG_OBJECT (qtdemux,
10653           "StereoVideo: composition type: %u, is_left_first: %u",
10654           frame_type, frame_layout);
10655
10656       if (stereo_mono_change_count > 1) {
10657         GST_FIXME_OBJECT (qtdemux,
10658             "Mixed-mono flags are not yet supported in qtdemux.");
10659       }
10660
10661       stream->multiview_mode = mode;
10662       stream->multiview_flags = flags;
10663     }
10664   }
10665
10666   return TRUE;
10667 }
10668
10669 /* parse the traks.
10670  * With each track we associate a new QtDemuxStream that contains all the info
10671  * about the trak.
10672  * traks that do not decode to something (like strm traks) will not have a pad.
10673  */
10674 static gboolean
10675 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10676 {
10677   GstByteReader tkhd;
10678   int offset;
10679   GNode *mdia;
10680   GNode *mdhd;
10681   GNode *hdlr;
10682   GNode *minf;
10683   GNode *stbl;
10684   GNode *stsd;
10685   GNode *mp4a;
10686   GNode *mp4v;
10687   GNode *esds;
10688   GNode *tref;
10689   GNode *udta;
10690
10691   QtDemuxStream *stream = NULL;
10692   const guint8 *stsd_data;
10693   const guint8 *stsd_entry_data;
10694   guint remaining_stsd_len;
10695   guint stsd_entry_count;
10696   guint stsd_index;
10697   guint16 lang_code;            /* quicktime lang code or packed iso code */
10698   guint32 version;
10699   guint32 tkhd_flags = 0;
10700   guint8 tkhd_version = 0;
10701   guint32 w = 0, h = 0;
10702   guint value_size, stsd_len, len;
10703   guint32 track_id;
10704   guint32 dummy;
10705
10706   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10707
10708   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10709       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10710       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10711     goto corrupt_file;
10712
10713   /* pick between 64 or 32 bits */
10714   value_size = tkhd_version == 1 ? 8 : 4;
10715   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10716       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10717     goto corrupt_file;
10718
10719   /* Check if current moov has duplicated track_id */
10720   if (qtdemux_find_stream (qtdemux, track_id))
10721     goto existing_stream;
10722
10723   stream = _create_stream (qtdemux, track_id);
10724   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10725
10726   /* need defaults for fragments */
10727   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10728
10729   if ((tkhd_flags & 1) == 0)
10730     stream->disabled = TRUE;
10731
10732   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10733       tkhd_version, tkhd_flags, stream->track_id);
10734
10735   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10736     goto corrupt_file;
10737
10738   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10739     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10740     if (qtdemux->major_brand != FOURCC_mjp2 ||
10741         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10742       goto corrupt_file;
10743   }
10744
10745   len = QT_UINT32 ((guint8 *) mdhd->data);
10746   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10747   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10748   if (version == 0x01000000) {
10749     if (len < 42)
10750       goto corrupt_file;
10751     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10752     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10753     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10754   } else {
10755     if (len < 30)
10756       goto corrupt_file;
10757     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10758     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10759     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10760   }
10761
10762   if (lang_code < 0x400) {
10763     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10764   } else if (lang_code == 0x7fff) {
10765     stream->lang_id[0] = 0;     /* unspecified */
10766   } else {
10767     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10768     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10769     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10770     stream->lang_id[3] = 0;
10771   }
10772
10773   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10774       stream->timescale);
10775   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10776       stream->duration);
10777   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10778       lang_code, stream->lang_id);
10779
10780   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10781     goto corrupt_file;
10782
10783   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10784     /* chapters track reference */
10785     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10786     if (chap) {
10787       gsize length = GST_READ_UINT32_BE (chap->data);
10788       if (qtdemux->chapters_track_id)
10789         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10790
10791       if (length >= 12) {
10792         qtdemux->chapters_track_id =
10793             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10794       }
10795     }
10796   }
10797
10798   /* fragmented files may have bogus duration in moov */
10799   if (!qtdemux->fragmented &&
10800       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10801     guint64 tdur1, tdur2;
10802
10803     /* don't overflow */
10804     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10805     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10806
10807     /* HACK:
10808      * some of those trailers, nowadays, have prologue images that are
10809      * themselves video tracks as well. I haven't really found a way to
10810      * identify those yet, except for just looking at their duration. */
10811     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10812       GST_WARNING_OBJECT (qtdemux,
10813           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10814           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10815           "found, assuming preview image or something; skipping track",
10816           stream->duration, stream->timescale, qtdemux->duration,
10817           qtdemux->timescale);
10818       gst_qtdemux_stream_unref (stream);
10819       return TRUE;
10820     }
10821   }
10822
10823   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10824     goto corrupt_file;
10825
10826   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10827       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10828
10829   len = QT_UINT32 ((guint8 *) hdlr->data);
10830   if (len >= 20)
10831     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10832   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10833       GST_FOURCC_ARGS (stream->subtype));
10834
10835   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10836     goto corrupt_file;
10837
10838   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10839     goto corrupt_file;
10840
10841   /* Parse out svmi (and later st3d/sv3d) atoms */
10842   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10843     goto corrupt_file;
10844
10845   /* parse rest of tkhd */
10846   if (stream->subtype == FOURCC_vide) {
10847     guint32 matrix[9];
10848
10849     /* version 1 uses some 64-bit ints */
10850     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10851       goto corrupt_file;
10852
10853     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10854       goto corrupt_file;
10855
10856     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10857         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10858       goto corrupt_file;
10859
10860     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10861         &stream->stream_tags);
10862   }
10863
10864   /* parse stsd */
10865   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10866     goto corrupt_file;
10867   stsd_data = (const guint8 *) stsd->data;
10868
10869   /* stsd should at least have one entry */
10870   stsd_len = QT_UINT32 (stsd_data);
10871   if (stsd_len < 24) {
10872     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10873     if (stream->subtype == FOURCC_vivo) {
10874       gst_qtdemux_stream_unref (stream);
10875       return TRUE;
10876     } else {
10877       goto corrupt_file;
10878     }
10879   }
10880
10881   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10882   /* each stsd entry must contain at least 8 bytes */
10883   if (stream->stsd_entries_length == 0
10884       || stream->stsd_entries_length > stsd_len / 8) {
10885     stream->stsd_entries_length = 0;
10886     goto corrupt_file;
10887   }
10888   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10889   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10890   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10891
10892   stsd_entry_data = stsd_data + 16;
10893   remaining_stsd_len = stsd_len - 16;
10894   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10895     guint32 fourcc;
10896     gchar *codec = NULL;
10897     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10898
10899     /* and that entry should fit within stsd */
10900     len = QT_UINT32 (stsd_entry_data);
10901     if (len > remaining_stsd_len)
10902       goto corrupt_file;
10903
10904     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10905     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10906         GST_FOURCC_ARGS (entry->fourcc));
10907     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10908
10909     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10910       goto error_encrypted;
10911
10912     if (fourcc == FOURCC_aavd) {
10913       if (stream->subtype != FOURCC_soun) {
10914         GST_ERROR_OBJECT (qtdemux,
10915             "Unexpeced stsd type 'aavd' outside 'soun' track");
10916       } else {
10917         /* encrypted audio with sound sample description v0 */
10918         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10919         stream->protected = TRUE;
10920         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
10921           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10922       }
10923     }
10924
10925     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10926       /* FIXME this looks wrong, there might be multiple children
10927        * with the same type */
10928       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10929       stream->protected = TRUE;
10930       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10931         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10932     }
10933
10934     if (stream->subtype == FOURCC_vide) {
10935       GNode *colr;
10936       GNode *fiel;
10937       GNode *pasp;
10938       gboolean gray;
10939       gint depth, palette_size, palette_count;
10940       guint32 *palette_data = NULL;
10941
10942       entry->sampled = TRUE;
10943
10944       stream->display_width = w >> 16;
10945       stream->display_height = h >> 16;
10946
10947       offset = 16;
10948       if (len < 86)             /* TODO verify */
10949         goto corrupt_file;
10950
10951       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10952       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10953       entry->fps_n = 0;         /* this is filled in later */
10954       entry->fps_d = 0;         /* this is filled in later */
10955       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10956       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10957
10958       /* if color_table_id is 0, ctab atom must follow; however some files
10959        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10960        * if color table is not present we'll correct the value */
10961       if (entry->color_table_id == 0 &&
10962           (len < 90
10963               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10964         entry->color_table_id = -1;
10965       }
10966
10967       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10968           entry->width, entry->height, entry->bits_per_sample,
10969           entry->color_table_id);
10970
10971       depth = entry->bits_per_sample;
10972
10973       /* more than 32 bits means grayscale */
10974       gray = (depth > 32);
10975       /* low 32 bits specify the depth  */
10976       depth &= 0x1F;
10977
10978       /* different number of palette entries is determined by depth. */
10979       palette_count = 0;
10980       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10981         palette_count = (1 << depth);
10982       palette_size = palette_count * 4;
10983
10984       if (entry->color_table_id) {
10985         switch (palette_count) {
10986           case 0:
10987             break;
10988           case 2:
10989             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
10990             break;
10991           case 4:
10992             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
10993             break;
10994           case 16:
10995             if (gray)
10996               palette_data =
10997                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
10998             else
10999               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11000             break;
11001           case 256:
11002             if (gray)
11003               palette_data =
11004                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11005             else
11006               palette_data =
11007                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11008             break;
11009           default:
11010             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11011                 (_("The video in this file might not play correctly.")),
11012                 ("unsupported palette depth %d", depth));
11013             break;
11014         }
11015       } else {
11016         gint i, j, start, end;
11017
11018         if (len < 94)
11019           goto corrupt_file;
11020
11021         /* read table */
11022         start = QT_UINT32 (stsd_entry_data + offset + 70);
11023         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11024         end = QT_UINT16 (stsd_entry_data + offset + 76);
11025
11026         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11027             start, end, palette_count);
11028
11029         if (end > 255)
11030           end = 255;
11031         if (start > end)
11032           start = end;
11033
11034         if (len < 94 + (end - start) * 8)
11035           goto corrupt_file;
11036
11037         /* palette is always the same size */
11038         palette_data = g_malloc0 (256 * 4);
11039         palette_size = 256 * 4;
11040
11041         for (j = 0, i = start; i <= end; j++, i++) {
11042           guint32 a, r, g, b;
11043
11044           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11045           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11046           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11047           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11048
11049           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11050               (g & 0xff00) | (b >> 8);
11051         }
11052       }
11053
11054       if (entry->caps)
11055         gst_caps_unref (entry->caps);
11056
11057       entry->caps =
11058           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11059           &codec);
11060       if (G_UNLIKELY (!entry->caps)) {
11061         g_free (palette_data);
11062         goto unknown_stream;
11063       }
11064
11065       if (codec) {
11066         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11067             GST_TAG_VIDEO_CODEC, codec, NULL);
11068         g_free (codec);
11069         codec = NULL;
11070       }
11071
11072       if (palette_data) {
11073         GstStructure *s;
11074
11075         if (entry->rgb8_palette)
11076           gst_memory_unref (entry->rgb8_palette);
11077         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11078             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11079
11080         s = gst_caps_get_structure (entry->caps, 0);
11081
11082         /* non-raw video has a palette_data property. raw video has the palette as
11083          * an extra plane that we append to the output buffers before we push
11084          * them*/
11085         if (!gst_structure_has_name (s, "video/x-raw")) {
11086           GstBuffer *palette;
11087
11088           palette = gst_buffer_new ();
11089           gst_buffer_append_memory (palette, entry->rgb8_palette);
11090           entry->rgb8_palette = NULL;
11091
11092           gst_caps_set_simple (entry->caps, "palette_data",
11093               GST_TYPE_BUFFER, palette, NULL);
11094           gst_buffer_unref (palette);
11095         }
11096       } else if (palette_count != 0) {
11097         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11098             (NULL), ("Unsupported palette depth %d", depth));
11099       }
11100
11101       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11102           QT_UINT16 (stsd_entry_data + offset + 32));
11103
11104       esds = NULL;
11105       pasp = NULL;
11106       colr = NULL;
11107       fiel = NULL;
11108       /* pick 'the' stsd child */
11109       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11110       // We should skip parsing the stsd for non-protected streams if
11111       // the entry doesn't match the fourcc, since they don't change
11112       // format. However, for protected streams we can have partial
11113       // encryption, where parts of the stream are encrypted and parts
11114       // not. For both parts of such streams, we should ensure the
11115       // esds overrides are parsed for both from the stsd.
11116       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11117         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11118           mp4v = NULL;
11119         else if (!stream->protected)
11120           mp4v = NULL;
11121       }
11122
11123       if (mp4v) {
11124         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11125         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11126         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11127         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11128       }
11129
11130       if (pasp) {
11131         const guint8 *pasp_data = (const guint8 *) pasp->data;
11132         gint len = QT_UINT32 (pasp_data);
11133
11134         if (len == 16) {
11135           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11136           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11137         } else {
11138           CUR_STREAM (stream)->par_w = 0;
11139           CUR_STREAM (stream)->par_h = 0;
11140         }
11141       } else {
11142         CUR_STREAM (stream)->par_w = 0;
11143         CUR_STREAM (stream)->par_h = 0;
11144       }
11145
11146       if (fiel) {
11147         const guint8 *fiel_data = (const guint8 *) fiel->data;
11148         gint len = QT_UINT32 (fiel_data);
11149
11150         if (len == 10) {
11151           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11152           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11153         }
11154       }
11155
11156       if (colr) {
11157         const guint8 *colr_data = (const guint8 *) colr->data;
11158         gint len = QT_UINT32 (colr_data);
11159
11160         if (len == 19 || len == 18) {
11161           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11162
11163           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11164             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11165             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11166             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11167             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11168
11169             CUR_STREAM (stream)->colorimetry.primaries =
11170                 gst_video_color_primaries_from_iso (primaries);
11171             CUR_STREAM (stream)->colorimetry.transfer =
11172                 gst_video_transfer_function_from_iso (transfer_function);
11173             CUR_STREAM (stream)->colorimetry.matrix =
11174                 gst_video_color_matrix_from_iso (matrix);
11175             CUR_STREAM (stream)->colorimetry.range =
11176                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11177                 GST_VIDEO_COLOR_RANGE_16_235;
11178           } else {
11179             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11180           }
11181         } else {
11182           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11183         }
11184       }
11185
11186       if (esds) {
11187         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11188             stream->stream_tags);
11189       } else {
11190         switch (fourcc) {
11191           case FOURCC_H264:
11192           case FOURCC_avc1:
11193           case FOURCC_avc3:
11194           {
11195             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11196             const guint8 *avc_data = stsd_entry_data + 0x56;
11197
11198             /* find avcC */
11199             while (len >= 0x8) {
11200               gint size;
11201
11202               if (QT_UINT32 (avc_data) <= len)
11203                 size = QT_UINT32 (avc_data) - 0x8;
11204               else
11205                 size = len - 0x8;
11206
11207               if (size < 1)
11208                 /* No real data, so break out */
11209                 break;
11210
11211               switch (QT_FOURCC (avc_data + 0x4)) {
11212                 case FOURCC_avcC:
11213                 {
11214                   /* parse, if found */
11215                   GstBuffer *buf;
11216
11217                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11218
11219                   /* First 4 bytes are the length of the atom, the next 4 bytes
11220                    * are the fourcc, the next 1 byte is the version, and the
11221                    * subsequent bytes are profile_tier_level structure like data. */
11222                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11223                       avc_data + 8 + 1, size - 1);
11224                   buf = gst_buffer_new_and_alloc (size);
11225                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11226                   gst_caps_set_simple (entry->caps,
11227                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11228                   gst_buffer_unref (buf);
11229
11230                   break;
11231                 }
11232                 case FOURCC_strf:
11233                 {
11234                   GstBuffer *buf;
11235
11236                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11237
11238                   /* First 4 bytes are the length of the atom, the next 4 bytes
11239                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11240                    * next 1 byte is the version, and the
11241                    * subsequent bytes are sequence parameter set like data. */
11242
11243                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11244                   if (size > 1) {
11245                     gst_codec_utils_h264_caps_set_level_and_profile
11246                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11247
11248                     buf = gst_buffer_new_and_alloc (size);
11249                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11250                     gst_caps_set_simple (entry->caps,
11251                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11252                     gst_buffer_unref (buf);
11253                   }
11254                   break;
11255                 }
11256                 case FOURCC_btrt:
11257                 {
11258                   guint avg_bitrate, max_bitrate;
11259
11260                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11261                   if (size < 12)
11262                     break;
11263
11264                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11265                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11266
11267                   if (!max_bitrate && !avg_bitrate)
11268                     break;
11269
11270                   /* Some muxers seem to swap the average and maximum bitrates
11271                    * (I'm looking at you, YouTube), so we swap for sanity. */
11272                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11273                     guint temp = avg_bitrate;
11274
11275                     avg_bitrate = max_bitrate;
11276                     max_bitrate = temp;
11277                   }
11278
11279                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11280                     gst_tag_list_add (stream->stream_tags,
11281                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11282                         max_bitrate, NULL);
11283                   }
11284                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11285                     gst_tag_list_add (stream->stream_tags,
11286                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11287                         NULL);
11288                   }
11289
11290                   break;
11291                 }
11292
11293                 default:
11294                   break;
11295               }
11296
11297               len -= size + 8;
11298               avc_data += size + 8;
11299             }
11300
11301             break;
11302           }
11303           case FOURCC_H265:
11304           case FOURCC_hvc1:
11305           case FOURCC_hev1:
11306           case FOURCC_dvh1:
11307           case FOURCC_dvhe:
11308           {
11309             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11310             const guint8 *hevc_data = stsd_entry_data + 0x56;
11311
11312             /* find hevc */
11313             while (len >= 0x8) {
11314               gint size;
11315
11316               if (QT_UINT32 (hevc_data) <= len)
11317                 size = QT_UINT32 (hevc_data) - 0x8;
11318               else
11319                 size = len - 0x8;
11320
11321               if (size < 1)
11322                 /* No real data, so break out */
11323                 break;
11324
11325               switch (QT_FOURCC (hevc_data + 0x4)) {
11326                 case FOURCC_hvcC:
11327                 {
11328                   /* parse, if found */
11329                   GstBuffer *buf;
11330
11331                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11332
11333                   /* First 4 bytes are the length of the atom, the next 4 bytes
11334                    * are the fourcc, the next 1 byte is the version, and the
11335                    * subsequent bytes are sequence parameter set like data. */
11336                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11337                       (entry->caps, hevc_data + 8 + 1, size - 1);
11338
11339                   buf = gst_buffer_new_and_alloc (size);
11340                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11341                   gst_caps_set_simple (entry->caps,
11342                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11343                   gst_buffer_unref (buf);
11344                   break;
11345                 }
11346                 default:
11347                   break;
11348               }
11349               len -= size + 8;
11350               hevc_data += size + 8;
11351             }
11352             break;
11353           }
11354           case FOURCC_mp4v:
11355           case FOURCC_MP4V:
11356           case FOURCC_fmp4:
11357           case FOURCC_FMP4:
11358           case FOURCC_xvid:
11359           case FOURCC_XVID:
11360           {
11361             GNode *glbl;
11362
11363             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11364                 GST_FOURCC_ARGS (fourcc));
11365
11366             /* codec data might be in glbl extension atom */
11367             glbl = mp4v ?
11368                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11369             if (glbl) {
11370               guint8 *data;
11371               GstBuffer *buf;
11372               gint len;
11373
11374               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11375               data = glbl->data;
11376               len = QT_UINT32 (data);
11377               if (len > 0x8) {
11378                 len -= 0x8;
11379                 buf = gst_buffer_new_and_alloc (len);
11380                 gst_buffer_fill (buf, 0, data + 8, len);
11381                 gst_caps_set_simple (entry->caps,
11382                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11383                 gst_buffer_unref (buf);
11384               }
11385             }
11386             break;
11387           }
11388           case FOURCC_mjp2:
11389           {
11390             /* see annex I of the jpeg2000 spec */
11391             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11392             const guint8 *data;
11393             const gchar *colorspace = NULL;
11394             gint ncomp = 0;
11395             guint32 ncomp_map = 0;
11396             gint32 *comp_map = NULL;
11397             guint32 nchan_def = 0;
11398             gint32 *chan_def = NULL;
11399
11400             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11401             /* some required atoms */
11402             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11403             if (!mjp2)
11404               break;
11405             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11406             if (!jp2h)
11407               break;
11408
11409             /* number of components; redundant with info in codestream, but useful
11410                to a muxer */
11411             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11412             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11413               break;
11414             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11415
11416             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11417             if (!colr)
11418               break;
11419             GST_DEBUG_OBJECT (qtdemux, "found colr");
11420             /* extract colour space info */
11421             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11422               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11423                 case 16:
11424                   colorspace = "sRGB";
11425                   break;
11426                 case 17:
11427                   colorspace = "GRAY";
11428                   break;
11429                 case 18:
11430                   colorspace = "sYUV";
11431                   break;
11432                 default:
11433                   colorspace = NULL;
11434                   break;
11435               }
11436             }
11437             if (!colorspace)
11438               /* colr is required, and only values 16, 17, and 18 are specified,
11439                  so error if we have no colorspace */
11440               break;
11441
11442             /* extract component mapping */
11443             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11444             if (cmap) {
11445               guint32 cmap_len = 0;
11446               int i;
11447               cmap_len = QT_UINT32 (cmap->data);
11448               if (cmap_len >= 8) {
11449                 /* normal box, subtract off header */
11450                 cmap_len -= 8;
11451                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11452                 if (cmap_len % 4 == 0) {
11453                   ncomp_map = (cmap_len / 4);
11454                   comp_map = g_new0 (gint32, ncomp_map);
11455                   for (i = 0; i < ncomp_map; i++) {
11456                     guint16 cmp;
11457                     guint8 mtyp, pcol;
11458                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11459                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11460                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11461                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11462                   }
11463                 }
11464               }
11465             }
11466             /* extract channel definitions */
11467             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11468             if (cdef) {
11469               guint32 cdef_len = 0;
11470               int i;
11471               cdef_len = QT_UINT32 (cdef->data);
11472               if (cdef_len >= 10) {
11473                 /* normal box, subtract off header and len */
11474                 cdef_len -= 10;
11475                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11476                 if (cdef_len % 6 == 0) {
11477                   nchan_def = (cdef_len / 6);
11478                   chan_def = g_new0 (gint32, nchan_def);
11479                   for (i = 0; i < nchan_def; i++)
11480                     chan_def[i] = -1;
11481                   for (i = 0; i < nchan_def; i++) {
11482                     guint16 cn, typ, asoc;
11483                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11484                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11485                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11486                     if (cn < nchan_def) {
11487                       switch (typ) {
11488                         case 0:
11489                           chan_def[cn] = asoc;
11490                           break;
11491                         case 1:
11492                           chan_def[cn] = 0;     /* alpha */
11493                           break;
11494                         default:
11495                           chan_def[cn] = -typ;
11496                       }
11497                     }
11498                   }
11499                 }
11500               }
11501             }
11502
11503             gst_caps_set_simple (entry->caps,
11504                 "num-components", G_TYPE_INT, ncomp, NULL);
11505             gst_caps_set_simple (entry->caps,
11506                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11507
11508             if (comp_map) {
11509               GValue arr = { 0, };
11510               GValue elt = { 0, };
11511               int i;
11512               g_value_init (&arr, GST_TYPE_ARRAY);
11513               g_value_init (&elt, G_TYPE_INT);
11514               for (i = 0; i < ncomp_map; i++) {
11515                 g_value_set_int (&elt, comp_map[i]);
11516                 gst_value_array_append_value (&arr, &elt);
11517               }
11518               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11519                   "component-map", &arr);
11520               g_value_unset (&elt);
11521               g_value_unset (&arr);
11522               g_free (comp_map);
11523             }
11524
11525             if (chan_def) {
11526               GValue arr = { 0, };
11527               GValue elt = { 0, };
11528               int i;
11529               g_value_init (&arr, GST_TYPE_ARRAY);
11530               g_value_init (&elt, G_TYPE_INT);
11531               for (i = 0; i < nchan_def; i++) {
11532                 g_value_set_int (&elt, chan_def[i]);
11533                 gst_value_array_append_value (&arr, &elt);
11534               }
11535               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11536                   "channel-definitions", &arr);
11537               g_value_unset (&elt);
11538               g_value_unset (&arr);
11539               g_free (chan_def);
11540             }
11541
11542             /* some optional atoms */
11543             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11544             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11545
11546             /* indicate possible fields in caps */
11547             if (field) {
11548               data = (guint8 *) field->data + 8;
11549               if (*data != 1)
11550                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11551                     (gint) * data, NULL);
11552             }
11553             /* add codec_data if provided */
11554             if (prefix) {
11555               GstBuffer *buf;
11556               gint len;
11557
11558               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11559               data = prefix->data;
11560               len = QT_UINT32 (data);
11561               if (len > 0x8) {
11562                 len -= 0x8;
11563                 buf = gst_buffer_new_and_alloc (len);
11564                 gst_buffer_fill (buf, 0, data + 8, len);
11565                 gst_caps_set_simple (entry->caps,
11566                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11567                 gst_buffer_unref (buf);
11568               }
11569             }
11570             break;
11571           }
11572           case FOURCC_SVQ3:
11573           case FOURCC_VP31:
11574           {
11575             GstBuffer *buf;
11576             GstBuffer *seqh = NULL;
11577             const guint8 *gamma_data = NULL;
11578             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11579
11580             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11581                 &seqh);
11582             if (gamma_data) {
11583               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11584                   QT_FP32 (gamma_data), NULL);
11585             }
11586             if (seqh) {
11587               /* sorry for the bad name, but we don't know what this is, other
11588                * than its own fourcc */
11589               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11590                   NULL);
11591               gst_buffer_unref (seqh);
11592             }
11593
11594             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11595             buf = gst_buffer_new_and_alloc (len);
11596             gst_buffer_fill (buf, 0, stsd_data, len);
11597             gst_caps_set_simple (entry->caps,
11598                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11599             gst_buffer_unref (buf);
11600             break;
11601           }
11602           case FOURCC_jpeg:
11603           {
11604             /* https://developer.apple.com/standards/qtff-2001.pdf,
11605              * page 92, "Video Sample Description", under table 3.1 */
11606             GstByteReader br;
11607
11608             const gint compressor_offset =
11609                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11610             const gint min_size = compressor_offset + 32 + 2 + 2;
11611             GNode *jpeg;
11612             guint32 len;
11613             guint16 color_table_id = 0;
11614             gboolean ok;
11615
11616             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11617
11618             /* recover information on interlaced/progressive */
11619             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11620             if (!jpeg)
11621               break;
11622
11623             len = QT_UINT32 (jpeg->data);
11624             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11625                 min_size);
11626             if (len >= min_size) {
11627               gst_byte_reader_init (&br, jpeg->data, len);
11628
11629               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11630               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11631               if (color_table_id != 0) {
11632                 /* the spec says there can be concatenated chunks in the data, and we want
11633                  * to find one called field. Walk through them. */
11634                 gint offset = min_size;
11635                 while (offset + 8 < len) {
11636                   guint32 size = 0, tag;
11637                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11638                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11639                   if (!ok || size < 8) {
11640                     GST_WARNING_OBJECT (qtdemux,
11641                         "Failed to walk optional chunk list");
11642                     break;
11643                   }
11644                   GST_DEBUG_OBJECT (qtdemux,
11645                       "Found optional %4.4s chunk, size %u",
11646                       (const char *) &tag, size);
11647                   if (tag == FOURCC_fiel) {
11648                     guint8 n_fields = 0, ordering = 0;
11649                     gst_byte_reader_get_uint8 (&br, &n_fields);
11650                     gst_byte_reader_get_uint8 (&br, &ordering);
11651                     if (n_fields == 1 || n_fields == 2) {
11652                       GST_DEBUG_OBJECT (qtdemux,
11653                           "Found fiel tag with %u fields, ordering %u",
11654                           n_fields, ordering);
11655                       if (n_fields == 2)
11656                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11657                             "interlace-mode", G_TYPE_STRING, "interleaved",
11658                             NULL);
11659                     } else {
11660                       GST_WARNING_OBJECT (qtdemux,
11661                           "Found fiel tag with invalid fields (%u)", n_fields);
11662                     }
11663                   }
11664                   offset += size;
11665                 }
11666               } else {
11667                 GST_DEBUG_OBJECT (qtdemux,
11668                     "Color table ID is 0, not trying to get interlacedness");
11669               }
11670             } else {
11671               GST_WARNING_OBJECT (qtdemux,
11672                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11673             }
11674
11675             break;
11676           }
11677           case FOURCC_rle_:
11678           case FOURCC_WRLE:
11679           {
11680             gst_caps_set_simple (entry->caps,
11681                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11682                 NULL);
11683             break;
11684           }
11685           case FOURCC_XiTh:
11686           {
11687             GNode *xith, *xdxt;
11688
11689             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11690             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11691             if (!xith)
11692               break;
11693
11694             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11695             if (!xdxt)
11696               break;
11697
11698             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11699             /* collect the headers and store them in a stream list so that we can
11700              * send them out first */
11701             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11702             break;
11703           }
11704           case FOURCC_ovc1:
11705           {
11706             GNode *ovc1;
11707             guint8 *ovc1_data;
11708             guint ovc1_len;
11709             GstBuffer *buf;
11710
11711             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11712             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11713             if (!ovc1)
11714               break;
11715             ovc1_data = ovc1->data;
11716             ovc1_len = QT_UINT32 (ovc1_data);
11717             if (ovc1_len <= 198) {
11718               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11719               break;
11720             }
11721             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11722             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11723             gst_caps_set_simple (entry->caps,
11724                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11725             gst_buffer_unref (buf);
11726             break;
11727           }
11728           case FOURCC_vc_1:
11729           {
11730             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11731             const guint8 *vc1_data = stsd_entry_data + 0x56;
11732
11733             /* find dvc1 */
11734             while (len >= 8) {
11735               gint size;
11736
11737               if (QT_UINT32 (vc1_data) <= len)
11738                 size = QT_UINT32 (vc1_data) - 8;
11739               else
11740                 size = len - 8;
11741
11742               if (size < 1)
11743                 /* No real data, so break out */
11744                 break;
11745
11746               switch (QT_FOURCC (vc1_data + 0x4)) {
11747                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11748                 {
11749                   GstBuffer *buf;
11750
11751                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11752                   buf = gst_buffer_new_and_alloc (size);
11753                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11754                   gst_caps_set_simple (entry->caps,
11755                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11756                   gst_buffer_unref (buf);
11757                   break;
11758                 }
11759                 default:
11760                   break;
11761               }
11762               len -= size + 8;
11763               vc1_data += size + 8;
11764             }
11765             break;
11766           }
11767           case FOURCC_av01:
11768           {
11769             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11770             const guint8 *av1_data = stsd_entry_data + 0x56;
11771
11772             /* find av1C */
11773             while (len >= 0x8) {
11774               gint size;
11775
11776               if (QT_UINT32 (av1_data) <= len)
11777                 size = QT_UINT32 (av1_data) - 0x8;
11778               else
11779                 size = len - 0x8;
11780
11781               if (size < 1)
11782                 /* No real data, so break out */
11783                 break;
11784
11785               switch (QT_FOURCC (av1_data + 0x4)) {
11786                 case FOURCC_av1C:
11787                 {
11788                   /* parse, if found */
11789                   GstBuffer *buf;
11790                   guint8 pres_delay_field;
11791
11792                   GST_DEBUG_OBJECT (qtdemux,
11793                       "found av1C codec_data in stsd of size %d", size);
11794
11795                   /* not enough data, just ignore and hope for the best */
11796                   if (size < 5)
11797                     break;
11798
11799                   /* Content is:
11800                    * 4 bytes: atom length
11801                    * 4 bytes: fourcc
11802                    * 1 byte: version
11803                    * 3 bytes: flags
11804                    * 3 bits: reserved
11805                    * 1 bits:  initial_presentation_delay_present
11806                    * 4 bits: initial_presentation_delay (if present else reserved
11807                    * rest: OBUs.
11808                    */
11809
11810                   if (av1_data[9] != 0) {
11811                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11812                     break;
11813                   }
11814
11815                   /* We skip initial_presentation_delay* for now */
11816                   pres_delay_field = *(av1_data + 12);
11817                   if (pres_delay_field & (1 << 5)) {
11818                     gst_caps_set_simple (entry->caps,
11819                         "presentation-delay", G_TYPE_INT,
11820                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11821                   }
11822                   if (size > 5) {
11823                     buf = gst_buffer_new_and_alloc (size - 5);
11824                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11825                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11826                     gst_caps_set_simple (entry->caps,
11827                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11828                     gst_buffer_unref (buf);
11829                   }
11830                   break;
11831                 }
11832                 default:
11833                   break;
11834               }
11835
11836               len -= size + 8;
11837               av1_data += size + 8;
11838             }
11839
11840             break;
11841           }
11842
11843             /* TODO: Need to parse vpcC for VP8 codec too.
11844              * Note that VPCodecConfigurationBox (vpcC) is defined for
11845              * vp08, vp09, and vp10 fourcc. */
11846           case FOURCC_vp09:
11847           {
11848             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11849             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11850
11851             /* find vpcC */
11852             while (len >= 0x8) {
11853               gint size;
11854
11855               if (QT_UINT32 (vpcc_data) <= len)
11856                 size = QT_UINT32 (vpcc_data) - 0x8;
11857               else
11858                 size = len - 0x8;
11859
11860               if (size < 1)
11861                 /* No real data, so break out */
11862                 break;
11863
11864               switch (QT_FOURCC (vpcc_data + 0x4)) {
11865                 case FOURCC_vpcC:
11866                 {
11867                   const gchar *profile_str = NULL;
11868                   const gchar *chroma_format_str = NULL;
11869                   guint8 profile;
11870                   guint8 bitdepth;
11871                   guint8 chroma_format;
11872                   GstVideoColorimetry cinfo;
11873
11874                   /* parse, if found */
11875                   GST_DEBUG_OBJECT (qtdemux,
11876                       "found vp codec_data in stsd of size %d", size);
11877
11878                   /* the meaning of "size" is length of the atom body, excluding
11879                    * atom length and fourcc fields */
11880                   if (size < 12)
11881                     break;
11882
11883                   /* Content is:
11884                    * 4 bytes: atom length
11885                    * 4 bytes: fourcc
11886                    * 1 byte: version
11887                    * 3 bytes: flags
11888                    * 1 byte: profile
11889                    * 1 byte: level
11890                    * 4 bits: bitDepth
11891                    * 3 bits: chromaSubsampling
11892                    * 1 bit: videoFullRangeFlag
11893                    * 1 byte: colourPrimaries
11894                    * 1 byte: transferCharacteristics
11895                    * 1 byte: matrixCoefficients
11896                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11897                    * rest: codecIntializationData (not used for vp8 and vp9)
11898                    */
11899
11900                   if (vpcc_data[8] != 1) {
11901                     GST_WARNING_OBJECT (qtdemux,
11902                         "unknown vpcC version %d", vpcc_data[8]);
11903                     break;
11904                   }
11905
11906                   profile = vpcc_data[12];
11907                   switch (profile) {
11908                     case 0:
11909                       profile_str = "0";
11910                       break;
11911                     case 1:
11912                       profile_str = "1";
11913                       break;
11914                     case 2:
11915                       profile_str = "2";
11916                       break;
11917                     case 3:
11918                       profile_str = "3";
11919                       break;
11920                     default:
11921                       break;
11922                   }
11923
11924                   if (profile_str) {
11925                     gst_caps_set_simple (entry->caps,
11926                         "profile", G_TYPE_STRING, profile_str, NULL);
11927                   }
11928
11929                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11930                    * but webm spec define various ones. Add level to caps
11931                    * if we really need it then */
11932
11933                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11934                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11935                     gst_caps_set_simple (entry->caps,
11936                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11937                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11938                   }
11939
11940                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11941                   switch (chroma_format) {
11942                     case 0:
11943                     case 1:
11944                       chroma_format_str = "4:2:0";
11945                       break;
11946                     case 2:
11947                       chroma_format_str = "4:2:2";
11948                       break;
11949                     case 3:
11950                       chroma_format_str = "4:4:4";
11951                       break;
11952                     default:
11953                       break;
11954                   }
11955
11956                   if (chroma_format_str) {
11957                     gst_caps_set_simple (entry->caps,
11958                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11959                         NULL);
11960                   }
11961
11962                   if ((vpcc_data[14] & 0x1) != 0)
11963                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
11964                   else
11965                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
11966                   cinfo.primaries =
11967                       gst_video_color_primaries_from_iso (vpcc_data[15]);
11968                   cinfo.transfer =
11969                       gst_video_transfer_function_from_iso (vpcc_data[16]);
11970                   cinfo.matrix =
11971                       gst_video_color_matrix_from_iso (vpcc_data[17]);
11972
11973                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
11974                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
11975                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
11976                     /* set this only if all values are known, otherwise this
11977                      * might overwrite valid ones parsed from other color box */
11978                     CUR_STREAM (stream)->colorimetry = cinfo;
11979                   }
11980                   break;
11981                 }
11982                 default:
11983                   break;
11984               }
11985
11986               len -= size + 8;
11987               vpcc_data += size + 8;
11988             }
11989
11990             break;
11991           }
11992           default:
11993             break;
11994         }
11995       }
11996
11997       GST_INFO_OBJECT (qtdemux,
11998           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11999           GST_FOURCC_ARGS (fourcc), entry->caps);
12000
12001     } else if (stream->subtype == FOURCC_soun) {
12002       GNode *wave;
12003       int version, samplesize;
12004       guint16 compression_id;
12005       gboolean amrwb = FALSE;
12006
12007       offset = 16;
12008       /* sample description entry (16) + sound sample description v0 (20) */
12009       if (len < 36)
12010         goto corrupt_file;
12011
12012       version = QT_UINT32 (stsd_entry_data + offset);
12013       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12014       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12015       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12016       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12017
12018       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12019       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12020           QT_UINT32 (stsd_entry_data + offset + 4));
12021       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12022       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12023       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12024       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12025           QT_UINT16 (stsd_entry_data + offset + 14));
12026       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12027
12028       if (compression_id == 0xfffe)
12029         entry->sampled = TRUE;
12030
12031       /* first assume uncompressed audio */
12032       entry->bytes_per_sample = samplesize / 8;
12033       entry->samples_per_frame = entry->n_channels;
12034       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12035       entry->samples_per_packet = entry->samples_per_frame;
12036       entry->bytes_per_packet = entry->bytes_per_sample;
12037
12038       offset = 36;
12039
12040       if (version == 0x00010000) {
12041         /* sample description entry (16) + sound sample description v1 (20+16) */
12042         if (len < 52)
12043           goto corrupt_file;
12044
12045         /* take information from here over the normal sample description */
12046         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12047         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12048         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12049         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12050
12051         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12052         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12053             entry->samples_per_packet);
12054         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12055             entry->bytes_per_packet);
12056         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12057             entry->bytes_per_frame);
12058         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12059             entry->bytes_per_sample);
12060
12061         if (!entry->sampled && entry->bytes_per_packet) {
12062           entry->samples_per_frame = (entry->bytes_per_frame /
12063               entry->bytes_per_packet) * entry->samples_per_packet;
12064           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12065               entry->samples_per_frame);
12066         }
12067       } else if (version == 0x00020000) {
12068         /* sample description entry (16) + sound sample description v2 (56) */
12069         if (len < 72)
12070           goto corrupt_file;
12071
12072         /* take information from here over the normal sample description */
12073         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12074         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12075         entry->samples_per_frame = entry->n_channels;
12076         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12077         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12078         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12079         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12080
12081         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12082         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12083         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12084         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12085             entry->bytes_per_sample * 8);
12086         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12087             QT_UINT32 (stsd_entry_data + offset + 24));
12088         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12089             entry->bytes_per_packet);
12090         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12091             entry->samples_per_packet);
12092       } else if (version != 0x00000) {
12093         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12094             version);
12095       }
12096
12097       switch (fourcc) {
12098           /* Yes, these have to be hard-coded */
12099         case FOURCC_MAC6:
12100         {
12101           entry->samples_per_packet = 6;
12102           entry->bytes_per_packet = 1;
12103           entry->bytes_per_frame = 1 * entry->n_channels;
12104           entry->bytes_per_sample = 1;
12105           entry->samples_per_frame = 6 * entry->n_channels;
12106           break;
12107         }
12108         case FOURCC_MAC3:
12109         {
12110           entry->samples_per_packet = 3;
12111           entry->bytes_per_packet = 1;
12112           entry->bytes_per_frame = 1 * entry->n_channels;
12113           entry->bytes_per_sample = 1;
12114           entry->samples_per_frame = 3 * entry->n_channels;
12115           break;
12116         }
12117         case FOURCC_ima4:
12118         {
12119           entry->samples_per_packet = 64;
12120           entry->bytes_per_packet = 34;
12121           entry->bytes_per_frame = 34 * entry->n_channels;
12122           entry->bytes_per_sample = 2;
12123           entry->samples_per_frame = 64 * entry->n_channels;
12124           break;
12125         }
12126         case FOURCC_ulaw:
12127         case FOURCC_alaw:
12128         {
12129           entry->samples_per_packet = 1;
12130           entry->bytes_per_packet = 1;
12131           entry->bytes_per_frame = 1 * entry->n_channels;
12132           entry->bytes_per_sample = 1;
12133           entry->samples_per_frame = 1 * entry->n_channels;
12134           break;
12135         }
12136         case FOURCC_agsm:
12137         {
12138           entry->samples_per_packet = 160;
12139           entry->bytes_per_packet = 33;
12140           entry->bytes_per_frame = 33 * entry->n_channels;
12141           entry->bytes_per_sample = 2;
12142           entry->samples_per_frame = 160 * entry->n_channels;
12143           break;
12144         }
12145           /* fix up any invalid header information from above */
12146         case FOURCC_twos:
12147         case FOURCC_sowt:
12148         case FOURCC_raw_:
12149         case FOURCC_lpcm:
12150           /* Sometimes these are set to 0 in the sound sample descriptions so
12151            * let's try to infer useful values from the other information we
12152            * have available */
12153           if (entry->bytes_per_sample == 0)
12154             entry->bytes_per_sample =
12155                 entry->bytes_per_frame / entry->n_channels;
12156           if (entry->bytes_per_sample == 0)
12157             entry->bytes_per_sample = samplesize / 8;
12158
12159           if (entry->bytes_per_frame == 0)
12160             entry->bytes_per_frame =
12161                 entry->bytes_per_sample * entry->n_channels;
12162
12163           if (entry->bytes_per_packet == 0)
12164             entry->bytes_per_packet = entry->bytes_per_sample;
12165
12166           if (entry->samples_per_frame == 0)
12167             entry->samples_per_frame = entry->n_channels;
12168
12169           if (entry->samples_per_packet == 0)
12170             entry->samples_per_packet = entry->samples_per_frame;
12171
12172           break;
12173         case FOURCC_in24:
12174         case FOURCC_in32:
12175         case FOURCC_fl32:
12176         case FOURCC_fl64:
12177         case FOURCC_s16l:{
12178           switch (fourcc) {
12179             case FOURCC_in24:
12180               entry->bytes_per_sample = 3;
12181               break;
12182             case FOURCC_in32:
12183             case FOURCC_fl32:
12184               entry->bytes_per_sample = 4;
12185               break;
12186             case FOURCC_fl64:
12187               entry->bytes_per_sample = 8;
12188               break;
12189             case FOURCC_s16l:
12190               entry->bytes_per_sample = 2;
12191               break;
12192             default:
12193               g_assert_not_reached ();
12194               break;
12195           }
12196           entry->samples_per_frame = entry->n_channels;
12197           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12198           entry->samples_per_packet = entry->samples_per_frame;
12199           entry->bytes_per_packet = entry->bytes_per_sample;
12200           break;
12201         }
12202         default:
12203           break;
12204       }
12205
12206       if (entry->caps)
12207         gst_caps_unref (entry->caps);
12208
12209       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12210           stsd_entry_data + 32, len - 16, &codec);
12211
12212       switch (fourcc) {
12213         case FOURCC_in24:
12214         case FOURCC_in32:
12215         case FOURCC_fl32:
12216         case FOURCC_fl64:
12217         {
12218           GNode *enda;
12219           GNode *fmt;
12220
12221           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12222
12223           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12224           if (!enda) {
12225             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12226             if (wave)
12227               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12228           }
12229           if (enda) {
12230             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12231             const gchar *format_str;
12232
12233             switch (fourcc) {
12234               case FOURCC_in24:
12235                 format_str = (enda_value) ? "S24LE" : "S24BE";
12236                 break;
12237               case FOURCC_in32:
12238                 format_str = (enda_value) ? "S32LE" : "S32BE";
12239                 break;
12240               case FOURCC_fl32:
12241                 format_str = (enda_value) ? "F32LE" : "F32BE";
12242                 break;
12243               case FOURCC_fl64:
12244                 format_str = (enda_value) ? "F64LE" : "F64BE";
12245                 break;
12246               default:
12247                 g_assert_not_reached ();
12248                 break;
12249             }
12250             gst_caps_set_simple (entry->caps,
12251                 "format", G_TYPE_STRING, format_str, NULL);
12252           }
12253           break;
12254         }
12255         case FOURCC_owma:
12256         {
12257           const guint8 *owma_data;
12258           const gchar *codec_name = NULL;
12259           guint owma_len;
12260           GstBuffer *buf;
12261           gint version = 1;
12262           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12263           /* FIXME this should also be gst_riff_strf_auds,
12264            * but the latter one is actually missing bits-per-sample :( */
12265           typedef struct
12266           {
12267             gint16 wFormatTag;
12268             gint16 nChannels;
12269             gint32 nSamplesPerSec;
12270             gint32 nAvgBytesPerSec;
12271             gint16 nBlockAlign;
12272             gint16 wBitsPerSample;
12273             gint16 cbSize;
12274           } WAVEFORMATEX;
12275           WAVEFORMATEX *wfex;
12276
12277           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12278           owma_data = stsd_entry_data;
12279           owma_len = QT_UINT32 (owma_data);
12280           if (owma_len <= 54) {
12281             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12282             break;
12283           }
12284           wfex = (WAVEFORMATEX *) (owma_data + 36);
12285           buf = gst_buffer_new_and_alloc (owma_len - 54);
12286           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12287           if (wfex->wFormatTag == 0x0161) {
12288             codec_name = "Windows Media Audio";
12289             version = 2;
12290           } else if (wfex->wFormatTag == 0x0162) {
12291             codec_name = "Windows Media Audio 9 Pro";
12292             version = 3;
12293           } else if (wfex->wFormatTag == 0x0163) {
12294             codec_name = "Windows Media Audio 9 Lossless";
12295             /* is that correct? gstffmpegcodecmap.c is missing it, but
12296              * fluendo codec seems to support it */
12297             version = 4;
12298           }
12299
12300           gst_caps_set_simple (entry->caps,
12301               "codec_data", GST_TYPE_BUFFER, buf,
12302               "wmaversion", G_TYPE_INT, version,
12303               "block_align", G_TYPE_INT,
12304               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12305               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12306               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12307               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12308           gst_buffer_unref (buf);
12309
12310           if (codec_name) {
12311             g_free (codec);
12312             codec = g_strdup (codec_name);
12313           }
12314           break;
12315         }
12316         case FOURCC_wma_:
12317         {
12318           gint len = QT_UINT32 (stsd_entry_data) - offset;
12319           const guint8 *wfex_data = stsd_entry_data + offset;
12320           const gchar *codec_name = NULL;
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           /* FIXME: unify with similar wavformatex parsing code above */
12338           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12339
12340           /* find wfex */
12341           while (len >= 8) {
12342             gint size;
12343
12344             if (QT_UINT32 (wfex_data) <= len)
12345               size = QT_UINT32 (wfex_data) - 8;
12346             else
12347               size = len - 8;
12348
12349             if (size < 1)
12350               /* No real data, so break out */
12351               break;
12352
12353             switch (QT_FOURCC (wfex_data + 4)) {
12354               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12355               {
12356                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12357
12358                 if (size < 8 + 18)
12359                   break;
12360
12361                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12362                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12363                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12364                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12365                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12366                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12367                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12368
12369                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12370                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12371                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12372                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12373                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12374                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12375
12376                 if (wfex.wFormatTag == 0x0161) {
12377                   codec_name = "Windows Media Audio";
12378                   version = 2;
12379                 } else if (wfex.wFormatTag == 0x0162) {
12380                   codec_name = "Windows Media Audio 9 Pro";
12381                   version = 3;
12382                 } else if (wfex.wFormatTag == 0x0163) {
12383                   codec_name = "Windows Media Audio 9 Lossless";
12384                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12385                    * fluendo codec seems to support it */
12386                   version = 4;
12387                 }
12388
12389                 gst_caps_set_simple (entry->caps,
12390                     "wmaversion", G_TYPE_INT, version,
12391                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12392                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12393                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12394                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12395
12396                 if (size > wfex.cbSize) {
12397                   GstBuffer *buf;
12398
12399                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12400                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12401                       size - wfex.cbSize);
12402                   gst_caps_set_simple (entry->caps,
12403                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12404                   gst_buffer_unref (buf);
12405                 } else {
12406                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12407                 }
12408
12409                 if (codec_name) {
12410                   g_free (codec);
12411                   codec = g_strdup (codec_name);
12412                 }
12413                 break;
12414               }
12415               default:
12416                 break;
12417             }
12418             len -= size + 8;
12419             wfex_data += size + 8;
12420           }
12421           break;
12422         }
12423         case FOURCC_opus:
12424         {
12425           const guint8 *opus_data;
12426           guint8 *channel_mapping = NULL;
12427           guint32 rate;
12428           guint8 channels;
12429           guint8 channel_mapping_family;
12430           guint8 stream_count;
12431           guint8 coupled_count;
12432           guint8 i;
12433
12434           opus_data = stsd_entry_data;
12435
12436           channels = GST_READ_UINT8 (opus_data + 45);
12437           rate = GST_READ_UINT32_LE (opus_data + 48);
12438           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12439           stream_count = GST_READ_UINT8 (opus_data + 55);
12440           coupled_count = GST_READ_UINT8 (opus_data + 56);
12441
12442           if (channels > 0) {
12443             channel_mapping = g_malloc (channels * sizeof (guint8));
12444             for (i = 0; i < channels; i++)
12445               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12446           }
12447
12448           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12449               channel_mapping_family, stream_count, coupled_count,
12450               channel_mapping);
12451           break;
12452         }
12453         default:
12454           break;
12455       }
12456
12457       if (codec) {
12458         GstStructure *s;
12459         gint bitrate = 0;
12460
12461         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12462             GST_TAG_AUDIO_CODEC, codec, NULL);
12463         g_free (codec);
12464         codec = NULL;
12465
12466         /* some bitrate info may have ended up in caps */
12467         s = gst_caps_get_structure (entry->caps, 0);
12468         gst_structure_get_int (s, "bitrate", &bitrate);
12469         if (bitrate > 0)
12470           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12471               GST_TAG_BITRATE, bitrate, NULL);
12472       }
12473
12474       esds = NULL;
12475       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12476       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12477         if (stream->protected) {
12478           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12479             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12480           }
12481           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12482             mp4a = NULL;
12483           }
12484         } else {
12485           mp4a = NULL;
12486         }
12487       }
12488
12489       wave = NULL;
12490       if (mp4a) {
12491         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12492         if (wave)
12493           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12494         if (!esds)
12495           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12496       }
12497
12498
12499       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12500          16 bits is a byte-swapped wave-style codec identifier,
12501          and we can find a WAVE header internally to a 'wave' atom here.
12502          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12503          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12504          is big-endian).
12505        */
12506       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12507         if (len < offset + 20) {
12508           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12509         } else {
12510           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12511           const guint8 *data = stsd_entry_data + offset + 16;
12512           GNode *wavenode;
12513           GNode *waveheadernode;
12514
12515           wavenode = g_node_new ((guint8 *) data);
12516           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12517             const guint8 *waveheader;
12518             guint32 headerlen;
12519
12520             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12521             if (waveheadernode) {
12522               waveheader = (const guint8 *) waveheadernode->data;
12523               headerlen = QT_UINT32 (waveheader);
12524
12525               if (headerlen > 8) {
12526                 gst_riff_strf_auds *header = NULL;
12527                 GstBuffer *headerbuf;
12528                 GstBuffer *extra;
12529
12530                 waveheader += 8;
12531                 headerlen -= 8;
12532
12533                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12534                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12535
12536                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12537                         headerbuf, &header, &extra)) {
12538                   gst_caps_unref (entry->caps);
12539                   /* FIXME: Need to do something with the channel reorder map */
12540                   entry->caps =
12541                       gst_riff_create_audio_caps (header->format, NULL, header,
12542                       extra, NULL, NULL, NULL);
12543
12544                   if (extra)
12545                     gst_buffer_unref (extra);
12546                   g_free (header);
12547                 }
12548               }
12549             } else
12550               GST_DEBUG ("Didn't find waveheadernode for this codec");
12551           }
12552           g_node_destroy (wavenode);
12553         }
12554       } else if (esds) {
12555         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12556             stream->stream_tags);
12557       } else {
12558         switch (fourcc) {
12559 #if 0
12560             /* FIXME: what is in the chunk? */
12561           case FOURCC_QDMC:
12562           {
12563             gint len = QT_UINT32 (stsd_data);
12564
12565             /* seems to be always = 116 = 0x74 */
12566             break;
12567           }
12568 #endif
12569           case FOURCC_QDM2:
12570           {
12571             gint len = QT_UINT32 (stsd_entry_data);
12572
12573             if (len > 0x3C) {
12574               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12575
12576               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12577               gst_caps_set_simple (entry->caps,
12578                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12579               gst_buffer_unref (buf);
12580             }
12581             gst_caps_set_simple (entry->caps,
12582                 "samplesize", G_TYPE_INT, samplesize, NULL);
12583             break;
12584           }
12585           case FOURCC_alac:
12586           {
12587             GNode *alac, *wave = NULL;
12588
12589             /* apparently, m4a has this atom appended directly in the stsd entry,
12590              * while mov has it in a wave atom */
12591             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12592             if (alac) {
12593               /* alac now refers to stsd entry atom */
12594               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12595               if (wave)
12596                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12597               else
12598                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12599             }
12600             if (alac) {
12601               const guint8 *alac_data = alac->data;
12602               gint len = QT_UINT32 (alac->data);
12603               GstBuffer *buf;
12604
12605               if (len < 36) {
12606                 GST_DEBUG_OBJECT (qtdemux,
12607                     "discarding alac atom with unexpected len %d", len);
12608               } else {
12609                 /* codec-data contains alac atom size and prefix,
12610                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12611                 buf = gst_buffer_new_and_alloc (len);
12612                 gst_buffer_fill (buf, 0, alac->data, len);
12613                 gst_caps_set_simple (entry->caps,
12614                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12615                 gst_buffer_unref (buf);
12616
12617                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12618                 entry->n_channels = QT_UINT8 (alac_data + 21);
12619                 entry->rate = QT_UINT32 (alac_data + 32);
12620                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12621               }
12622             }
12623             gst_caps_set_simple (entry->caps,
12624                 "samplesize", G_TYPE_INT, samplesize, NULL);
12625             break;
12626           }
12627           case FOURCC_fLaC:
12628           {
12629             /* The codingname of the sample entry is 'fLaC' */
12630             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12631
12632             if (flac) {
12633               /* The 'dfLa' box is added to the sample entry to convey
12634                  initializing information for the decoder. */
12635               const GNode *dfla =
12636                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12637
12638               if (dfla) {
12639                 const guint32 len = QT_UINT32 (dfla->data);
12640
12641                 /* Must contain at least dfLa box header (12),
12642                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12643                 if (len < 50) {
12644                   GST_DEBUG_OBJECT (qtdemux,
12645                       "discarding dfla atom with unexpected len %d", len);
12646                 } else {
12647                   /* skip dfLa header to get the METADATA_BLOCKs */
12648                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12649                   const guint32 metadata_blocks_len = len - 12;
12650
12651                   gchar *stream_marker = g_strdup ("fLaC");
12652                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12653                       strlen (stream_marker));
12654
12655                   guint32 index = 0;
12656                   guint32 remainder = 0;
12657                   guint32 block_size = 0;
12658                   gboolean is_last = FALSE;
12659
12660                   GValue array = G_VALUE_INIT;
12661                   GValue value = G_VALUE_INIT;
12662
12663                   g_value_init (&array, GST_TYPE_ARRAY);
12664                   g_value_init (&value, GST_TYPE_BUFFER);
12665
12666                   gst_value_set_buffer (&value, block);
12667                   gst_value_array_append_value (&array, &value);
12668                   g_value_reset (&value);
12669
12670                   gst_buffer_unref (block);
12671
12672                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12673                    * of data, and we haven't already finished parsing */
12674                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12675                     remainder = metadata_blocks_len - index;
12676
12677                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12678                     block_size = 4 +
12679                         (metadata_blocks[index + 1] << 16) +
12680                         (metadata_blocks[index + 2] << 8) +
12681                         metadata_blocks[index + 3];
12682
12683                     /* be careful not to read off end of box */
12684                     if (block_size > remainder) {
12685                       break;
12686                     }
12687
12688                     is_last = metadata_blocks[index] >> 7;
12689
12690                     block = gst_buffer_new_and_alloc (block_size);
12691
12692                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12693                         block_size);
12694
12695                     gst_value_set_buffer (&value, block);
12696                     gst_value_array_append_value (&array, &value);
12697                     g_value_reset (&value);
12698
12699                     gst_buffer_unref (block);
12700
12701                     index += block_size;
12702                   }
12703
12704                   /* only append the metadata if we successfully read all of it */
12705                   if (is_last) {
12706                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12707                             (stream)->caps, 0), "streamheader", &array);
12708                   } else {
12709                     GST_WARNING_OBJECT (qtdemux,
12710                         "discarding all METADATA_BLOCKs due to invalid "
12711                         "block_size %d at idx %d, rem %d", block_size, index,
12712                         remainder);
12713                   }
12714
12715                   g_value_unset (&value);
12716                   g_value_unset (&array);
12717
12718                   /* The sample rate obtained from the stsd may not be accurate
12719                    * since it cannot represent rates greater than 65535Hz, so
12720                    * override that value with the sample rate from the
12721                    * METADATA_BLOCK_STREAMINFO block */
12722                   CUR_STREAM (stream)->rate =
12723                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12724                 }
12725               }
12726             }
12727             break;
12728           }
12729           case FOURCC_sawb:
12730             /* Fallthrough! */
12731             amrwb = TRUE;
12732           case FOURCC_samr:
12733           {
12734             gint len = QT_UINT32 (stsd_entry_data);
12735
12736             if (len > 0x24) {
12737               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12738               guint bitrate;
12739
12740               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12741
12742               /* If we have enough data, let's try to get the 'damr' atom. See
12743                * the 3GPP container spec (26.244) for more details. */
12744               if ((len - 0x34) > 8 &&
12745                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12746                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12747                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12748               }
12749
12750               gst_caps_set_simple (entry->caps,
12751                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12752               gst_buffer_unref (buf);
12753             }
12754             break;
12755           }
12756           case FOURCC_mp4a:
12757           {
12758             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12759             gint len = QT_UINT32 (stsd_entry_data);
12760             guint16 sound_version = 0;
12761             /* FIXME: Can this be determined somehow? There doesn't seem to be
12762              * anything in mp4a atom that specifis compression */
12763             gint profile = 2;
12764             guint16 channels = entry->n_channels;
12765             guint32 time_scale = (guint32) entry->rate;
12766             gint sample_rate_index = -1;
12767
12768             if (len >= 34) {
12769               sound_version = QT_UINT16 (stsd_entry_data + 16);
12770
12771               if (sound_version == 1) {
12772                 channels = QT_UINT16 (stsd_entry_data + 24);
12773                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12774               } else {
12775                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12776                     sound_version);
12777               }
12778             } else {
12779               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12780                   len);
12781             }
12782
12783             sample_rate_index =
12784                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12785             if (sample_rate_index >= 0 && channels > 0) {
12786               guint8 codec_data[2];
12787               GstBuffer *buf;
12788
12789               /* build AAC codec data */
12790               codec_data[0] = profile << 3;
12791               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12792               codec_data[1] = (sample_rate_index & 0x01) << 7;
12793               codec_data[1] |= (channels & 0xF) << 3;
12794
12795               buf = gst_buffer_new_and_alloc (2);
12796               gst_buffer_fill (buf, 0, codec_data, 2);
12797               gst_caps_set_simple (entry->caps,
12798                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12799               gst_buffer_unref (buf);
12800             }
12801             break;
12802           }
12803           case FOURCC_lpcm:
12804           case FOURCC_in24:
12805           case FOURCC_in32:
12806           case FOURCC_fl32:
12807           case FOURCC_fl64:
12808           case FOURCC_s16l:
12809             /* Fully handled elsewhere */
12810             break;
12811           default:
12812             GST_INFO_OBJECT (qtdemux,
12813                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12814             break;
12815         }
12816       }
12817       GST_INFO_OBJECT (qtdemux,
12818           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12819           GST_FOURCC_ARGS (fourcc), entry->caps);
12820
12821     } else if (stream->subtype == FOURCC_strm) {
12822       if (fourcc == FOURCC_rtsp) {
12823         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12824       } else {
12825         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12826             GST_FOURCC_ARGS (fourcc));
12827         goto unknown_stream;
12828       }
12829       entry->sampled = TRUE;
12830     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12831         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12832         || stream->subtype == FOURCC_clcp) {
12833
12834       entry->sampled = TRUE;
12835       entry->sparse = TRUE;
12836
12837       entry->caps =
12838           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12839           &codec);
12840       if (codec) {
12841         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12842             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12843         g_free (codec);
12844         codec = NULL;
12845       }
12846
12847       /* hunt for sort-of codec data */
12848       switch (fourcc) {
12849         case FOURCC_mp4s:
12850         {
12851           GNode *mp4s = NULL;
12852           GNode *esds = NULL;
12853
12854           /* look for palette in a stsd->mp4s->esds sub-atom */
12855           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12856           if (mp4s)
12857             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12858           if (esds == NULL) {
12859             /* Invalid STSD */
12860             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12861             break;
12862           }
12863
12864           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12865               stream->stream_tags);
12866           break;
12867         }
12868         default:
12869           GST_INFO_OBJECT (qtdemux,
12870               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12871           break;
12872       }
12873       GST_INFO_OBJECT (qtdemux,
12874           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12875           GST_FOURCC_ARGS (fourcc), entry->caps);
12876     } else {
12877       /* everything in 1 sample */
12878       entry->sampled = TRUE;
12879
12880       entry->caps =
12881           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12882           &codec);
12883
12884       if (entry->caps == NULL)
12885         goto unknown_stream;
12886
12887       if (codec) {
12888         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12889             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12890         g_free (codec);
12891         codec = NULL;
12892       }
12893     }
12894
12895     /* promote to sampled format */
12896     if (entry->fourcc == FOURCC_samr) {
12897       /* force mono 8000 Hz for AMR */
12898       entry->sampled = TRUE;
12899       entry->n_channels = 1;
12900       entry->rate = 8000;
12901     } else if (entry->fourcc == FOURCC_sawb) {
12902       /* force mono 16000 Hz for AMR-WB */
12903       entry->sampled = TRUE;
12904       entry->n_channels = 1;
12905       entry->rate = 16000;
12906     } else if (entry->fourcc == FOURCC_mp4a) {
12907       entry->sampled = TRUE;
12908     }
12909
12910
12911     stsd_entry_data += len;
12912     remaining_stsd_len -= len;
12913
12914   }
12915
12916   /* collect sample information */
12917   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12918     goto samples_failed;
12919
12920   if (qtdemux->fragmented) {
12921     guint64 offset;
12922
12923     /* need all moov samples as basis; probably not many if any at all */
12924     /* prevent moof parsing taking of at this time */
12925     offset = qtdemux->moof_offset;
12926     qtdemux->moof_offset = 0;
12927     if (stream->n_samples &&
12928         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12929       qtdemux->moof_offset = offset;
12930       goto samples_failed;
12931     }
12932     qtdemux->moof_offset = offset;
12933     /* movie duration more reliable in this case (e.g. mehd) */
12934     if (qtdemux->segment.duration &&
12935         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12936       stream->duration =
12937           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12938   }
12939
12940   /* configure segments */
12941   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12942     goto segments_failed;
12943
12944   /* add some language tag, if useful */
12945   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12946       strcmp (stream->lang_id, "und")) {
12947     const gchar *lang_code;
12948
12949     /* convert ISO 639-2 code to ISO 639-1 */
12950     lang_code = gst_tag_get_language_code (stream->lang_id);
12951     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12952         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12953   }
12954
12955   /* Check for UDTA tags */
12956   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12957     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12958   }
12959
12960   /* Insert and sort new stream in track-id order.
12961    * This will help in comparing old/new streams during stream update check */
12962   g_ptr_array_add (qtdemux->active_streams, stream);
12963   g_ptr_array_sort (qtdemux->active_streams,
12964       (GCompareFunc) qtdemux_track_id_compare_func);
12965   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12966       QTDEMUX_N_STREAMS (qtdemux));
12967
12968   return TRUE;
12969
12970 /* ERRORS */
12971 corrupt_file:
12972   {
12973     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12974         (_("This file is corrupt and cannot be played.")), (NULL));
12975     if (stream)
12976       gst_qtdemux_stream_unref (stream);
12977     return FALSE;
12978   }
12979 error_encrypted:
12980   {
12981     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12982     gst_qtdemux_stream_unref (stream);
12983     return FALSE;
12984   }
12985 samples_failed:
12986 segments_failed:
12987   {
12988     /* we posted an error already */
12989     /* free stbl sub-atoms */
12990     gst_qtdemux_stbl_free (stream);
12991     gst_qtdemux_stream_unref (stream);
12992     return FALSE;
12993   }
12994 existing_stream:
12995   {
12996     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12997         track_id);
12998     return TRUE;
12999   }
13000 unknown_stream:
13001   {
13002     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13003         GST_FOURCC_ARGS (stream->subtype));
13004     gst_qtdemux_stream_unref (stream);
13005     return TRUE;
13006   }
13007 }
13008
13009 /* If we can estimate the overall bitrate, and don't have information about the
13010  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13011  * the overall bitrate minus the sum of the bitrates of all other streams. This
13012  * should be useful for the common case where we have one audio and one video
13013  * stream and can estimate the bitrate of one, but not the other. */
13014 static void
13015 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13016 {
13017   QtDemuxStream *stream = NULL;
13018   gint64 size, sys_bitrate, sum_bitrate = 0;
13019   GstClockTime duration;
13020   guint bitrate;
13021   gint i;
13022
13023   if (qtdemux->fragmented)
13024     return;
13025
13026   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13027
13028   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13029       || size <= 0) {
13030     GST_DEBUG_OBJECT (qtdemux,
13031         "Size in bytes of the stream not known - bailing");
13032     return;
13033   }
13034
13035   /* Subtract the header size */
13036   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13037       size, qtdemux->header_size);
13038
13039   if (size < qtdemux->header_size)
13040     return;
13041
13042   size = size - qtdemux->header_size;
13043
13044   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13045     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13046     return;
13047   }
13048
13049   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13050     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13051     switch (str->subtype) {
13052       case FOURCC_soun:
13053       case FOURCC_vide:
13054         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13055             CUR_STREAM (str)->caps);
13056         /* retrieve bitrate, prefer avg then max */
13057         bitrate = 0;
13058         if (str->stream_tags) {
13059           if (gst_tag_list_get_uint (str->stream_tags,
13060                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13061             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13062           if (gst_tag_list_get_uint (str->stream_tags,
13063                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13064             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13065           if (gst_tag_list_get_uint (str->stream_tags,
13066                   GST_TAG_BITRATE, &bitrate))
13067             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13068         }
13069         if (bitrate)
13070           sum_bitrate += bitrate;
13071         else {
13072           if (stream) {
13073             GST_DEBUG_OBJECT (qtdemux,
13074                 ">1 stream with unknown bitrate - bailing");
13075             return;
13076           } else
13077             stream = str;
13078         }
13079
13080       default:
13081         /* For other subtypes, we assume no significant impact on bitrate */
13082         break;
13083     }
13084   }
13085
13086   if (!stream) {
13087     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13088     return;
13089   }
13090
13091   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13092
13093   if (sys_bitrate < sum_bitrate) {
13094     /* This can happen, since sum_bitrate might be derived from maximum
13095      * bitrates and not average bitrates */
13096     GST_DEBUG_OBJECT (qtdemux,
13097         "System bitrate less than sum bitrate - bailing");
13098     return;
13099   }
13100
13101   bitrate = sys_bitrate - sum_bitrate;
13102   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13103       ", Stream bitrate = %u", sys_bitrate, bitrate);
13104
13105   if (!stream->stream_tags)
13106     stream->stream_tags = gst_tag_list_new_empty ();
13107   else
13108     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13109
13110   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13111       GST_TAG_BITRATE, bitrate, NULL);
13112 }
13113
13114 static GstFlowReturn
13115 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13116 {
13117   GstFlowReturn ret = GST_FLOW_OK;
13118   gint i;
13119
13120   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13121
13122   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13123     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13124     guint32 sample_num = 0;
13125
13126     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13127         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13128
13129     if (qtdemux->fragmented && qtdemux->pullbased) {
13130       /* need all moov samples first */
13131       GST_OBJECT_LOCK (qtdemux);
13132       while (stream->n_samples == 0)
13133         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13134           break;
13135       GST_OBJECT_UNLOCK (qtdemux);
13136     } else {
13137       /* discard any stray moof */
13138       qtdemux->moof_offset = 0;
13139     }
13140
13141     /* prepare braking */
13142     if (ret != GST_FLOW_ERROR)
13143       ret = GST_FLOW_OK;
13144
13145     /* in pull mode, we should have parsed some sample info by now;
13146      * and quite some code will not handle no samples.
13147      * in push mode, we'll just have to deal with it */
13148     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13149       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13150       g_ptr_array_remove_index (qtdemux->active_streams, i);
13151       i--;
13152       continue;
13153     } else if (stream->track_id == qtdemux->chapters_track_id &&
13154         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13155       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13156          so that it doesn't look like a subtitle track */
13157       g_ptr_array_remove_index (qtdemux->active_streams, i);
13158       i--;
13159       continue;
13160     }
13161
13162     /* parse the initial sample for use in setting the frame rate cap */
13163     while (sample_num == 0 && sample_num < stream->n_samples) {
13164       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13165         break;
13166       ++sample_num;
13167     }
13168   }
13169
13170   return ret;
13171 }
13172
13173 static gboolean
13174 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13175 {
13176   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13177 }
13178
13179 static gboolean
13180 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13181 {
13182   gint i;
13183
13184   /* Different length, updated */
13185   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13186     return TRUE;
13187
13188   /* streams in list are sorted in track-id order */
13189   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13190     /* Different stream-id, updated */
13191     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13192             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13193       return TRUE;
13194   }
13195
13196   return FALSE;
13197 }
13198
13199 static gboolean
13200 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13201     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13202 {
13203   /* Connect old stream's srcpad to new stream */
13204   newstream->pad = oldstream->pad;
13205   oldstream->pad = NULL;
13206
13207   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13208    * case we need to force one through */
13209   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13210
13211   return gst_qtdemux_configure_stream (qtdemux, newstream);
13212 }
13213
13214 static gboolean
13215 qtdemux_update_streams (GstQTDemux * qtdemux)
13216 {
13217   gint i;
13218   g_assert (qtdemux->streams_aware);
13219
13220   /* At below, figure out which stream in active_streams has identical stream-id
13221    * with that of in old_streams. If there is matching stream-id,
13222    * corresponding newstream will not be exposed again,
13223    * but demux will reuse srcpad of matched old stream
13224    *
13225    * active_streams : newly created streams from the latest moov
13226    * old_streams : existing streams (belong to previous moov)
13227    */
13228
13229   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13230     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13231     QtDemuxStream *oldstream = NULL;
13232     guint target;
13233
13234     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13235         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13236
13237     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13238             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13239       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13240
13241       /* null pad stream cannot be reused */
13242       if (oldstream->pad == NULL)
13243         oldstream = NULL;
13244     }
13245
13246     if (oldstream) {
13247       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13248
13249       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13250         return FALSE;
13251
13252       /* we don't need to preserve order of old streams */
13253       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13254     } else {
13255       GstTagList *list;
13256
13257       /* now we have all info and can expose */
13258       list = stream->stream_tags;
13259       stream->stream_tags = NULL;
13260       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13261         return FALSE;
13262     }
13263   }
13264
13265   return TRUE;
13266 }
13267
13268 /* Must be called with expose lock */
13269 static GstFlowReturn
13270 qtdemux_expose_streams (GstQTDemux * qtdemux)
13271 {
13272   gint i;
13273
13274   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13275
13276   if (!qtdemux_is_streams_update (qtdemux)) {
13277     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13278     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13279       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13280       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13281       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13282         return GST_FLOW_ERROR;
13283     }
13284
13285     g_ptr_array_set_size (qtdemux->old_streams, 0);
13286     qtdemux->need_segment = TRUE;
13287
13288     return GST_FLOW_OK;
13289   }
13290
13291   if (qtdemux->streams_aware) {
13292     if (!qtdemux_update_streams (qtdemux))
13293       return GST_FLOW_ERROR;
13294   } else {
13295     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13296       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13297       GstTagList *list;
13298
13299       /* now we have all info and can expose */
13300       list = stream->stream_tags;
13301       stream->stream_tags = NULL;
13302       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13303         return GST_FLOW_ERROR;
13304
13305     }
13306   }
13307
13308   gst_qtdemux_guess_bitrate (qtdemux);
13309
13310   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13311
13312   /* If we have still old_streams, it's no more used stream */
13313   for (i = 0; i < qtdemux->old_streams->len; i++) {
13314     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13315
13316     if (stream->pad) {
13317       GstEvent *event;
13318
13319       event = gst_event_new_eos ();
13320       if (qtdemux->segment_seqnum)
13321         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13322
13323       gst_pad_push_event (stream->pad, event);
13324     }
13325   }
13326
13327   g_ptr_array_set_size (qtdemux->old_streams, 0);
13328
13329   /* check if we should post a redirect in case there is a single trak
13330    * and it is a redirecting trak */
13331   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13332       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13333     GstMessage *m;
13334
13335     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13336         "an external content");
13337     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13338         gst_structure_new ("redirect",
13339             "new-location", G_TYPE_STRING,
13340             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13341     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13342     g_free (qtdemux->redirect_location);
13343     qtdemux->redirect_location =
13344         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13345   }
13346
13347   g_ptr_array_foreach (qtdemux->active_streams,
13348       (GFunc) qtdemux_do_allocation, qtdemux);
13349
13350   qtdemux->need_segment = TRUE;
13351
13352   qtdemux->exposed = TRUE;
13353   return GST_FLOW_OK;
13354 }
13355
13356 typedef struct
13357 {
13358   GstStructure *structure;      /* helper for sort function */
13359   gchar *location;
13360   guint min_req_bitrate;
13361   guint min_req_qt_version;
13362 } GstQtReference;
13363
13364 static gint
13365 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13366 {
13367   GstQtReference *ref_a = (GstQtReference *) a;
13368   GstQtReference *ref_b = (GstQtReference *) b;
13369
13370   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13371     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13372
13373   /* known bitrates go before unknown; higher bitrates go first */
13374   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13375 }
13376
13377 /* sort the redirects and post a message for the application.
13378  */
13379 static void
13380 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13381 {
13382   GstQtReference *best;
13383   GstStructure *s;
13384   GstMessage *msg;
13385   GValue list_val = { 0, };
13386   GList *l;
13387
13388   g_assert (references != NULL);
13389
13390   references = g_list_sort (references, qtdemux_redirects_sort_func);
13391
13392   best = (GstQtReference *) references->data;
13393
13394   g_value_init (&list_val, GST_TYPE_LIST);
13395
13396   for (l = references; l != NULL; l = l->next) {
13397     GstQtReference *ref = (GstQtReference *) l->data;
13398     GValue struct_val = { 0, };
13399
13400     ref->structure = gst_structure_new ("redirect",
13401         "new-location", G_TYPE_STRING, ref->location, NULL);
13402
13403     if (ref->min_req_bitrate > 0) {
13404       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13405           ref->min_req_bitrate, NULL);
13406     }
13407
13408     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13409     g_value_set_boxed (&struct_val, ref->structure);
13410     gst_value_list_append_value (&list_val, &struct_val);
13411     g_value_unset (&struct_val);
13412     /* don't free anything here yet, since we need best->structure below */
13413   }
13414
13415   g_assert (best != NULL);
13416   s = gst_structure_copy (best->structure);
13417
13418   if (g_list_length (references) > 1) {
13419     gst_structure_set_value (s, "locations", &list_val);
13420   }
13421
13422   g_value_unset (&list_val);
13423
13424   for (l = references; l != NULL; l = l->next) {
13425     GstQtReference *ref = (GstQtReference *) l->data;
13426
13427     gst_structure_free (ref->structure);
13428     g_free (ref->location);
13429     g_free (ref);
13430   }
13431   g_list_free (references);
13432
13433   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13434   g_free (qtdemux->redirect_location);
13435   qtdemux->redirect_location =
13436       g_strdup (gst_structure_get_string (s, "new-location"));
13437   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13438   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13439 }
13440
13441 /* look for redirect nodes, collect all redirect information and
13442  * process it.
13443  */
13444 static gboolean
13445 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13446 {
13447   GNode *rmra, *rmda, *rdrf;
13448
13449   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13450   if (rmra) {
13451     GList *redirects = NULL;
13452
13453     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13454     while (rmda) {
13455       GstQtReference ref = { NULL, NULL, 0, 0 };
13456       GNode *rmdr, *rmvc;
13457
13458       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13459         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13460         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13461             ref.min_req_bitrate);
13462       }
13463
13464       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13465         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13466         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13467
13468 #ifndef GST_DISABLE_GST_DEBUG
13469         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13470 #endif
13471         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13472
13473         GST_LOG_OBJECT (qtdemux,
13474             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13475             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13476             bitmask, check_type);
13477         if (package == FOURCC_qtim && check_type == 0) {
13478           ref.min_req_qt_version = version;
13479         }
13480       }
13481
13482       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13483       if (rdrf) {
13484         guint32 ref_type;
13485         guint8 *ref_data;
13486         guint ref_len;
13487
13488         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13489         if (ref_len > 20) {
13490           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13491           ref_data = (guint8 *) rdrf->data + 20;
13492           if (ref_type == FOURCC_alis) {
13493             guint record_len, record_version, fn_len;
13494
13495             if (ref_len > 70) {
13496               /* MacOSX alias record, google for alias-layout.txt */
13497               record_len = QT_UINT16 (ref_data + 4);
13498               record_version = QT_UINT16 (ref_data + 4 + 2);
13499               fn_len = QT_UINT8 (ref_data + 50);
13500               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13501                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13502               }
13503             } else {
13504               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13505                   ref_len);
13506             }
13507           } else if (ref_type == FOURCC_url_) {
13508             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13509           } else {
13510             GST_DEBUG_OBJECT (qtdemux,
13511                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13512                 GST_FOURCC_ARGS (ref_type));
13513           }
13514           if (ref.location != NULL) {
13515             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13516             redirects =
13517                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13518           } else {
13519             GST_WARNING_OBJECT (qtdemux,
13520                 "Failed to extract redirect location from rdrf atom");
13521           }
13522         } else {
13523           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13524         }
13525       }
13526
13527       /* look for others */
13528       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13529     }
13530
13531     if (redirects != NULL) {
13532       qtdemux_process_redirects (qtdemux, redirects);
13533     }
13534   }
13535   return TRUE;
13536 }
13537
13538 static GstTagList *
13539 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13540 {
13541   const gchar *fmt;
13542
13543   if (tags == NULL) {
13544     tags = gst_tag_list_new_empty ();
13545     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13546   }
13547
13548   if (qtdemux->major_brand == FOURCC_mjp2)
13549     fmt = "Motion JPEG 2000";
13550   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13551     fmt = "3GP";
13552   else if (qtdemux->major_brand == FOURCC_qt__)
13553     fmt = "Quicktime";
13554   else if (qtdemux->fragmented)
13555     fmt = "ISO fMP4";
13556   else
13557     fmt = "ISO MP4/M4A";
13558
13559   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13560       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13561
13562   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13563       fmt, NULL);
13564
13565   return tags;
13566 }
13567
13568 /* we have read the complete moov node now.
13569  * This function parses all of the relevant info, creates the traks and
13570  * prepares all data structures for playback
13571  */
13572 static gboolean
13573 qtdemux_parse_tree (GstQTDemux * qtdemux)
13574 {
13575   GNode *mvhd;
13576   GNode *trak;
13577   GNode *udta;
13578   GNode *mvex;
13579   GNode *pssh;
13580   guint64 creation_time;
13581   GstDateTime *datetime = NULL;
13582   gint version;
13583
13584   /* make sure we have a usable taglist */
13585   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13586
13587   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13588   if (mvhd == NULL) {
13589     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13590     return qtdemux_parse_redirects (qtdemux);
13591   }
13592
13593   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13594   if (version == 1) {
13595     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13596     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13597     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13598   } else if (version == 0) {
13599     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13600     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13601     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13602   } else {
13603     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13604     return FALSE;
13605   }
13606
13607   /* Moving qt creation time (secs since 1904) to unix time */
13608   if (creation_time != 0) {
13609     /* Try to use epoch first as it should be faster and more commonly found */
13610     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13611       gint64 now_s;
13612
13613       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13614       /* some data cleansing sanity */
13615       now_s = g_get_real_time () / G_USEC_PER_SEC;
13616       if (now_s + 24 * 3600 < creation_time) {
13617         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13618       } else {
13619         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13620       }
13621     } else {
13622       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13623       GDateTime *dt, *dt_local;
13624
13625       dt = g_date_time_add_seconds (base_dt, creation_time);
13626       dt_local = g_date_time_to_local (dt);
13627       datetime = gst_date_time_new_from_g_date_time (dt_local);
13628
13629       g_date_time_unref (base_dt);
13630       g_date_time_unref (dt);
13631     }
13632   }
13633   if (datetime) {
13634     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13635     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13636         datetime, NULL);
13637     gst_date_time_unref (datetime);
13638   }
13639
13640   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13641   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13642
13643   /* check for fragmented file and get some (default) data */
13644   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13645   if (mvex) {
13646     GNode *mehd;
13647     GstByteReader mehd_data;
13648
13649     /* let track parsing or anyone know weird stuff might happen ... */
13650     qtdemux->fragmented = TRUE;
13651
13652     /* compensate for total duration */
13653     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13654     if (mehd)
13655       qtdemux_parse_mehd (qtdemux, &mehd_data);
13656   }
13657
13658   /* Update the movie segment duration, unless it was directly given to us
13659    * by upstream. Otherwise let it as is, as we don't want to mangle the
13660    * duration provided by upstream that may come e.g. from a MPD file. */
13661   if (!qtdemux->upstream_format_is_time) {
13662     GstClockTime duration;
13663     /* set duration in the segment info */
13664     gst_qtdemux_get_duration (qtdemux, &duration);
13665     qtdemux->segment.duration = duration;
13666     /* also do not exceed duration; stop is set that way post seek anyway,
13667      * and segment activation falls back to duration,
13668      * whereas loop only checks stop, so let's align this here as well */
13669     qtdemux->segment.stop = duration;
13670   }
13671
13672   /* parse all traks */
13673   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13674   while (trak) {
13675     qtdemux_parse_trak (qtdemux, trak);
13676     /* iterate all siblings */
13677     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13678   }
13679
13680   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13681
13682   /* find tags */
13683   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13684   if (udta) {
13685     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13686   } else {
13687     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13688   }
13689
13690   /* maybe also some tags in meta box */
13691   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13692   if (udta) {
13693     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13694     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13695   } else {
13696     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13697   }
13698
13699   /* parse any protection system info */
13700   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13701   while (pssh) {
13702     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13703     qtdemux_parse_pssh (qtdemux, pssh);
13704     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13705   }
13706
13707   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13708
13709   return TRUE;
13710 }
13711
13712 /* taken from ffmpeg */
13713 static int
13714 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13715 {
13716   int count = 4;
13717   int len = 0;
13718
13719   while (count--) {
13720     int c;
13721
13722     if (ptr >= end)
13723       return -1;
13724
13725     c = *ptr++;
13726     len = (len << 7) | (c & 0x7f);
13727     if (!(c & 0x80))
13728       break;
13729   }
13730   *end_out = ptr;
13731   return len;
13732 }
13733
13734 static GList *
13735 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13736     gsize codec_data_size)
13737 {
13738   GList *list = NULL;
13739   guint8 *p = codec_data;
13740   gint i, offset, num_packets;
13741   guint *length, last;
13742
13743   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13744
13745   if (codec_data == NULL || codec_data_size == 0)
13746     goto error;
13747
13748   /* start of the stream and vorbis audio or theora video, need to
13749    * send the codec_priv data as first three packets */
13750   num_packets = p[0] + 1;
13751   GST_DEBUG_OBJECT (qtdemux,
13752       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13753       (guint) num_packets, codec_data_size);
13754
13755   /* Let's put some limits, Don't think there even is a xiph codec
13756    * with more than 3-4 headers */
13757   if (G_UNLIKELY (num_packets > 16)) {
13758     GST_WARNING_OBJECT (qtdemux,
13759         "Unlikely number of xiph headers, most likely not valid");
13760     goto error;
13761   }
13762
13763   length = g_alloca (num_packets * sizeof (guint));
13764   last = 0;
13765   offset = 1;
13766
13767   /* first packets, read length values */
13768   for (i = 0; i < num_packets - 1; i++) {
13769     length[i] = 0;
13770     while (offset < codec_data_size) {
13771       length[i] += p[offset];
13772       if (p[offset++] != 0xff)
13773         break;
13774     }
13775     last += length[i];
13776   }
13777   if (offset + last > codec_data_size)
13778     goto error;
13779
13780   /* last packet is the remaining size */
13781   length[i] = codec_data_size - offset - last;
13782
13783   for (i = 0; i < num_packets; i++) {
13784     GstBuffer *hdr;
13785
13786     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13787
13788     if (offset + length[i] > codec_data_size)
13789       goto error;
13790
13791     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13792     list = g_list_append (list, hdr);
13793
13794     offset += length[i];
13795   }
13796
13797   return list;
13798
13799   /* ERRORS */
13800 error:
13801   {
13802     if (list != NULL)
13803       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13804     return NULL;
13805   }
13806
13807 }
13808
13809 /* this can change the codec originally present in @list */
13810 static void
13811 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13812     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13813 {
13814   int len = QT_UINT32 (esds->data);
13815   guint8 *ptr = esds->data;
13816   guint8 *end = ptr + len;
13817   int tag;
13818   guint8 *data_ptr = NULL;
13819   int data_len = 0;
13820   guint8 object_type_id = 0;
13821   guint8 stream_type = 0;
13822   const char *codec_name = NULL;
13823   GstCaps *caps = NULL;
13824
13825   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13826   ptr += 8;
13827   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13828   ptr += 4;
13829   while (ptr + 1 < end) {
13830     tag = QT_UINT8 (ptr);
13831     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13832     ptr++;
13833     len = read_descr_size (ptr, end, &ptr);
13834     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13835
13836     /* Check the stated amount of data is available for reading */
13837     if (len < 0 || ptr + len > end)
13838       break;
13839
13840     switch (tag) {
13841       case ES_DESCRIPTOR_TAG:
13842         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13843         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13844         ptr += 3;
13845         break;
13846       case DECODER_CONFIG_DESC_TAG:{
13847         guint max_bitrate, avg_bitrate;
13848
13849         object_type_id = QT_UINT8 (ptr);
13850         stream_type = QT_UINT8 (ptr + 1) >> 2;
13851         max_bitrate = QT_UINT32 (ptr + 5);
13852         avg_bitrate = QT_UINT32 (ptr + 9);
13853         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13854         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13855         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13856         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13857         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13858         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13859           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13860               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13861         }
13862         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13863           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13864               avg_bitrate, NULL);
13865         }
13866         ptr += 13;
13867         break;
13868       }
13869       case DECODER_SPECIFIC_INFO_TAG:
13870         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13871         if (object_type_id == 0xe0 && len == 0x40) {
13872           guint8 *data;
13873           GstStructure *s;
13874           guint32 clut[16];
13875           gint i;
13876
13877           GST_DEBUG_OBJECT (qtdemux,
13878               "Have VOBSUB palette. Creating palette event");
13879           /* move to decConfigDescr data and read palette */
13880           data = ptr;
13881           for (i = 0; i < 16; i++) {
13882             clut[i] = QT_UINT32 (data);
13883             data += 4;
13884           }
13885
13886           s = gst_structure_new ("application/x-gst-dvd", "event",
13887               G_TYPE_STRING, "dvd-spu-clut-change",
13888               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13889               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13890               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13891               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13892               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13893               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13894               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13895               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13896               NULL);
13897
13898           /* store event and trigger custom processing */
13899           stream->pending_event =
13900               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13901         } else {
13902           /* Generic codec_data handler puts it on the caps */
13903           data_ptr = ptr;
13904           data_len = len;
13905         }
13906
13907         ptr += len;
13908         break;
13909       case SL_CONFIG_DESC_TAG:
13910         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13911         ptr += 1;
13912         break;
13913       default:
13914         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13915             tag);
13916         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13917         ptr += len;
13918         break;
13919     }
13920   }
13921
13922   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13923    * in use, and should also be used to override some other parameters for some
13924    * codecs. */
13925   switch (object_type_id) {
13926     case 0x20:                 /* MPEG-4 */
13927       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13928        * profile_and_level_indication */
13929       if (data_ptr != NULL && data_len >= 5 &&
13930           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13931         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13932             data_ptr + 4, data_len - 4);
13933       }
13934       break;                    /* Nothing special needed here */
13935     case 0x21:                 /* H.264 */
13936       codec_name = "H.264 / AVC";
13937       caps = gst_caps_new_simple ("video/x-h264",
13938           "stream-format", G_TYPE_STRING, "avc",
13939           "alignment", G_TYPE_STRING, "au", NULL);
13940       break;
13941     case 0x40:                 /* AAC (any) */
13942     case 0x66:                 /* AAC Main */
13943     case 0x67:                 /* AAC LC */
13944     case 0x68:                 /* AAC SSR */
13945       /* Override channels and rate based on the codec_data, as it's often
13946        * wrong. */
13947       /* Only do so for basic setup without HE-AAC extension */
13948       if (data_ptr && data_len == 2) {
13949         guint channels, rate;
13950
13951         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13952         if (channels > 0)
13953           entry->n_channels = channels;
13954
13955         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13956         if (rate > 0)
13957           entry->rate = rate;
13958       }
13959
13960       /* Set level and profile if possible */
13961       if (data_ptr != NULL && data_len >= 2) {
13962         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13963             data_ptr, data_len);
13964       } else {
13965         const gchar *profile_str = NULL;
13966         GstBuffer *buffer;
13967         GstMapInfo map;
13968         guint8 *codec_data;
13969         gint rate_idx, profile;
13970
13971         /* No codec_data, let's invent something.
13972          * FIXME: This is wrong for SBR! */
13973
13974         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13975
13976         buffer = gst_buffer_new_and_alloc (2);
13977         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13978         codec_data = map.data;
13979
13980         rate_idx =
13981             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13982             (stream)->rate);
13983
13984         switch (object_type_id) {
13985           case 0x66:
13986             profile_str = "main";
13987             profile = 0;
13988             break;
13989           case 0x67:
13990             profile_str = "lc";
13991             profile = 1;
13992             break;
13993           case 0x68:
13994             profile_str = "ssr";
13995             profile = 2;
13996             break;
13997           default:
13998             profile = 3;
13999             break;
14000         }
14001
14002         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14003         codec_data[1] =
14004             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14005
14006         gst_buffer_unmap (buffer, &map);
14007         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14008             GST_TYPE_BUFFER, buffer, NULL);
14009         gst_buffer_unref (buffer);
14010
14011         if (profile_str) {
14012           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14013               G_TYPE_STRING, profile_str, NULL);
14014         }
14015       }
14016       break;
14017     case 0x60:                 /* MPEG-2, various profiles */
14018     case 0x61:
14019     case 0x62:
14020     case 0x63:
14021     case 0x64:
14022     case 0x65:
14023       codec_name = "MPEG-2 video";
14024       caps = gst_caps_new_simple ("video/mpeg",
14025           "mpegversion", G_TYPE_INT, 2,
14026           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14027       break;
14028     case 0x69:                 /* MPEG-2 BC audio */
14029     case 0x6B:                 /* MPEG-1 audio */
14030       caps = gst_caps_new_simple ("audio/mpeg",
14031           "mpegversion", G_TYPE_INT, 1, NULL);
14032       codec_name = "MPEG-1 audio";
14033       break;
14034     case 0x6A:                 /* MPEG-1 */
14035       codec_name = "MPEG-1 video";
14036       caps = gst_caps_new_simple ("video/mpeg",
14037           "mpegversion", G_TYPE_INT, 1,
14038           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14039       break;
14040     case 0x6C:                 /* MJPEG */
14041       caps =
14042           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14043           NULL);
14044       codec_name = "Motion-JPEG";
14045       break;
14046     case 0x6D:                 /* PNG */
14047       caps =
14048           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14049           NULL);
14050       codec_name = "PNG still images";
14051       break;
14052     case 0x6E:                 /* JPEG2000 */
14053       codec_name = "JPEG-2000";
14054       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14055       break;
14056     case 0xA4:                 /* Dirac */
14057       codec_name = "Dirac";
14058       caps = gst_caps_new_empty_simple ("video/x-dirac");
14059       break;
14060     case 0xA5:                 /* AC3 */
14061       codec_name = "AC-3 audio";
14062       caps = gst_caps_new_simple ("audio/x-ac3",
14063           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14064       break;
14065     case 0xA9:                 /* AC3 */
14066       codec_name = "DTS audio";
14067       caps = gst_caps_new_simple ("audio/x-dts",
14068           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14069       break;
14070     case 0xDD:
14071       if (stream_type == 0x05 && data_ptr) {
14072         GList *headers =
14073             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14074         if (headers) {
14075           GList *tmp;
14076           GValue arr_val = G_VALUE_INIT;
14077           GValue buf_val = G_VALUE_INIT;
14078           GstStructure *s;
14079
14080           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14081           codec_name = "Vorbis";
14082           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14083           g_value_init (&arr_val, GST_TYPE_ARRAY);
14084           g_value_init (&buf_val, GST_TYPE_BUFFER);
14085           for (tmp = headers; tmp; tmp = tmp->next) {
14086             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14087             gst_value_array_append_value (&arr_val, &buf_val);
14088           }
14089           s = gst_caps_get_structure (caps, 0);
14090           gst_structure_take_value (s, "streamheader", &arr_val);
14091           g_value_unset (&buf_val);
14092           g_list_free (headers);
14093
14094           data_ptr = NULL;
14095           data_len = 0;
14096         }
14097       }
14098       break;
14099     case 0xE1:                 /* QCELP */
14100       /* QCELP, the codec_data is a riff tag (little endian) with
14101        * 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). */
14102       caps = gst_caps_new_empty_simple ("audio/qcelp");
14103       codec_name = "QCELP";
14104       break;
14105     default:
14106       break;
14107   }
14108
14109   /* If we have a replacement caps, then change our caps for this stream */
14110   if (caps) {
14111     gst_caps_unref (entry->caps);
14112     entry->caps = caps;
14113   }
14114
14115   if (codec_name && list)
14116     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14117         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14118
14119   /* Add the codec_data attribute to caps, if we have it */
14120   if (data_ptr) {
14121     GstBuffer *buffer;
14122
14123     buffer = gst_buffer_new_and_alloc (data_len);
14124     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14125
14126     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14127     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14128
14129     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14130         buffer, NULL);
14131     gst_buffer_unref (buffer);
14132   }
14133
14134 }
14135
14136 static inline GstCaps *
14137 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14138 {
14139   GstCaps *caps;
14140   guint i;
14141   char *s, fourstr[5];
14142
14143   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14144   for (i = 0; i < 4; i++) {
14145     if (!g_ascii_isalnum (fourstr[i]))
14146       fourstr[i] = '_';
14147   }
14148   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14149   caps = gst_caps_new_empty_simple (s);
14150   g_free (s);
14151   return caps;
14152 }
14153
14154 #define _codec(name) \
14155   do { \
14156     if (codec_name) { \
14157       *codec_name = g_strdup (name); \
14158     } \
14159   } while (0)
14160
14161 static GstCaps *
14162 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14163     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14164     const guint8 * stsd_entry_data, gchar ** codec_name)
14165 {
14166   GstCaps *caps = NULL;
14167   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14168
14169   switch (fourcc) {
14170     case FOURCC_png:
14171       _codec ("PNG still images");
14172       caps = gst_caps_new_empty_simple ("image/png");
14173       break;
14174     case FOURCC_jpeg:
14175       _codec ("JPEG still images");
14176       caps =
14177           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14178           NULL);
14179       break;
14180     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14181     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14182     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14183     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14184       _codec ("Motion-JPEG");
14185       caps =
14186           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14187           NULL);
14188       break;
14189     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14190       _codec ("Motion-JPEG format B");
14191       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14192       break;
14193     case FOURCC_mjp2:
14194       _codec ("JPEG-2000");
14195       /* override to what it should be according to spec, avoid palette_data */
14196       entry->bits_per_sample = 24;
14197       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14198       break;
14199     case FOURCC_SVQ3:
14200       _codec ("Sorensen video v.3");
14201       caps = gst_caps_new_simple ("video/x-svq",
14202           "svqversion", G_TYPE_INT, 3, NULL);
14203       break;
14204     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14205     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14206       _codec ("Sorensen video v.1");
14207       caps = gst_caps_new_simple ("video/x-svq",
14208           "svqversion", G_TYPE_INT, 1, NULL);
14209       break;
14210     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14211       caps = gst_caps_new_empty_simple ("video/x-raw");
14212       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14213       _codec ("Windows Raw RGB");
14214       stream->alignment = 32;
14215       break;
14216     case FOURCC_raw_:
14217     {
14218       guint16 bps;
14219
14220       bps = QT_UINT16 (stsd_entry_data + 82);
14221       switch (bps) {
14222         case 15:
14223           format = GST_VIDEO_FORMAT_RGB15;
14224           break;
14225         case 16:
14226           format = GST_VIDEO_FORMAT_RGB16;
14227           break;
14228         case 24:
14229           format = GST_VIDEO_FORMAT_RGB;
14230           break;
14231         case 32:
14232           format = GST_VIDEO_FORMAT_ARGB;
14233           break;
14234         default:
14235           /* unknown */
14236           break;
14237       }
14238       break;
14239     }
14240     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14241       format = GST_VIDEO_FORMAT_I420;
14242       break;
14243     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14244     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14245       format = GST_VIDEO_FORMAT_I420;
14246       break;
14247     case FOURCC_2vuy:
14248     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14249       format = GST_VIDEO_FORMAT_UYVY;
14250       break;
14251     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14252       format = GST_VIDEO_FORMAT_v308;
14253       break;
14254     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14255       format = GST_VIDEO_FORMAT_v216;
14256       break;
14257     case FOURCC_v210:
14258       format = GST_VIDEO_FORMAT_v210;
14259       break;
14260     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14261       format = GST_VIDEO_FORMAT_r210;
14262       break;
14263       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14264          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14265          format = GST_VIDEO_FORMAT_v410;
14266          break;
14267        */
14268       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14269        * but different order than AYUV
14270        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14271        format = GST_VIDEO_FORMAT_v408;
14272        break;
14273        */
14274     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14275     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14276       _codec ("MPEG-1 video");
14277       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14278           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14279       break;
14280     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14281     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14282     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14283     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14284     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14285     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14286     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14287     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14288     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14289     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14290     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14291     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14292     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14293     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14294     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14295     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14296     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14297     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14298     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14299     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14300     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14301     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14302     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14303     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14304     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14305     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14306     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14307     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14308     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14309     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14310     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14311     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14312     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14313     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14314     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14315     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14316     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14317     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14318     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14319     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14320     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14321     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14322     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14323     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14324     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14325     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14326     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14327       _codec ("MPEG-2 video");
14328       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14329           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14330       break;
14331     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14332       _codec ("GIF still images");
14333       caps = gst_caps_new_empty_simple ("image/gif");
14334       break;
14335     case FOURCC_h263:
14336     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14337     case FOURCC_s263:
14338     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14339       _codec ("H.263");
14340       /* ffmpeg uses the height/width props, don't know why */
14341       caps = gst_caps_new_simple ("video/x-h263",
14342           "variant", G_TYPE_STRING, "itu", NULL);
14343       break;
14344     case FOURCC_mp4v:
14345     case FOURCC_MP4V:
14346       _codec ("MPEG-4 video");
14347       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14348           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14349       break;
14350     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14351     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14352       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14353       caps = gst_caps_new_simple ("video/x-msmpeg",
14354           "msmpegversion", G_TYPE_INT, 43, NULL);
14355       break;
14356     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14357       _codec ("DivX 3");
14358       caps = gst_caps_new_simple ("video/x-divx",
14359           "divxversion", G_TYPE_INT, 3, NULL);
14360       break;
14361     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14362     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14363       _codec ("DivX 4");
14364       caps = gst_caps_new_simple ("video/x-divx",
14365           "divxversion", G_TYPE_INT, 4, NULL);
14366       break;
14367     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14368       _codec ("DivX 5");
14369       caps = gst_caps_new_simple ("video/x-divx",
14370           "divxversion", G_TYPE_INT, 5, NULL);
14371       break;
14372
14373     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14374       _codec ("FFV1");
14375       caps = gst_caps_new_simple ("video/x-ffv",
14376           "ffvversion", G_TYPE_INT, 1, NULL);
14377       break;
14378
14379     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14380     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14381     case FOURCC_XVID:
14382     case FOURCC_xvid:
14383     case FOURCC_FMP4:
14384     case FOURCC_fmp4:
14385     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14386       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14387           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14388       _codec ("MPEG-4");
14389       break;
14390
14391     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14392       _codec ("Cinepak");
14393       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14394       break;
14395     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14396       _codec ("Apple QuickDraw");
14397       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14398       break;
14399     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14400       _codec ("Apple video");
14401       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14402       break;
14403     case FOURCC_H264:
14404     case FOURCC_avc1:
14405     case FOURCC_dva1:
14406       _codec ("H.264 / AVC");
14407       caps = gst_caps_new_simple ("video/x-h264",
14408           "stream-format", G_TYPE_STRING, "avc",
14409           "alignment", G_TYPE_STRING, "au", NULL);
14410       break;
14411     case FOURCC_avc3:
14412     case FOURCC_dvav:
14413       _codec ("H.264 / AVC");
14414       caps = gst_caps_new_simple ("video/x-h264",
14415           "stream-format", G_TYPE_STRING, "avc3",
14416           "alignment", G_TYPE_STRING, "au", NULL);
14417       break;
14418     case FOURCC_H265:
14419     case FOURCC_hvc1:
14420     case FOURCC_dvh1:
14421       _codec ("H.265 / HEVC");
14422       caps = gst_caps_new_simple ("video/x-h265",
14423           "stream-format", G_TYPE_STRING, "hvc1",
14424           "alignment", G_TYPE_STRING, "au", NULL);
14425       break;
14426     case FOURCC_hev1:
14427     case FOURCC_dvhe:
14428       _codec ("H.265 / HEVC");
14429       caps = gst_caps_new_simple ("video/x-h265",
14430           "stream-format", G_TYPE_STRING, "hev1",
14431           "alignment", G_TYPE_STRING, "au", NULL);
14432       break;
14433     case FOURCC_rle_:
14434       _codec ("Run-length encoding");
14435       caps = gst_caps_new_simple ("video/x-rle",
14436           "layout", G_TYPE_STRING, "quicktime", NULL);
14437       break;
14438     case FOURCC_WRLE:
14439       _codec ("Run-length encoding");
14440       caps = gst_caps_new_simple ("video/x-rle",
14441           "layout", G_TYPE_STRING, "microsoft", NULL);
14442       break;
14443     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14444     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14445       _codec ("Indeo Video 3");
14446       caps = gst_caps_new_simple ("video/x-indeo",
14447           "indeoversion", G_TYPE_INT, 3, NULL);
14448       break;
14449     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14450     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14451       _codec ("Intel Video 4");
14452       caps = gst_caps_new_simple ("video/x-indeo",
14453           "indeoversion", G_TYPE_INT, 4, NULL);
14454       break;
14455     case FOURCC_dvcp:
14456     case FOURCC_dvc_:
14457     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14458     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14459     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14460     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14461     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14462     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14463       _codec ("DV Video");
14464       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14465           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14466       break;
14467     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14468     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14469       _codec ("DVCPro50 Video");
14470       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14471           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14472       break;
14473     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14474     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14475       _codec ("DVCProHD Video");
14476       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14477           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14478       break;
14479     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14480       _codec ("Apple Graphics (SMC)");
14481       caps = gst_caps_new_empty_simple ("video/x-smc");
14482       break;
14483     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14484       _codec ("VP3");
14485       caps = gst_caps_new_empty_simple ("video/x-vp3");
14486       break;
14487     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14488       _codec ("VP6 Flash");
14489       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14490       break;
14491     case FOURCC_XiTh:
14492       _codec ("Theora");
14493       caps = gst_caps_new_empty_simple ("video/x-theora");
14494       /* theora uses one byte of padding in the data stream because it does not
14495        * allow 0 sized packets while theora does */
14496       entry->padding = 1;
14497       break;
14498     case FOURCC_drac:
14499       _codec ("Dirac");
14500       caps = gst_caps_new_empty_simple ("video/x-dirac");
14501       break;
14502     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14503       _codec ("TIFF still images");
14504       caps = gst_caps_new_empty_simple ("image/tiff");
14505       break;
14506     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14507       _codec ("Apple Intermediate Codec");
14508       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14509       break;
14510     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14511       _codec ("AVID DNxHD");
14512       caps = gst_caps_from_string ("video/x-dnxhd");
14513       break;
14514     case FOURCC_VP80:
14515     case FOURCC_vp08:
14516       _codec ("On2 VP8");
14517       caps = gst_caps_from_string ("video/x-vp8");
14518       break;
14519     case FOURCC_vp09:
14520       _codec ("Google VP9");
14521       caps = gst_caps_from_string ("video/x-vp9");
14522       break;
14523     case FOURCC_apcs:
14524       _codec ("Apple ProRes LT");
14525       caps =
14526           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14527           NULL);
14528       break;
14529     case FOURCC_apch:
14530       _codec ("Apple ProRes HQ");
14531       caps =
14532           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14533           NULL);
14534       break;
14535     case FOURCC_apcn:
14536       _codec ("Apple ProRes");
14537       caps =
14538           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14539           "standard", NULL);
14540       break;
14541     case FOURCC_apco:
14542       _codec ("Apple ProRes Proxy");
14543       caps =
14544           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14545           "proxy", NULL);
14546       break;
14547     case FOURCC_ap4h:
14548       _codec ("Apple ProRes 4444");
14549       caps =
14550           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14551           "4444", NULL);
14552
14553       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14554       if (entry->bits_per_sample > 0) {
14555         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14556             NULL);
14557       }
14558       break;
14559     case FOURCC_ap4x:
14560       _codec ("Apple ProRes 4444 XQ");
14561       caps =
14562           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14563           "4444xq", NULL);
14564
14565       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14566       if (entry->bits_per_sample > 0) {
14567         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14568             NULL);
14569       }
14570       break;
14571     case FOURCC_cfhd:
14572       _codec ("GoPro CineForm");
14573       caps = gst_caps_from_string ("video/x-cineform");
14574       break;
14575     case FOURCC_vc_1:
14576     case FOURCC_ovc1:
14577       _codec ("VC-1");
14578       caps = gst_caps_new_simple ("video/x-wmv",
14579           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14580       break;
14581     case FOURCC_av01:
14582       _codec ("AV1");
14583       caps = gst_caps_new_empty_simple ("video/x-av1");
14584       break;
14585     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14586     default:
14587     {
14588       caps = _get_unknown_codec_name ("video", fourcc);
14589       break;
14590     }
14591   }
14592
14593   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14594     GstVideoInfo info;
14595
14596     gst_video_info_init (&info);
14597     gst_video_info_set_format (&info, format, entry->width, entry->height);
14598
14599     caps = gst_video_info_to_caps (&info);
14600     *codec_name = gst_pb_utils_get_codec_description (caps);
14601
14602     /* enable clipping for raw video streams */
14603     stream->need_clip = TRUE;
14604     stream->alignment = 32;
14605   }
14606
14607   return caps;
14608 }
14609
14610 static guint
14611 round_up_pow2 (guint n)
14612 {
14613   n = n - 1;
14614   n = n | (n >> 1);
14615   n = n | (n >> 2);
14616   n = n | (n >> 4);
14617   n = n | (n >> 8);
14618   n = n | (n >> 16);
14619   return n + 1;
14620 }
14621
14622 static GstCaps *
14623 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14624     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14625     int len, gchar ** codec_name)
14626 {
14627   GstCaps *caps;
14628   const GstStructure *s;
14629   const gchar *name;
14630   gint endian = 0;
14631   GstAudioFormat format = 0;
14632   gint depth;
14633
14634   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14635
14636   depth = entry->bytes_per_packet * 8;
14637
14638   switch (fourcc) {
14639     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14640     case FOURCC_raw_:
14641       /* 8-bit audio is unsigned */
14642       if (depth == 8)
14643         format = GST_AUDIO_FORMAT_U8;
14644       /* otherwise it's signed and big-endian just like 'twos' */
14645     case FOURCC_twos:
14646       endian = G_BIG_ENDIAN;
14647       /* fall-through */
14648     case FOURCC_sowt:
14649     {
14650       gchar *str;
14651
14652       if (!endian)
14653         endian = G_LITTLE_ENDIAN;
14654
14655       if (!format)
14656         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14657
14658       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14659       _codec (str);
14660       g_free (str);
14661
14662       caps = gst_caps_new_simple ("audio/x-raw",
14663           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14664           "layout", G_TYPE_STRING, "interleaved", NULL);
14665       stream->alignment = GST_ROUND_UP_8 (depth);
14666       stream->alignment = round_up_pow2 (stream->alignment);
14667       break;
14668     }
14669     case FOURCC_fl64:
14670       _codec ("Raw 64-bit floating-point audio");
14671       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14672        * endian later */
14673       caps = gst_caps_new_simple ("audio/x-raw",
14674           "format", G_TYPE_STRING, "F64BE",
14675           "layout", G_TYPE_STRING, "interleaved", NULL);
14676       stream->alignment = 8;
14677       break;
14678     case FOURCC_fl32:
14679       _codec ("Raw 32-bit floating-point audio");
14680       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14681        * endian later */
14682       caps = gst_caps_new_simple ("audio/x-raw",
14683           "format", G_TYPE_STRING, "F32BE",
14684           "layout", G_TYPE_STRING, "interleaved", NULL);
14685       stream->alignment = 4;
14686       break;
14687     case FOURCC_in24:
14688       _codec ("Raw 24-bit PCM audio");
14689       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14690        * endian later */
14691       caps = gst_caps_new_simple ("audio/x-raw",
14692           "format", G_TYPE_STRING, "S24BE",
14693           "layout", G_TYPE_STRING, "interleaved", NULL);
14694       stream->alignment = 4;
14695       break;
14696     case FOURCC_in32:
14697       _codec ("Raw 32-bit PCM audio");
14698       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14699        * endian later */
14700       caps = gst_caps_new_simple ("audio/x-raw",
14701           "format", G_TYPE_STRING, "S32BE",
14702           "layout", G_TYPE_STRING, "interleaved", NULL);
14703       stream->alignment = 4;
14704       break;
14705     case FOURCC_s16l:
14706       _codec ("Raw 16-bit PCM audio");
14707       caps = gst_caps_new_simple ("audio/x-raw",
14708           "format", G_TYPE_STRING, "S16LE",
14709           "layout", G_TYPE_STRING, "interleaved", NULL);
14710       stream->alignment = 2;
14711       break;
14712     case FOURCC_ulaw:
14713       _codec ("Mu-law audio");
14714       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14715       break;
14716     case FOURCC_alaw:
14717       _codec ("A-law audio");
14718       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14719       break;
14720     case 0x0200736d:
14721     case 0x6d730002:
14722       _codec ("Microsoft ADPCM");
14723       /* Microsoft ADPCM-ACM code 2 */
14724       caps = gst_caps_new_simple ("audio/x-adpcm",
14725           "layout", G_TYPE_STRING, "microsoft", NULL);
14726       break;
14727     case 0x1100736d:
14728     case 0x6d730011:
14729       _codec ("DVI/IMA ADPCM");
14730       caps = gst_caps_new_simple ("audio/x-adpcm",
14731           "layout", G_TYPE_STRING, "dvi", NULL);
14732       break;
14733     case 0x1700736d:
14734     case 0x6d730017:
14735       _codec ("DVI/Intel IMA ADPCM");
14736       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14737       caps = gst_caps_new_simple ("audio/x-adpcm",
14738           "layout", G_TYPE_STRING, "quicktime", NULL);
14739       break;
14740     case 0x5500736d:
14741     case 0x6d730055:
14742       /* MPEG layer 3, CBR only (pre QT4.1) */
14743     case FOURCC__mp3:
14744     case FOURCC_mp3_:
14745       _codec ("MPEG-1 layer 3");
14746       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14747       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14748           "mpegversion", G_TYPE_INT, 1, NULL);
14749       break;
14750     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14751       _codec ("MPEG-1 layer 2");
14752       /* MPEG layer 2 */
14753       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14754           "mpegversion", G_TYPE_INT, 1, NULL);
14755       break;
14756     case 0x20736d:
14757     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14758       _codec ("EAC-3 audio");
14759       caps = gst_caps_new_simple ("audio/x-eac3",
14760           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14761       entry->sampled = TRUE;
14762       break;
14763     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14764     case FOURCC_ac_3:
14765       _codec ("AC-3 audio");
14766       caps = gst_caps_new_simple ("audio/x-ac3",
14767           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14768       entry->sampled = TRUE;
14769       break;
14770     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14771     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14772       _codec ("DTS audio");
14773       caps = gst_caps_new_simple ("audio/x-dts",
14774           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14775       entry->sampled = TRUE;
14776       break;
14777     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14778     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14779       _codec ("DTS-HD audio");
14780       caps = gst_caps_new_simple ("audio/x-dts",
14781           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14782       entry->sampled = TRUE;
14783       break;
14784     case FOURCC_MAC3:
14785       _codec ("MACE-3");
14786       caps = gst_caps_new_simple ("audio/x-mace",
14787           "maceversion", G_TYPE_INT, 3, NULL);
14788       break;
14789     case FOURCC_MAC6:
14790       _codec ("MACE-6");
14791       caps = gst_caps_new_simple ("audio/x-mace",
14792           "maceversion", G_TYPE_INT, 6, NULL);
14793       break;
14794     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14795       /* ogg/vorbis */
14796       caps = gst_caps_new_empty_simple ("application/ogg");
14797       break;
14798     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14799       _codec ("DV audio");
14800       caps = gst_caps_new_empty_simple ("audio/x-dv");
14801       break;
14802     case FOURCC_mp4a:
14803       _codec ("MPEG-4 AAC audio");
14804       caps = gst_caps_new_simple ("audio/mpeg",
14805           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14806           "stream-format", G_TYPE_STRING, "raw", NULL);
14807       break;
14808     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14809       _codec ("QDesign Music");
14810       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14811       break;
14812     case FOURCC_QDM2:
14813       _codec ("QDesign Music v.2");
14814       /* FIXME: QDesign music version 2 (no constant) */
14815       if (FALSE && data) {
14816         caps = gst_caps_new_simple ("audio/x-qdm2",
14817             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14818             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14819             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14820       } else {
14821         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14822       }
14823       break;
14824     case FOURCC_agsm:
14825       _codec ("GSM audio");
14826       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14827       break;
14828     case FOURCC_samr:
14829       _codec ("AMR audio");
14830       caps = gst_caps_new_empty_simple ("audio/AMR");
14831       break;
14832     case FOURCC_sawb:
14833       _codec ("AMR-WB audio");
14834       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14835       break;
14836     case FOURCC_ima4:
14837       _codec ("Quicktime IMA ADPCM");
14838       caps = gst_caps_new_simple ("audio/x-adpcm",
14839           "layout", G_TYPE_STRING, "quicktime", NULL);
14840       break;
14841     case FOURCC_alac:
14842       _codec ("Apple lossless audio");
14843       caps = gst_caps_new_empty_simple ("audio/x-alac");
14844       break;
14845     case FOURCC_fLaC:
14846       _codec ("Free Lossless Audio Codec");
14847       caps = gst_caps_new_simple ("audio/x-flac",
14848           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14849       break;
14850     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14851       _codec ("QualComm PureVoice");
14852       caps = gst_caps_from_string ("audio/qcelp");
14853       break;
14854     case FOURCC_wma_:
14855     case FOURCC_owma:
14856       _codec ("WMA");
14857       caps = gst_caps_new_empty_simple ("audio/x-wma");
14858       break;
14859     case FOURCC_opus:
14860       _codec ("Opus");
14861       caps = gst_caps_new_empty_simple ("audio/x-opus");
14862       break;
14863     case FOURCC_lpcm:
14864     {
14865       guint32 flags = 0;
14866       guint32 depth = 0;
14867       guint32 width = 0;
14868       GstAudioFormat format;
14869       enum
14870       {
14871         FLAG_IS_FLOAT = 0x1,
14872         FLAG_IS_BIG_ENDIAN = 0x2,
14873         FLAG_IS_SIGNED = 0x4,
14874         FLAG_IS_PACKED = 0x8,
14875         FLAG_IS_ALIGNED_HIGH = 0x10,
14876         FLAG_IS_NON_INTERLEAVED = 0x20
14877       };
14878       _codec ("Raw LPCM audio");
14879
14880       if (data && len >= 36) {
14881         depth = QT_UINT32 (data + 24);
14882         flags = QT_UINT32 (data + 28);
14883         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14884       }
14885       if ((flags & FLAG_IS_FLOAT) == 0) {
14886         if (depth == 0)
14887           depth = 16;
14888         if (width == 0)
14889           width = 16;
14890         if ((flags & FLAG_IS_ALIGNED_HIGH))
14891           depth = width;
14892
14893         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14894             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14895             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14896         caps = gst_caps_new_simple ("audio/x-raw",
14897             "format", G_TYPE_STRING,
14898             format !=
14899             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14900             "UNKNOWN", "layout", G_TYPE_STRING,
14901             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14902             "interleaved", NULL);
14903         stream->alignment = GST_ROUND_UP_8 (depth);
14904         stream->alignment = round_up_pow2 (stream->alignment);
14905       } else {
14906         if (width == 0)
14907           width = 32;
14908         if (width == 64) {
14909           if (flags & FLAG_IS_BIG_ENDIAN)
14910             format = GST_AUDIO_FORMAT_F64BE;
14911           else
14912             format = GST_AUDIO_FORMAT_F64LE;
14913         } else {
14914           if (flags & FLAG_IS_BIG_ENDIAN)
14915             format = GST_AUDIO_FORMAT_F32BE;
14916           else
14917             format = GST_AUDIO_FORMAT_F32LE;
14918         }
14919         caps = gst_caps_new_simple ("audio/x-raw",
14920             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14921             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14922             "non-interleaved" : "interleaved", NULL);
14923         stream->alignment = width / 8;
14924       }
14925       break;
14926     }
14927     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14928     {
14929       _codec ("AC4");
14930       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14931       break;
14932     }
14933     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14934       /* ? */
14935     default:
14936     {
14937       caps = _get_unknown_codec_name ("audio", fourcc);
14938       break;
14939     }
14940   }
14941
14942   if (caps) {
14943     GstCaps *templ_caps =
14944         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14945     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14946     gst_caps_unref (caps);
14947     gst_caps_unref (templ_caps);
14948     caps = intersection;
14949   }
14950
14951   /* enable clipping for raw audio streams */
14952   s = gst_caps_get_structure (caps, 0);
14953   name = gst_structure_get_name (s);
14954   if (g_str_has_prefix (name, "audio/x-raw")) {
14955     stream->need_clip = TRUE;
14956     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14957     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14958     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
14959         stream->max_buffer_size);
14960   }
14961   return caps;
14962 }
14963
14964 static GstCaps *
14965 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14966     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14967     const guint8 * stsd_entry_data, gchar ** codec_name)
14968 {
14969   GstCaps *caps;
14970
14971   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14972
14973   switch (fourcc) {
14974     case FOURCC_mp4s:
14975       _codec ("DVD subtitle");
14976       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14977       stream->process_func = gst_qtdemux_process_buffer_dvd;
14978       break;
14979     case FOURCC_text:
14980       _codec ("Quicktime timed text");
14981       goto text;
14982     case FOURCC_tx3g:
14983       _codec ("3GPP timed text");
14984     text:
14985       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14986           "utf8", NULL);
14987       /* actual text piece needs to be extracted */
14988       stream->process_func = gst_qtdemux_process_buffer_text;
14989       break;
14990     case FOURCC_stpp:
14991       _codec ("XML subtitles");
14992       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14993       break;
14994     case FOURCC_c608:
14995       _codec ("CEA 608 Closed Caption");
14996       caps =
14997           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14998           G_TYPE_STRING, "s334-1a", NULL);
14999       stream->process_func = gst_qtdemux_process_buffer_clcp;
15000       stream->need_split = TRUE;
15001       break;
15002     case FOURCC_c708:
15003       _codec ("CEA 708 Closed Caption");
15004       caps =
15005           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15006           G_TYPE_STRING, "cdp", NULL);
15007       stream->process_func = gst_qtdemux_process_buffer_clcp;
15008       break;
15009
15010     default:
15011     {
15012       caps = _get_unknown_codec_name ("text", fourcc);
15013       break;
15014     }
15015   }
15016   return caps;
15017 }
15018
15019 static GstCaps *
15020 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15021     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15022     const guint8 * stsd_entry_data, gchar ** codec_name)
15023 {
15024   GstCaps *caps;
15025
15026   switch (fourcc) {
15027     case FOURCC_m1v:
15028       _codec ("MPEG 1 video");
15029       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15030           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15031       break;
15032     default:
15033       caps = NULL;
15034       break;
15035   }
15036   return caps;
15037 }
15038
15039 static void
15040 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15041     const gchar * system_id)
15042 {
15043   gint i;
15044
15045   if (!qtdemux->protection_system_ids)
15046     qtdemux->protection_system_ids =
15047         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15048   /* Check whether we already have an entry for this system ID. */
15049   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15050     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15051     if (g_ascii_strcasecmp (system_id, id) == 0) {
15052       return;
15053     }
15054   }
15055   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15056   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15057           -1));
15058 }