Merge branch 'tizen_gst_1.22.7' into tizen_gst_1.22.8
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 #include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
119 typedef struct _QtDemuxSphericalMetadata QtDemuxSphericalMetadata;
120
121 struct _QtDemuxSphericalMetadata
122 {
123   gboolean is_spherical;
124   gboolean is_stitched;
125   char *stitching_software;
126   char *projection_type;
127   char *stereo_mode;
128   int source_count;
129   int init_view_heading;
130   int init_view_pitch;
131   int init_view_roll;
132   int timestamp;
133   int full_pano_width_pixels;
134   int full_pano_height_pixels;
135   int cropped_area_image_width;
136   int cropped_area_image_height;
137   int cropped_area_left;
138   int cropped_area_top;
139   QTDEMUX_AMBISONIC_TYPE ambisonic_type;
140   QTDEMUX_AMBISONIC_FORMAT ambisonic_format;
141   QTDEMUX_AMBISONIC_ORDER ambisonic_order;
142 };
143
144 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
145
146 /* Macros for converting to/from timescale */
147 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
148 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
149
150 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
151 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
152
153 /* timestamp is the DTS */
154 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
155 /* timestamp + offset + cslg_shift is the outgoing PTS */
156 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
157 /* timestamp + offset is the PTS used for internal seek calculations */
158 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
159 /* timestamp + duration - dts is the duration */
160 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
161
162 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
163
164 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
165 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
166     GST_TRACE("Locking from thread %p", g_thread_self()); \
167     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
168     GST_TRACE("Locked from thread %p", g_thread_self()); \
169  } G_STMT_END
170
171 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
172     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
173     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
174  } G_STMT_END
175
176 /*
177  * Quicktime has tracks and segments. A track is a continuous piece of
178  * multimedia content. The track is not always played from start to finish but
179  * instead, pieces of the track are 'cut out' and played in sequence. This is
180  * what the segments do.
181  *
182  * Inside the track we have keyframes (K) and delta frames. The track has its
183  * own timing, which starts from 0 and extends to end. The position in the track
184  * is called the media_time.
185  *
186  * The segments now describe the pieces that should be played from this track
187  * and are basically tuples of media_time/duration/rate entries. We can have
188  * multiple segments and they are all played after one another. An example:
189  *
190  * segment 1: media_time: 1 second, duration: 1 second, rate 1
191  * segment 2: media_time: 3 second, duration: 2 second, rate 2
192  *
193  * To correctly play back this track, one must play: 1 second of media starting
194  * from media_time 1 followed by 2 seconds of media starting from media_time 3
195  * at a rate of 2.
196  *
197  * Each of the segments will be played at a specific time, the first segment at
198  * time 0, the second one after the duration of the first one, etc.. Note that
199  * the time in resulting playback is not identical to the media_time of the
200  * track anymore.
201  *
202  * Visually, assuming the track has 4 second of media_time:
203  *
204  *                (a)                   (b)          (c)              (d)
205  *         .-----------------------------------------------------------.
206  * track:  | K.....K.........K........K.......K.......K...........K... |
207  *         '-----------------------------------------------------------'
208  *         0              1              2              3              4
209  *           .------------^              ^   .----------^              ^
210  *          /              .-------------'  /       .------------------'
211  *         /              /          .-----'       /
212  *         .--------------.         .--------------.
213  *         | segment 1    |         | segment 2    |
214  *         '--------------'         '--------------'
215  *
216  * The challenge here is to cut out the right pieces of the track for each of
217  * the playback segments. This fortunately can easily be done with the SEGMENT
218  * events of GStreamer.
219  *
220  * For playback of segment 1, we need to provide the decoder with the keyframe
221  * (a), in the above figure, but we must instruct it only to output the decoded
222  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
223  * position set to the time of the segment: 0.
224  *
225  * We then proceed to push data from keyframe (a) to frame (b). The decoder
226  * decodes but clips all before media_time 1.
227  *
228  * After finishing a segment, we push out a new SEGMENT event with the clipping
229  * boundaries of the new data.
230  *
231  * This is a good usecase for the GStreamer accumulated SEGMENT events.
232  */
233
234 struct _QtDemuxSegment
235 {
236   /* global time and duration, all gst time */
237   GstClockTime time;
238   GstClockTime stop_time;
239   GstClockTime duration;
240   /* media time of trak, all gst time */
241   GstClockTime media_start;
242   GstClockTime media_stop;
243   gdouble rate;
244   /* Media start time in trak timescale units */
245   guint32 trak_media_start;
246 };
247
248 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
249
250 /* Used with fragmented MP4 files (mfra atom) */
251 struct _QtDemuxRandomAccessEntry
252 {
253   GstClockTime ts;
254   guint64 moof_offset;
255 };
256
257
258 /* Contains properties and cryptographic info for a set of samples from a
259  * track protected using Common Encryption (cenc) */
260 struct _QtDemuxCencSampleSetInfo
261 {
262   GstStructure *default_properties;
263
264   /* @crypto_info holds one GstStructure per sample */
265   GPtrArray *crypto_info;
266 };
267
268 struct _QtDemuxAavdEncryptionInfo
269 {
270   GstStructure *default_properties;
271 };
272
273 static const gchar *
274 qt_demux_state_string (enum QtDemuxState state)
275 {
276   switch (state) {
277     case QTDEMUX_STATE_INITIAL:
278       return "<INITIAL>";
279     case QTDEMUX_STATE_HEADER:
280       return "<HEADER>";
281     case QTDEMUX_STATE_MOVIE:
282       return "<MOVIE>";
283     case QTDEMUX_STATE_BUFFER_MDAT:
284       return "<BUFFER_MDAT>";
285     default:
286       return "<UNKNOWN>";
287   }
288 }
289
290 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
291
292 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
293
294 static GstStaticPadTemplate gst_qtdemux_sink_template =
295     GST_STATIC_PAD_TEMPLATE ("sink",
296     GST_PAD_SINK,
297     GST_PAD_ALWAYS,
298     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
299         "application/x-3gp")
300     );
301
302 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
303 GST_STATIC_PAD_TEMPLATE ("video_%u",
304     GST_PAD_SRC,
305     GST_PAD_SOMETIMES,
306     GST_STATIC_CAPS_ANY);
307
308 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
309 GST_STATIC_PAD_TEMPLATE ("audio_%u",
310     GST_PAD_SRC,
311     GST_PAD_SOMETIMES,
312     GST_STATIC_CAPS_ANY);
313
314 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
315 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
316     GST_PAD_SRC,
317     GST_PAD_SOMETIMES,
318     GST_STATIC_CAPS_ANY);
319
320 static GstStaticPadTemplate gst_qtdemux_metasrc_template =
321 GST_STATIC_PAD_TEMPLATE ("meta_%u",
322     GST_PAD_SRC,
323     GST_PAD_SOMETIMES,
324     GST_STATIC_CAPS_ANY);
325
326 #define gst_qtdemux_parent_class parent_class
327 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
328 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
329     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
330
331 static void gst_qtdemux_dispose (GObject * object);
332 static void gst_qtdemux_finalize (GObject * object);
333
334 static guint32
335 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
336     GstClockTime media_time);
337 static guint32
338 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
339     QtDemuxStream * str, gint64 media_offset);
340
341 #if 0
342 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
343 static GstIndex *gst_qtdemux_get_index (GstElement * element);
344 #endif
345 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
346     GstStateChange transition);
347 static void gst_qtdemux_set_context (GstElement * element,
348     GstContext * context);
349 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
350 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
351     GstObject * parent, GstPadMode mode, gboolean active);
352
353 static void gst_qtdemux_loop (GstPad * pad);
354 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
355     GstBuffer * inbuf);
356 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
357     GstEvent * event);
358 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
359     GstQuery * query);
360 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
361 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
362     QtDemuxStream * stream);
363 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
364     QtDemuxStream * stream);
365 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
366     gboolean force);
367
368 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
369
370 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
371     const guint8 * buffer, guint length);
372 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
373     const guint8 * buffer, guint length);
374 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
375
376 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
378     GstTagList * list);
379 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
380     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
381     const guint8 * stsd_entry_data, gchar ** codec_name);
382 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
383     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
384     const guint8 * data, int len, gchar ** codec_name);
385 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
386     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
387     gchar ** codec_name);
388 static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
389     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
390     gchar ** codec_name);
391 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
392     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
393     const guint8 * stsd_entry_data, gchar ** codec_name);
394
395 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
396     QtDemuxStream * stream, guint32 n);
397 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
398 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
399 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
400 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
401 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
402 static void qtdemux_do_allocation (QtDemuxStream * stream,
403     GstQTDemux * qtdemux);
404 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
405     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
406 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
407     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
408     GstClockTime * _start, GstClockTime * _stop);
409 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
410     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
411
412 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
413 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
414
415 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
416
417 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
418     QtDemuxStream * stream, guint sample_index);
419 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
420     const gchar * id);
421 static void qtdemux_gst_structure_free (GstStructure * gststructure);
422 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
423 static void qtdemux_clear_protection_events_on_all_streams (GstQTDemux *
424     qtdemux);
425
426 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
427 static void gst_tag_register_spherical_tags (void);
428 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
429
430 static void
431 gst_qtdemux_class_init (GstQTDemuxClass * klass)
432 {
433   GObjectClass *gobject_class;
434   GstElementClass *gstelement_class;
435
436   gobject_class = (GObjectClass *) klass;
437   gstelement_class = (GstElementClass *) klass;
438
439   parent_class = g_type_class_peek_parent (klass);
440
441   gobject_class->dispose = gst_qtdemux_dispose;
442   gobject_class->finalize = gst_qtdemux_finalize;
443
444   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
445 #if 0
446   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
447   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
448 #endif
449   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
450
451   gst_tag_register_musicbrainz_tags ();
452
453 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
454   gst_tag_register_spherical_tags ();
455 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
456
457   gst_element_class_add_static_pad_template (gstelement_class,
458       &gst_qtdemux_sink_template);
459   gst_element_class_add_static_pad_template (gstelement_class,
460       &gst_qtdemux_videosrc_template);
461   gst_element_class_add_static_pad_template (gstelement_class,
462       &gst_qtdemux_audiosrc_template);
463   gst_element_class_add_static_pad_template (gstelement_class,
464       &gst_qtdemux_subsrc_template);
465   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
466       "Codec/Demuxer",
467       "Demultiplex a QuickTime file into audio and video streams",
468       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
469
470   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
471   gst_riff_init ();
472 }
473
474 static void
475 gst_qtdemux_init (GstQTDemux * qtdemux)
476 {
477   qtdemux->sinkpad =
478       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
479   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
480   gst_pad_set_activatemode_function (qtdemux->sinkpad,
481       qtdemux_sink_activate_mode);
482   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
483   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
484   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
485   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
486
487   qtdemux->adapter = gst_adapter_new ();
488   g_queue_init (&qtdemux->protection_event_queue);
489   qtdemux->flowcombiner = gst_flow_combiner_new ();
490   g_mutex_init (&qtdemux->expose_lock);
491
492   qtdemux->active_streams = g_ptr_array_new_with_free_func
493       ((GDestroyNotify) gst_qtdemux_stream_unref);
494   qtdemux->old_streams = g_ptr_array_new_with_free_func
495       ((GDestroyNotify) gst_qtdemux_stream_unref);
496
497 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
498   qtdemux->spherical_metadata = (QtDemuxSphericalMetadata *)
499       malloc (sizeof (QtDemuxSphericalMetadata));
500
501   if (qtdemux->spherical_metadata) {
502     qtdemux->spherical_metadata->is_spherical = FALSE;
503     qtdemux->spherical_metadata->is_stitched = FALSE;
504     qtdemux->spherical_metadata->stitching_software = NULL;
505     qtdemux->spherical_metadata->projection_type = NULL;
506     qtdemux->spherical_metadata->stereo_mode = NULL;
507     qtdemux->spherical_metadata->source_count = 0;
508     qtdemux->spherical_metadata->init_view_heading = 0;
509     qtdemux->spherical_metadata->init_view_pitch = 0;
510     qtdemux->spherical_metadata->init_view_roll = 0;
511     qtdemux->spherical_metadata->timestamp = 0;
512     qtdemux->spherical_metadata->full_pano_width_pixels = 0;
513     qtdemux->spherical_metadata->full_pano_height_pixels = 0;
514     qtdemux->spherical_metadata->cropped_area_image_width = 0;
515     qtdemux->spherical_metadata->cropped_area_image_height = 0;
516     qtdemux->spherical_metadata->cropped_area_left = 0;
517     qtdemux->spherical_metadata->cropped_area_top = 0;
518     qtdemux->spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_UNKNOWN;
519     qtdemux->spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_UNKNOWN;
520     qtdemux->spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_UNKNOWN;
521   }
522 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
523
524   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
525
526   gst_qtdemux_reset (qtdemux, TRUE);
527 }
528
529 static void
530 gst_qtdemux_finalize (GObject * object)
531 {
532   GstQTDemux *qtdemux = GST_QTDEMUX (object);
533
534   g_free (qtdemux->redirect_location);
535
536   G_OBJECT_CLASS (parent_class)->finalize (object);
537 }
538
539 static void
540 gst_qtdemux_dispose (GObject * object)
541 {
542   GstQTDemux *qtdemux = GST_QTDEMUX (object);
543
544 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
545   if (qtdemux->spherical_metadata) {
546     if (qtdemux->spherical_metadata->stitching_software)
547       free(qtdemux->spherical_metadata->stitching_software);
548     if (qtdemux->spherical_metadata->projection_type)
549       free(qtdemux->spherical_metadata->projection_type);
550     if (qtdemux->spherical_metadata->stereo_mode)
551       free(qtdemux->spherical_metadata->stereo_mode);
552
553     free(qtdemux->spherical_metadata);
554     qtdemux->spherical_metadata = NULL;
555   }
556 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
557
558   if (qtdemux->adapter) {
559     g_object_unref (G_OBJECT (qtdemux->adapter));
560     qtdemux->adapter = NULL;
561   }
562   gst_tag_list_unref (qtdemux->tag_list);
563   gst_flow_combiner_free (qtdemux->flowcombiner);
564   g_queue_clear_full (&qtdemux->protection_event_queue,
565       (GDestroyNotify) gst_event_unref);
566
567   g_free (qtdemux->cenc_aux_info_sizes);
568   qtdemux->cenc_aux_info_sizes = NULL;
569   g_mutex_clear (&qtdemux->expose_lock);
570
571   g_ptr_array_free (qtdemux->active_streams, TRUE);
572   g_ptr_array_free (qtdemux->old_streams, TRUE);
573
574   G_OBJECT_CLASS (parent_class)->dispose (object);
575 }
576
577 static void
578 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
579 {
580   if (qtdemux->redirect_location) {
581     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
582         (_("This file contains no playable streams.")),
583         ("no known streams found, a redirect message has been posted"),
584         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
585   } else {
586     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
587         (_("This file contains no playable streams.")),
588         ("no known streams found"));
589   }
590 }
591
592 static GstBuffer *
593 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
594 {
595   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
596       mem, size, 0, size, mem, free_func);
597 }
598
599 static GstFlowReturn
600 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
601     GstBuffer ** buf)
602 {
603   GstFlowReturn flow;
604   GstMapInfo map;
605   gsize bsize;
606
607   if (G_UNLIKELY (size == 0)) {
608     GstFlowReturn ret;
609     GstBuffer *tmp = NULL;
610
611     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
612     if (ret != GST_FLOW_OK)
613       return ret;
614
615     gst_buffer_map (tmp, &map, GST_MAP_READ);
616     size = QT_UINT32 (map.data);
617     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
618
619     gst_buffer_unmap (tmp, &map);
620     gst_buffer_unref (tmp);
621   }
622
623   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
624   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
625     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
626       /* we're pulling header but already got most interesting bits,
627        * so never mind the rest (e.g. tags) (that much) */
628       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
629           size);
630       return GST_FLOW_EOS;
631     } else {
632       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
633           (_("This file is invalid and cannot be played.")),
634           ("atom has bogus size %" G_GUINT64_FORMAT, size));
635       return GST_FLOW_ERROR;
636     }
637   }
638
639   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
640
641   if (G_UNLIKELY (flow != GST_FLOW_OK))
642     return flow;
643
644   bsize = gst_buffer_get_size (*buf);
645   /* Catch short reads - we don't want any partial atoms */
646   if (G_UNLIKELY (bsize < size)) {
647     GST_WARNING_OBJECT (qtdemux,
648         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
649     gst_buffer_unref (*buf);
650     *buf = NULL;
651     return GST_FLOW_EOS;
652   }
653
654   return flow;
655 }
656
657 #if 1
658 static gboolean
659 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
660     GstFormat src_format, gint64 src_value, GstFormat dest_format,
661     gint64 * dest_value)
662 {
663   gboolean res = TRUE;
664   QtDemuxStream *stream = gst_pad_get_element_private (pad);
665   gint32 index;
666
667   if (stream->subtype != FOURCC_vide) {
668     res = FALSE;
669     goto done;
670   }
671
672   switch (src_format) {
673     case GST_FORMAT_TIME:
674       switch (dest_format) {
675         case GST_FORMAT_BYTES:{
676           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
677           if (-1 == index) {
678             res = FALSE;
679             goto done;
680           }
681
682           *dest_value = stream->samples[index].offset;
683
684           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
685               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
686               GST_TIME_ARGS (src_value), *dest_value);
687           break;
688         }
689         default:
690           res = FALSE;
691           break;
692       }
693       break;
694     case GST_FORMAT_BYTES:
695       switch (dest_format) {
696         case GST_FORMAT_TIME:{
697           index =
698               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
699               stream, src_value);
700
701           if (-1 == index) {
702             res = FALSE;
703             goto done;
704           }
705
706           *dest_value =
707               QTSTREAMTIME_TO_GSTTIME (stream,
708               stream->samples[index].timestamp);
709           GST_DEBUG_OBJECT (qtdemux,
710               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
711               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
712           break;
713         }
714         default:
715           res = FALSE;
716           break;
717       }
718       break;
719     default:
720       res = FALSE;
721       break;
722   }
723
724 done:
725   return res;
726 }
727 #endif
728
729 static gboolean
730 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
731 {
732   gboolean res = FALSE;
733
734   *duration = GST_CLOCK_TIME_NONE;
735
736   if (qtdemux->duration != 0 &&
737       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
738     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
739     res = TRUE;
740   } else {
741     *duration = GST_CLOCK_TIME_NONE;
742   }
743
744   return res;
745 }
746
747 static gboolean
748 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
749     GstQuery * query)
750 {
751   gboolean res = FALSE;
752   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
753
754   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
755
756   switch (GST_QUERY_TYPE (query)) {
757     case GST_QUERY_POSITION:{
758       GstFormat fmt;
759
760       gst_query_parse_position (query, &fmt, NULL);
761       if (fmt == GST_FORMAT_TIME
762           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
763         gst_query_set_position (query, GST_FORMAT_TIME,
764             qtdemux->segment.position);
765         res = TRUE;
766       }
767     }
768       break;
769     case GST_QUERY_DURATION:{
770       GstFormat fmt;
771
772       gst_query_parse_duration (query, &fmt, NULL);
773       if (fmt == GST_FORMAT_TIME) {
774         /* First try to query upstream */
775         res = gst_pad_query_default (pad, parent, query);
776         if (!res) {
777           GstClockTime duration;
778           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
779             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
780             res = TRUE;
781           }
782         }
783       }
784       break;
785     }
786     case GST_QUERY_CONVERT:{
787       GstFormat src_fmt, dest_fmt;
788       gint64 src_value, dest_value = 0;
789
790       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
791
792       res = gst_qtdemux_src_convert (qtdemux, pad,
793           src_fmt, src_value, dest_fmt, &dest_value);
794       if (res)
795         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
796
797       break;
798     }
799     case GST_QUERY_FORMATS:
800       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
801       res = TRUE;
802       break;
803     case GST_QUERY_SEEKING:{
804       GstFormat fmt;
805       gboolean seekable;
806
807       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
808
809       if (fmt == GST_FORMAT_BYTES) {
810         /* We always refuse BYTES seeks from downstream */
811         break;
812       }
813
814       /* try upstream first */
815       res = gst_pad_query_default (pad, parent, query);
816
817       if (!res) {
818         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
819         if (fmt == GST_FORMAT_TIME) {
820           GstClockTime duration;
821
822           gst_qtdemux_get_duration (qtdemux, &duration);
823           seekable = TRUE;
824           if (!qtdemux->pullbased) {
825             GstQuery *q;
826
827             /* we might be able with help from upstream */
828             seekable = FALSE;
829             q = gst_query_new_seeking (GST_FORMAT_BYTES);
830             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
831               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
832               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
833             }
834             gst_query_unref (q);
835           }
836           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
837           res = TRUE;
838         }
839       }
840       break;
841     }
842     case GST_QUERY_SEGMENT:
843     {
844       GstFormat format;
845       gint64 start, stop;
846
847       format = qtdemux->segment.format;
848
849       start =
850           gst_segment_to_stream_time (&qtdemux->segment, format,
851           qtdemux->segment.start);
852       if ((stop = qtdemux->segment.stop) == -1)
853         stop = qtdemux->segment.duration;
854       else
855         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
856
857       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
858       res = TRUE;
859       break;
860     }
861     default:
862       res = gst_pad_query_default (pad, parent, query);
863       break;
864   }
865
866   return res;
867 }
868
869 static void
870 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
871 {
872   if (G_LIKELY (stream->pad)) {
873     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
874         GST_DEBUG_PAD_NAME (stream->pad));
875
876     if (!gst_tag_list_is_empty (stream->stream_tags)) {
877       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
878           stream->stream_tags);
879       gst_pad_push_event (stream->pad,
880           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
881 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
882       /* post message qtdemux tag (for early recive application) */
883       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
884             gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
885                   gst_tag_list_copy (stream->stream_tags)));
886 #endif
887     }
888
889     if (G_UNLIKELY (stream->send_global_tags)) {
890       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
891           qtdemux->tag_list);
892       gst_pad_push_event (stream->pad,
893           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
894       stream->send_global_tags = FALSE;
895     }
896   }
897 }
898
899 /* push event on all source pads; takes ownership of the event */
900 static void
901 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
902 {
903   gboolean has_valid_stream = FALSE;
904   GstEventType etype = GST_EVENT_TYPE (event);
905   guint i;
906
907   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
908       GST_EVENT_TYPE_NAME (event));
909
910   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
911     GstPad *pad;
912     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
913     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
914
915     if ((pad = stream->pad)) {
916       has_valid_stream = TRUE;
917
918       if (etype == GST_EVENT_EOS) {
919         /* let's not send twice */
920         if (stream->sent_eos)
921           continue;
922         stream->sent_eos = TRUE;
923       }
924
925       gst_pad_push_event (pad, gst_event_ref (event));
926     }
927   }
928
929   gst_event_unref (event);
930
931   /* if it is EOS and there are no pads, post an error */
932   if (!has_valid_stream && etype == GST_EVENT_EOS) {
933     gst_qtdemux_post_no_playable_stream_error (qtdemux);
934   }
935 }
936
937 typedef struct
938 {
939   guint64 media_time;
940 } FindData;
941
942 static gint
943 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
944 {
945   if ((gint64) s1->timestamp > *media_time)
946     return 1;
947   if ((gint64) s1->timestamp == *media_time)
948     return 0;
949
950   return -1;
951 }
952
953 /* find the index of the sample that includes the data for @media_time using a
954  * binary search.  Only to be called in optimized cases of linear search below.
955  *
956  * Returns the index of the sample with the corresponding *DTS*.
957  */
958 static guint32
959 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
960     guint64 media_time)
961 {
962   QtDemuxSample *result;
963   guint32 index;
964
965   /* convert media_time to mov format */
966   media_time =
967       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
968
969   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
970       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
971       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
972
973   if (G_LIKELY (result))
974     index = result - str->samples;
975   else
976     index = 0;
977
978   return index;
979 }
980
981
982
983 /* find the index of the sample that includes the data for @media_offset using a
984  * linear search
985  *
986  * Returns the index of the sample.
987  */
988 static guint32
989 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
990     QtDemuxStream * str, gint64 media_offset)
991 {
992   QtDemuxSample *result = str->samples;
993   guint32 index = 0;
994
995   if (result == NULL || str->n_samples == 0)
996     return -1;
997
998   if (media_offset == result->offset)
999     return index;
1000
1001   result++;
1002   while (index < str->n_samples - 1) {
1003     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1004       goto parse_failed;
1005
1006     if (media_offset < result->offset)
1007       break;
1008
1009     index++;
1010     result++;
1011   }
1012   return index;
1013
1014   /* ERRORS */
1015 parse_failed:
1016   {
1017     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1018     return -1;
1019   }
1020 }
1021
1022 /* find the index of the sample that includes the data for @media_time using a
1023  * linear search, and keeping in mind that not all samples may have been parsed
1024  * yet.  If possible, it will delegate to binary search.
1025  *
1026  * Returns the index of the sample.
1027  */
1028 static guint32
1029 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1030     GstClockTime media_time)
1031 {
1032   guint32 index = 0;
1033   guint64 mov_time;
1034   QtDemuxSample *sample;
1035
1036   /* convert media_time to mov format */
1037   mov_time =
1038       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1039
1040   sample = str->samples;
1041   if (mov_time == sample->timestamp + sample->pts_offset)
1042     return index;
1043
1044   /* use faster search if requested time in already parsed range */
1045   sample = str->samples + str->stbl_index;
1046   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1047     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1048     sample = str->samples + index;
1049   } else {
1050     while (index < str->n_samples - 1) {
1051       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1052         goto parse_failed;
1053
1054       sample = str->samples + index + 1;
1055       if (mov_time < sample->timestamp) {
1056         sample = str->samples + index;
1057         break;
1058       }
1059
1060       index++;
1061     }
1062   }
1063
1064   /* sample->timestamp is now <= media_time, need to find the corresponding
1065    * PTS now by looking backwards */
1066   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1067     index--;
1068     sample = str->samples + index;
1069   }
1070
1071   return index;
1072
1073   /* ERRORS */
1074 parse_failed:
1075   {
1076     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1077     return -1;
1078   }
1079 }
1080
1081 /* find the index of the keyframe needed to decode the sample at @index
1082  * of stream @str, or of a subsequent keyframe (depending on @next)
1083  *
1084  * Returns the index of the keyframe.
1085  */
1086 static guint32
1087 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1088     guint32 index, gboolean next)
1089 {
1090   guint32 new_index = index;
1091
1092   if (index >= str->n_samples) {
1093     new_index = str->n_samples;
1094     goto beach;
1095   }
1096
1097   /* all keyframes, return index */
1098   if (str->all_keyframe) {
1099     new_index = index;
1100     goto beach;
1101   }
1102
1103   /* else search until we have a keyframe */
1104   while (new_index < str->n_samples) {
1105     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1106       goto parse_failed;
1107
1108     if (str->samples[new_index].keyframe)
1109       break;
1110
1111     if (new_index == 0)
1112       break;
1113
1114     if (next)
1115       new_index++;
1116     else
1117       new_index--;
1118   }
1119
1120   if (new_index == str->n_samples) {
1121     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1122     new_index = -1;
1123   }
1124
1125 beach:
1126   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1127       "gave %u", next ? "after" : "before", index, new_index);
1128
1129   return new_index;
1130
1131   /* ERRORS */
1132 parse_failed:
1133   {
1134     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1135     return -1;
1136   }
1137 }
1138
1139 /* find the segment for @time_position for @stream
1140  *
1141  * Returns the index of the segment containing @time_position.
1142  * Returns the last segment and sets the @eos variable to TRUE
1143  * if the time is beyond the end. @eos may be NULL
1144  */
1145 static guint32
1146 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1147     GstClockTime time_position)
1148 {
1149   gint i;
1150   guint32 seg_idx;
1151
1152   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1153       GST_TIME_ARGS (time_position));
1154
1155   seg_idx = -1;
1156   for (i = 0; i < stream->n_segments; i++) {
1157     QtDemuxSegment *segment = &stream->segments[i];
1158
1159     GST_LOG_OBJECT (stream->pad,
1160         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1161         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1162
1163     /* For the last segment we include stop_time in the last segment */
1164     if (i < stream->n_segments - 1) {
1165       if (segment->time <= time_position && time_position < segment->stop_time) {
1166         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1167         seg_idx = i;
1168         break;
1169       }
1170     } else {
1171       /* Last segment always matches */
1172       seg_idx = i;
1173       break;
1174     }
1175   }
1176   return seg_idx;
1177 }
1178
1179 /* move the stream @str to the sample position @index.
1180  *
1181  * Updates @str->sample_index and marks discontinuity if needed.
1182  */
1183 static void
1184 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1185     guint32 index)
1186 {
1187   /* no change needed */
1188   if (index == str->sample_index)
1189     return;
1190
1191   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1192       str->n_samples);
1193
1194   /* position changed, we have a discont */
1195   str->sample_index = index;
1196   str->offset_in_sample = 0;
1197   /* Each time we move in the stream we store the position where we are
1198    * starting from */
1199   str->from_sample = index;
1200   str->discont = TRUE;
1201 }
1202
1203 static void
1204 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1205     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1206 {
1207   guint64 min_offset;
1208   gint64 min_byte_offset = -1;
1209   guint i;
1210
1211   min_offset = next ? G_MAXUINT64 : desired_time;
1212
1213   /* for each stream, find the index of the sample in the segment
1214    * and move back to the previous keyframe. */
1215   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1216     QtDemuxStream *str;
1217     guint32 index, kindex;
1218     guint32 seg_idx;
1219     GstClockTime media_start;
1220     GstClockTime media_time;
1221     GstClockTime seg_time;
1222     QtDemuxSegment *seg;
1223     gboolean empty_segment = FALSE;
1224
1225     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1226
1227     if (CUR_STREAM (str)->sparse && !use_sparse)
1228       continue;
1229
1230     /* raw audio streams can be ignored as we can seek anywhere within them */
1231     if (str->subtype == FOURCC_soun && str->need_clip)
1232       continue;
1233
1234     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1235     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1236
1237     /* get segment and time in the segment */
1238     seg = &str->segments[seg_idx];
1239     seg_time = (desired_time - seg->time) * seg->rate;
1240
1241     while (QTSEGMENT_IS_EMPTY (seg)) {
1242       seg_time = 0;
1243       empty_segment = TRUE;
1244       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1245           seg_idx);
1246       seg_idx++;
1247       if (seg_idx == str->n_segments)
1248         break;
1249       seg = &str->segments[seg_idx];
1250     }
1251
1252     if (seg_idx == str->n_segments) {
1253       /* FIXME track shouldn't have the last segment as empty, but if it
1254        * happens we better handle it */
1255       continue;
1256     }
1257
1258     /* get the media time in the segment */
1259     media_start = seg->media_start + seg_time;
1260
1261     /* get the index of the sample with media time */
1262     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1263     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1264         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1265         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1266         empty_segment);
1267
1268     /* shift to next frame if we are looking for next keyframe */
1269     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1270         && index < str->stbl_index)
1271       index++;
1272
1273     if (!empty_segment) {
1274       /* find previous or next keyframe */
1275       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1276
1277       /* if looking for next one, we will settle for one before if none found after */
1278       if (next && kindex == -1)
1279         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1280
1281       /* Update the requested time whenever a keyframe was found, to make it
1282        * accurate and avoid having the first buffer fall outside of the segment
1283        */
1284       if (kindex != -1) {
1285         index = kindex;
1286
1287         /* get timestamp of keyframe */
1288         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1289         GST_DEBUG_OBJECT (qtdemux,
1290             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1291             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1292             str->samples[kindex].offset);
1293
1294         /* keyframes in the segment get a chance to change the
1295          * desired_offset. keyframes out of the segment are
1296          * ignored. */
1297         if (media_time >= seg->media_start) {
1298           GstClockTime seg_time;
1299
1300           /* this keyframe is inside the segment, convert back to
1301            * segment time */
1302           seg_time = (media_time - seg->media_start) + seg->time;
1303
1304           /* Adjust the offset based on the earliest suitable keyframe found,
1305            * based on which GST_SEEK_FLAG_SNAP_* is present (indicated by 'next').
1306            * For SNAP_BEFORE we look for the earliest keyframe before desired_time,
1307            * and in case of SNAP_AFTER - for the closest one after it. */
1308           if (seg_time < min_offset)
1309             min_offset = seg_time;
1310         }
1311       }
1312     }
1313
1314     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1315       min_byte_offset = str->samples[index].offset;
1316   }
1317
1318   if (key_time)
1319     *key_time = min_offset;
1320   if (key_offset)
1321     *key_offset = min_byte_offset;
1322 }
1323
1324 static gboolean
1325 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1326     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1327 {
1328   gboolean res;
1329
1330   g_return_val_if_fail (format != NULL, FALSE);
1331   g_return_val_if_fail (cur != NULL, FALSE);
1332   g_return_val_if_fail (stop != NULL, FALSE);
1333
1334   if (*format == GST_FORMAT_TIME)
1335     return TRUE;
1336
1337   res = TRUE;
1338   if (cur_type != GST_SEEK_TYPE_NONE)
1339     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1340   if (res && stop_type != GST_SEEK_TYPE_NONE)
1341     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1342
1343   if (res)
1344     *format = GST_FORMAT_TIME;
1345
1346   return res;
1347 }
1348
1349 /* perform seek in push based mode:
1350    find BYTE position to move to based on time and delegate to upstream
1351 */
1352 static gboolean
1353 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1354 {
1355   gdouble rate;
1356   GstFormat format;
1357   GstSeekFlags flags;
1358   GstSeekType cur_type, stop_type;
1359   gint64 cur, stop, key_cur;
1360   gboolean res;
1361   gint64 byte_cur;
1362   gint64 original_stop;
1363   guint32 seqnum;
1364
1365   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1366
1367   gst_event_parse_seek (event, &rate, &format, &flags,
1368       &cur_type, &cur, &stop_type, &stop);
1369   seqnum = gst_event_get_seqnum (event);
1370
1371   /* Directly send the instant-rate-change event here before taking the
1372    * stream-lock so that it can be applied as soon as possible */
1373   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1374     GstEvent *ev;
1375
1376     /* instant rate change only supported if direction does not change. All
1377      * other requirements are already checked before creating the seek event
1378      * but let's double-check here to be sure */
1379     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1380         (qtdemux->segment.rate < 0 && rate > 0) ||
1381         cur_type != GST_SEEK_TYPE_NONE ||
1382         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1383       GST_ERROR_OBJECT (qtdemux,
1384           "Instant rate change seeks only supported in the "
1385           "same direction, without flushing and position change");
1386       return FALSE;
1387     }
1388
1389     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1390         (GstSegmentFlags) flags);
1391     gst_event_set_seqnum (ev, seqnum);
1392     gst_qtdemux_push_event (qtdemux, ev);
1393     return TRUE;
1394   }
1395
1396   /* only forward streaming and seeking is possible */
1397   if (rate <= 0)
1398     goto unsupported_seek;
1399
1400   /* convert to TIME if needed and possible */
1401   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1402           stop_type, &stop))
1403     goto no_format;
1404
1405   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1406    * the original stop position to use when upstream pushes the new segment
1407    * for this seek */
1408   original_stop = stop;
1409   stop = -1;
1410
1411   /* find reasonable corresponding BYTE position,
1412    * also try to mind about keyframes, since we can not go back a bit for them
1413    * later on */
1414   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1415    * mostly just work, but let's not yet boldly go there  ... */
1416   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1417
1418   if (byte_cur == -1)
1419     goto abort_seek;
1420
1421   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1422       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1423       stop);
1424
1425   GST_OBJECT_LOCK (qtdemux);
1426   qtdemux->seek_offset = byte_cur;
1427   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1428     qtdemux->push_seek_start = cur;
1429   } else {
1430     qtdemux->push_seek_start = key_cur;
1431   }
1432
1433   if (stop_type == GST_SEEK_TYPE_NONE) {
1434     qtdemux->push_seek_stop = qtdemux->segment.stop;
1435   } else {
1436     qtdemux->push_seek_stop = original_stop;
1437   }
1438   GST_OBJECT_UNLOCK (qtdemux);
1439
1440   qtdemux->segment_seqnum = seqnum;
1441   /* BYTE seek event */
1442   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1443       stop_type, stop);
1444   gst_event_set_seqnum (event, seqnum);
1445   res = gst_pad_push_event (qtdemux->sinkpad, event);
1446
1447   return res;
1448
1449   /* ERRORS */
1450 abort_seek:
1451   {
1452     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1453         "seek aborted.");
1454     return FALSE;
1455   }
1456 unsupported_seek:
1457   {
1458     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1459     return FALSE;
1460   }
1461 no_format:
1462   {
1463     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1464     return FALSE;
1465   }
1466 }
1467
1468 /* perform the seek.
1469  *
1470  * We set all segment_indexes in the streams to unknown and
1471  * adjust the time_position to the desired position. this is enough
1472  * to trigger a segment switch in the streaming thread to start
1473  * streaming from the desired position.
1474  *
1475  * Keyframe seeking is a little more complicated when dealing with
1476  * segments. Ideally we want to move to the previous keyframe in
1477  * the segment but there might not be a keyframe in the segment. In
1478  * fact, none of the segments could contain a keyframe. We take a
1479  * practical approach: seek to the previous keyframe in the segment,
1480  * if there is none, seek to the beginning of the segment.
1481  *
1482  * Called with STREAM_LOCK
1483  */
1484 static gboolean
1485 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1486     guint32 seqnum, GstSeekFlags flags)
1487 {
1488   gint64 desired_offset;
1489   guint i;
1490
1491   desired_offset = segment->position;
1492
1493   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1494       GST_TIME_ARGS (desired_offset));
1495
1496   /* may not have enough fragmented info to do this adjustment,
1497    * and we can't scan (and probably should not) at this time with
1498    * possibly flushing upstream */
1499   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1500     gint64 min_offset;
1501     gboolean next, before, after;
1502
1503     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1504     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1505     next = after && !before;
1506     if (segment->rate < 0)
1507       next = !next;
1508
1509     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1510         NULL);
1511     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1512         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1513     desired_offset = min_offset;
1514   }
1515
1516   /* and set all streams to the final position */
1517   GST_OBJECT_LOCK (qtdemux);
1518   gst_flow_combiner_reset (qtdemux->flowcombiner);
1519   GST_OBJECT_UNLOCK (qtdemux);
1520   qtdemux->segment_seqnum = seqnum;
1521   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1522     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1523
1524     stream->time_position = desired_offset;
1525     stream->accumulated_base = 0;
1526     stream->sample_index = -1;
1527     stream->offset_in_sample = 0;
1528     stream->segment_index = -1;
1529     stream->sent_eos = FALSE;
1530     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1531
1532     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1533       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1534   }
1535   segment->position = desired_offset;
1536   if (segment->rate >= 0) {
1537     segment->start = desired_offset;
1538     /* We need to update time as we update start in that direction */
1539     segment->time = desired_offset;
1540
1541     /* we stop at the end */
1542     if (segment->stop == -1)
1543       segment->stop = segment->duration;
1544   } else {
1545     segment->stop = desired_offset;
1546   }
1547
1548   if (qtdemux->fragmented)
1549     qtdemux->fragmented_seek_pending = TRUE;
1550
1551   return TRUE;
1552 }
1553
1554 /* do a seek in pull based mode */
1555 static gboolean
1556 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1557 {
1558   gdouble rate = 1.0;
1559   GstFormat format;
1560   GstSeekFlags flags;
1561   GstSeekType cur_type, stop_type;
1562   gint64 cur, stop;
1563   gboolean flush, instant_rate_change;
1564   gboolean update;
1565   GstSegment seeksegment;
1566   guint32 seqnum = GST_SEQNUM_INVALID;
1567   GstEvent *flush_event;
1568   gboolean ret;
1569
1570   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1571
1572   gst_event_parse_seek (event, &rate, &format, &flags,
1573       &cur_type, &cur, &stop_type, &stop);
1574   seqnum = gst_event_get_seqnum (event);
1575
1576   /* we have to have a format as the segment format. Try to convert
1577    * if not. */
1578   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1579           stop_type, &stop))
1580     goto no_format;
1581
1582   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1583
1584   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1585   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1586
1587   /* Directly send the instant-rate-change event here before taking the
1588    * stream-lock so that it can be applied as soon as possible */
1589   if (instant_rate_change) {
1590     GstEvent *ev;
1591
1592     /* instant rate change only supported if direction does not change. All
1593      * other requirements are already checked before creating the seek event
1594      * but let's double-check here to be sure */
1595     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1596         (qtdemux->segment.rate < 0 && rate > 0) ||
1597         cur_type != GST_SEEK_TYPE_NONE ||
1598         stop_type != GST_SEEK_TYPE_NONE || flush) {
1599       GST_ERROR_OBJECT (qtdemux,
1600           "Instant rate change seeks only supported in the "
1601           "same direction, without flushing and position change");
1602       return FALSE;
1603     }
1604
1605     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1606         (GstSegmentFlags) flags);
1607     gst_event_set_seqnum (ev, seqnum);
1608     gst_qtdemux_push_event (qtdemux, ev);
1609     return TRUE;
1610   }
1611
1612   /* stop streaming, either by flushing or by pausing the task */
1613   if (flush) {
1614     flush_event = gst_event_new_flush_start ();
1615     if (seqnum != GST_SEQNUM_INVALID)
1616       gst_event_set_seqnum (flush_event, seqnum);
1617     /* unlock upstream pull_range */
1618     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1619     /* make sure out loop function exits */
1620     gst_qtdemux_push_event (qtdemux, flush_event);
1621   } else {
1622     /* non flushing seek, pause the task */
1623     gst_pad_pause_task (qtdemux->sinkpad);
1624   }
1625
1626   /* wait for streaming to finish */
1627   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1628
1629   /* copy segment, we need this because we still need the old
1630    * segment when we close the current segment. */
1631   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1632
1633   /* configure the segment with the seek variables */
1634   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1635   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1636           cur_type, cur, stop_type, stop, &update)) {
1637     ret = FALSE;
1638     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1639   } else {
1640     /* now do the seek */
1641     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1642   }
1643
1644   /* prepare for streaming again */
1645   if (flush) {
1646     flush_event = gst_event_new_flush_stop (TRUE);
1647     if (seqnum != GST_SEQNUM_INVALID)
1648       gst_event_set_seqnum (flush_event, seqnum);
1649
1650     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1651     gst_qtdemux_push_event (qtdemux, flush_event);
1652   }
1653
1654   /* commit the new segment */
1655   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1656
1657   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1658     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1659         qtdemux->segment.format, qtdemux->segment.position);
1660     if (seqnum != GST_SEQNUM_INVALID)
1661       gst_message_set_seqnum (msg, seqnum);
1662     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1663   }
1664
1665   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1666   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1667       qtdemux->sinkpad, NULL);
1668
1669   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1670
1671   return ret;
1672
1673   /* ERRORS */
1674 no_format:
1675   {
1676     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1677     return FALSE;
1678   }
1679 }
1680
1681 static gboolean
1682 qtdemux_ensure_index (GstQTDemux * qtdemux)
1683 {
1684   guint i;
1685
1686   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1687
1688   /* Build complete index */
1689   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1690     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1691
1692     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1693       GST_LOG_OBJECT (qtdemux,
1694           "Building complete index of track-id %u for seeking failed!",
1695           stream->track_id);
1696       return FALSE;
1697     }
1698   }
1699
1700   return TRUE;
1701 }
1702
1703 static gboolean
1704 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1705     GstEvent * event)
1706 {
1707   gboolean res = TRUE;
1708   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1709
1710   switch (GST_EVENT_TYPE (event)) {
1711     case GST_EVENT_RECONFIGURE:
1712       GST_OBJECT_LOCK (qtdemux);
1713       gst_flow_combiner_reset (qtdemux->flowcombiner);
1714       GST_OBJECT_UNLOCK (qtdemux);
1715       res = gst_pad_event_default (pad, parent, event);
1716       break;
1717     case GST_EVENT_SEEK:
1718     {
1719       GstSeekFlags flags = 0;
1720       GstFormat seek_format;
1721       gboolean instant_rate_change;
1722
1723 #ifndef GST_DISABLE_GST_DEBUG
1724       GstClockTime ts = gst_util_get_timestamp ();
1725 #endif
1726       guint32 seqnum = gst_event_get_seqnum (event);
1727
1728       qtdemux->received_seek = TRUE;
1729
1730       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1731           NULL);
1732       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1733
1734       if (seqnum == qtdemux->segment_seqnum) {
1735         GST_LOG_OBJECT (pad,
1736             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1737         gst_event_unref (event);
1738         return TRUE;
1739       }
1740
1741       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1742         /* seek should be handled by upstream, we might need to re-download fragments */
1743         GST_DEBUG_OBJECT (qtdemux,
1744             "let upstream handle seek for fragmented playback");
1745         goto upstream;
1746       }
1747
1748       if (seek_format == GST_FORMAT_BYTES) {
1749         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1750         gst_event_unref (event);
1751         return FALSE;
1752       }
1753
1754       gst_event_parse_seek_trickmode_interval (event,
1755           &qtdemux->trickmode_interval);
1756
1757       /* Build complete index for seeking;
1758        * if not a fragmented file at least and we're really doing a seek,
1759        * not just an instant-rate-change */
1760       if (!qtdemux->fragmented && !instant_rate_change) {
1761         if (!qtdemux_ensure_index (qtdemux))
1762           goto index_failed;
1763       }
1764 #ifndef GST_DISABLE_GST_DEBUG
1765       ts = gst_util_get_timestamp () - ts;
1766       GST_INFO_OBJECT (qtdemux,
1767           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1768 #endif
1769       if (qtdemux->pullbased) {
1770         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1771       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1772         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1773         res = TRUE;
1774       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1775           && QTDEMUX_N_STREAMS (qtdemux)
1776           && !qtdemux->fragmented) {
1777         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1778       } else {
1779         GST_DEBUG_OBJECT (qtdemux,
1780             "ignoring seek in push mode in current state");
1781         res = FALSE;
1782       }
1783       gst_event_unref (event);
1784     }
1785       break;
1786     default:
1787     upstream:
1788       res = gst_pad_event_default (pad, parent, event);
1789       break;
1790   }
1791
1792 done:
1793   return res;
1794
1795   /* ERRORS */
1796 index_failed:
1797   {
1798     GST_ERROR_OBJECT (qtdemux, "Index failed");
1799     gst_event_unref (event);
1800     res = FALSE;
1801     goto done;
1802   }
1803 }
1804
1805 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1806  *
1807  * If @fw is false, the coding order is explored backwards.
1808  *
1809  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1810  * sample is found for that track.
1811  *
1812  * The stream and sample index of the sample with the minimum offset in the direction explored
1813  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1814  *
1815  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1816  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1817  * @_stream and @_index. */
1818 static void
1819 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1820     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1821 {
1822   gint i, index;
1823   gint64 time, min_time;
1824   QtDemuxStream *stream;
1825   gint iter;
1826
1827   min_time = -1;
1828   stream = NULL;
1829   index = -1;
1830
1831   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1832     QtDemuxStream *str;
1833     gint inc;
1834     gboolean set_sample;
1835
1836     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1837     set_sample = !set;
1838
1839     if (fw) {
1840       i = 0;
1841       inc = 1;
1842     } else {
1843       i = str->n_samples - 1;
1844       inc = -1;
1845     }
1846
1847     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1848       if (str->samples[i].size == 0)
1849         continue;
1850
1851       if (fw && (str->samples[i].offset < byte_pos))
1852         continue;
1853
1854       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1855         continue;
1856
1857       /* move stream to first available sample */
1858       if (set) {
1859         gst_qtdemux_move_stream (qtdemux, str, i);
1860         set_sample = TRUE;
1861       }
1862
1863       /* avoid index from sparse streams since they might be far away */
1864       if (!CUR_STREAM (str)->sparse) {
1865         /* determine min/max time */
1866         time = QTSAMPLE_PTS (str, &str->samples[i]);
1867         if (min_time == -1 || (!fw && time > min_time) ||
1868             (fw && time < min_time)) {
1869           min_time = time;
1870         }
1871
1872         /* determine stream with leading sample, to get its position */
1873         if (!stream ||
1874             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1875             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1876           stream = str;
1877           index = i;
1878         }
1879       }
1880       break;
1881     }
1882
1883     /* no sample for this stream, mark eos */
1884     if (!set_sample)
1885       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1886   }
1887
1888   if (_time)
1889     *_time = min_time;
1890   if (_stream)
1891     *_stream = stream;
1892   if (_index)
1893     *_index = index;
1894 }
1895
1896 /* Copied from mpegtsbase code */
1897 /* FIXME: replace this function when we add new util function for stream-id creation */
1898 static gchar *
1899 _get_upstream_id (GstQTDemux * demux)
1900 {
1901   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1902
1903   if (!upstream_id) {
1904     /* Try to create one from the upstream URI, else use a randome number */
1905     GstQuery *query;
1906     gchar *uri = NULL;
1907
1908     /* Try to generate one from the URI query and
1909      * if it fails take a random number instead */
1910     query = gst_query_new_uri ();
1911     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1912       gst_query_parse_uri (query, &uri);
1913     }
1914
1915     if (uri) {
1916       GChecksum *cs;
1917
1918       /* And then generate an SHA256 sum of the URI */
1919       cs = g_checksum_new (G_CHECKSUM_SHA256);
1920       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1921       g_free (uri);
1922       upstream_id = g_strdup (g_checksum_get_string (cs));
1923       g_checksum_free (cs);
1924     } else {
1925       /* Just get some random number if the URI query fails */
1926       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1927           "implementing a deterministic way of creating a stream-id");
1928       upstream_id =
1929           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1930           g_random_int (), g_random_int ());
1931     }
1932
1933     gst_query_unref (query);
1934   }
1935   return upstream_id;
1936 }
1937
1938 static QtDemuxStream *
1939 _create_stream (GstQTDemux * demux, guint32 track_id)
1940 {
1941   QtDemuxStream *stream;
1942   gchar *upstream_id;
1943
1944   stream = g_new0 (QtDemuxStream, 1);
1945   stream->demux = demux;
1946   stream->track_id = track_id;
1947   upstream_id = _get_upstream_id (demux);
1948   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1949   g_free (upstream_id);
1950   /* new streams always need a discont */
1951   stream->discont = TRUE;
1952   /* we enable clipping for raw audio/video streams */
1953   stream->need_clip = FALSE;
1954   stream->process_func = NULL;
1955   stream->segment_index = -1;
1956   stream->time_position = 0;
1957   stream->sample_index = -1;
1958   stream->offset_in_sample = 0;
1959   stream->new_stream = TRUE;
1960   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1961   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1962   stream->protected = FALSE;
1963   stream->protection_scheme_type = 0;
1964   stream->protection_scheme_version = 0;
1965   stream->protection_scheme_info = NULL;
1966   stream->n_samples_moof = 0;
1967   stream->duration_moof = 0;
1968   stream->duration_last_moof = 0;
1969   stream->alignment = 1;
1970   stream->stream_tags = gst_tag_list_new_empty ();
1971   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1972   g_queue_init (&stream->protection_scheme_event_queue);
1973   stream->ref_count = 1;
1974   /* consistent default for push based mode */
1975   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1976   return stream;
1977 }
1978
1979 static gboolean
1980 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1981 {
1982   GstStructure *structure;
1983   const gchar *variant;
1984   const GstCaps *mediacaps = NULL;
1985
1986   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1987
1988   structure = gst_caps_get_structure (caps, 0);
1989   variant = gst_structure_get_string (structure, "variant");
1990
1991   if (variant && strcmp (variant, "mse-bytestream") == 0) {
1992     demux->variant = VARIANT_MSE_BYTESTREAM;
1993   }
1994
1995   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1996     QtDemuxStream *stream;
1997     const GValue *value;
1998
1999     demux->fragmented = TRUE;
2000     demux->variant = VARIANT_MSS_FRAGMENTED;
2001
2002     if (QTDEMUX_N_STREAMS (demux) > 1) {
2003       /* can't do this, we can only renegotiate for another mss format */
2004       return FALSE;
2005     }
2006
2007     value = gst_structure_get_value (structure, "media-caps");
2008     /* create stream */
2009     if (value) {
2010       const GValue *timescale_v;
2011
2012       /* TODO update when stream changes during playback */
2013
2014       if (QTDEMUX_N_STREAMS (demux) == 0) {
2015         stream = _create_stream (demux, 1);
2016         g_ptr_array_add (demux->active_streams, stream);
2017         /* mss has no stsd/stsd entry, use id 0 as default */
2018         stream->stsd_entries_length = 1;
2019         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2020         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2021       } else {
2022         stream = QTDEMUX_NTH_STREAM (demux, 0);
2023       }
2024
2025       timescale_v = gst_structure_get_value (structure, "timescale");
2026       if (timescale_v) {
2027         stream->timescale = g_value_get_uint64 (timescale_v);
2028       } else {
2029         /* default mss timescale */
2030         stream->timescale = 10000000;
2031       }
2032       demux->timescale = stream->timescale;
2033
2034       mediacaps = gst_value_get_caps (value);
2035       if (!CUR_STREAM (stream)->caps
2036           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2037         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2038             mediacaps);
2039         stream->new_caps = TRUE;
2040       }
2041       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2042       structure = gst_caps_get_structure (mediacaps, 0);
2043       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2044         stream->subtype = FOURCC_vide;
2045
2046         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2047         gst_structure_get_int (structure, "height",
2048             &CUR_STREAM (stream)->height);
2049         gst_structure_get_fraction (structure, "framerate",
2050             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2051       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2052         gint rate = 0;
2053         stream->subtype = FOURCC_soun;
2054         gst_structure_get_int (structure, "channels",
2055             &CUR_STREAM (stream)->n_channels);
2056         gst_structure_get_int (structure, "rate", &rate);
2057         CUR_STREAM (stream)->rate = rate;
2058       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
2059         if (gst_structure_has_field (structure, "original-media-type")) {
2060           const gchar *media_type =
2061               gst_structure_get_string (structure, "original-media-type");
2062           if (g_str_has_prefix (media_type, "video")) {
2063             stream->subtype = FOURCC_vide;
2064           } else if (g_str_has_prefix (media_type, "audio")) {
2065             stream->subtype = FOURCC_soun;
2066           }
2067         }
2068       }
2069     }
2070     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2071   }
2072
2073   return TRUE;
2074 }
2075
2076 static void
2077 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2078 {
2079   gint i;
2080
2081   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2082
2083   if (hard || qtdemux->upstream_format_is_time) {
2084     qtdemux->state = QTDEMUX_STATE_INITIAL;
2085     qtdemux->neededbytes = 16;
2086     qtdemux->todrop = 0;
2087     qtdemux->pullbased = FALSE;
2088     g_clear_pointer (&qtdemux->redirect_location, g_free);
2089     qtdemux->first_mdat = -1;
2090     qtdemux->header_size = 0;
2091     qtdemux->mdatoffset = -1;
2092     qtdemux->restoredata_offset = -1;
2093     if (qtdemux->mdatbuffer)
2094       gst_buffer_unref (qtdemux->mdatbuffer);
2095     if (qtdemux->restoredata_buffer)
2096       gst_buffer_unref (qtdemux->restoredata_buffer);
2097     qtdemux->mdatbuffer = NULL;
2098     qtdemux->restoredata_buffer = NULL;
2099     qtdemux->mdatleft = 0;
2100     qtdemux->mdatsize = 0;
2101     if (qtdemux->comp_brands)
2102       gst_buffer_unref (qtdemux->comp_brands);
2103     qtdemux->comp_brands = NULL;
2104     qtdemux->last_moov_offset = -1;
2105     if (qtdemux->moov_node_compressed) {
2106       g_node_destroy (qtdemux->moov_node_compressed);
2107       if (qtdemux->moov_node)
2108         g_free (qtdemux->moov_node->data);
2109     }
2110     qtdemux->moov_node_compressed = NULL;
2111     if (qtdemux->moov_node)
2112       g_node_destroy (qtdemux->moov_node);
2113     qtdemux->moov_node = NULL;
2114     if (qtdemux->tag_list)
2115       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2116     qtdemux->tag_list = gst_tag_list_new_empty ();
2117     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2118 #if 0
2119     if (qtdemux->element_index)
2120       gst_object_unref (qtdemux->element_index);
2121     qtdemux->element_index = NULL;
2122 #endif
2123     qtdemux->major_brand = 0;
2124     qtdemux->upstream_format_is_time = FALSE;
2125     qtdemux->upstream_seekable = FALSE;
2126     qtdemux->upstream_size = 0;
2127
2128     qtdemux->fragment_start = -1;
2129     qtdemux->fragment_start_offset = -1;
2130     qtdemux->duration = 0;
2131     qtdemux->moof_offset = 0;
2132     qtdemux->chapters_track_id = 0;
2133     qtdemux->have_group_id = FALSE;
2134     qtdemux->group_id = G_MAXUINT;
2135
2136     g_queue_clear_full (&qtdemux->protection_event_queue,
2137         (GDestroyNotify) gst_event_unref);
2138
2139     qtdemux->received_seek = FALSE;
2140     qtdemux->first_moof_already_parsed = FALSE;
2141   }
2142   qtdemux->offset = 0;
2143   gst_adapter_clear (qtdemux->adapter);
2144   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2145   qtdemux->need_segment = TRUE;
2146
2147   if (hard) {
2148     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2149     qtdemux->trickmode_interval = 0;
2150     g_ptr_array_set_size (qtdemux->active_streams, 0);
2151     g_ptr_array_set_size (qtdemux->old_streams, 0);
2152     qtdemux->n_video_streams = 0;
2153     qtdemux->n_audio_streams = 0;
2154     qtdemux->n_sub_streams = 0;
2155     qtdemux->n_meta_streams = 0;
2156     qtdemux->exposed = FALSE;
2157     qtdemux->fragmented = FALSE;
2158     qtdemux->variant = VARIANT_NONE;
2159     gst_caps_replace (&qtdemux->media_caps, NULL);
2160     qtdemux->timescale = 0;
2161     qtdemux->got_moov = FALSE;
2162     qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
2163     qtdemux->cenc_aux_info_offset = 0;
2164     g_free (qtdemux->cenc_aux_info_sizes);
2165     qtdemux->cenc_aux_info_sizes = NULL;
2166     qtdemux->cenc_aux_sample_count = 0;
2167     if (qtdemux->protection_system_ids) {
2168       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2169       qtdemux->protection_system_ids = NULL;
2170     }
2171     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2172         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2173         GST_BIN_FLAG_STREAMS_AWARE);
2174
2175     if (qtdemux->preferred_protection_system_id) {
2176       g_free (qtdemux->preferred_protection_system_id);
2177       qtdemux->preferred_protection_system_id = NULL;
2178     }
2179   } else if (qtdemux->variant == VARIANT_MSS_FRAGMENTED) {
2180     gst_flow_combiner_reset (qtdemux->flowcombiner);
2181     g_ptr_array_foreach (qtdemux->active_streams,
2182         (GFunc) gst_qtdemux_stream_clear, NULL);
2183   } else {
2184     gst_flow_combiner_reset (qtdemux->flowcombiner);
2185     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2186       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2187       stream->sent_eos = FALSE;
2188       stream->time_position = 0;
2189       stream->accumulated_base = 0;
2190       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2191     }
2192   }
2193 }
2194
2195 static void
2196 qtdemux_clear_protection_events_on_all_streams (GstQTDemux * qtdemux)
2197 {
2198   for (unsigned i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2199     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2200     g_queue_clear_full (&stream->protection_scheme_event_queue,
2201         (GDestroyNotify) gst_event_unref);
2202   }
2203 }
2204
2205 /* Maps the @segment to the qt edts internal segments and pushes
2206  * the corresponding segment event.
2207  *
2208  * If it ends up being at a empty segment, a gap will be pushed and the next
2209  * edts segment will be activated in sequence.
2210  *
2211  * To be used in push-mode only */
2212 static void
2213 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2214 {
2215   gint i, iter;
2216
2217   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2218     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2219
2220     stream->time_position = segment->start;
2221
2222     /* in push mode we should be guaranteed that we will have empty segments
2223      * at the beginning and then one segment after, other scenarios are not
2224      * supported and are discarded when parsing the edts */
2225     for (i = 0; i < stream->n_segments; i++) {
2226       if (stream->segments[i].stop_time > segment->start) {
2227         /* push the empty segment and move to the next one */
2228         gst_qtdemux_activate_segment (qtdemux, stream, i,
2229             stream->time_position);
2230         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2231           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2232               stream->time_position);
2233
2234           /* accumulate previous segments */
2235           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2236             stream->accumulated_base +=
2237                 (stream->segment.stop -
2238                 stream->segment.start) / ABS (stream->segment.rate);
2239           continue;
2240         }
2241
2242         g_assert (i == stream->n_segments - 1);
2243       }
2244     }
2245   }
2246 }
2247
2248 static void
2249 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2250     GPtrArray * src)
2251 {
2252   guint i;
2253   guint len;
2254
2255   len = src->len;
2256
2257   if (len == 0)
2258     return;
2259
2260   for (i = 0; i < len; i++) {
2261     QtDemuxStream *stream = g_ptr_array_index (src, i);
2262
2263 #ifndef GST_DISABLE_GST_DEBUG
2264     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2265         stream, GST_STR_NULL (stream->stream_id), dest);
2266 #endif
2267     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2268   }
2269
2270   g_ptr_array_set_size (src, 0);
2271 }
2272
2273 static gboolean
2274 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2275     GstEvent * event)
2276 {
2277   GstQTDemux *demux = GST_QTDEMUX (parent);
2278   gboolean res = TRUE;
2279
2280   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2281
2282   switch (GST_EVENT_TYPE (event)) {
2283     case GST_EVENT_SEGMENT:
2284     {
2285       gint64 offset = 0;
2286       QtDemuxStream *stream;
2287       gint idx;
2288       GstSegment segment;
2289
2290       /* some debug output */
2291       gst_event_copy_segment (event, &segment);
2292       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2293           &segment);
2294
2295       if (segment.format == GST_FORMAT_TIME) {
2296         demux->upstream_format_is_time = TRUE;
2297         demux->segment_seqnum = gst_event_get_seqnum (event);
2298       } else {
2299         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2300             "not in time format");
2301
2302         /* chain will send initial newsegment after pads have been added */
2303         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2304           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2305           goto exit;
2306         }
2307       }
2308
2309       /* check if this matches a time seek we received previously
2310        * FIXME for backwards compatibility reasons we use the
2311        * seek_offset here to compare. In the future we might want to
2312        * change this to use the seqnum as it uniquely should identify
2313        * the segment that corresponds to the seek. */
2314       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2315           ", received segment offset %" G_GINT64_FORMAT,
2316           demux->seek_offset, segment.start);
2317       if (segment.format == GST_FORMAT_BYTES
2318           && demux->seek_offset == segment.start) {
2319         GST_OBJECT_LOCK (demux);
2320         offset = segment.start;
2321
2322         segment.format = GST_FORMAT_TIME;
2323         segment.start = demux->push_seek_start;
2324         segment.stop = demux->push_seek_stop;
2325         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2326             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2327             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2328         GST_OBJECT_UNLOCK (demux);
2329       }
2330
2331       /* we only expect a BYTE segment, e.g. following a seek */
2332       if (segment.format == GST_FORMAT_BYTES) {
2333         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2334           offset = segment.start;
2335
2336           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2337               NULL, (gint64 *) & segment.start);
2338           if ((gint64) segment.start < 0)
2339             segment.start = 0;
2340         }
2341         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2342           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2343               NULL, (gint64 *) & segment.stop);
2344           /* keyframe seeking should already arrange for start >= stop,
2345            * but make sure in other rare cases */
2346           segment.stop = MAX (segment.stop, segment.start);
2347         }
2348       } else if (segment.format == GST_FORMAT_TIME) {
2349         /* push all data on the adapter before starting this
2350          * new segment */
2351         gst_qtdemux_process_adapter (demux, TRUE);
2352       } else {
2353         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2354         goto exit;
2355       }
2356
2357       /* We shouldn't modify upstream driven TIME FORMAT segment */
2358       if (!demux->upstream_format_is_time) {
2359         /* accept upstream's notion of segment and distribute along */
2360         segment.format = GST_FORMAT_TIME;
2361         segment.position = segment.time = segment.start;
2362         segment.duration = demux->segment.duration;
2363         segment.base = gst_segment_to_running_time (&demux->segment,
2364             GST_FORMAT_TIME, demux->segment.position);
2365       }
2366
2367       gst_segment_copy_into (&segment, &demux->segment);
2368       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2369
2370       /* map segment to internal qt segments and push on each stream */
2371       if (QTDEMUX_N_STREAMS (demux)) {
2372         demux->need_segment = TRUE;
2373         gst_qtdemux_check_send_pending_segment (demux);
2374       }
2375
2376       /* clear leftover in current segment, if any */
2377       gst_adapter_clear (demux->adapter);
2378
2379       /* set up streaming thread */
2380       demux->offset = offset;
2381       if (demux->upstream_format_is_time) {
2382         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2383             "set values to restart reading from a new atom");
2384         demux->neededbytes = 16;
2385         demux->todrop = 0;
2386       } else {
2387         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2388             NULL);
2389         if (stream) {
2390           demux->todrop = stream->samples[idx].offset - offset;
2391           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2392         } else {
2393           /* set up for EOS */
2394           demux->neededbytes = -1;
2395           demux->todrop = 0;
2396         }
2397       }
2398     exit:
2399       gst_event_unref (event);
2400       res = TRUE;
2401       goto drop;
2402     }
2403     case GST_EVENT_FLUSH_START:
2404     {
2405       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2406         gst_event_unref (event);
2407         goto drop;
2408       }
2409       QTDEMUX_EXPOSE_LOCK (demux);
2410       res = gst_pad_event_default (demux->sinkpad, parent, event);
2411       QTDEMUX_EXPOSE_UNLOCK (demux);
2412       goto drop;
2413     }
2414     case GST_EVENT_FLUSH_STOP:
2415     {
2416       guint64 dur;
2417
2418       dur = demux->segment.duration;
2419       gst_qtdemux_reset (demux, FALSE);
2420       demux->segment.duration = dur;
2421
2422       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2423         gst_event_unref (event);
2424         goto drop;
2425       }
2426       break;
2427     }
2428     case GST_EVENT_EOS:
2429       /* If we are in push mode, and get an EOS before we've seen any streams,
2430        * then error out - we have nowhere to send the EOS */
2431       if (!demux->pullbased) {
2432         gint i;
2433         gboolean has_valid_stream = FALSE;
2434         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2435           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2436             has_valid_stream = TRUE;
2437             break;
2438           }
2439         }
2440         if (!has_valid_stream)
2441           gst_qtdemux_post_no_playable_stream_error (demux);
2442         else {
2443           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2444               (guint) gst_adapter_available (demux->adapter));
2445           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2446             res = FALSE;
2447           }
2448         }
2449       }
2450       break;
2451     case GST_EVENT_CAPS:{
2452       GstCaps *caps = NULL;
2453
2454       gst_event_parse_caps (event, &caps);
2455       gst_qtdemux_setcaps (demux, caps);
2456       res = TRUE;
2457       gst_event_unref (event);
2458       goto drop;
2459     }
2460     case GST_EVENT_PROTECTION:
2461     {
2462       const gchar *system_id = NULL;
2463
2464       gst_event_parse_protection (event, &system_id, NULL, NULL);
2465       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2466           system_id);
2467       gst_qtdemux_append_protection_system_id (demux, system_id);
2468       /* save the event for later, for source pads that have not been created */
2469       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2470       /* send it to all pads that already exist */
2471       gst_qtdemux_push_event (demux, event);
2472       res = TRUE;
2473       goto drop;
2474     }
2475     case GST_EVENT_STREAM_START:
2476     {
2477       res = TRUE;
2478       gst_event_unref (event);
2479
2480       /* Drain all the buffers */
2481       gst_qtdemux_process_adapter (demux, TRUE);
2482       gst_qtdemux_reset (demux, FALSE);
2483       /* We expect new moov box after new stream-start event */
2484       if (demux->exposed) {
2485         gst_qtdemux_stream_concat (demux,
2486             demux->old_streams, demux->active_streams);
2487       }
2488
2489       goto drop;
2490     }
2491     default:
2492       break;
2493   }
2494
2495   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2496
2497 drop:
2498   return res;
2499 }
2500
2501 static gboolean
2502 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2503     GstQuery * query)
2504 {
2505   GstQTDemux *demux = GST_QTDEMUX (parent);
2506   gboolean res = FALSE;
2507
2508   switch (GST_QUERY_TYPE (query)) {
2509     case GST_QUERY_BITRATE:
2510     {
2511       GstClockTime duration;
2512
2513       /* populate demux->upstream_size if not done yet */
2514       gst_qtdemux_check_seekability (demux);
2515
2516       if (demux->upstream_size != -1
2517           && gst_qtdemux_get_duration (demux, &duration)) {
2518         guint bitrate =
2519             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2520             duration);
2521
2522         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2523             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2524             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2525
2526         /* TODO: better results based on ranges/index tables */
2527         gst_query_set_bitrate (query, bitrate);
2528         res = TRUE;
2529       }
2530       break;
2531     }
2532     default:
2533       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2534       break;
2535   }
2536
2537   return res;
2538 }
2539
2540
2541 #if 0
2542 static void
2543 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2544 {
2545   GstQTDemux *demux = GST_QTDEMUX (element);
2546
2547   GST_OBJECT_LOCK (demux);
2548   if (demux->element_index)
2549     gst_object_unref (demux->element_index);
2550   if (index) {
2551     demux->element_index = gst_object_ref (index);
2552   } else {
2553     demux->element_index = NULL;
2554   }
2555   GST_OBJECT_UNLOCK (demux);
2556   /* object lock might be taken again */
2557   if (index)
2558     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2559   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2560       demux->element_index, demux->index_id);
2561 }
2562
2563 static GstIndex *
2564 gst_qtdemux_get_index (GstElement * element)
2565 {
2566   GstIndex *result = NULL;
2567   GstQTDemux *demux = GST_QTDEMUX (element);
2568
2569   GST_OBJECT_LOCK (demux);
2570   if (demux->element_index)
2571     result = gst_object_ref (demux->element_index);
2572   GST_OBJECT_UNLOCK (demux);
2573
2574   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2575
2576   return result;
2577 }
2578 #endif
2579
2580 static void
2581 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2582 {
2583   g_free ((gpointer) stream->stco.data);
2584   stream->stco.data = NULL;
2585   g_free ((gpointer) stream->stsz.data);
2586   stream->stsz.data = NULL;
2587   g_free ((gpointer) stream->stsc.data);
2588   stream->stsc.data = NULL;
2589   g_free ((gpointer) stream->stts.data);
2590   stream->stts.data = NULL;
2591   g_free ((gpointer) stream->stss.data);
2592   stream->stss.data = NULL;
2593   g_free ((gpointer) stream->stps.data);
2594   stream->stps.data = NULL;
2595   g_free ((gpointer) stream->ctts.data);
2596   stream->ctts.data = NULL;
2597 }
2598
2599 static void
2600 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2601 {
2602   g_free (stream->segments);
2603   stream->segments = NULL;
2604   stream->segment_index = -1;
2605   stream->accumulated_base = 0;
2606 }
2607
2608 static void
2609 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2610 {
2611   g_free (stream->samples);
2612   stream->samples = NULL;
2613   gst_qtdemux_stbl_free (stream);
2614
2615   /* fragments */
2616   g_free (stream->ra_entries);
2617   stream->ra_entries = NULL;
2618   stream->n_ra_entries = 0;
2619
2620   stream->sample_index = -1;
2621   stream->stbl_index = -1;
2622   stream->n_samples = 0;
2623   stream->time_position = 0;
2624
2625   stream->n_samples_moof = 0;
2626   stream->duration_moof = 0;
2627   stream->duration_last_moof = 0;
2628 }
2629
2630 static void
2631 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2632 {
2633   gint i;
2634   if (stream->allocator)
2635     gst_object_unref (stream->allocator);
2636   while (stream->buffers) {
2637     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2638     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2639   }
2640   for (i = 0; i < stream->stsd_entries_length; i++) {
2641     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2642     if (entry->rgb8_palette) {
2643       gst_memory_unref (entry->rgb8_palette);
2644       entry->rgb8_palette = NULL;
2645     }
2646     entry->sparse = FALSE;
2647   }
2648
2649   if (stream->stream_tags)
2650     gst_tag_list_unref (stream->stream_tags);
2651
2652   stream->stream_tags = gst_tag_list_new_empty ();
2653   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2654   g_free (stream->redirect_uri);
2655   stream->redirect_uri = NULL;
2656   stream->sent_eos = FALSE;
2657   stream->protected = FALSE;
2658   if (stream->protection_scheme_info) {
2659     if (stream->protection_scheme_type == FOURCC_cenc
2660         || stream->protection_scheme_type == FOURCC_cbcs) {
2661       QtDemuxCencSampleSetInfo *info =
2662           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2663       if (info->default_properties)
2664         gst_structure_free (info->default_properties);
2665       if (info->crypto_info)
2666         g_ptr_array_free (info->crypto_info, TRUE);
2667     }
2668     if (stream->protection_scheme_type == FOURCC_aavd) {
2669       QtDemuxAavdEncryptionInfo *info =
2670           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2671       if (info->default_properties)
2672         gst_structure_free (info->default_properties);
2673     }
2674     g_free (stream->protection_scheme_info);
2675     stream->protection_scheme_info = NULL;
2676   }
2677   stream->protection_scheme_type = 0;
2678   stream->protection_scheme_version = 0;
2679   g_queue_clear_full (&stream->protection_scheme_event_queue,
2680       (GDestroyNotify) gst_event_unref);
2681   gst_qtdemux_stream_flush_segments_data (stream);
2682   gst_qtdemux_stream_flush_samples_data (stream);
2683 }
2684
2685 static void
2686 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2687 {
2688   gint i;
2689   gst_qtdemux_stream_clear (stream);
2690   for (i = 0; i < stream->stsd_entries_length; i++) {
2691     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2692     if (entry->caps) {
2693       gst_caps_unref (entry->caps);
2694       entry->caps = NULL;
2695     }
2696   }
2697   g_free (stream->stsd_entries);
2698   stream->stsd_entries = NULL;
2699   stream->stsd_entries_length = 0;
2700 }
2701
2702 static QtDemuxStream *
2703 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2704 {
2705   g_atomic_int_add (&stream->ref_count, 1);
2706
2707   return stream;
2708 }
2709
2710 static void
2711 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2712 {
2713   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2714     gst_qtdemux_stream_reset (stream);
2715     gst_tag_list_unref (stream->stream_tags);
2716     if (stream->pad) {
2717       GstQTDemux *demux = stream->demux;
2718       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2719       GST_OBJECT_LOCK (demux);
2720       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2721       GST_OBJECT_UNLOCK (demux);
2722     }
2723     g_free (stream->stream_id);
2724     g_free (stream);
2725   }
2726 }
2727
2728 static GstStateChangeReturn
2729 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2730 {
2731   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2732   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2733
2734   switch (transition) {
2735     case GST_STATE_CHANGE_READY_TO_PAUSED:
2736       gst_qtdemux_reset (qtdemux, TRUE);
2737       break;
2738     default:
2739       break;
2740   }
2741
2742   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2743
2744   switch (transition) {
2745     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2746       gst_qtdemux_reset (qtdemux, TRUE);
2747       break;
2748     }
2749     default:
2750       break;
2751   }
2752
2753   return result;
2754 }
2755
2756 static void
2757 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2758 {
2759   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2760
2761   g_return_if_fail (GST_IS_CONTEXT (context));
2762
2763   if (gst_context_has_context_type (context,
2764           "drm-preferred-decryption-system-id")) {
2765     const GstStructure *s;
2766
2767     s = gst_context_get_structure (context);
2768     g_free (qtdemux->preferred_protection_system_id);
2769     qtdemux->preferred_protection_system_id =
2770         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2771     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2772         qtdemux->preferred_protection_system_id);
2773   }
2774
2775   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2776 }
2777
2778 static void
2779 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2780 {
2781   /* counts as header data */
2782   qtdemux->header_size += length;
2783
2784   /* only consider at least a sufficiently complete ftyp atom */
2785   if (length >= 20) {
2786     GstBuffer *buf;
2787     guint32 minor_version;
2788     const guint8 *p;
2789
2790     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2791     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2792         GST_FOURCC_ARGS (qtdemux->major_brand));
2793     minor_version = QT_UINT32 (buffer + 12);
2794     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2795     if (qtdemux->comp_brands)
2796       gst_buffer_unref (qtdemux->comp_brands);
2797     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2798     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2799
2800     p = buffer + 16;
2801     length = length - 16;
2802     while (length > 0) {
2803       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2804           GST_FOURCC_ARGS (QT_FOURCC (p)));
2805       length -= 4;
2806       p += 4;
2807     }
2808   }
2809 }
2810
2811 static void
2812 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2813 {
2814   /* only consider at least a sufficiently complete styp atom */
2815   if (length >= 20) {
2816     GstBuffer *buf;
2817     guint32 major_brand;
2818     guint32 minor_version;
2819     const guint8 *p;
2820
2821     major_brand = QT_FOURCC (buffer + 8);
2822     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2823         GST_FOURCC_ARGS (major_brand));
2824     minor_version = QT_UINT32 (buffer + 12);
2825     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2826     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2827     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2828
2829     p = buffer + 16;
2830     length = length - 16;
2831     while (length > 0) {
2832       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2833           GST_FOURCC_ARGS (QT_FOURCC (p)));
2834       length -= 4;
2835       p += 4;
2836     }
2837   }
2838 }
2839
2840 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
2841 static void
2842 _get_int_value_from_xml_string (GstQTDemux * qtdemux,
2843     const char *xml_str, const char *param_name, int *value)
2844 {
2845   char *value_start, *value_end, *endptr;
2846   const short value_length_max = 12;
2847   char init_view_ret[12];
2848   int value_length = 0;
2849   int i = 0;
2850
2851   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2852
2853   if (!value_start) {
2854     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2855         param_name);
2856     return;
2857   }
2858
2859   value_start += strlen (param_name);
2860   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2861     value_start++;
2862
2863   value_end = strchr (value_start, '<');
2864   if (!value_end) {
2865     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2866     return;
2867   }
2868
2869   value_length = value_end - value_start;
2870   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2871           || (value_start[value_length - 1] == '\t')))
2872     value_length--;
2873
2874   if (value_start[i] == '+' || value_start[i] == '-')
2875     i++;
2876   while (i < value_length) {
2877     if (value_start[i] < '0' || value_start[i] > '9') {
2878       GST_ERROR_OBJECT (qtdemux,
2879           "error: incorrect value, integer was expected\n");
2880       return;
2881     }
2882     i++;
2883   }
2884
2885   if (value_length >= value_length_max || value_length < 1) {
2886     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2887     return;
2888   }
2889
2890   strncpy (init_view_ret, value_start, value_length_max);
2891   init_view_ret[value_length] = '\0';
2892
2893   *value = strtol (init_view_ret, &endptr, 10);
2894   if (endptr == init_view_ret) {
2895     GST_ERROR_OBJECT (qtdemux, "error: no digits were found\n");
2896     return;
2897   }
2898
2899   return;
2900 }
2901
2902 static void
2903 _get_string_value_from_xml_string (GstQTDemux * qtdemux,
2904     const char *xml_str, const char *param_name, char **value)
2905 {
2906   char *value_start, *value_end;
2907   const short value_length_max = 256;
2908   int value_length = 0;
2909
2910   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2911
2912   if (!value_start) {
2913     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2914         param_name);
2915     return;
2916   }
2917
2918   value_start += strlen (param_name);
2919   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2920     value_start++;
2921
2922   value_end = strchr (value_start, '<');
2923   if (!value_end) {
2924     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2925     return;
2926   }
2927
2928   value_length = value_end - value_start;
2929   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2930           || (value_start[value_length - 1] == '\t')))
2931     value_length--;
2932
2933   if (value_length >= value_length_max || value_length < 1) {
2934     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2935     return;
2936   }
2937
2938   *value = strndup(value_start, value_length);
2939
2940   return;
2941 }
2942
2943 static void
2944 _get_bool_value_from_xml_string (GstQTDemux * qtdemux,
2945     const char *xml_str, const char *param_name, gboolean * value)
2946 {
2947   char *value_start, *value_end;
2948   int value_length = 0;
2949
2950   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2951
2952   if (!value_start) {
2953     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2954         param_name);
2955     return;
2956   }
2957
2958   value_start += strlen (param_name);
2959   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2960     value_start++;
2961
2962   value_end = strchr (value_start, '<');
2963   if (!value_end) {
2964     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2965     return;
2966   }
2967
2968   value_length = value_end - value_start;
2969   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2970           || (value_start[value_length - 1] == '\t')))
2971     value_length--;
2972
2973   if (value_length < 1) {
2974     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2975     return;
2976   }
2977
2978   *value = g_strstr_len(value_start, value_length, "true") ? TRUE : FALSE;
2979
2980   return;
2981 }
2982
2983 static void
2984 _parse_spatial_video_metadata_from_xml_string (GstQTDemux * qtdemux, const char *xmlStr)
2985 {
2986   const char is_spherical_str[] = "<GSpherical:Spherical>";
2987   const char is_stitched_str[] = "<GSpherical:Stitched>";
2988   const char stitching_software_str[] = "<GSpherical:StitchingSoftware>";
2989   const char projection_type_str[] = "<GSpherical:ProjectionType>";
2990   const char stereo_mode_str[] = "<GSpherical:StereoMode>";
2991   const char source_count_str[] = "<GSpherical:SourceCount>";
2992   const char init_view_heading_str[] = "<GSpherical:InitialViewHeadingDegrees>";
2993   const char init_view_pitch_str[] = "<GSpherical:InitialViewPitchDegrees>";
2994   const char init_view_roll_str[] = "<GSpherical:InitialViewRollDegrees>";
2995   const char timestamp_str[] = "<GSpherical:Timestamp>";
2996   const char full_pano_width_str[] = "<GSpherical:FullPanoWidthPixels>";
2997   const char full_pano_height_str[] = "<GSpherical:FullPanoHeightPixels>";
2998   const char cropped_area_image_width_str[] =
2999       "<GSpherical:CroppedAreaImageWidthPixels>";
3000   const char cropped_area_image_height_str[] =
3001       "<GSpherical:CroppedAreaImageHeightPixels>";
3002   const char cropped_area_left_str[] = "<GSpherical:CroppedAreaLeftPixels>";
3003   const char cropped_area_top_str[] = "<GSpherical:CroppedAreaTopPixels>";
3004
3005   QtDemuxSphericalMetadata * spherical_metadata = qtdemux->spherical_metadata;
3006
3007   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_spherical_str,
3008       (gboolean *) & spherical_metadata->is_spherical);
3009   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_stitched_str,
3010       (gboolean *) & spherical_metadata->is_stitched);
3011
3012   if (spherical_metadata->is_spherical && spherical_metadata->is_stitched) {
3013     _get_string_value_from_xml_string (qtdemux, xmlStr,
3014         stitching_software_str, &spherical_metadata->stitching_software);
3015     _get_string_value_from_xml_string (qtdemux, xmlStr,
3016         projection_type_str, &spherical_metadata->projection_type);
3017     _get_string_value_from_xml_string (qtdemux, xmlStr, stereo_mode_str,
3018         &spherical_metadata->stereo_mode);
3019     _get_int_value_from_xml_string (qtdemux, xmlStr, source_count_str,
3020         &spherical_metadata->source_count);
3021     _get_int_value_from_xml_string (qtdemux, xmlStr,
3022         init_view_heading_str, &spherical_metadata->init_view_heading);
3023     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_pitch_str,
3024         &spherical_metadata->init_view_pitch);
3025     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_roll_str,
3026         &spherical_metadata->init_view_roll);
3027     _get_int_value_from_xml_string (qtdemux, xmlStr, timestamp_str,
3028         &spherical_metadata->timestamp);
3029     _get_int_value_from_xml_string (qtdemux, xmlStr, full_pano_width_str,
3030         &spherical_metadata->full_pano_width_pixels);
3031     _get_int_value_from_xml_string (qtdemux, xmlStr,
3032         full_pano_height_str, &spherical_metadata->full_pano_height_pixels);
3033     _get_int_value_from_xml_string (qtdemux, xmlStr,
3034         cropped_area_image_width_str,
3035         &spherical_metadata->cropped_area_image_width);
3036     _get_int_value_from_xml_string (qtdemux, xmlStr,
3037         cropped_area_image_height_str,
3038         &spherical_metadata->cropped_area_image_height);
3039     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_left_str,
3040         &spherical_metadata->cropped_area_left);
3041     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_top_str,
3042         &spherical_metadata->cropped_area_top);
3043   }
3044
3045   return;
3046 }
3047
3048 static void
3049 gst_tag_register_spherical_tags (void) {
3050   gst_tag_register ("is_spherical", GST_TAG_FLAG_META,
3051       G_TYPE_INT,
3052       _("tag-spherical"),
3053       _("Flag indicating if the video is a spherical video"),
3054       NULL);
3055   gst_tag_register ("is_stitched", GST_TAG_FLAG_META,
3056       G_TYPE_INT,
3057       _("tag-stitched"),
3058       _("Flag indicating if the video is stitched"),
3059       NULL);
3060   gst_tag_register ("stitching_software", GST_TAG_FLAG_META,
3061       G_TYPE_STRING,
3062       _("tag-stitching-software"),
3063       _("Software used to stitch the spherical video"),
3064       NULL);
3065   gst_tag_register ("projection_type", GST_TAG_FLAG_META,
3066       G_TYPE_STRING,
3067       _("tag-projection-type"),
3068       _("Projection type used in the video frames"),
3069       NULL);
3070   gst_tag_register ("stereo_mode", GST_TAG_FLAG_META,
3071       G_TYPE_STRING,
3072       _("tag-stereo-mode"),
3073       _("Description of stereoscopic 3D layout"),
3074       NULL);
3075   gst_tag_register ("source_count", GST_TAG_FLAG_META,
3076       G_TYPE_INT,
3077       _("tag-source-count"),
3078       _("Number of cameras used to create the spherical video"),
3079       NULL);
3080   gst_tag_register ("init_view_heading", GST_TAG_FLAG_META,
3081       G_TYPE_INT,
3082       _("tag-init-view-heading"),
3083       _("The heading angle of the initial view in degrees"),
3084       NULL);
3085   gst_tag_register ("init_view_pitch", GST_TAG_FLAG_META,
3086       G_TYPE_INT,
3087       _("tag-init-view-pitch"),
3088       _("The pitch angle of the initial view in degrees"),
3089       NULL);
3090   gst_tag_register ("init_view_roll", GST_TAG_FLAG_META,
3091       G_TYPE_INT,
3092       _("tag-init-view-roll"),
3093       _("The roll angle of the initial view in degrees"),
3094       NULL);
3095   gst_tag_register ("timestamp", GST_TAG_FLAG_META,
3096       G_TYPE_INT,
3097       _("tag-timestamp"),
3098       _("Epoch timestamp of when the first frame in the video was recorded"),
3099       NULL);
3100   gst_tag_register ("full_pano_width_pixels", GST_TAG_FLAG_META,
3101       G_TYPE_INT,
3102       _("tag-full-pano-width"),
3103       _("Width of the encoded video frame in pixels"),
3104       NULL);
3105   gst_tag_register ("full_pano_height_pixels", GST_TAG_FLAG_META,
3106       G_TYPE_INT,
3107       _("tag-full-pano-height"),
3108       _("Height of the encoded video frame in pixels"),
3109       NULL);
3110   gst_tag_register ("cropped_area_image_width", GST_TAG_FLAG_META,
3111       G_TYPE_INT,
3112       _("tag-cropped-area-image-width"),
3113       _("Width of the video frame to display (e.g. cropping)"),
3114       NULL);
3115   gst_tag_register ("cropped_area_image_height", GST_TAG_FLAG_META,
3116       G_TYPE_INT,
3117       _("tag-cropped-area-image-height"),
3118       _("Height of the video frame to display (e.g. cropping)"),
3119       NULL);
3120   gst_tag_register ("cropped_area_left", GST_TAG_FLAG_META,
3121       G_TYPE_INT,
3122       _("tag-cropped-area-left"),
3123       _("Column where the left edge of the image was cropped from the"
3124           " full sized panorama"),
3125       NULL);
3126   gst_tag_register ("cropped_area_top", GST_TAG_FLAG_META,
3127       G_TYPE_INT,
3128       _("tag-cropped-area-top"),
3129       _("Row where the top edge of the image was cropped from the"
3130           " full sized panorama"),
3131       NULL);
3132   gst_tag_register ("ambisonic_type", GST_TAG_FLAG_META,
3133       G_TYPE_INT,
3134       _("tag-ambisonic-type"),
3135       _("Specifies the type of ambisonic audio represented"),
3136       NULL);
3137   gst_tag_register ("ambisonic_format", GST_TAG_FLAG_META,
3138       G_TYPE_INT,
3139       _("tag-ambisonic-format"),
3140       _("Specifies the ambisonic audio format"),
3141       NULL);
3142   gst_tag_register ("ambisonic_order", GST_TAG_FLAG_META,
3143       G_TYPE_INT,
3144       _("tag-ambisonic-order"),
3145       _("Specifies the ambisonic audio channel order"),
3146       NULL);
3147
3148   return;
3149 }
3150
3151 static void
3152 _send_spherical_metadata_msg_to_bus (GstQTDemux * qtdemux)
3153 {
3154   GstTagList *taglist;
3155   QtDemuxSphericalMetadata *spherical_metadata = qtdemux->spherical_metadata;
3156
3157   GST_DEBUG_OBJECT (qtdemux, "is_spherical = %d",
3158       spherical_metadata->is_spherical);
3159   GST_DEBUG_OBJECT (qtdemux, "is_stitched = %d",
3160       spherical_metadata->is_stitched);
3161   GST_DEBUG_OBJECT (qtdemux, "stitching_software = %s",
3162       spherical_metadata->stitching_software);
3163   GST_DEBUG_OBJECT (qtdemux, "projection_type = %s",
3164       spherical_metadata->projection_type);
3165   GST_DEBUG_OBJECT (qtdemux, "stereo_mode = %s",
3166       spherical_metadata->stereo_mode);
3167   GST_DEBUG_OBJECT (qtdemux, "source_count %d",
3168       spherical_metadata->source_count);
3169   GST_DEBUG_OBJECT (qtdemux, "init_view_heading = %d",
3170       spherical_metadata->init_view_heading);
3171   GST_DEBUG_OBJECT (qtdemux, "init_view_pitch = %d",
3172       spherical_metadata->init_view_pitch);
3173   GST_DEBUG_OBJECT (qtdemux, "init_view_roll = %d",
3174       spherical_metadata->init_view_roll);
3175   GST_DEBUG_OBJECT (qtdemux, "timestamp = %d", spherical_metadata->timestamp);
3176   GST_DEBUG_OBJECT (qtdemux, "full_pano_width_pixels = %d",
3177       spherical_metadata->full_pano_width_pixels);
3178   GST_DEBUG_OBJECT (qtdemux, "full_pano_height_pixels = %d",
3179       spherical_metadata->full_pano_height_pixels);
3180   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_width = %d",
3181       spherical_metadata->cropped_area_image_width);
3182   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_height = %d",
3183       spherical_metadata->cropped_area_image_height);
3184   GST_DEBUG_OBJECT (qtdemux, "cropped_area_left = %d",
3185       spherical_metadata->cropped_area_left);
3186   GST_DEBUG_OBJECT (qtdemux, "cropped_area_top = %d",
3187       spherical_metadata->cropped_area_top);
3188   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type = %d",
3189       spherical_metadata->ambisonic_type);
3190   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order = %d",
3191       spherical_metadata->ambisonic_order);
3192   GST_DEBUG_OBJECT (qtdemux, "ambisonic_format = %d",
3193       spherical_metadata->ambisonic_format);
3194
3195   taglist = gst_tag_list_new_empty ();
3196   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3197       "is_spherical", spherical_metadata->is_spherical,
3198       "is_stitched", spherical_metadata->is_stitched,
3199       "source_count", spherical_metadata->source_count,
3200       "init_view_heading", spherical_metadata->init_view_heading,
3201       "init_view_pitch", spherical_metadata->init_view_pitch,
3202       "init_view_roll", spherical_metadata->init_view_roll,
3203       "timestamp", spherical_metadata->timestamp,
3204       "full_pano_width_pixels", spherical_metadata->full_pano_width_pixels,
3205       "full_pano_height_pixels", spherical_metadata->full_pano_height_pixels,
3206       "cropped_area_image_width", spherical_metadata->cropped_area_image_width,
3207       "cropped_area_image_height", spherical_metadata->cropped_area_image_height,
3208       "cropped_area_left", spherical_metadata->cropped_area_left,
3209       "cropped_area_top", spherical_metadata->cropped_area_top,
3210       "ambisonic_type", spherical_metadata->ambisonic_type,
3211       "ambisonic_format", spherical_metadata->ambisonic_format,
3212       "ambisonic_order", spherical_metadata->ambisonic_order,
3213       NULL);
3214
3215   if (spherical_metadata->stitching_software)
3216     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3217         "stitching_software", spherical_metadata->stitching_software,
3218         NULL);
3219   if (spherical_metadata->projection_type)
3220     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3221         "projection_type", spherical_metadata->projection_type,
3222         NULL);
3223   if (spherical_metadata->stereo_mode)
3224     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3225         "stereo_mode", spherical_metadata->stereo_mode,
3226         NULL);
3227
3228   gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
3229           gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
3230                   gst_tag_list_copy (taglist)));
3231
3232   gst_tag_list_unref(taglist);
3233
3234   return;
3235 }
3236
3237 static void
3238 qtdemux_parse_SA3D (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3239 {
3240   guint offset = 0;
3241
3242   guint8 version = 0;
3243   guint8 ambisonic_type  = 0;
3244   guint32 ambisonic_order = 0;
3245   guint8 ambisonic_channel_ordering = 0;
3246   guint8 ambisonic_normalization = 0;
3247   guint32 num_channels = 0;
3248   guint32 channel_map[49] = { 0 };      /* Up to 6th order */
3249
3250   int i;
3251
3252   GST_DEBUG_OBJECT (qtdemux, "qtdemux_parse_SA3D");
3253
3254   qtdemux->header_size += length;
3255   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3256
3257   if (length <= offset + 16) {
3258     GST_DEBUG_OBJECT (qtdemux, "SA3D atom is too short, skipping");
3259     return;
3260   }
3261
3262   version = QT_UINT8 (buffer + offset);
3263   ambisonic_type = QT_UINT8 (buffer + offset + 1);
3264   ambisonic_order = QT_UINT32 (buffer + offset + 2);
3265   ambisonic_channel_ordering = QT_UINT8 (buffer + offset + 6);
3266   ambisonic_normalization = QT_UINT8 (buffer + offset + 7);
3267   num_channels = QT_UINT32 (buffer + offset + 8);
3268   for (i = 0; i < num_channels; ++i)
3269     channel_map[i] = QT_UINT32 (buffer + offset + 12 + i * 4);
3270
3271   GST_DEBUG_OBJECT (qtdemux, "version: %d", version);
3272   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type: %d", ambisonic_type);
3273   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order: %d", ambisonic_order);
3274   GST_DEBUG_OBJECT (qtdemux, "ambisonic_channel_ordering: %d",
3275       ambisonic_channel_ordering);
3276   GST_DEBUG_OBJECT (qtdemux, "ambisonic_normalization: %d",
3277       ambisonic_normalization);
3278   GST_DEBUG_OBJECT (qtdemux, "num_channels: %d", num_channels);
3279   for (i = 0; i < num_channels; ++i)
3280     GST_DEBUG_OBJECT (qtdemux, "channel_map: %d", channel_map[i]);
3281
3282   if (version == RFC_AMBISONIC_SA3DBOX_VERSION_SUPPORTED) {
3283     if (ambisonic_type == RFC_AMBISONIC_TYPE_PERIPHONIC)
3284       qtdemux->spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_PERIPHONIC;
3285
3286     if (ambisonic_order == RFC_AMBISONIC_ORDER_FOA) {
3287       if (num_channels == 4) {
3288         qtdemux->spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_FOA;
3289
3290         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN)
3291             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D)
3292             && (channel_map[0] == 0) && (channel_map[1] == 1)
3293             && (channel_map[2] == 2) && (channel_map[3] == 3))
3294           qtdemux->spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMBIX;
3295
3296         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA)
3297             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA)
3298             && (channel_map[0] == 0) && (channel_map[1] == 3)
3299             && (channel_map[2] == 1) && (channel_map[3] == 2))
3300           qtdemux->spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMB;
3301       }
3302     }
3303   }
3304
3305   return;
3306 }
3307 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3308
3309 static void
3310 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
3311     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
3312     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
3313     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
3314     const guint8 * constant_iv)
3315 {
3316   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
3317   gst_buffer_fill (kid_buf, 0, kid, 16);
3318   if (info->default_properties)
3319     gst_structure_free (info->default_properties);
3320   info->default_properties =
3321       gst_structure_new ("application/x-cenc",
3322       "iv_size", G_TYPE_UINT, iv_size,
3323       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
3324       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
3325   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
3326       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
3327   gst_buffer_unref (kid_buf);
3328   if (protection_scheme_type == FOURCC_cbcs) {
3329     if (crypt_byte_block != 0 || skip_byte_block != 0) {
3330       gst_structure_set (info->default_properties, "crypt_byte_block",
3331           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
3332           skip_byte_block, NULL);
3333     }
3334     if (constant_iv != NULL) {
3335       GstBuffer *constant_iv_buf =
3336           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
3337       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
3338       gst_structure_set (info->default_properties, "constant_iv_size",
3339           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
3340           NULL);
3341       gst_buffer_unref (constant_iv_buf);
3342     }
3343     gst_structure_set (info->default_properties, "cipher-mode",
3344         G_TYPE_STRING, "cbcs", NULL);
3345   } else {
3346     gst_structure_set (info->default_properties, "cipher-mode",
3347         G_TYPE_STRING, "cenc", NULL);
3348   }
3349 }
3350
3351 static gboolean
3352 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
3353     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
3354 {
3355   guint32 algorithm_id = 0;
3356   const guint8 *kid;
3357   gboolean is_encrypted = TRUE;
3358   guint8 iv_size = 8;
3359
3360   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
3361     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
3362     return FALSE;
3363   }
3364
3365   algorithm_id >>= 8;
3366   if (algorithm_id == 0) {
3367     is_encrypted = FALSE;
3368   } else if (algorithm_id == 1) {
3369     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
3370   } else if (algorithm_id == 2) {
3371     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
3372   }
3373
3374   if (!gst_byte_reader_get_uint8 (br, &iv_size))
3375     return FALSE;
3376
3377   if (!gst_byte_reader_get_data (br, 16, &kid))
3378     return FALSE;
3379
3380   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
3381       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
3382   gst_structure_set (info->default_properties, "piff_algorithm_id",
3383       G_TYPE_UINT, algorithm_id, NULL);
3384   return TRUE;
3385 }
3386
3387
3388 static void
3389 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
3390     guint offset)
3391 {
3392   GstByteReader br;
3393   guint8 version;
3394   guint32 flags = 0;
3395   guint i;
3396   guint iv_size = 8;
3397   QtDemuxStream *stream;
3398   GstStructure *structure;
3399   QtDemuxCencSampleSetInfo *ss_info = NULL;
3400   const gchar *system_id;
3401   gboolean uses_sub_sample_encryption = FALSE;
3402   guint32 sample_count;
3403
3404   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
3405     return;
3406
3407   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
3408
3409   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
3410   if (!gst_structure_has_name (structure, "application/x-cenc")) {
3411     GST_WARNING_OBJECT (qtdemux,
3412         "Attempting PIFF box parsing on an unencrypted stream.");
3413     return;
3414   }
3415
3416   if (!gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
3417           G_TYPE_STRING, &system_id, NULL)) {
3418     GST_WARNING_OBJECT (qtdemux, "%s field not present in caps",
3419         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD);
3420     return;
3421   }
3422
3423   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
3424
3425   stream->protected = TRUE;
3426   stream->protection_scheme_type = FOURCC_cenc;
3427
3428   if (!stream->protection_scheme_info)
3429     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
3430
3431   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3432   if (!ss_info->default_properties) {
3433     ss_info->default_properties =
3434         gst_structure_new ("application/x-cenc",
3435         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
3436         NULL);
3437
3438   }
3439
3440   if (ss_info->crypto_info) {
3441     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3442     g_ptr_array_free (ss_info->crypto_info, TRUE);
3443     ss_info->crypto_info = NULL;
3444   }
3445
3446   /* skip UUID */
3447   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
3448
3449   if (!gst_byte_reader_get_uint8 (&br, &version)) {
3450     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
3451     return;
3452   }
3453
3454   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
3455     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
3456     return;
3457   }
3458
3459   if ((flags & 0x000001)) {
3460     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
3461             &br))
3462       return;
3463   } else if ((flags & 0x000002)) {
3464     uses_sub_sample_encryption = TRUE;
3465   }
3466
3467   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
3468           &iv_size)) {
3469     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
3470     return;
3471   }
3472
3473   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
3474     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
3475     return;
3476   }
3477
3478   ss_info->crypto_info =
3479       g_ptr_array_new_full (sample_count,
3480       (GDestroyNotify) qtdemux_gst_structure_free);
3481
3482   for (i = 0; i < sample_count; ++i) {
3483     GstStructure *properties;
3484     guint8 *data;
3485     GstBuffer *buf;
3486
3487     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3488     if (properties == NULL) {
3489       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3490       qtdemux->cenc_aux_sample_count = i;
3491       return;
3492     }
3493
3494     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
3495       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
3496       gst_structure_free (properties);
3497       qtdemux->cenc_aux_sample_count = i;
3498       return;
3499     }
3500     buf = gst_buffer_new_wrapped (data, iv_size);
3501     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3502     gst_buffer_unref (buf);
3503
3504     if (uses_sub_sample_encryption) {
3505       guint16 n_subsamples;
3506       const GValue *kid_buf_value;
3507
3508       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
3509           || n_subsamples == 0) {
3510         GST_ERROR_OBJECT (qtdemux,
3511             "failed to get subsample count for sample %u", i);
3512         gst_structure_free (properties);
3513         qtdemux->cenc_aux_sample_count = i;
3514         return;
3515       }
3516       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3517       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
3518         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3519             i);
3520         gst_structure_free (properties);
3521         qtdemux->cenc_aux_sample_count = i;
3522         return;
3523       }
3524       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3525
3526       kid_buf_value =
3527           gst_structure_get_value (ss_info->default_properties, "kid");
3528
3529       gst_structure_set (properties,
3530           "subsample_count", G_TYPE_UINT, n_subsamples,
3531           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3532       gst_structure_set_value (properties, "kid", kid_buf_value);
3533       gst_buffer_unref (buf);
3534     } else {
3535       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3536     }
3537
3538     g_ptr_array_add (ss_info->crypto_info, properties);
3539   }
3540
3541   qtdemux->cenc_aux_sample_count = sample_count;
3542 }
3543
3544 static void
3545 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3546 {
3547   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
3548     0x97, 0xA9, 0x42, 0xE8,
3549     0x9C, 0x71, 0x99, 0x94,
3550     0x91, 0xE3, 0xAF, 0xAC
3551   };
3552   static const guint8 playready_uuid[] = {
3553     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
3554     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
3555   };
3556
3557   static const guint8 piff_sample_encryption_uuid[] = {
3558     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3559     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3560   };
3561
3562 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
3563   static const guint8 spherical_uuid[] = {
3564     0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
3565     0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd
3566   };
3567 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3568
3569   guint offset;
3570
3571   /* counts as header data */
3572   qtdemux->header_size += length;
3573
3574   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3575
3576   if (length <= offset + 16) {
3577     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3578     return;
3579   }
3580
3581 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
3582   if (memcmp (buffer + offset, spherical_uuid, 16) == 0) {
3583     const char *contents;
3584
3585     GST_DEBUG_OBJECT (qtdemux, "spherical uuid was found");
3586     contents = (char *) (buffer + offset + 16);
3587     GST_DEBUG_OBJECT (qtdemux, "contents: %s\n", contents);
3588
3589     if (qtdemux->spherical_metadata)
3590       _parse_spatial_video_metadata_from_xml_string (qtdemux, contents);
3591
3592     return;
3593   }
3594 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3595
3596   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3597     GstBuffer *buf;
3598     GstTagList *taglist;
3599
3600     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3601         length - offset - 16, NULL);
3602     taglist = gst_tag_list_from_xmp_buffer (buf);
3603     gst_buffer_unref (buf);
3604
3605     /* make sure we have a usable taglist */
3606     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3607
3608     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3609
3610   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3611     int len;
3612     const gunichar2 *s_utf16;
3613     char *contents;
3614
3615     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3616     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3617     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3618     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3619
3620     g_free (contents);
3621
3622     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3623         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3624         (NULL));
3625   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3626     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3627   } else {
3628     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3629         GST_READ_UINT32_LE (buffer + offset),
3630         GST_READ_UINT32_LE (buffer + offset + 4),
3631         GST_READ_UINT32_LE (buffer + offset + 8),
3632         GST_READ_UINT32_LE (buffer + offset + 12));
3633   }
3634 }
3635
3636 static void
3637 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3638 {
3639   GstSidxParser sidx_parser;
3640   GstIsoffParserResult res;
3641   guint consumed;
3642
3643   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3644
3645   res =
3646       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3647       &consumed);
3648   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3649   if (res == GST_ISOFF_QT_PARSER_DONE) {
3650     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3651   }
3652   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3653 }
3654
3655 static void
3656 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3657 {
3658   guint64 start_time;
3659   guint32 entry_count;
3660
3661   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3662
3663   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3664
3665   if (gst_byte_reader_get_remaining (data) < 4) {
3666     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3667     return;
3668   }
3669
3670   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3671   if (entry_count == 0)
3672     return;
3673
3674   /* XXX: We assume that all start times are the same as different start times
3675    * would violate the MP4 synchronization model, so we just take the first
3676    * one here and apply it to all tracks.
3677    */
3678
3679   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3680     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3681     return;
3682   }
3683
3684   /* Skip track id */
3685   gst_byte_reader_skip_unchecked (data, 4);
3686
3687   /* In 100ns intervals */
3688   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3689
3690   /* Convert from Jan 1 1601 to Jan 1 1970 */
3691   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3692     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3693     return;
3694   }
3695   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3696
3697   /* Convert to GstClockTime */
3698   start_time *= 100;
3699
3700   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3701       GST_TIME_ARGS (start_time));
3702
3703   qtdemux->start_utc_time = start_time;
3704 }
3705
3706 /* caller verifies at least 8 bytes in buf */
3707 static void
3708 extract_initial_length_and_fourcc (const guint8 * data, gsize size,
3709     guint64 * plength, guint32 * pfourcc)
3710 {
3711   guint64 length;
3712   guint32 fourcc;
3713
3714   length = QT_UINT32 (data);
3715   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3716   fourcc = QT_FOURCC (data + 4);
3717   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3718
3719   if (length == 0) {
3720     length = G_MAXUINT64;
3721   } else if (length == 1 && size >= 16) {
3722     /* this means we have an extended size, which is the 64 bit value of
3723      * the next 8 bytes */
3724     length = QT_UINT64 (data + 8);
3725     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3726   }
3727
3728   if (plength)
3729     *plength = length;
3730   if (pfourcc)
3731     *pfourcc = fourcc;
3732 }
3733
3734 static gboolean
3735 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3736 {
3737   guint32 version = 0;
3738   GstClockTime duration = 0;
3739
3740   if (!gst_byte_reader_get_uint32_be (br, &version))
3741     goto failed;
3742
3743   version >>= 24;
3744   if (version == 1) {
3745     if (!gst_byte_reader_get_uint64_be (br, &duration))
3746       goto failed;
3747   } else {
3748     guint32 dur = 0;
3749
3750     if (!gst_byte_reader_get_uint32_be (br, &dur))
3751       goto failed;
3752     duration = dur;
3753   }
3754
3755   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3756   qtdemux->duration = duration;
3757
3758   return TRUE;
3759
3760 failed:
3761   {
3762     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3763     return FALSE;
3764   }
3765 }
3766
3767 static gboolean
3768 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3769     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3770 {
3771   if (!stream->parsed_trex && qtdemux->moov_node) {
3772     GNode *mvex, *trex;
3773     GstByteReader trex_data;
3774
3775     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3776     if (mvex) {
3777       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3778           &trex_data);
3779       while (trex) {
3780         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3781
3782         /* skip version/flags */
3783         if (!gst_byte_reader_skip (&trex_data, 4))
3784           goto next;
3785         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3786           goto next;
3787         if (id != stream->track_id)
3788           goto next;
3789         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3790           goto next;
3791         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3792           goto next;
3793         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3794           goto next;
3795         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3796           goto next;
3797
3798         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3799             "duration %d,  size %d, flags 0x%x", stream->track_id,
3800             dur, size, flags);
3801
3802         stream->parsed_trex = TRUE;
3803         stream->def_sample_description_index = sdi;
3804         stream->def_sample_duration = dur;
3805         stream->def_sample_size = size;
3806         stream->def_sample_flags = flags;
3807
3808       next:
3809         /* iterate all siblings */
3810         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3811             &trex_data);
3812       }
3813     }
3814   }
3815
3816   *ds_duration = stream->def_sample_duration;
3817   *ds_size = stream->def_sample_size;
3818   *ds_flags = stream->def_sample_flags;
3819
3820   /* even then, above values are better than random ... */
3821   if (G_UNLIKELY (!stream->parsed_trex)) {
3822     GST_WARNING_OBJECT (qtdemux,
3823         "failed to find fragment defaults for stream %d", stream->track_id);
3824     return FALSE;
3825   }
3826
3827   return TRUE;
3828 }
3829
3830 /* This method should be called whenever a more accurate duration might
3831  * have been found. It will update all relevant variables if/where needed
3832  */
3833 static void
3834 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3835 {
3836   guint i;
3837   guint64 movdur;
3838   GstClockTime prevdur;
3839
3840   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3841
3842   if (movdur > qtdemux->duration) {
3843     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3844     GST_DEBUG_OBJECT (qtdemux,
3845         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3846         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3847     qtdemux->duration = movdur;
3848     GST_DEBUG_OBJECT (qtdemux,
3849         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3850         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3851         GST_TIME_ARGS (qtdemux->segment.stop));
3852     if (qtdemux->segment.duration == prevdur) {
3853       /* If the current segment has duration/stop identical to previous duration
3854        * update them also (because they were set at that point in time with
3855        * the wrong duration */
3856       /* We convert the value *from* the timescale version to avoid rounding errors */
3857       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3858       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3859       qtdemux->segment.duration = fixeddur;
3860       qtdemux->segment.stop = fixeddur;
3861     }
3862   }
3863
3864   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3865     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3866
3867     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3868     if (movdur > stream->duration) {
3869       GST_DEBUG_OBJECT (qtdemux,
3870           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3871           GST_TIME_ARGS (duration));
3872       stream->duration = movdur;
3873       /* internal duration tracking state has been updated above, so */
3874       /* preserve an open-ended dummy segment rather than repeatedly updating
3875        * it and spamming downstream accordingly with segment events */
3876       /* also mangle the edit list end time when fragmented with a single edit
3877        * list that may only cover any non-fragmented data */
3878       if ((stream->dummy_segment ||
3879               (qtdemux->fragmented && stream->n_segments == 1)) &&
3880           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3881         /* Update all dummy values to new duration */
3882         stream->segments[0].stop_time = duration;
3883         stream->segments[0].duration = duration;
3884         stream->segments[0].media_stop = duration;
3885
3886         /* let downstream know we possibly have a new stop time */
3887         if (stream->segment_index != -1) {
3888           GstClockTime pos;
3889
3890           if (qtdemux->segment.rate >= 0) {
3891             pos = stream->segment.start;
3892           } else {
3893             pos = stream->segment.stop;
3894           }
3895
3896           gst_qtdemux_stream_update_segment (qtdemux, stream,
3897               stream->segment_index, pos, NULL, NULL);
3898         }
3899       }
3900     }
3901   }
3902 }
3903
3904 static gboolean
3905 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3906     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3907     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3908     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3909     gboolean has_tfdt)
3910 {
3911   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3912   guint64 timestamp;
3913   gint32 data_offset = 0;
3914   guint8 version;
3915   guint32 flags = 0, first_flags = 0, samples_count = 0;
3916   gint i;
3917   guint8 *data;
3918   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3919   QtDemuxSample *sample;
3920   gboolean ismv = FALSE;
3921   gint64 initial_offset;
3922   gint32 min_ct = 0;
3923
3924   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3925       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3926       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3927       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3928
3929   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3930     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3931     return TRUE;
3932   }
3933
3934   /* presence of stss or not can't really tell us much,
3935    * and flags and so on tend to be marginally reliable in these files */
3936   if (stream->subtype == FOURCC_soun) {
3937     GST_DEBUG_OBJECT (qtdemux,
3938         "sound track in fragmented file; marking all keyframes");
3939     stream->all_keyframe = TRUE;
3940   }
3941
3942   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3943       !gst_byte_reader_get_uint24_be (trun, &flags))
3944     goto fail;
3945
3946   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3947     goto fail;
3948
3949   if (flags & TR_DATA_OFFSET) {
3950     /* note this is really signed */
3951     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3952       goto fail;
3953     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3954     /* default base offset = first byte of moof */
3955     if (*base_offset == -1) {
3956       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3957       *base_offset = moof_offset;
3958     }
3959     *running_offset = *base_offset + data_offset;
3960   } else {
3961     /* if no offset at all, that would mean data starts at moof start,
3962      * which is a bit wrong and is ismv crappy way, so compensate
3963      * assuming data is in mdat following moof */
3964     if (*base_offset == -1) {
3965       *base_offset = moof_offset + moof_length + 8;
3966       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3967       ismv = TRUE;
3968     }
3969     if (*running_offset == -1)
3970       *running_offset = *base_offset;
3971   }
3972
3973   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3974       *running_offset);
3975   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3976       data_offset, flags, samples_count);
3977
3978   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3979     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3980       GST_DEBUG_OBJECT (qtdemux,
3981           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3982       flags ^= TR_FIRST_SAMPLE_FLAGS;
3983     } else {
3984       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3985         goto fail;
3986       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3987     }
3988   }
3989
3990   /* FIXME ? spec says other bits should also be checked to determine
3991    * entry size (and prefix size for that matter) */
3992   entry_size = 0;
3993   dur_offset = size_offset = 0;
3994   if (flags & TR_SAMPLE_DURATION) {
3995     GST_LOG_OBJECT (qtdemux, "entry duration present");
3996     dur_offset = entry_size;
3997     entry_size += 4;
3998   }
3999   if (flags & TR_SAMPLE_SIZE) {
4000     GST_LOG_OBJECT (qtdemux, "entry size present");
4001     size_offset = entry_size;
4002     entry_size += 4;
4003   }
4004   if (flags & TR_SAMPLE_FLAGS) {
4005     GST_LOG_OBJECT (qtdemux, "entry flags present");
4006     flags_offset = entry_size;
4007     entry_size += 4;
4008   }
4009   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
4010     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
4011     ct_offset = entry_size;
4012     entry_size += 4;
4013   }
4014
4015   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
4016     goto fail;
4017   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
4018
4019   if (stream->n_samples + samples_count >=
4020       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
4021     goto index_too_big;
4022
4023   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
4024       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
4025       (stream->n_samples + samples_count) *
4026       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
4027
4028   /* create a new array of samples if it's the first sample parsed */
4029   if (stream->n_samples == 0) {
4030     g_assert (stream->samples == NULL);
4031     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
4032     /* or try to reallocate it with space enough to insert the new samples */
4033   } else
4034     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
4035         stream->n_samples + samples_count);
4036   if (stream->samples == NULL)
4037     goto out_of_memory;
4038
4039   if (qtdemux->fragment_start != -1) {
4040     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
4041     qtdemux->fragment_start = -1;
4042   } else {
4043     if (stream->n_samples == 0) {
4044       if (decode_ts > 0) {
4045         timestamp = decode_ts;
4046       } else if (stream->pending_seek != NULL) {
4047         /* if we don't have a timestamp from a tfdt box, we'll use the one
4048          * from the mfra seek table */
4049         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
4050             GST_TIME_ARGS (stream->pending_seek->ts));
4051
4052         /* FIXME: this is not fully correct, the timestamp refers to the random
4053          * access sample refered to in the tfra entry, which may not necessarily
4054          * be the first sample in the tfrag/trun (but hopefully/usually is) */
4055         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
4056       } else {
4057         timestamp = 0;
4058       }
4059
4060       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
4061       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
4062           GST_TIME_ARGS (gst_ts));
4063     } else {
4064       /* If this is a GST_FORMAT_BYTES stream and we have a tfdt then use it
4065        * instead of the sum of sample durations */
4066       if (has_tfdt && !qtdemux->upstream_format_is_time) {
4067         timestamp = decode_ts;
4068         gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
4069         GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
4070             " (using tfdt)", GST_TIME_ARGS (gst_ts));
4071       } else {
4072         /* subsequent fragments extend stream */
4073         timestamp =
4074             stream->samples[stream->n_samples - 1].timestamp +
4075             stream->samples[stream->n_samples - 1].duration;
4076         gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
4077         GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
4078             " (extends previous samples)", GST_TIME_ARGS (gst_ts));
4079       }
4080     }
4081   }
4082
4083   initial_offset = *running_offset;
4084
4085   sample = stream->samples + stream->n_samples;
4086   for (i = 0; i < samples_count; i++) {
4087     guint32 dur, size, sflags;
4088     gint32 ct;
4089
4090     /* first read sample data */
4091     if (flags & TR_SAMPLE_DURATION) {
4092       dur = QT_UINT32 (data + dur_offset);
4093     } else {
4094       dur = d_sample_duration;
4095     }
4096     if (flags & TR_SAMPLE_SIZE) {
4097       size = QT_UINT32 (data + size_offset);
4098     } else {
4099       size = d_sample_size;
4100     }
4101     if (flags & TR_FIRST_SAMPLE_FLAGS) {
4102       if (i == 0) {
4103         sflags = first_flags;
4104       } else {
4105         sflags = d_sample_flags;
4106       }
4107     } else if (flags & TR_SAMPLE_FLAGS) {
4108       sflags = QT_UINT32 (data + flags_offset);
4109     } else {
4110       sflags = d_sample_flags;
4111     }
4112
4113     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
4114       /* Read offsets as signed numbers regardless of trun version as very
4115        * high offsets are unlikely and there are files out there that use
4116        * version=0 truns with negative offsets */
4117       ct = QT_UINT32 (data + ct_offset);
4118
4119       /* FIXME: Set offset to 0 for "no decode samples". This needs
4120        * to be handled in a codec specific manner ideally. */
4121       if (ct == G_MININT32)
4122         ct = 0;
4123     } else {
4124       ct = 0;
4125     }
4126     data += entry_size;
4127
4128     /* fill the sample information */
4129     sample->offset = *running_offset;
4130     sample->pts_offset = ct;
4131     sample->size = size;
4132     sample->timestamp = timestamp;
4133     sample->duration = dur;
4134     /* sample-is-difference-sample */
4135     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
4136      * now idea how it relates to bitfield other than massive LE/BE confusion */
4137     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
4138     *running_offset += size;
4139     timestamp += dur;
4140     stream->duration_moof += dur;
4141     sample++;
4142
4143     if (ct < min_ct)
4144       min_ct = ct;
4145   }
4146
4147   /* Shift PTS/DTS to allow for negative composition offsets while keeping
4148    * A/V sync in place. This is similar to the code handling ctts/cslg in the
4149    * non-fragmented case.
4150    */
4151   if (min_ct < 0)
4152     stream->cslg_shift = -min_ct;
4153   else
4154     stream->cslg_shift = 0;
4155
4156   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
4157       stream->cslg_shift);
4158
4159   /* Update total duration if needed */
4160   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
4161
4162   /* Pre-emptively figure out size of mdat based on trun information.
4163    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
4164    * size, else we will still be able to use this when dealing with gap'ed
4165    * input */
4166   qtdemux->mdatleft = *running_offset - initial_offset;
4167   qtdemux->mdatoffset = initial_offset;
4168   qtdemux->mdatsize = qtdemux->mdatleft;
4169
4170   stream->n_samples += samples_count;
4171   stream->n_samples_moof += samples_count;
4172
4173   if (stream->pending_seek != NULL)
4174     stream->pending_seek = NULL;
4175
4176   return TRUE;
4177
4178 fail:
4179   {
4180     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
4181     return FALSE;
4182   }
4183 out_of_memory:
4184   {
4185     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
4186         stream->n_samples);
4187     return FALSE;
4188   }
4189 index_too_big:
4190   {
4191     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
4192         "be larger than %uMB (broken file?)", stream->n_samples,
4193         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
4194     return FALSE;
4195   }
4196 }
4197
4198 /* find stream with @id */
4199 static inline QtDemuxStream *
4200 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
4201 {
4202   QtDemuxStream *stream;
4203   gint i;
4204
4205   /* check */
4206   if (G_UNLIKELY (!id)) {
4207     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
4208     return NULL;
4209   }
4210
4211   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4212     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4213     if (stream->track_id == id)
4214       return stream;
4215   }
4216   if (qtdemux->variant == VARIANT_MSS_FRAGMENTED) {
4217     /* mss should have only 1 stream anyway */
4218     return QTDEMUX_NTH_STREAM (qtdemux, 0);
4219   }
4220
4221   return NULL;
4222 }
4223
4224 static gboolean
4225 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
4226     guint32 * fragment_number)
4227 {
4228   if (!gst_byte_reader_skip (mfhd, 4))
4229     goto fail;
4230   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
4231     goto fail;
4232   return TRUE;
4233 fail:
4234   {
4235     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
4236     return FALSE;
4237   }
4238 }
4239
4240 static gboolean
4241 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
4242     QtDemuxStream ** stream, guint32 * default_sample_duration,
4243     guint32 * default_sample_size, guint32 * default_sample_flags,
4244     gint64 * base_offset)
4245 {
4246   guint32 flags = 0;
4247   guint32 track_id = 0;
4248
4249   if (!gst_byte_reader_skip (tfhd, 1) ||
4250       !gst_byte_reader_get_uint24_be (tfhd, &flags))
4251     goto invalid_track;
4252
4253   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
4254     goto invalid_track;
4255
4256   *stream = qtdemux_find_stream (qtdemux, track_id);
4257   if (G_UNLIKELY (!*stream))
4258     goto unknown_stream;
4259
4260   if (flags & TF_DEFAULT_BASE_IS_MOOF)
4261     *base_offset = qtdemux->moof_offset;
4262
4263   if (flags & TF_BASE_DATA_OFFSET)
4264     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
4265       goto invalid_track;
4266
4267   /* obtain stream defaults */
4268   if (qtdemux_parse_trex (qtdemux, *stream,
4269           default_sample_duration, default_sample_size, default_sample_flags)) {
4270
4271     /* Default sample description index is only valid if trex parsing succeeded */
4272     (*stream)->stsd_sample_description_id =
4273         (*stream)->def_sample_description_index - 1;
4274   }
4275
4276   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
4277     guint32 sample_description_index;
4278     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
4279       goto invalid_track;
4280     (*stream)->stsd_sample_description_id = sample_description_index - 1;
4281   }
4282
4283   if (qtdemux->variant == VARIANT_MSS_FRAGMENTED) {
4284     /* mss has no stsd entry */
4285     (*stream)->stsd_sample_description_id = 0;
4286   }
4287
4288   if (flags & TF_DEFAULT_SAMPLE_DURATION)
4289     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
4290       goto invalid_track;
4291
4292   if (flags & TF_DEFAULT_SAMPLE_SIZE)
4293     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
4294       goto invalid_track;
4295
4296   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
4297     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
4298       goto invalid_track;
4299
4300   return TRUE;
4301
4302 invalid_track:
4303   {
4304     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
4305     return FALSE;
4306   }
4307 unknown_stream:
4308   {
4309     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
4310     return TRUE;
4311   }
4312 }
4313
4314 static gboolean
4315 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
4316     guint64 * decode_time)
4317 {
4318   guint32 version = 0;
4319
4320   if (!gst_byte_reader_get_uint32_be (br, &version))
4321     return FALSE;
4322
4323   version >>= 24;
4324   if (version == 1) {
4325     if (!gst_byte_reader_get_uint64_be (br, decode_time))
4326       goto failed;
4327   } else {
4328     guint32 dec_time = 0;
4329     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
4330       goto failed;
4331     *decode_time = dec_time;
4332   }
4333
4334   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
4335       *decode_time);
4336
4337   return TRUE;
4338
4339 failed:
4340   {
4341     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
4342     return FALSE;
4343   }
4344 }
4345
4346 /* Returns a pointer to a GstStructure containing the properties of
4347  * the stream sample identified by @sample_index. The caller must unref
4348  * the returned object after use. Returns NULL if unsuccessful. */
4349 static GstStructure *
4350 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
4351     QtDemuxStream * stream, guint sample_index)
4352 {
4353   QtDemuxCencSampleSetInfo *info = NULL;
4354
4355   g_return_val_if_fail (stream != NULL, NULL);
4356   g_return_val_if_fail (stream->protected, NULL);
4357   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
4358
4359   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4360
4361   /* Currently, cenc properties for groups of samples are not supported, so
4362    * simply return a copy of the default sample properties */
4363   return gst_structure_copy (info->default_properties);
4364 }
4365
4366 /* Parses the sizes of sample auxiliary information contained within a stream,
4367  * as given in a saiz box. Returns array of sample_count guint8 size values,
4368  * or NULL on failure */
4369 static guint8 *
4370 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
4371     GstByteReader * br, guint32 * sample_count)
4372 {
4373   guint32 flags = 0;
4374   guint8 *info_sizes;
4375   guint8 default_info_size;
4376
4377   g_return_val_if_fail (qtdemux != NULL, NULL);
4378   g_return_val_if_fail (stream != NULL, NULL);
4379   g_return_val_if_fail (br != NULL, NULL);
4380   g_return_val_if_fail (sample_count != NULL, NULL);
4381
4382   if (!gst_byte_reader_get_uint32_be (br, &flags))
4383     return NULL;
4384
4385   if (flags & 0x1) {
4386     /* aux_info_type and aux_info_type_parameter are ignored */
4387     if (!gst_byte_reader_skip (br, 8))
4388       return NULL;
4389   }
4390
4391   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
4392     return NULL;
4393   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
4394
4395   if (!gst_byte_reader_get_uint32_be (br, sample_count))
4396     return NULL;
4397   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
4398
4399
4400   if (default_info_size == 0) {
4401     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
4402       return NULL;
4403     }
4404   } else {
4405     info_sizes = g_new (guint8, *sample_count);
4406     memset (info_sizes, default_info_size, *sample_count);
4407   }
4408
4409   return info_sizes;
4410 }
4411
4412 /* Parses the offset of sample auxiliary information contained within a stream,
4413  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
4414 static gboolean
4415 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
4416     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
4417     guint64 * offset)
4418 {
4419   guint8 version = 0;
4420   guint32 flags = 0;
4421   guint32 aux_info_type = 0;
4422   guint32 aux_info_type_parameter = 0;
4423   guint32 entry_count;
4424   guint32 off_32;
4425   guint64 off_64;
4426   const guint8 *aux_info_type_data = NULL;
4427
4428   g_return_val_if_fail (qtdemux != NULL, FALSE);
4429   g_return_val_if_fail (stream != NULL, FALSE);
4430   g_return_val_if_fail (br != NULL, FALSE);
4431   g_return_val_if_fail (offset != NULL, FALSE);
4432
4433   if (!gst_byte_reader_get_uint8 (br, &version))
4434     return FALSE;
4435
4436   if (!gst_byte_reader_get_uint24_be (br, &flags))
4437     return FALSE;
4438
4439   if (flags & 0x1) {
4440
4441     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
4442       return FALSE;
4443     aux_info_type = QT_FOURCC (aux_info_type_data);
4444
4445     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
4446       return FALSE;
4447   } else if (stream->protected) {
4448     aux_info_type = stream->protection_scheme_type;
4449   } else {
4450     aux_info_type = CUR_STREAM (stream)->fourcc;
4451   }
4452
4453   if (info_type)
4454     *info_type = aux_info_type;
4455   if (info_type_parameter)
4456     *info_type_parameter = aux_info_type_parameter;
4457
4458   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
4459       "aux_info_type_parameter:  %#06x",
4460       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
4461
4462   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
4463     return FALSE;
4464
4465   if (entry_count != 1) {
4466     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
4467     return FALSE;
4468   }
4469
4470   if (version == 0) {
4471     if (!gst_byte_reader_get_uint32_be (br, &off_32))
4472       return FALSE;
4473     *offset = (guint64) off_32;
4474   } else {
4475     if (!gst_byte_reader_get_uint64_be (br, &off_64))
4476       return FALSE;
4477     *offset = off_64;
4478   }
4479
4480   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
4481   return TRUE;
4482 }
4483
4484 static void
4485 qtdemux_gst_structure_free (GstStructure * gststructure)
4486 {
4487   if (gststructure) {
4488     gst_structure_free (gststructure);
4489   }
4490 }
4491
4492 /* Parses auxiliary information relating to samples protected using
4493  * Common Encryption (cenc); the format of this information
4494  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
4495  * otherwise. */
4496 static gboolean
4497 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
4498     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
4499 {
4500   QtDemuxCencSampleSetInfo *ss_info = NULL;
4501   guint8 size;
4502   gint i;
4503   GPtrArray *old_crypto_info = NULL;
4504   guint old_entries = 0;
4505
4506   g_return_val_if_fail (qtdemux != NULL, FALSE);
4507   g_return_val_if_fail (stream != NULL, FALSE);
4508   g_return_val_if_fail (br != NULL, FALSE);
4509   g_return_val_if_fail (stream->protected, FALSE);
4510   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
4511
4512   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4513
4514   if (ss_info->crypto_info) {
4515     old_crypto_info = ss_info->crypto_info;
4516     /* Count number of non-null entries remaining at the tail end */
4517     for (i = old_crypto_info->len - 1; i >= 0; i--) {
4518       if (g_ptr_array_index (old_crypto_info, i) == NULL)
4519         break;
4520       old_entries++;
4521     }
4522   }
4523
4524   ss_info->crypto_info =
4525       g_ptr_array_new_full (sample_count + old_entries,
4526       (GDestroyNotify) qtdemux_gst_structure_free);
4527
4528   /* We preserve old entries because we parse the next moof in advance
4529    * of consuming all samples from the previous moof, and otherwise
4530    * we'd discard the corresponding crypto info for the samples
4531    * from the previous fragment. */
4532   if (old_entries) {
4533     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
4534         old_entries);
4535     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
4536       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
4537               i));
4538       g_ptr_array_index (old_crypto_info, i) = NULL;
4539     }
4540   }
4541
4542   if (old_crypto_info) {
4543     /* Everything now belongs to the new array */
4544     g_ptr_array_free (old_crypto_info, TRUE);
4545   }
4546
4547   for (i = 0; i < sample_count; ++i) {
4548     GstStructure *properties;
4549     guint16 n_subsamples = 0;
4550     guint8 *data;
4551     guint iv_size;
4552     GstBuffer *buf;
4553     gboolean could_read_iv;
4554
4555     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
4556     if (properties == NULL) {
4557       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
4558       return FALSE;
4559     }
4560     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
4561       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
4562       gst_structure_free (properties);
4563       return FALSE;
4564     }
4565     could_read_iv =
4566         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
4567     if (could_read_iv) {
4568       buf = gst_buffer_new_wrapped (data, iv_size);
4569       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
4570       gst_buffer_unref (buf);
4571     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
4572       const GValue *constant_iv_size_value =
4573           gst_structure_get_value (properties, "constant_iv_size");
4574       const GValue *constant_iv_value =
4575           gst_structure_get_value (properties, "iv");
4576       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
4577         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
4578         gst_structure_free (properties);
4579         return FALSE;
4580       }
4581       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
4582       gst_structure_remove_field (properties, "constant_iv_size");
4583     } else if (stream->protection_scheme_type == FOURCC_cenc) {
4584       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
4585       gst_structure_free (properties);
4586       return FALSE;
4587     }
4588     size = info_sizes[i];
4589     if (size > iv_size) {
4590       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4591           || !(n_subsamples > 0)) {
4592         gst_structure_free (properties);
4593         GST_ERROR_OBJECT (qtdemux,
4594             "failed to get subsample count for sample %u", i);
4595         return FALSE;
4596       }
4597       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4598       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4599         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4600             i);
4601         gst_structure_free (properties);
4602         return FALSE;
4603       }
4604       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4605       if (!buf) {
4606         gst_structure_free (properties);
4607         return FALSE;
4608       }
4609       gst_structure_set (properties,
4610           "subsample_count", G_TYPE_UINT, n_subsamples,
4611           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4612       gst_buffer_unref (buf);
4613     } else {
4614       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4615     }
4616     g_ptr_array_add (ss_info->crypto_info, properties);
4617   }
4618   return TRUE;
4619 }
4620
4621 /* Converts a UUID in raw byte form to a string representation, as defined in
4622  * RFC 4122. The caller takes ownership of the returned string and is
4623  * responsible for freeing it after use. */
4624 static gchar *
4625 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4626 {
4627   const guint8 *uuid = (const guint8 *) uuid_bytes;
4628
4629   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4630       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4631       uuid[0], uuid[1], uuid[2], uuid[3],
4632       uuid[4], uuid[5], uuid[6], uuid[7],
4633       uuid[8], uuid[9], uuid[10], uuid[11],
4634       uuid[12], uuid[13], uuid[14], uuid[15]);
4635 }
4636
4637 /* Parses a Protection System Specific Header box (pssh), as defined in the
4638  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4639  * information needed by a specific content protection system in order to
4640  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4641  * otherwise. */
4642 static gboolean
4643 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4644 {
4645   gchar *sysid_string;
4646   guint32 pssh_size = QT_UINT32 (node->data);
4647   GstBuffer *pssh = NULL;
4648   GstEvent *event = NULL;
4649   guint32 parent_box_type;
4650   gint i;
4651
4652   if (G_UNLIKELY (pssh_size < 32U)) {
4653     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4654     return FALSE;
4655   }
4656
4657   sysid_string =
4658       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4659
4660   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4661
4662   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4663   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4664       gst_buffer_get_size (pssh));
4665
4666   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4667
4668   /* Push an event containing the pssh box onto the queues of all streams. */
4669   event = gst_event_new_protection (sysid_string, pssh,
4670       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4671   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4672     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4673     GST_TRACE_OBJECT (qtdemux,
4674         "adding protection event for stream %s and system %s",
4675         stream->stream_id, sysid_string);
4676     g_queue_push_tail (&stream->protection_scheme_event_queue,
4677         gst_event_ref (event));
4678   }
4679   g_free (sysid_string);
4680   gst_event_unref (event);
4681   gst_buffer_unref (pssh);
4682   return TRUE;
4683 }
4684
4685 static gboolean
4686 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4687     guint64 moof_offset, QtDemuxStream * stream)
4688 {
4689   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4690   GNode *uuid_node;
4691   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4692   GNode *saiz_node, *saio_node, *pssh_node;
4693   GstByteReader saiz_data, saio_data;
4694   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4695   gint64 base_offset, running_offset;
4696   guint32 frag_num;
4697   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4698
4699   /* NOTE @stream ignored */
4700
4701   moof_node = g_node_new ((guint8 *) buffer);
4702   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4703   qtdemux_node_dump (qtdemux, moof_node);
4704
4705   /* Get fragment number from mfhd and check it's valid */
4706   mfhd_node =
4707       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4708   if (mfhd_node == NULL)
4709     goto missing_mfhd;
4710   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4711     goto fail;
4712   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4713
4714   /* unknown base_offset to start with */
4715   base_offset = running_offset = -1;
4716   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4717   while (traf_node) {
4718     guint64 decode_time = 0;
4719
4720     /* Fragment Header node */
4721     tfhd_node =
4722         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4723         &tfhd_data);
4724     if (!tfhd_node)
4725       goto missing_tfhd;
4726     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4727             &ds_size, &ds_flags, &base_offset))
4728       goto missing_tfhd;
4729
4730     /* The following code assumes at most a single set of sample auxiliary
4731      * data in the fragment (consisting of a saiz box and a corresponding saio
4732      * box); in theory, however, there could be multiple sets of sample
4733      * auxiliary data in a fragment. */
4734     saiz_node =
4735         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4736         &saiz_data);
4737     if (saiz_node) {
4738       guint32 info_type = 0;
4739       guint64 offset = 0;
4740       guint32 info_type_parameter = 0;
4741
4742       g_free (qtdemux->cenc_aux_info_sizes);
4743
4744       qtdemux->cenc_aux_info_sizes =
4745           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4746           &qtdemux->cenc_aux_sample_count);
4747       if (qtdemux->cenc_aux_info_sizes == NULL) {
4748         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4749         goto fail;
4750       }
4751       saio_node =
4752           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4753           &saio_data);
4754       if (!saio_node) {
4755         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4756         g_free (qtdemux->cenc_aux_info_sizes);
4757         qtdemux->cenc_aux_info_sizes = NULL;
4758         goto fail;
4759       }
4760
4761       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4762                   &info_type, &info_type_parameter, &offset))) {
4763         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4764         g_free (qtdemux->cenc_aux_info_sizes);
4765         qtdemux->cenc_aux_info_sizes = NULL;
4766         goto fail;
4767       }
4768       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4769         offset += (guint64) (base_offset - qtdemux->moof_offset);
4770       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4771           && info_type_parameter == 0U) {
4772         GstByteReader br;
4773         if (offset > length) {
4774           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4775           qtdemux->cenc_aux_info_offset = offset;
4776         } else {
4777           gst_byte_reader_init (&br, buffer + offset, length - offset);
4778           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4779                   qtdemux->cenc_aux_info_sizes,
4780                   qtdemux->cenc_aux_sample_count)) {
4781             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4782             g_free (qtdemux->cenc_aux_info_sizes);
4783             qtdemux->cenc_aux_info_sizes = NULL;
4784             goto fail;
4785           }
4786         }
4787       }
4788     }
4789
4790     tfdt_node =
4791         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4792         &tfdt_data);
4793     if (tfdt_node) {
4794       /* We'll use decode_time to interpolate timestamps
4795        * in case the input timestamps are missing */
4796       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4797
4798       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4799           " (%" GST_TIME_FORMAT ")", decode_time,
4800           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4801                   decode_time) : GST_CLOCK_TIME_NONE));
4802
4803       /* Discard the fragment buffer timestamp info to avoid using it.
4804        * Rely on tfdt instead as it is more accurate than the timestamp
4805        * that is fetched from a manifest/playlist and is usually
4806        * less accurate. */
4807       qtdemux->fragment_start = -1;
4808     }
4809
4810     if (G_UNLIKELY (!stream)) {
4811       /* we lost track of offset, we'll need to regain it,
4812        * but can delay complaining until later or avoid doing so altogether */
4813       base_offset = -2;
4814       goto next;
4815     }
4816     if (G_UNLIKELY (base_offset < -1))
4817       goto lost_offset;
4818
4819     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4820
4821     if (!qtdemux->pullbased) {
4822       /* Sample tables can grow enough to be problematic if the system memory
4823        * is very low (e.g. embedded devices) and the videos very long
4824        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4825        * Fortunately, we can easily discard them for each new fragment when
4826        * we know qtdemux will not receive seeks outside of the current fragment.
4827        * adaptivedemux honors this assumption.
4828        * This optimization is also useful for applications that use qtdemux as
4829        * a push-based simple demuxer, like Media Source Extensions. */
4830       gst_qtdemux_stream_flush_samples_data (stream);
4831     }
4832
4833     /* initialise moof sample data */
4834     stream->n_samples_moof = 0;
4835     stream->duration_last_moof = stream->duration_moof;
4836     stream->duration_moof = 0;
4837
4838     /* Track Run node */
4839     trun_node =
4840         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4841         &trun_data);
4842     while (trun_node) {
4843       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4844           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4845           &running_offset, decode_time, (tfdt_node != NULL));
4846       /* iterate all siblings */
4847       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4848           &trun_data);
4849       /* don't use tfdt for subsequent trun as it only refers to the first */
4850       tfdt_node = NULL;
4851     }
4852
4853     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4854     if (uuid_node) {
4855       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4856       guint32 box_length = QT_UINT32 (uuid_buffer);
4857
4858       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4859     }
4860
4861     /* if no new base_offset provided for next traf,
4862      * base is end of current traf */
4863     base_offset = running_offset;
4864     running_offset = -1;
4865
4866     if (stream->n_samples_moof && stream->duration_moof)
4867       stream->new_caps = TRUE;
4868
4869   next:
4870     /* iterate all siblings */
4871     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4872   }
4873
4874   /* parse any protection system info */
4875   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4876   if (pssh_node) {
4877     /* Unref old protection events if we are going to receive new ones. */
4878     qtdemux_clear_protection_events_on_all_streams (qtdemux);
4879   }
4880   while (pssh_node) {
4881     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4882     qtdemux_parse_pssh (qtdemux, pssh_node);
4883     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4884   }
4885
4886   if (!qtdemux->upstream_format_is_time
4887       && qtdemux->variant != VARIANT_MSE_BYTESTREAM
4888       && !qtdemux->first_moof_already_parsed
4889       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4890       && min_dts != 0) {
4891     /* Unless the user has explicitly requested another seek, perform an
4892      * internal seek to the time specified in the tfdt.
4893      *
4894      * This way if the user opens a file where the first tfdt is 1 hour
4895      * into the presentation, they will not have to wait 1 hour for run
4896      * time to catch up and actual playback to start. */
4897     gint i;
4898
4899     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4900         "performing an internal seek to %" GST_TIME_FORMAT,
4901         GST_TIME_ARGS (min_dts));
4902
4903     qtdemux->segment.start = min_dts;
4904     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4905
4906     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4907       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4908       stream->time_position = min_dts;
4909     }
4910
4911     /* Before this code was run a segment was already sent when the moov was
4912      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4913      * be emitted after a moov, and we can emit a second segment anyway for
4914      * special cases like this. */
4915     qtdemux->need_segment = TRUE;
4916   }
4917
4918   qtdemux->first_moof_already_parsed = TRUE;
4919
4920   g_node_destroy (moof_node);
4921   return TRUE;
4922
4923 missing_tfhd:
4924   {
4925     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4926     goto fail;
4927   }
4928 missing_mfhd:
4929   {
4930     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4931     goto fail;
4932   }
4933 lost_offset:
4934   {
4935     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4936     goto fail;
4937   }
4938 fail:
4939   {
4940     g_node_destroy (moof_node);
4941     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4942         (_("This file is corrupt and cannot be played.")), (NULL));
4943     return FALSE;
4944   }
4945 }
4946
4947 #if 0
4948 /* might be used if some day we actually use mfra & co
4949  * for random access to fragments,
4950  * but that will require quite some modifications and much less relying
4951  * on a sample array */
4952 #endif
4953
4954 static gboolean
4955 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4956 {
4957   QtDemuxStream *stream;
4958   guint32 ver_flags, track_id, len, num_entries, i;
4959   guint value_size, traf_size, trun_size, sample_size;
4960   guint64 time = 0, moof_offset = 0;
4961 #if 0
4962   GstBuffer *buf = NULL;
4963   GstFlowReturn ret;
4964 #endif
4965   GstByteReader tfra;
4966
4967   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4968
4969   if (!gst_byte_reader_skip (&tfra, 8))
4970     return FALSE;
4971
4972   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4973     return FALSE;
4974
4975   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4976       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4977       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4978     return FALSE;
4979
4980   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4981
4982   stream = qtdemux_find_stream (qtdemux, track_id);
4983   if (stream == NULL)
4984     goto unknown_trackid;
4985
4986   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4987   sample_size = (len & 3) + 1;
4988   trun_size = ((len & 12) >> 2) + 1;
4989   traf_size = ((len & 48) >> 4) + 1;
4990
4991   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4992       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4993
4994   if (num_entries == 0)
4995     goto no_samples;
4996
4997   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4998           value_size + value_size + traf_size + trun_size + sample_size))
4999     goto corrupt_file;
5000
5001   g_free (stream->ra_entries);
5002   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
5003   stream->n_ra_entries = num_entries;
5004
5005   for (i = 0; i < num_entries; i++) {
5006     qt_atom_parser_get_offset (&tfra, value_size, &time);
5007     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
5008     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
5009     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
5010     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
5011
5012     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
5013
5014     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
5015         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
5016
5017     stream->ra_entries[i].ts = time;
5018     stream->ra_entries[i].moof_offset = moof_offset;
5019
5020     /* don't want to go through the entire file and read all moofs at startup */
5021 #if 0
5022     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
5023     if (ret != GST_FLOW_OK)
5024       goto corrupt_file;
5025     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
5026         moof_offset, stream);
5027     gst_buffer_unref (buf);
5028 #endif
5029   }
5030
5031   check_update_duration (qtdemux, time);
5032
5033   return TRUE;
5034
5035 /* ERRORS */
5036 unknown_trackid:
5037   {
5038     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
5039     return FALSE;
5040   }
5041 corrupt_file:
5042   {
5043     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
5044     return FALSE;
5045   }
5046 no_samples:
5047   {
5048     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
5049     return FALSE;
5050   }
5051 }
5052
5053 static gboolean
5054 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
5055 {
5056   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
5057   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
5058   GstBuffer *mfro = NULL, *mfra = NULL;
5059   GstFlowReturn flow;
5060   gboolean ret = FALSE;
5061   GNode *mfra_node, *tfra_node;
5062   guint64 mfra_offset = 0;
5063   guint32 fourcc, mfra_size;
5064   gint64 len;
5065
5066   /* query upstream size in bytes */
5067   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
5068     goto size_query_failed;
5069
5070   /* mfro box should be at the very end of the file */
5071   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
5072   if (flow != GST_FLOW_OK)
5073     goto exit;
5074
5075   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
5076
5077   fourcc = QT_FOURCC (mfro_map.data + 4);
5078   if (fourcc != FOURCC_mfro)
5079     goto exit;
5080
5081   GST_INFO_OBJECT (qtdemux, "Found mfro box");
5082   if (mfro_map.size < 16)
5083     goto invalid_mfro_size;
5084
5085   mfra_size = QT_UINT32 (mfro_map.data + 12);
5086   if (mfra_size >= len)
5087     goto invalid_mfra_size;
5088
5089   mfra_offset = len - mfra_size;
5090
5091   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
5092       mfra_offset, mfra_size);
5093
5094   /* now get and parse mfra box */
5095   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
5096   if (flow != GST_FLOW_OK)
5097     goto broken_file;
5098
5099   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
5100
5101   mfra_node = g_node_new ((guint8 *) mfra_map.data);
5102   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
5103
5104   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
5105
5106   while (tfra_node) {
5107     qtdemux_parse_tfra (qtdemux, tfra_node);
5108     /* iterate all siblings */
5109     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
5110   }
5111   g_node_destroy (mfra_node);
5112
5113   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
5114   ret = TRUE;
5115
5116 exit:
5117
5118   if (mfro) {
5119     if (mfro_map.memory != NULL)
5120       gst_buffer_unmap (mfro, &mfro_map);
5121     gst_buffer_unref (mfro);
5122   }
5123   if (mfra) {
5124     if (mfra_map.memory != NULL)
5125       gst_buffer_unmap (mfra, &mfra_map);
5126     gst_buffer_unref (mfra);
5127   }
5128   return ret;
5129
5130 /* ERRORS */
5131 size_query_failed:
5132   {
5133     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
5134     goto exit;
5135   }
5136 invalid_mfro_size:
5137   {
5138     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
5139     goto exit;
5140   }
5141 invalid_mfra_size:
5142   {
5143     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
5144     goto exit;
5145   }
5146 broken_file:
5147   {
5148     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
5149     goto exit;
5150   }
5151 }
5152
5153 static guint64
5154 add_offset (guint64 offset, guint64 advance)
5155 {
5156   /* Avoid 64-bit overflow by clamping */
5157   if (offset > G_MAXUINT64 - advance)
5158     return G_MAXUINT64;
5159   return offset + advance;
5160 }
5161
5162 static GstFlowReturn
5163 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
5164 {
5165   guint64 length = 0;
5166   guint32 fourcc = 0;
5167   GstBuffer *buf = NULL;
5168   GstFlowReturn ret = GST_FLOW_OK;
5169   guint64 cur_offset = qtdemux->offset;
5170   GstMapInfo map;
5171
5172   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
5173   if (G_UNLIKELY (ret != GST_FLOW_OK))
5174     goto beach;
5175   gst_buffer_map (buf, &map, GST_MAP_READ);
5176   if (G_LIKELY (map.size >= 8))
5177     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
5178   gst_buffer_unmap (buf, &map);
5179   gst_buffer_unref (buf);
5180
5181   /* maybe we already got most we needed, so only consider this eof */
5182   if (G_UNLIKELY (length == 0)) {
5183     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
5184         (_("Invalid atom size.")),
5185         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
5186             GST_FOURCC_ARGS (fourcc)));
5187     ret = GST_FLOW_EOS;
5188     goto beach;
5189   }
5190
5191   switch (fourcc) {
5192     case FOURCC_moof:
5193       /* record for later parsing when needed */
5194       if (!qtdemux->moof_offset) {
5195         qtdemux->moof_offset = qtdemux->offset;
5196       }
5197       if (qtdemux_pull_mfro_mfra (qtdemux)) {
5198         /* FIXME */
5199       } else {
5200         qtdemux->offset += length;      /* skip moof and keep going */
5201       }
5202       if (qtdemux->got_moov) {
5203         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
5204         ret = GST_FLOW_EOS;
5205         goto beach;
5206       }
5207       break;
5208     case FOURCC_mdat:
5209     case FOURCC_free:
5210     case FOURCC_skip:
5211     case FOURCC_wide:
5212     case FOURCC_PICT:
5213     case FOURCC_pnot:
5214     {
5215       GST_LOG_OBJECT (qtdemux,
5216           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
5217           GST_FOURCC_ARGS (fourcc), cur_offset);
5218       qtdemux->offset = add_offset (qtdemux->offset, length);
5219       break;
5220     }
5221     case FOURCC_moov:
5222     {
5223       GstBuffer *moov = NULL;
5224
5225       if (qtdemux->got_moov) {
5226         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
5227         qtdemux->offset = add_offset (qtdemux->offset, length);
5228         goto beach;
5229       }
5230
5231       if (length == G_MAXUINT64) {
5232         /* Read until the end */
5233         gint64 duration;
5234         if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES,
5235                 &duration)) {
5236           GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5237               (_("Cannot query file size")),
5238               ("Duration query on sink pad failed"));
5239           ret = GST_FLOW_ERROR;
5240           goto beach;
5241         }
5242         if (G_UNLIKELY (cur_offset > duration)) {
5243           GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5244               (_("Cannot query file size")),
5245               ("Duration %" G_GINT64_FORMAT " < current offset %"
5246                   G_GUINT64_FORMAT, duration, cur_offset));
5247           ret = GST_FLOW_ERROR;
5248           goto beach;
5249         }
5250         length = duration - cur_offset;
5251         if (length > QTDEMUX_MAX_ATOM_SIZE) {
5252           GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5253               (_("Cannot demux file")),
5254               ("Moov atom size %" G_GINT64_FORMAT " > maximum %d", length,
5255                   QTDEMUX_MAX_ATOM_SIZE));
5256           ret = GST_FLOW_ERROR;
5257           goto beach;
5258         }
5259       }
5260
5261       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
5262       if (ret != GST_FLOW_OK)
5263         goto beach;
5264       gst_buffer_map (moov, &map, GST_MAP_READ);
5265
5266       if (length != map.size) {
5267         /* Some files have a 'moov' atom at the end of the file which contains
5268          * a terminal 'free' atom where the body of the atom is missing.
5269          * Check for, and permit, this special case.
5270          */
5271         if (map.size >= 8) {
5272           guint8 *final_data = map.data + (map.size - 8);
5273           guint32 final_length = QT_UINT32 (final_data);
5274           guint32 final_fourcc = QT_FOURCC (final_data + 4);
5275
5276           if (final_fourcc == FOURCC_free
5277               && map.size + final_length - 8 == length) {
5278             /* Ok, we've found that special case. Allocate a new buffer with
5279              * that free atom actually present. */
5280             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
5281             gst_buffer_fill (newmoov, 0, map.data, map.size);
5282             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
5283             gst_buffer_unmap (moov, &map);
5284             gst_buffer_unref (moov);
5285             moov = newmoov;
5286             gst_buffer_map (moov, &map, GST_MAP_READ);
5287           }
5288         }
5289       }
5290
5291       if (length != map.size) {
5292         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5293             (_("This file is incomplete and cannot be played.")),
5294             ("We got less than expected (received %" G_GSIZE_FORMAT
5295                 ", wanted %" G_GUINT64_FORMAT ", offset %" G_GUINT64_FORMAT ")",
5296                 map.size, length, cur_offset));
5297         gst_buffer_unmap (moov, &map);
5298         gst_buffer_unref (moov);
5299         ret = GST_FLOW_ERROR;
5300         goto beach;
5301       }
5302       qtdemux->offset += length;
5303
5304       qtdemux_parse_moov (qtdemux, map.data, length);
5305       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
5306
5307       qtdemux_parse_tree (qtdemux);
5308       if (qtdemux->moov_node_compressed) {
5309         g_node_destroy (qtdemux->moov_node_compressed);
5310         g_free (qtdemux->moov_node->data);
5311       }
5312       qtdemux->moov_node_compressed = NULL;
5313       g_node_destroy (qtdemux->moov_node);
5314       qtdemux->moov_node = NULL;
5315       gst_buffer_unmap (moov, &map);
5316       gst_buffer_unref (moov);
5317       qtdemux->got_moov = TRUE;
5318
5319       break;
5320     }
5321     case FOURCC_ftyp:
5322     {
5323       GstBuffer *ftyp = NULL;
5324
5325       /* extract major brand; might come in handy for ISO vs QT issues */
5326       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
5327       if (ret != GST_FLOW_OK)
5328         goto beach;
5329       qtdemux->offset += length;
5330       gst_buffer_map (ftyp, &map, GST_MAP_READ);
5331       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
5332       gst_buffer_unmap (ftyp, &map);
5333       gst_buffer_unref (ftyp);
5334       break;
5335     }
5336     case FOURCC_styp:
5337     {
5338       GstBuffer *styp = NULL;
5339
5340       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
5341       if (ret != GST_FLOW_OK)
5342         goto beach;
5343       qtdemux->offset += length;
5344       gst_buffer_map (styp, &map, GST_MAP_READ);
5345       qtdemux_parse_styp (qtdemux, map.data, map.size);
5346       gst_buffer_unmap (styp, &map);
5347       gst_buffer_unref (styp);
5348       break;
5349     }
5350     case FOURCC_uuid:
5351     {
5352       GstBuffer *uuid = NULL;
5353
5354       /* uuid are extension atoms */
5355       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
5356       if (ret != GST_FLOW_OK)
5357         goto beach;
5358       qtdemux->offset += length;
5359       gst_buffer_map (uuid, &map, GST_MAP_READ);
5360       qtdemux_parse_uuid (qtdemux, map.data, map.size);
5361       gst_buffer_unmap (uuid, &map);
5362       gst_buffer_unref (uuid);
5363       break;
5364     }
5365     case FOURCC_sidx:
5366     {
5367       GstBuffer *sidx = NULL;
5368       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
5369       if (ret != GST_FLOW_OK)
5370         goto beach;
5371       qtdemux->offset += length;
5372       gst_buffer_map (sidx, &map, GST_MAP_READ);
5373       qtdemux_parse_sidx (qtdemux, map.data, map.size);
5374       gst_buffer_unmap (sidx, &map);
5375       gst_buffer_unref (sidx);
5376       break;
5377     }
5378     case FOURCC_meta:
5379     {
5380       GstBuffer *meta = NULL;
5381       GNode *node, *child;
5382       GstByteReader child_data;
5383       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
5384       if (ret != GST_FLOW_OK)
5385         goto beach;
5386       qtdemux->offset += length;
5387       gst_buffer_map (meta, &map, GST_MAP_READ);
5388
5389       node = g_node_new (map.data);
5390
5391       qtdemux_parse_node (qtdemux, node, map.data, map.size);
5392
5393       /* Parse ONVIF Export File Format CorrectStartTime box if available */
5394       if ((child =
5395               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
5396                   &child_data))) {
5397         qtdemux_parse_cstb (qtdemux, &child_data);
5398       }
5399
5400       g_node_destroy (node);
5401
5402       gst_buffer_unmap (meta, &map);
5403       gst_buffer_unref (meta);
5404       break;
5405     }
5406     default:
5407     {
5408       GstBuffer *unknown = NULL;
5409
5410       GST_LOG_OBJECT (qtdemux,
5411           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
5412           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
5413           cur_offset);
5414       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
5415       if (ret != GST_FLOW_OK)
5416         goto beach;
5417       gst_buffer_map (unknown, &map, GST_MAP_READ);
5418       GST_MEMDUMP ("Unknown tag", map.data, map.size);
5419       gst_buffer_unmap (unknown, &map);
5420       gst_buffer_unref (unknown);
5421       qtdemux->offset += length;
5422       break;
5423     }
5424   }
5425
5426 beach:
5427   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
5428     /* digested all data, show what we have */
5429 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
5430     if (qtdemux->spherical_metadata)
5431       _send_spherical_metadata_msg_to_bus (qtdemux);
5432 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
5433     qtdemux_prepare_streams (qtdemux);
5434     QTDEMUX_EXPOSE_LOCK (qtdemux);
5435     ret = qtdemux_expose_streams (qtdemux);
5436     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
5437
5438     qtdemux->state = QTDEMUX_STATE_MOVIE;
5439     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
5440         qtdemux->state);
5441     return ret;
5442   }
5443   return ret;
5444 }
5445
5446 /* Seeks to the previous keyframe of the indexed stream and
5447  * aligns other streams with respect to the keyframe timestamp
5448  * of indexed stream. Only called in case of Reverse Playback
5449  */
5450 static GstFlowReturn
5451 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
5452 {
5453   guint32 seg_idx = 0, k_index = 0;
5454   guint32 ref_seg_idx, ref_k_index;
5455   GstClockTime k_pos = 0, last_stop = 0;
5456   QtDemuxSegment *seg = NULL;
5457   QtDemuxStream *ref_str = NULL;
5458   guint64 seg_media_start_mov;  /* segment media start time in mov format */
5459   guint64 target_ts;
5460   gint i;
5461
5462   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
5463    * and finally align all the other streams on that timestamp with their
5464    * respective keyframes */
5465   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
5466     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
5467
5468     /* No candidate yet, take the first stream */
5469     if (!ref_str) {
5470       ref_str = str;
5471       continue;
5472     }
5473
5474     /* So that stream has a segment, we prefer video streams */
5475     if (str->subtype == FOURCC_vide) {
5476       ref_str = str;
5477       break;
5478     }
5479   }
5480
5481   if (G_UNLIKELY (!ref_str)) {
5482     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
5483     goto eos;
5484   }
5485
5486   if (G_UNLIKELY (!ref_str->from_sample)) {
5487     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
5488     goto eos;
5489   }
5490
5491   /* So that stream has been playing from from_sample to to_sample. We will
5492    * get the timestamp of the previous sample and search for a keyframe before
5493    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
5494   if (ref_str->subtype == FOURCC_vide) {
5495     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
5496         ref_str->from_sample - 1, FALSE);
5497   } else {
5498     if (ref_str->from_sample >= 10)
5499       k_index = ref_str->from_sample - 10;
5500     else
5501       k_index = 0;
5502   }
5503
5504   target_ts =
5505       ref_str->samples[k_index].timestamp +
5506       ref_str->samples[k_index].pts_offset;
5507
5508   /* get current segment for that stream */
5509   seg = &ref_str->segments[ref_str->segment_index];
5510   /* Use segment start in original timescale for comparisons */
5511   seg_media_start_mov = seg->trak_media_start;
5512
5513   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
5514       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
5515       k_index, target_ts, seg_media_start_mov,
5516       GST_TIME_ARGS (seg->media_start));
5517
5518   /* Crawl back through segments to find the one containing this I frame */
5519   while (target_ts < seg_media_start_mov) {
5520     GST_DEBUG_OBJECT (qtdemux,
5521         "keyframe position (sample %u) is out of segment %u " " target %"
5522         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
5523         ref_str->segment_index, target_ts, seg_media_start_mov);
5524
5525     if (G_UNLIKELY (!ref_str->segment_index)) {
5526       /* Reached first segment, let's consider it's EOS */
5527       goto eos;
5528     }
5529     ref_str->segment_index--;
5530     seg = &ref_str->segments[ref_str->segment_index];
5531     /* Use segment start in original timescale for comparisons */
5532     seg_media_start_mov = seg->trak_media_start;
5533   }
5534   /* Calculate time position of the keyframe and where we should stop */
5535   k_pos =
5536       QTSTREAMTIME_TO_GSTTIME (ref_str,
5537       target_ts - seg->trak_media_start) + seg->time;
5538   last_stop =
5539       QTSTREAMTIME_TO_GSTTIME (ref_str,
5540       ref_str->samples[ref_str->from_sample].timestamp -
5541       seg->trak_media_start) + seg->time;
5542
5543   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
5544       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
5545       k_index, GST_TIME_ARGS (k_pos));
5546
5547   /* Set last_stop with the keyframe timestamp we pushed of that stream */
5548   qtdemux->segment.position = last_stop;
5549   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
5550       GST_TIME_ARGS (last_stop));
5551
5552   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
5553     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
5554     goto eos;
5555   }
5556
5557   ref_seg_idx = ref_str->segment_index;
5558   ref_k_index = k_index;
5559
5560   /* Align them all on this */
5561   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
5562     guint32 index = 0;
5563     GstClockTime seg_time = 0;
5564     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
5565
5566     /* aligning reference stream again might lead to backing up to yet another
5567      * keyframe (due to timestamp rounding issues),
5568      * potentially putting more load on downstream; so let's try to avoid */
5569     if (str == ref_str) {
5570       seg_idx = ref_seg_idx;
5571       seg = &str->segments[seg_idx];
5572       k_index = ref_k_index;
5573       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
5574           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
5575     } else {
5576       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
5577       GST_DEBUG_OBJECT (qtdemux,
5578           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
5579           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
5580
5581       /* get segment and time in the segment */
5582       seg = &str->segments[seg_idx];
5583       seg_time = k_pos - seg->time;
5584
5585       /* get the media time in the segment.
5586        * No adjustment for empty "filler" segments */
5587       if (seg->media_start != GST_CLOCK_TIME_NONE)
5588         seg_time += seg->media_start;
5589
5590       /* get the index of the sample with media time */
5591       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
5592       GST_DEBUG_OBJECT (qtdemux,
5593           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
5594           GST_TIME_ARGS (seg_time), index);
5595
5596       /* find previous keyframe */
5597       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
5598     }
5599
5600     /* Remember until where we want to go */
5601     if (str->from_sample == 0) {
5602       GST_LOG_OBJECT (qtdemux, "already at sample 0");
5603       str->to_sample = 0;
5604     } else {
5605       str->to_sample = str->from_sample - 1;
5606     }
5607     /* Define our time position */
5608     target_ts =
5609         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
5610     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
5611     if (seg->media_start != GST_CLOCK_TIME_NONE)
5612       str->time_position -= seg->media_start;
5613
5614     /* Now seek back in time */
5615     gst_qtdemux_move_stream (qtdemux, str, k_index);
5616     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
5617         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
5618         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
5619   }
5620
5621   return GST_FLOW_OK;
5622
5623 eos:
5624   return GST_FLOW_EOS;
5625 }
5626
5627 /*
5628  * Gets the current qt segment start, stop and position for the
5629  * given time offset. This is used in update_segment()
5630  */
5631 static void
5632 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5633     QtDemuxStream * stream, GstClockTime offset,
5634     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5635 {
5636   GstClockTime seg_time;
5637   GstClockTime start, stop, time;
5638   QtDemuxSegment *segment;
5639
5640   segment = &stream->segments[stream->segment_index];
5641
5642   /* get time in this segment */
5643   seg_time = (offset - segment->time) * segment->rate;
5644
5645   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5646       GST_TIME_ARGS (seg_time));
5647
5648   if (G_UNLIKELY (seg_time > segment->duration)) {
5649     GST_LOG_OBJECT (stream->pad,
5650         "seg_time > segment->duration %" GST_TIME_FORMAT,
5651         GST_TIME_ARGS (segment->duration));
5652     seg_time = segment->duration;
5653   }
5654
5655   /* qtdemux->segment.stop is in outside-time-realm, whereas
5656    * segment->media_stop is in track-time-realm.
5657    *
5658    * In order to compare the two, we need to bring segment.stop
5659    * into the track-time-realm
5660    *
5661    * FIXME - does this comment still hold? Don't see any conversion here */
5662
5663   stop = qtdemux->segment.stop;
5664   if (stop == GST_CLOCK_TIME_NONE)
5665     stop = qtdemux->segment.duration;
5666   if (stop == GST_CLOCK_TIME_NONE)
5667     stop = segment->media_stop;
5668   else
5669     stop =
5670         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5671
5672   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5673     start = segment->time + seg_time;
5674     time = offset;
5675     stop = start - seg_time + segment->duration;
5676   } else if (qtdemux->segment.rate >= 0) {
5677     start = MIN (segment->media_start + seg_time, stop);
5678     time = offset;
5679   } else {
5680     if (segment->media_start >= qtdemux->segment.start) {
5681       time = segment->time;
5682     } else {
5683       time = segment->time + (qtdemux->segment.start - segment->media_start);
5684     }
5685
5686     start = MAX (segment->media_start, qtdemux->segment.start);
5687     stop = MIN (segment->media_start + seg_time, stop);
5688   }
5689
5690   *_start = start;
5691   *_stop = stop;
5692   *_time = time;
5693 }
5694
5695 /*
5696  * Updates the qt segment used for the stream and pushes a new segment event
5697  * downstream on this stream's pad.
5698  */
5699 static gboolean
5700 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5701     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5702     GstClockTime * _stop)
5703 {
5704   QtDemuxSegment *segment;
5705   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5706   gdouble rate;
5707   GstEvent *event;
5708
5709   /* update the current segment */
5710   stream->segment_index = seg_idx;
5711
5712   /* get the segment */
5713   segment = &stream->segments[seg_idx];
5714
5715   if (G_UNLIKELY (offset < segment->time)) {
5716     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5717         GST_TIME_ARGS (segment->time));
5718     return FALSE;
5719   }
5720
5721   /* segment lies beyond total indicated duration */
5722   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5723           segment->time > qtdemux->segment.duration)) {
5724     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5725         " < segment->time %" GST_TIME_FORMAT,
5726         GST_TIME_ARGS (qtdemux->segment.duration),
5727         GST_TIME_ARGS (segment->time));
5728     return FALSE;
5729   }
5730
5731   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5732       &start, &stop, &time);
5733
5734   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5735       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5736       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5737
5738   /* combine global rate with that of the segment */
5739   rate = segment->rate * qtdemux->segment.rate;
5740
5741   /* Copy flags from main segment */
5742   stream->segment.flags = qtdemux->segment.flags;
5743
5744   /* update the segment values used for clipping */
5745   stream->segment.offset = qtdemux->segment.offset;
5746   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5747   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5748   stream->segment.rate = rate;
5749   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5750       stream->cslg_shift);
5751   if (stop != -1)
5752     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5753         stream->cslg_shift);
5754   else
5755     stream->segment.stop = stop;
5756   stream->segment.time = time;
5757   stream->segment.position = stream->segment.start;
5758
5759   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5760       &stream->segment);
5761
5762   /* now prepare and send the segment */
5763   if (stream->pad) {
5764     event = gst_event_new_segment (&stream->segment);
5765     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5766       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5767     }
5768     gst_pad_push_event (stream->pad, event);
5769     /* assume we can send more data now */
5770     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5771     /* clear to send tags on this pad now */
5772     gst_qtdemux_push_tags (qtdemux, stream);
5773   }
5774
5775   if (_start)
5776     *_start = start;
5777   if (_stop)
5778     *_stop = stop;
5779
5780   return TRUE;
5781 }
5782
5783 /* activate the given segment number @seg_idx of @stream at time @offset.
5784  * @offset is an absolute global position over all the segments.
5785  *
5786  * This will push out a NEWSEGMENT event with the right values and
5787  * position the stream index to the first decodable sample before
5788  * @offset.
5789  */
5790 static gboolean
5791 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5792     guint32 seg_idx, GstClockTime offset)
5793 {
5794   QtDemuxSegment *segment;
5795   guint32 index, kf_index;
5796   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5797
5798   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5799       seg_idx, GST_TIME_ARGS (offset));
5800
5801   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5802           &start, &stop))
5803     return FALSE;
5804
5805   segment = &stream->segments[stream->segment_index];
5806
5807   /* in the fragmented case, we pick a fragment that starts before our
5808    * desired position and rely on downstream to wait for a keyframe
5809    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5810    * tfra entries tells us which trun/sample the key unit is in, but we don't
5811    * make use of this additional information at the moment) */
5812   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5813     stream->to_sample = G_MAXUINT32;
5814     return TRUE;
5815   } else {
5816     /* well, it will be taken care of below */
5817     qtdemux->fragmented_seek_pending = FALSE;
5818     /* FIXME ideally the do_fragmented_seek can be done right here,
5819      * rather than at loop level
5820      * (which might even allow handling edit lists in a fragmented file) */
5821   }
5822
5823   /* We don't need to look for a sample in push-based */
5824   if (!qtdemux->pullbased)
5825     return TRUE;
5826
5827   /* and move to the keyframe before the indicated media time of the
5828    * segment */
5829   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5830     if (qtdemux->segment.rate >= 0) {
5831       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5832       stream->to_sample = G_MAXUINT32;
5833       GST_DEBUG_OBJECT (stream->pad,
5834           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5835           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5836           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5837     } else {
5838       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5839       stream->to_sample = index;
5840       GST_DEBUG_OBJECT (stream->pad,
5841           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5842           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5843           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5844     }
5845   } else {
5846     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5847         "this is an empty segment");
5848     return TRUE;
5849   }
5850
5851   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5852    * encountered an error and printed a message so we return appropriately */
5853   if (index == -1)
5854     return FALSE;
5855
5856   /* we're at the right spot */
5857   if (index == stream->sample_index) {
5858     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5859     return TRUE;
5860   }
5861
5862   /* find keyframe of the target index */
5863   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5864
5865   /* go back two frames to provide lead-in for non-raw audio decoders */
5866   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5867     guint32 lead_in = 2;
5868     guint32 old_index = kf_index;
5869     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5870
5871     if (gst_structure_has_name (s, "audio/mpeg")) {
5872       gint mpegversion;
5873       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5874           && mpegversion == 1) {
5875         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5876         lead_in = 30;
5877       }
5878     }
5879
5880     kf_index = MAX (kf_index, lead_in) - lead_in;
5881     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5882       GST_DEBUG_OBJECT (stream->pad,
5883           "Moving backwards %u frames to ensure sufficient sound lead-in",
5884           old_index - kf_index);
5885     } else {
5886       kf_index = old_index;
5887     }
5888   }
5889
5890   /* if we move forwards, we don't have to go back to the previous
5891    * keyframe since we already sent that. We can also just jump to
5892    * the keyframe right before the target index if there is one. */
5893   if (index > stream->sample_index) {
5894     /* moving forwards check if we move past a keyframe */
5895     if (kf_index > stream->sample_index) {
5896       GST_DEBUG_OBJECT (stream->pad,
5897           "moving forwards to keyframe at %u "
5898           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5899           kf_index,
5900           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5901           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5902       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5903     } else {
5904       GST_DEBUG_OBJECT (stream->pad,
5905           "moving forwards, keyframe at %u "
5906           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5907           kf_index,
5908           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5909           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5910     }
5911   } else {
5912     GST_DEBUG_OBJECT (stream->pad,
5913         "moving backwards to %sframe at %u "
5914         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5915         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5916         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5917         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5918     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5919   }
5920
5921   return TRUE;
5922 }
5923
5924 /* prepare to get the current sample of @stream, getting essential values.
5925  *
5926  * This function will also prepare and send the segment when needed.
5927  *
5928  * Return FALSE if the stream is EOS.
5929  *
5930  * PULL-BASED
5931  */
5932 static gboolean
5933 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5934     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5935     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5936     gboolean * keyframe)
5937 {
5938   QtDemuxSample *sample;
5939   GstClockTime time_position;
5940   guint32 seg_idx;
5941
5942   g_return_val_if_fail (stream != NULL, FALSE);
5943
5944   time_position = stream->time_position;
5945   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5946     goto eos;
5947
5948   seg_idx = stream->segment_index;
5949   if (G_UNLIKELY (seg_idx == -1)) {
5950     /* find segment corresponding to time_position if we are looking
5951      * for a segment. */
5952     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5953   }
5954
5955   /* different segment, activate it, sample_index will be set. */
5956   if (G_UNLIKELY (stream->segment_index != seg_idx))
5957     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5958
5959   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5960               segments[stream->segment_index]))) {
5961     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5962
5963     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5964         " prepare empty sample");
5965
5966     *empty = TRUE;
5967     *pts = *dts = time_position;
5968     *duration = seg->duration - (time_position - seg->time);
5969
5970     return TRUE;
5971   }
5972
5973   *empty = FALSE;
5974
5975   if (stream->sample_index == -1)
5976     stream->sample_index = 0;
5977
5978   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5979       stream->sample_index, stream->n_samples);
5980
5981   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5982     if (!qtdemux->fragmented)
5983       goto eos;
5984
5985     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5986     do {
5987       GstFlowReturn flow;
5988
5989       GST_OBJECT_LOCK (qtdemux);
5990       flow = qtdemux_add_fragmented_samples (qtdemux);
5991       GST_OBJECT_UNLOCK (qtdemux);
5992
5993       if (flow != GST_FLOW_OK)
5994         goto eos;
5995     }
5996     while (stream->sample_index >= stream->n_samples);
5997   }
5998
5999   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6000     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
6001         stream->sample_index);
6002     return FALSE;
6003   }
6004
6005   /* now get the info for the sample we're at */
6006   sample = &stream->samples[stream->sample_index];
6007
6008   *dts = QTSAMPLE_DTS (stream, sample);
6009   *pts = QTSAMPLE_PTS (stream, sample);
6010   *offset = sample->offset;
6011   *size = sample->size;
6012   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
6013   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6014
6015   return TRUE;
6016
6017   /* special cases */
6018 eos:
6019   {
6020     stream->time_position = GST_CLOCK_TIME_NONE;
6021     return FALSE;
6022   }
6023 }
6024
6025 /* move to the next sample in @stream.
6026  *
6027  * Moves to the next segment when needed.
6028  */
6029 static void
6030 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
6031 {
6032   QtDemuxSample *sample;
6033   QtDemuxSegment *segment;
6034
6035   /* get current segment */
6036   segment = &stream->segments[stream->segment_index];
6037
6038   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
6039     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
6040     goto next_segment;
6041   }
6042
6043   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
6044     /* Mark the stream as EOS */
6045     GST_DEBUG_OBJECT (qtdemux,
6046         "reached max allowed sample %u, mark EOS", stream->to_sample);
6047     stream->time_position = GST_CLOCK_TIME_NONE;
6048     return;
6049   }
6050
6051   /* move to next sample */
6052   stream->sample_index++;
6053   stream->offset_in_sample = 0;
6054
6055   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
6056       stream->n_samples);
6057
6058   /* reached the last sample, we need the next segment */
6059   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
6060     goto next_segment;
6061
6062   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6063     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
6064         stream->sample_index);
6065     return;
6066   }
6067
6068   /* get next sample */
6069   sample = &stream->samples[stream->sample_index];
6070
6071   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
6072       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
6073       GST_TIME_ARGS (segment->media_stop));
6074
6075   /* see if we are past the segment */
6076   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
6077     goto next_segment;
6078
6079   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
6080     /* inside the segment, update time_position, looks very familiar to
6081      * GStreamer segments, doesn't it? */
6082     stream->time_position =
6083         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
6084   } else {
6085     /* not yet in segment, time does not yet increment. This means
6086      * that we are still prerolling keyframes to the decoder so it can
6087      * decode the first sample of the segment. */
6088     stream->time_position = segment->time;
6089   }
6090   return;
6091
6092   /* move to the next segment */
6093 next_segment:
6094   {
6095     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
6096
6097     if (stream->segment_index == stream->n_segments - 1) {
6098       /* are we at the end of the last segment, we're EOS */
6099       stream->time_position = GST_CLOCK_TIME_NONE;
6100     } else {
6101       /* else we're only at the end of the current segment */
6102       stream->time_position = segment->stop_time;
6103     }
6104     /* make sure we select a new segment */
6105
6106     /* accumulate previous segments */
6107     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
6108       stream->accumulated_base +=
6109           (stream->segment.stop -
6110           stream->segment.start) / ABS (stream->segment.rate);
6111
6112     stream->segment_index = -1;
6113   }
6114 }
6115
6116 static void
6117 gst_qtdemux_sync_streams (GstQTDemux * demux)
6118 {
6119   gint i;
6120
6121   if (QTDEMUX_N_STREAMS (demux) <= 1)
6122     return;
6123
6124   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6125     QtDemuxStream *stream;
6126     GstClockTime end_time;
6127
6128     stream = QTDEMUX_NTH_STREAM (demux, i);
6129
6130     if (!stream->pad)
6131       continue;
6132
6133     /* TODO advance time on subtitle streams here, if any some day */
6134
6135     /* some clips/trailers may have unbalanced streams at the end,
6136      * so send EOS on shorter stream to prevent stalling others */
6137
6138     /* do not mess with EOS if SEGMENT seeking */
6139     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
6140       continue;
6141
6142     if (demux->pullbased) {
6143       /* loop mode is sample time based */
6144       if (!STREAM_IS_EOS (stream))
6145         continue;
6146     } else {
6147       /* push mode is byte position based */
6148       if (stream->n_samples &&
6149           stream->samples[stream->n_samples - 1].offset >= demux->offset)
6150         continue;
6151     }
6152
6153     if (stream->sent_eos)
6154       continue;
6155
6156     /* only act if some gap */
6157     end_time = stream->segments[stream->n_segments - 1].stop_time;
6158     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
6159         ", stream end: %" GST_TIME_FORMAT,
6160         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
6161     if (GST_CLOCK_TIME_IS_VALID (end_time)
6162         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
6163       GstEvent *event;
6164
6165       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
6166           GST_PAD_NAME (stream->pad));
6167       stream->sent_eos = TRUE;
6168       event = gst_event_new_eos ();
6169       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6170         gst_event_set_seqnum (event, demux->segment_seqnum);
6171       gst_pad_push_event (stream->pad, event);
6172     }
6173   }
6174 }
6175
6176 /* EOS and NOT_LINKED need to be combined. This means that we return:
6177  *
6178  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
6179  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
6180  */
6181 static GstFlowReturn
6182 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
6183     GstFlowReturn ret)
6184 {
6185   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
6186
6187   if (stream->pad)
6188     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
6189         ret);
6190   else
6191     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
6192
6193   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
6194   return ret;
6195 }
6196
6197 /* the input buffer metadata must be writable. Returns NULL when the buffer is
6198  * completely clipped
6199  *
6200  * Should be used only with raw buffers */
6201 static GstBuffer *
6202 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6203     GstBuffer * buf)
6204 {
6205   guint64 start, stop, cstart, cstop, diff;
6206   GstClockTime pts, duration;
6207   gsize size, osize;
6208   gint num_rate, denom_rate;
6209   gint frame_size;
6210   gboolean clip_data;
6211   guint offset;
6212
6213   osize = size = gst_buffer_get_size (buf);
6214   offset = 0;
6215
6216   /* depending on the type, setup the clip parameters */
6217   if (stream->subtype == FOURCC_soun) {
6218     frame_size = CUR_STREAM (stream)->bytes_per_frame;
6219     num_rate = GST_SECOND;
6220     denom_rate = (gint) CUR_STREAM (stream)->rate;
6221     clip_data = TRUE;
6222   } else if (stream->subtype == FOURCC_vide) {
6223     frame_size = size;
6224     num_rate = CUR_STREAM (stream)->fps_n;
6225     denom_rate = CUR_STREAM (stream)->fps_d;
6226     clip_data = FALSE;
6227   } else
6228     goto wrong_type;
6229
6230   if (frame_size <= 0)
6231     goto bad_frame_size;
6232
6233   /* we can only clip if we have a valid pts */
6234   pts = GST_BUFFER_PTS (buf);
6235   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
6236     goto no_pts;
6237
6238   duration = GST_BUFFER_DURATION (buf);
6239
6240   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
6241     duration =
6242         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
6243   }
6244
6245   start = pts;
6246   stop = start + duration;
6247
6248   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
6249               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
6250     goto clipped;
6251
6252   /* see if some clipping happened */
6253   diff = cstart - start;
6254   if (diff > 0) {
6255     pts += diff;
6256     duration -= diff;
6257
6258     if (clip_data) {
6259       /* bring clipped time to samples and to bytes */
6260       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
6261       diff *= frame_size;
6262
6263       GST_DEBUG_OBJECT (qtdemux,
6264           "clipping start to %" GST_TIME_FORMAT " %"
6265           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
6266
6267       offset = diff;
6268       size -= diff;
6269     }
6270   }
6271   diff = stop - cstop;
6272   if (diff > 0) {
6273     duration -= diff;
6274
6275     if (clip_data) {
6276       /* bring clipped time to samples and then to bytes */
6277       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
6278       diff *= frame_size;
6279       GST_DEBUG_OBJECT (qtdemux,
6280           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
6281           " bytes", GST_TIME_ARGS (cstop), diff);
6282       size -= diff;
6283     }
6284   }
6285
6286   if (offset != 0 || size != osize)
6287     gst_buffer_resize (buf, offset, size);
6288
6289   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
6290   GST_BUFFER_PTS (buf) = pts;
6291   GST_BUFFER_DURATION (buf) = duration;
6292
6293   return buf;
6294
6295   /* dropped buffer */
6296 wrong_type:
6297   {
6298     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
6299     return buf;
6300   }
6301 bad_frame_size:
6302   {
6303     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
6304     return buf;
6305   }
6306 no_pts:
6307   {
6308     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
6309     return buf;
6310   }
6311 clipped:
6312   {
6313     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
6314     gst_buffer_unref (buf);
6315     return NULL;
6316   }
6317 }
6318
6319 static GstBuffer *
6320 gst_qtdemux_align_buffer (GstQTDemux * demux,
6321     GstBuffer * buffer, gsize alignment)
6322 {
6323   GstMapInfo map;
6324
6325   gst_buffer_map (buffer, &map, GST_MAP_READ);
6326
6327   if (map.size < sizeof (guintptr)) {
6328     gst_buffer_unmap (buffer, &map);
6329     return buffer;
6330   }
6331
6332   if (((guintptr) map.data) & (alignment - 1)) {
6333     GstBuffer *new_buffer;
6334     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
6335
6336     new_buffer = gst_buffer_new_allocate (NULL,
6337         gst_buffer_get_size (buffer), &params);
6338
6339     /* Copy data "by hand", so ensure alignment is kept: */
6340     gst_buffer_fill (new_buffer, 0, map.data, map.size);
6341
6342     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
6343     GST_DEBUG_OBJECT (demux,
6344         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
6345         alignment);
6346
6347     gst_buffer_unmap (buffer, &map);
6348     gst_buffer_unref (buffer);
6349
6350     return new_buffer;
6351   }
6352
6353   gst_buffer_unmap (buffer, &map);
6354   return buffer;
6355 }
6356
6357 static guint8 *
6358 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
6359     gsize * res)
6360 {
6361   guint8 *storage;
6362   gsize i;
6363
6364   /* We are converting from pairs to triplets */
6365   *res = ccpair_size / 2 * 3;
6366   storage = g_malloc (*res);
6367   for (i = 0; i * 2 < ccpair_size; i += 1) {
6368     /* FIXME: Use line offset 0 as we simply can't know here */
6369     if (field == 1)
6370       storage[i * 3] = 0x80 | 0x00;
6371     else
6372       storage[i * 3] = 0x00 | 0x00;
6373     storage[i * 3 + 1] = ccpair[i * 2];
6374     storage[i * 3 + 2] = ccpair[i * 2 + 1];
6375   }
6376
6377   return storage;
6378 }
6379
6380 static guint8 *
6381 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
6382     gsize * cclen)
6383 {
6384   guint8 *res = NULL;
6385   guint32 atom_length, fourcc;
6386   QtDemuxStreamStsdEntry *stsd_entry;
6387
6388   GST_MEMDUMP ("caption atom", data, size);
6389
6390   /* There might be multiple atoms */
6391
6392   *cclen = 0;
6393   if (size < 8)
6394     goto invalid_cdat;
6395   atom_length = QT_UINT32 (data);
6396   fourcc = QT_FOURCC (data + 4);
6397   if (G_UNLIKELY (atom_length > size || atom_length == 8))
6398     goto invalid_cdat;
6399
6400   GST_DEBUG_OBJECT (stream->pad, "here");
6401
6402   /* Check if we have something compatible */
6403   stsd_entry = CUR_STREAM (stream);
6404   switch (stsd_entry->fourcc) {
6405     case FOURCC_c608:{
6406       guint8 *cdat = NULL, *cdt2 = NULL;
6407       gsize cdat_size = 0, cdt2_size = 0;
6408       /* Should be cdat or cdt2 */
6409       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
6410         GST_WARNING_OBJECT (stream->pad,
6411             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
6412             GST_FOURCC_ARGS (fourcc));
6413         goto invalid_cdat;
6414       }
6415
6416       /* Convert to S334-1 Annex A byte triplet */
6417       if (fourcc == FOURCC_cdat)
6418         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
6419       else
6420         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
6421       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
6422           size, atom_length);
6423
6424       /* Check for another atom ? */
6425       if (size > atom_length + 8) {
6426         guint32 new_atom_length = QT_UINT32 (data + atom_length);
6427         if (size >= atom_length + new_atom_length) {
6428           fourcc = QT_FOURCC (data + atom_length + 4);
6429           if (fourcc == FOURCC_cdat) {
6430             if (cdat == NULL)
6431               cdat =
6432                   convert_to_s334_1a (data + atom_length + 8,
6433                   new_atom_length - 8, 1, &cdat_size);
6434             else
6435               GST_WARNING_OBJECT (stream->pad,
6436                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
6437           } else {
6438             if (cdt2 == NULL)
6439               cdt2 =
6440                   convert_to_s334_1a (data + atom_length + 8,
6441                   new_atom_length - 8, 2, &cdt2_size);
6442             else
6443               GST_WARNING_OBJECT (stream->pad,
6444                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
6445           }
6446         }
6447       }
6448
6449       *cclen = cdat_size + cdt2_size;
6450       res = g_malloc (*cclen);
6451       if (cdat_size)
6452         memcpy (res, cdat, cdat_size);
6453       if (cdt2_size)
6454         memcpy (res + cdat_size, cdt2, cdt2_size);
6455       g_free (cdat);
6456       g_free (cdt2);
6457     }
6458       break;
6459     case FOURCC_c708:
6460       if (fourcc != FOURCC_ccdp) {
6461         GST_WARNING_OBJECT (stream->pad,
6462             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
6463             GST_FOURCC_ARGS (fourcc));
6464         goto invalid_cdat;
6465       }
6466       *cclen = atom_length - 8;
6467       res = g_memdup2 (data + 8, *cclen);
6468       break;
6469     default:
6470       /* Keep this here in case other closed caption formats are added */
6471       g_assert_not_reached ();
6472       break;
6473   }
6474
6475   GST_MEMDUMP ("Output", res, *cclen);
6476   return res;
6477
6478   /* Errors */
6479 invalid_cdat:
6480   GST_WARNING ("[cdat] atom is too small or invalid");
6481   return NULL;
6482 }
6483
6484 /* Handle Closed Caption sample buffers.
6485  * The input buffer metadata must be writable,
6486  * but time/duration etc not yet set and need not be preserved */
6487 static GstBuffer *
6488 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
6489     GstBuffer * buf)
6490 {
6491   GstBuffer *outbuf = NULL;
6492   GstMapInfo map;
6493   guint8 *cc;
6494   gsize cclen = 0;
6495
6496   gst_buffer_map (buf, &map, GST_MAP_READ);
6497
6498   /* empty buffer is sent to terminate previous subtitle */
6499   if (map.size <= 2) {
6500     gst_buffer_unmap (buf, &map);
6501     gst_buffer_unref (buf);
6502     return NULL;
6503   }
6504
6505   /* For closed caption, we need to extract the information from the
6506    * [cdat],[cdt2] or [ccdp] atom */
6507   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
6508   gst_buffer_unmap (buf, &map);
6509   if (cc) {
6510     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
6511     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6512   } else {
6513     /* Conversion failed or there's nothing */
6514   }
6515   gst_buffer_unref (buf);
6516
6517   return outbuf;
6518 }
6519
6520 /* DVD subpicture specific sample handling.
6521  * the input buffer metadata must be writable,
6522  * but time/duration etc not yet set and need not be preserved */
6523 static GstBuffer *
6524 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
6525     GstBuffer * buf)
6526 {
6527   /* send a one time dvd clut event */
6528   if (stream->pending_event && stream->pad)
6529     gst_pad_push_event (stream->pad, stream->pending_event);
6530   stream->pending_event = NULL;
6531
6532   /* empty buffer is sent to terminate previous subtitle */
6533   if (gst_buffer_get_size (buf) <= 2) {
6534     gst_buffer_unref (buf);
6535     return NULL;
6536   }
6537
6538   /* That's all the processing needed for subpictures */
6539   return buf;
6540 }
6541
6542 /* Timed text formats
6543  * the input buffer metadata must be writable,
6544  * but time/duration etc not yet set and need not be preserved */
6545 static GstBuffer *
6546 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
6547     GstBuffer * buf)
6548 {
6549   GstBuffer *outbuf = NULL;
6550   GstMapInfo map;
6551   guint nsize = 0;
6552   gchar *str;
6553
6554   /* not many cases for now */
6555   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
6556           stream->subtype != FOURCC_sbtl)) {
6557     return buf;
6558   }
6559
6560   gst_buffer_map (buf, &map, GST_MAP_READ);
6561
6562   /* empty buffer is sent to terminate previous subtitle */
6563   if (map.size <= 2) {
6564     gst_buffer_unmap (buf, &map);
6565     gst_buffer_unref (buf);
6566     return NULL;
6567   }
6568
6569   nsize = GST_READ_UINT16_BE (map.data);
6570   nsize = MIN (nsize, map.size - 2);
6571
6572   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
6573       nsize, map.size);
6574
6575   /* takes care of UTF-8 validation or UTF-16 recognition,
6576    * no other encoding expected */
6577   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
6578   gst_buffer_unmap (buf, &map);
6579
6580   if (str) {
6581     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
6582     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6583   } else {
6584     /* this should not really happen unless the subtitle is corrupted */
6585   }
6586   gst_buffer_unref (buf);
6587
6588   /* FIXME ? convert optional subsequent style info to markup */
6589
6590   return outbuf;
6591 }
6592
6593 /* WebVTT sample handling according to 14496-30 */
6594 static GstBuffer *
6595 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
6596     GstBuffer * buf)
6597 {
6598   GstBuffer *outbuf = NULL;
6599   GstMapInfo map;
6600
6601   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
6602     g_assert_not_reached ();    /* The buffer must be mappable */
6603   }
6604
6605   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
6606     GstEvent *gap = NULL;
6607     /* Push a gap event */
6608     stream->segment.position = GST_BUFFER_PTS (buf);
6609     gap =
6610         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
6611     gst_pad_push_event (stream->pad, gap);
6612
6613     if (GST_BUFFER_DURATION_IS_VALID (buf))
6614       stream->segment.position += GST_BUFFER_DURATION (buf);
6615   } else {
6616     outbuf =
6617         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
6618         GST_BUFFER_DURATION (buf), map.data, map.size);
6619     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6620   }
6621
6622   gst_buffer_unmap (buf, &map);
6623   gst_buffer_unref (buf);
6624
6625   return outbuf;
6626 }
6627
6628 static GstFlowReturn
6629 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6630     GstBuffer * buf)
6631 {
6632   GstFlowReturn ret = GST_FLOW_OK;
6633   GstClockTime pts, duration;
6634
6635   if (stream->need_clip)
6636     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6637
6638   if (G_UNLIKELY (buf == NULL))
6639     goto exit;
6640
6641   if (G_UNLIKELY (stream->discont)) {
6642     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6643     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6644     stream->discont = FALSE;
6645   } else {
6646     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6647   }
6648
6649   GST_LOG_OBJECT (qtdemux,
6650       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6651       ", duration %" GST_TIME_FORMAT " on pad %s",
6652       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6653       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6654       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6655
6656   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6657     GstStructure *crypto_info;
6658     QtDemuxAavdEncryptionInfo *info =
6659         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6660
6661     crypto_info = gst_structure_copy (info->default_properties);
6662     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6663       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6664   }
6665
6666   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6667           || stream->protection_scheme_type == FOURCC_cbcs)) {
6668     GstStructure *crypto_info;
6669     QtDemuxCencSampleSetInfo *info =
6670         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6671     gint index;
6672     GstEvent *event;
6673
6674     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6675       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6676           GST_PTR_FORMAT, event);
6677       gst_pad_push_event (stream->pad, event);
6678     }
6679
6680     if (info->crypto_info == NULL) {
6681       if (stream->protection_scheme_type == FOURCC_cbcs) {
6682         if (CUR_STREAM (stream)->fourcc == FOURCC_enca ||
6683             CUR_STREAM (stream)->fourcc == FOURCC_encs ||
6684             CUR_STREAM (stream)->fourcc == FOURCC_enct ||
6685             CUR_STREAM (stream)->fourcc == FOURCC_encv) {
6686           crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6687           if (!crypto_info
6688               || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6689             GST_ERROR_OBJECT (qtdemux,
6690                 "failed to attach cbcs metadata to buffer");
6691             qtdemux_gst_structure_free (crypto_info);
6692           } else {
6693             GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6694           }
6695         } else {
6696           GST_TRACE_OBJECT (qtdemux,
6697               "cbcs stream is not encrypted yet, not adding protection metadata");
6698         }
6699       } else {
6700         GST_DEBUG_OBJECT (qtdemux,
6701             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6702       }
6703     } else {
6704       /* The end of the crypto_info array matches our n_samples position,
6705        * so count backward from there */
6706       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6707       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6708         /* steal structure from array */
6709         crypto_info = g_ptr_array_index (info->crypto_info, index);
6710         g_ptr_array_index (info->crypto_info, index) = NULL;
6711         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6712             info->crypto_info->len);
6713         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6714           GST_ERROR_OBJECT (qtdemux,
6715               "failed to attach cenc metadata to buffer");
6716       } else {
6717         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6718             index, stream->sample_index);
6719       }
6720     }
6721   }
6722
6723   if (stream->alignment > 1)
6724     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6725
6726   pts = GST_BUFFER_PTS (buf);
6727   duration = GST_BUFFER_DURATION (buf);
6728
6729   ret = gst_pad_push (stream->pad, buf);
6730
6731   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6732     /* mark position in stream, we'll need this to know when to send GAP event */
6733     stream->segment.position = pts + duration;
6734   }
6735
6736 exit:
6737
6738   return ret;
6739 }
6740
6741 static GstFlowReturn
6742 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6743     GstBuffer * buf)
6744 {
6745   GstFlowReturn ret = GST_FLOW_OK;
6746
6747   if (stream->subtype == FOURCC_clcp
6748       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6749     GstMapInfo map;
6750     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6751     guint n_triplets, i;
6752     guint field1_off = 0, field2_off = 0;
6753
6754     /* We have to split CEA608 buffers so that each outgoing buffer contains
6755      * one byte pair per field according to the framerate of the video track.
6756      *
6757      * If there is only a single byte pair per field we don't have to do
6758      * anything
6759      */
6760
6761     gst_buffer_map (buf, &map, GST_MAP_READ);
6762
6763     n_triplets = map.size / 3;
6764     for (i = 0; i < n_triplets; i++) {
6765       if (map.data[3 * i] & 0x80)
6766         n_field1++;
6767       else
6768         n_field2++;
6769     }
6770
6771     g_assert (n_field1 || n_field2);
6772
6773     /* If there's more than 1 frame we have to split, otherwise we can just
6774      * pass through */
6775     if (n_field1 > 1 || n_field2 > 1) {
6776       n_output_buffers =
6777           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6778           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6779
6780       for (i = 0; i < n_output_buffers; i++) {
6781         GstBuffer *outbuf =
6782             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6783         GstMapInfo outmap;
6784         guint8 *outptr;
6785
6786         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6787         outptr = outmap.data;
6788
6789         if (n_field1) {
6790           gboolean found = FALSE;
6791
6792           while (map.data + field1_off < map.data + map.size) {
6793             if (map.data[field1_off] & 0x80) {
6794               memcpy (outptr, &map.data[field1_off], 3);
6795               field1_off += 3;
6796               found = TRUE;
6797               break;
6798             }
6799             field1_off += 3;
6800           }
6801
6802           if (!found) {
6803             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6804
6805             memcpy (outptr, empty, 3);
6806           }
6807
6808           outptr += 3;
6809         }
6810
6811         if (n_field2) {
6812           gboolean found = FALSE;
6813
6814           while (map.data + field2_off < map.data + map.size) {
6815             if ((map.data[field2_off] & 0x80) == 0) {
6816               memcpy (outptr, &map.data[field2_off], 3);
6817               field2_off += 3;
6818               found = TRUE;
6819               break;
6820             }
6821             field2_off += 3;
6822           }
6823
6824           if (!found) {
6825             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6826
6827             memcpy (outptr, empty, 3);
6828           }
6829
6830           outptr += 3;
6831         }
6832
6833         gst_buffer_unmap (outbuf, &outmap);
6834
6835         GST_BUFFER_PTS (outbuf) =
6836             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6837             GST_SECOND * CUR_STREAM (stream)->fps_d,
6838             CUR_STREAM (stream)->fps_n);
6839         GST_BUFFER_DURATION (outbuf) =
6840             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6841             CUR_STREAM (stream)->fps_n);
6842         GST_BUFFER_OFFSET (outbuf) = -1;
6843         GST_BUFFER_OFFSET_END (outbuf) = -1;
6844
6845         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6846
6847         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6848           break;
6849       }
6850       gst_buffer_unmap (buf, &map);
6851       gst_buffer_unref (buf);
6852     } else {
6853       gst_buffer_unmap (buf, &map);
6854       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6855     }
6856   } else {
6857     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6858   }
6859
6860   return ret;
6861 }
6862
6863 /* Sets a buffer's attributes properly and pushes it downstream.
6864  * Also checks for additional actions and custom processing that may
6865  * need to be done first.
6866  */
6867 static GstFlowReturn
6868 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6869     QtDemuxStream * stream, GstBuffer * buf,
6870     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6871     gboolean keyframe, GstClockTime position, guint64 byte_position)
6872 {
6873   GstFlowReturn ret = GST_FLOW_OK;
6874
6875   /* offset the timestamps according to the edit list */
6876
6877   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6878     gchar *url;
6879     GstMapInfo map;
6880
6881     gst_buffer_map (buf, &map, GST_MAP_READ);
6882     url = g_strndup ((gchar *) map.data, map.size);
6883     gst_buffer_unmap (buf, &map);
6884     if (url != NULL && strlen (url) != 0) {
6885       /* we have RTSP redirect now */
6886       g_free (qtdemux->redirect_location);
6887       qtdemux->redirect_location = g_strdup (url);
6888       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6889           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6890               gst_structure_new ("redirect",
6891                   "new-location", G_TYPE_STRING, url, NULL)));
6892     } else {
6893       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6894           "posting");
6895     }
6896     g_free (url);
6897   }
6898
6899   /* position reporting */
6900   if (qtdemux->segment.rate >= 0) {
6901     qtdemux->segment.position = position;
6902     gst_qtdemux_sync_streams (qtdemux);
6903   }
6904
6905   if (G_UNLIKELY (!stream->pad)) {
6906     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6907     gst_buffer_unref (buf);
6908     goto exit;
6909   }
6910
6911   /* send out pending buffers */
6912   while (stream->buffers) {
6913     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6914
6915     if (G_UNLIKELY (stream->discont)) {
6916       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6917       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6918       stream->discont = FALSE;
6919     } else {
6920       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6921     }
6922
6923     if (stream->alignment > 1)
6924       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6925     gst_pad_push (stream->pad, buffer);
6926
6927     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6928   }
6929
6930   /* we're going to modify the metadata */
6931   buf = gst_buffer_make_writable (buf);
6932
6933   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6934     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6935     GstCaps *caps = gst_static_caps_get (&unix_caps);
6936     gst_buffer_add_reference_timestamp_meta (buf, caps,
6937         pts + qtdemux->start_utc_time - stream->cslg_shift,
6938         GST_CLOCK_TIME_NONE);
6939     gst_caps_unref (caps);
6940   }
6941
6942   GST_BUFFER_DTS (buf) = dts;
6943   GST_BUFFER_PTS (buf) = pts;
6944   GST_BUFFER_DURATION (buf) = duration;
6945   GST_BUFFER_OFFSET (buf) = -1;
6946   GST_BUFFER_OFFSET_END (buf) = -1;
6947
6948   if (G_UNLIKELY (stream->process_func))
6949     buf = stream->process_func (qtdemux, stream, buf);
6950
6951   if (!buf) {
6952     goto exit;
6953   }
6954
6955   if (!keyframe) {
6956     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6957     stream->on_keyframe = FALSE;
6958   } else {
6959     stream->on_keyframe = TRUE;
6960   }
6961
6962   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6963     gst_buffer_append_memory (buf,
6964         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6965
6966   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6967     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6968   }
6969 #if 0
6970   if (G_UNLIKELY (qtdemux->element_index)) {
6971     GstClockTime stream_time;
6972
6973     stream_time =
6974         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6975         timestamp);
6976     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6977       GST_LOG_OBJECT (qtdemux,
6978           "adding association %" GST_TIME_FORMAT "-> %"
6979           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6980       gst_index_add_association (qtdemux->element_index,
6981           qtdemux->index_id,
6982           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6983           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6984           GST_FORMAT_BYTES, byte_position, NULL);
6985     }
6986   }
6987 #endif
6988
6989   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6990
6991 exit:
6992   return ret;
6993 }
6994
6995 static const QtDemuxRandomAccessEntry *
6996 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6997     GstClockTime pos, gboolean after)
6998 {
6999   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
7000   guint n_entries = stream->n_ra_entries;
7001   guint i;
7002
7003   /* we assume the table is sorted */
7004   for (i = 0; i < n_entries; ++i) {
7005     if (entries[i].ts > pos)
7006       break;
7007   }
7008
7009   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
7010    * probably okay to assume that the index lists the very first fragment */
7011   if (i == 0)
7012     return &entries[0];
7013
7014   if (after)
7015     return &entries[i];
7016   else
7017     return &entries[i - 1];
7018 }
7019
7020 static gboolean
7021 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
7022 {
7023   const QtDemuxRandomAccessEntry *best_entry = NULL;
7024   gint i;
7025
7026   GST_OBJECT_LOCK (qtdemux);
7027
7028   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
7029
7030   /* first see if we can determine where to go to using mfra,
7031    * before we start clearing things */
7032   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
7033     const QtDemuxRandomAccessEntry *entry;
7034     QtDemuxStream *stream;
7035     gboolean is_audio_or_video;
7036
7037     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
7038
7039     if (stream->ra_entries == NULL)
7040       continue;
7041
7042     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
7043       is_audio_or_video = TRUE;
7044     else
7045       is_audio_or_video = FALSE;
7046
7047     entry =
7048         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
7049         stream->time_position, !is_audio_or_video);
7050
7051     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
7052         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
7053
7054     stream->pending_seek = entry;
7055
7056     /* decide position to jump to just based on audio/video tracks, not subs */
7057     if (!is_audio_or_video)
7058       continue;
7059
7060     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
7061       best_entry = entry;
7062   }
7063
7064   /* no luck, will handle seek otherwise */
7065   if (best_entry == NULL) {
7066     GST_OBJECT_UNLOCK (qtdemux);
7067     return FALSE;
7068   }
7069
7070   /* ok, now we can prepare for processing as of located moof */
7071   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
7072     QtDemuxStream *stream;
7073
7074     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
7075
7076     g_free (stream->samples);
7077     stream->samples = NULL;
7078     stream->n_samples = 0;
7079     stream->stbl_index = -1;    /* no samples have yet been parsed */
7080     stream->sample_index = -1;
7081
7082     if (stream->protection_scheme_info) {
7083       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
7084       if (stream->protection_scheme_type == FOURCC_cenc
7085           || stream->protection_scheme_type == FOURCC_cbcs) {
7086         QtDemuxCencSampleSetInfo *info =
7087             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
7088         if (info->crypto_info) {
7089           g_ptr_array_free (info->crypto_info, TRUE);
7090           info->crypto_info = NULL;
7091         }
7092       }
7093     }
7094   }
7095
7096   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
7097       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
7098       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
7099       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
7100
7101   qtdemux->moof_offset = best_entry->moof_offset;
7102
7103   qtdemux_add_fragmented_samples (qtdemux);
7104
7105   GST_OBJECT_UNLOCK (qtdemux);
7106   return TRUE;
7107 }
7108
7109 static GstFlowReturn
7110 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
7111 {
7112   GstFlowReturn ret = GST_FLOW_OK;
7113   GstBuffer *buf = NULL;
7114   QtDemuxStream *stream, *target_stream = NULL;
7115   GstClockTime min_time;
7116   guint64 offset = 0;
7117   GstClockTime dts = GST_CLOCK_TIME_NONE;
7118   GstClockTime pts = GST_CLOCK_TIME_NONE;
7119   GstClockTime duration = 0;
7120   gboolean keyframe = FALSE;
7121   guint sample_size = 0;
7122   guint num_samples = 1;
7123   gboolean empty = 0;
7124   guint size;
7125   gint i;
7126
7127   if (qtdemux->fragmented_seek_pending) {
7128     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
7129     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
7130       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
7131       qtdemux->fragmented_seek_pending = FALSE;
7132     } else {
7133       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
7134     }
7135   }
7136
7137   /* Figure out the next stream sample to output, min_time is expressed in
7138    * global time and runs over the edit list segments. */
7139   min_time = G_MAXUINT64;
7140   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
7141     GstClockTime position;
7142
7143     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
7144     position = stream->time_position;
7145
7146     /* position of -1 is EOS */
7147     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
7148       min_time = position;
7149       target_stream = stream;
7150     }
7151   }
7152   /* all are EOS */
7153   if (G_UNLIKELY (target_stream == NULL)) {
7154     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
7155     goto eos;
7156   }
7157
7158   /* check for segment end */
7159   if (G_UNLIKELY (qtdemux->segment.stop != -1
7160           && qtdemux->segment.rate >= 0
7161           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
7162     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
7163     target_stream->time_position = GST_CLOCK_TIME_NONE;
7164     goto eos_stream;
7165   }
7166
7167   /* fetch info for the current sample of this stream */
7168   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
7169               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
7170     goto eos_stream;
7171
7172   /* Send catche-up GAP event for each other stream if required.
7173    * This logic will be applied only for positive rate */
7174   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
7175       qtdemux->segment.rate >= 0; i++) {
7176     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
7177
7178     if (stream == target_stream ||
7179         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
7180         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
7181       continue;
7182
7183     if (stream->pad) {
7184       GstClockTime gap_threshold;
7185       /* kind of running time with offset segment.base and segment.start */
7186       GstClockTime pseudo_target_time = target_stream->segment.base;
7187       GstClockTime pseudo_cur_time = stream->segment.base;
7188
7189       /* make sure positive offset, segment.position can be smallr than
7190        * segment.start for some reasons */
7191       if (target_stream->segment.position >= target_stream->segment.start) {
7192         pseudo_target_time +=
7193             (target_stream->segment.position - target_stream->segment.start);
7194       }
7195
7196       if (stream->segment.position >= stream->segment.start)
7197         pseudo_cur_time += (stream->segment.position - stream->segment.start);
7198
7199       /* Only send gap events on non-subtitle streams if lagging way behind. */
7200       if (stream->subtype == FOURCC_subp
7201           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
7202           stream->subtype == FOURCC_wvtt)
7203         gap_threshold = 1 * GST_SECOND;
7204       else
7205         gap_threshold = 3 * GST_SECOND;
7206
7207       /* send gap events until the stream catches up */
7208       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
7209       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
7210           pseudo_cur_time < (G_MAXUINT64 - gap_threshold) &&
7211           pseudo_cur_time + gap_threshold < pseudo_target_time) {
7212         GstEvent *gap =
7213             gst_event_new_gap (stream->segment.position, gap_threshold);
7214         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
7215
7216         gst_pad_push_event (stream->pad, gap);
7217         stream->segment.position += gap_threshold;
7218         pseudo_cur_time += gap_threshold;
7219       }
7220     }
7221   }
7222
7223   stream = target_stream;
7224
7225   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
7226   if (stream->new_caps) {
7227     gst_qtdemux_configure_stream (qtdemux, stream);
7228     qtdemux_do_allocation (stream, qtdemux);
7229   }
7230
7231   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
7232   if (G_UNLIKELY (qtdemux->segment.
7233           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
7234     if (stream->subtype == FOURCC_vide) {
7235       if (!keyframe) {
7236         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
7237             stream->track_id);
7238         goto next;
7239       } else if (qtdemux->trickmode_interval > 0) {
7240         GstClockTimeDiff interval;
7241
7242         if (qtdemux->segment.rate > 0)
7243           interval = stream->time_position - stream->last_keyframe_dts;
7244         else
7245           interval = stream->last_keyframe_dts - stream->time_position;
7246
7247         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
7248             && interval < qtdemux->trickmode_interval) {
7249           GST_LOG_OBJECT (qtdemux,
7250               "Skipping keyframe within interval on track-id %u",
7251               stream->track_id);
7252           goto next;
7253         } else {
7254           stream->last_keyframe_dts = stream->time_position;
7255         }
7256       }
7257     }
7258   }
7259
7260   GST_DEBUG_OBJECT (qtdemux,
7261       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
7262       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
7263       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
7264       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
7265       GST_TIME_ARGS (duration));
7266
7267   if (G_UNLIKELY (empty)) {
7268     /* empty segment, push a gap if there's a second or more
7269      * difference and move to the next one */
7270     if ((pts + duration - stream->segment.position) >= GST_SECOND)
7271       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
7272     stream->segment.position = pts + duration;
7273     goto next;
7274   }
7275
7276   /* hmm, empty sample, skip and move to next sample */
7277   if (G_UNLIKELY (sample_size <= 0))
7278     goto next;
7279
7280   /* last pushed sample was out of boundary, goto next sample */
7281   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
7282     goto next;
7283
7284   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
7285     GST_DEBUG_OBJECT (qtdemux,
7286         "size %d larger than stream max_buffer_size %d, trimming",
7287         sample_size, stream->max_buffer_size);
7288     size =
7289         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
7290   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
7291       && sample_size < stream->min_buffer_size) {
7292     guint start_sample_index = stream->sample_index;
7293     guint accumulated_size = sample_size;
7294     guint64 expected_next_offset = offset + sample_size;
7295
7296     GST_DEBUG_OBJECT (qtdemux,
7297         "size %d smaller than stream min_buffer_size %d, combining with the next",
7298         sample_size, stream->min_buffer_size);
7299
7300     while (stream->sample_index < stream->to_sample
7301         && stream->sample_index + 1 < stream->n_samples) {
7302       const QtDemuxSample *next_sample;
7303
7304       /* Increment temporarily */
7305       stream->sample_index++;
7306
7307       /* Failed to parse sample so let's go back to the previous one that was
7308        * still successful */
7309       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
7310         stream->sample_index--;
7311         break;
7312       }
7313
7314       next_sample = &stream->samples[stream->sample_index];
7315
7316       /* Not contiguous with the previous sample so let's go back to the
7317        * previous one that was still successful */
7318       if (next_sample->offset != expected_next_offset) {
7319         stream->sample_index--;
7320         break;
7321       }
7322
7323       accumulated_size += next_sample->size;
7324       expected_next_offset += next_sample->size;
7325       if (accumulated_size >= stream->min_buffer_size)
7326         break;
7327     }
7328
7329     num_samples = stream->sample_index + 1 - start_sample_index;
7330     stream->sample_index = start_sample_index;
7331     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
7332         num_samples, accumulated_size);
7333     size = accumulated_size;
7334   } else {
7335     size = sample_size;
7336   }
7337
7338   if (qtdemux->cenc_aux_info_offset > 0) {
7339     GstMapInfo map;
7340     GstByteReader br;
7341     GstBuffer *aux_info = NULL;
7342
7343     /* pull the data stored before the sample */
7344     ret =
7345         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
7346         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
7347     if (G_UNLIKELY (ret != GST_FLOW_OK))
7348       goto beach;
7349     gst_buffer_map (aux_info, &map, GST_MAP_READ);
7350     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
7351     gst_byte_reader_init (&br, map.data + 8, map.size);
7352     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
7353             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
7354       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
7355       gst_buffer_unmap (aux_info, &map);
7356       gst_buffer_unref (aux_info);
7357       ret = GST_FLOW_ERROR;
7358       goto beach;
7359     }
7360     gst_buffer_unmap (aux_info, &map);
7361     gst_buffer_unref (aux_info);
7362   }
7363
7364   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
7365       offset);
7366
7367   if (stream->use_allocator) {
7368     /* if we have a per-stream allocator, use it */
7369     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
7370   }
7371
7372   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
7373       size, &buf);
7374   if (G_UNLIKELY (ret != GST_FLOW_OK))
7375     goto beach;
7376
7377   /* Update for both splitting and combining of samples */
7378   if (size != sample_size) {
7379     pts += gst_util_uint64_scale_int (GST_SECOND,
7380         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
7381         stream->timescale);
7382     dts +=
7383         gst_util_uint64_scale_int (GST_SECOND,
7384         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
7385         stream->timescale);
7386     duration =
7387         gst_util_uint64_scale_int (GST_SECOND,
7388         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
7389   }
7390
7391   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
7392       dts, pts, duration, keyframe, min_time, offset);
7393
7394   if (size < sample_size) {
7395     QtDemuxSample *sample = &stream->samples[stream->sample_index];
7396     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
7397
7398     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
7399         sample->timestamp +
7400         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
7401     if (time_position >= segment->media_start) {
7402       /* inside the segment, update time_position, looks very familiar to
7403        * GStreamer segments, doesn't it? */
7404       stream->time_position = (time_position - segment->media_start) +
7405           segment->time;
7406     } else {
7407       /* not yet in segment, time does not yet increment. This means
7408        * that we are still prerolling keyframes to the decoder so it can
7409        * decode the first sample of the segment. */
7410       stream->time_position = segment->time;
7411     }
7412   } else if (size > sample_size) {
7413     /* Increase to the last sample we already pulled so that advancing
7414      * below brings us to the next sample we need to pull */
7415     stream->sample_index += num_samples - 1;
7416   }
7417
7418   /* combine flows */
7419   GST_OBJECT_LOCK (qtdemux);
7420   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
7421   GST_OBJECT_UNLOCK (qtdemux);
7422   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
7423    * we have no more data for the pad to push */
7424   if (ret == GST_FLOW_EOS)
7425     ret = GST_FLOW_OK;
7426
7427   stream->offset_in_sample += size;
7428   if (stream->offset_in_sample >= sample_size) {
7429     gst_qtdemux_advance_sample (qtdemux, stream);
7430   }
7431   goto beach;
7432
7433 next:
7434   gst_qtdemux_advance_sample (qtdemux, stream);
7435
7436 beach:
7437   return ret;
7438
7439   /* special cases */
7440 eos:
7441   {
7442     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
7443     ret = GST_FLOW_EOS;
7444     goto beach;
7445   }
7446 eos_stream:
7447   {
7448     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
7449     /* EOS will be raised if all are EOS */
7450     ret = GST_FLOW_OK;
7451     goto beach;
7452   }
7453 }
7454
7455 static void
7456 gst_qtdemux_loop (GstPad * pad)
7457 {
7458   GstQTDemux *qtdemux;
7459   guint64 cur_offset;
7460   GstFlowReturn ret;
7461
7462   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
7463
7464   cur_offset = qtdemux->offset;
7465   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
7466       cur_offset, qt_demux_state_string (qtdemux->state));
7467
7468   switch (qtdemux->state) {
7469     case QTDEMUX_STATE_INITIAL:
7470     case QTDEMUX_STATE_HEADER:
7471       ret = gst_qtdemux_loop_state_header (qtdemux);
7472       break;
7473     case QTDEMUX_STATE_MOVIE:
7474       ret = gst_qtdemux_loop_state_movie (qtdemux);
7475       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
7476         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
7477       }
7478       break;
7479     default:
7480       /* ouch */
7481       goto invalid_state;
7482   }
7483
7484   /* if something went wrong, pause */
7485   if (ret != GST_FLOW_OK)
7486     goto pause;
7487
7488 done:
7489   gst_object_unref (qtdemux);
7490   return;
7491
7492   /* ERRORS */
7493 invalid_state:
7494   {
7495     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
7496         (NULL), ("streaming stopped, invalid state"));
7497     gst_pad_pause_task (pad);
7498     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
7499     goto done;
7500   }
7501 pause:
7502   {
7503     const gchar *reason = gst_flow_get_name (ret);
7504
7505     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
7506
7507     gst_pad_pause_task (pad);
7508
7509     /* fatal errors need special actions */
7510     /* check EOS */
7511     if (ret == GST_FLOW_EOS) {
7512       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
7513         /* we have no streams, post an error */
7514         gst_qtdemux_post_no_playable_stream_error (qtdemux);
7515       }
7516       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
7517         gint64 stop;
7518
7519         if ((stop = qtdemux->segment.stop) == -1)
7520           stop = qtdemux->segment.duration;
7521
7522         if (qtdemux->segment.rate >= 0) {
7523           GstMessage *message;
7524           GstEvent *event;
7525
7526           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
7527           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
7528               GST_FORMAT_TIME, stop);
7529           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
7530           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
7531             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
7532             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
7533           }
7534           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
7535           gst_qtdemux_push_event (qtdemux, event);
7536         } else {
7537           GstMessage *message;
7538           GstEvent *event;
7539
7540           /*  For Reverse Playback */
7541           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
7542           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
7543               GST_FORMAT_TIME, qtdemux->segment.start);
7544           event = gst_event_new_segment_done (GST_FORMAT_TIME,
7545               qtdemux->segment.start);
7546           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
7547             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
7548             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
7549           }
7550           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
7551           gst_qtdemux_push_event (qtdemux, event);
7552         }
7553       } else {
7554         GstEvent *event;
7555
7556         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
7557         event = gst_event_new_eos ();
7558         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
7559           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
7560         gst_qtdemux_push_event (qtdemux, event);
7561       }
7562     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
7563       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
7564       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
7565     }
7566     goto done;
7567   }
7568 }
7569
7570 /*
7571  * has_next_entry
7572  *
7573  * Returns if there are samples to be played.
7574  */
7575 static gboolean
7576 has_next_entry (GstQTDemux * demux)
7577 {
7578   QtDemuxStream *stream;
7579   gint i;
7580
7581   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
7582
7583   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7584     stream = QTDEMUX_NTH_STREAM (demux, i);
7585
7586     if (stream->sample_index == -1) {
7587       stream->sample_index = 0;
7588       stream->offset_in_sample = 0;
7589     }
7590
7591     if (stream->sample_index >= stream->n_samples) {
7592       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7593       continue;
7594     }
7595     GST_DEBUG_OBJECT (demux, "Found a sample");
7596     return TRUE;
7597   }
7598
7599   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
7600   return FALSE;
7601 }
7602
7603 /*
7604  * next_entry_size
7605  *
7606  * Returns the size of the first entry at the current offset.
7607  * If -1, there are none (which means EOS or empty file).
7608  */
7609 static guint64
7610 next_entry_size (GstQTDemux * demux)
7611 {
7612   QtDemuxStream *stream, *target_stream = NULL;
7613   guint64 smalloffs = (guint64) - 1;
7614   QtDemuxSample *sample;
7615   gint i;
7616
7617   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
7618       demux->offset);
7619
7620   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7621     stream = QTDEMUX_NTH_STREAM (demux, i);
7622
7623     if (stream->sample_index == -1) {
7624       stream->sample_index = 0;
7625       stream->offset_in_sample = 0;
7626     }
7627
7628     if (stream->sample_index >= stream->n_samples) {
7629       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7630       continue;
7631     }
7632
7633     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7634       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7635           stream->sample_index);
7636       return -1;
7637     }
7638
7639     sample = &stream->samples[stream->sample_index];
7640
7641     GST_LOG_OBJECT (demux,
7642         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7643         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7644         stream->sample_index, sample->offset, sample->size);
7645
7646     if (((smalloffs == -1)
7647             || (sample->offset < smalloffs)) && (sample->size)) {
7648       smalloffs = sample->offset;
7649       target_stream = stream;
7650     }
7651   }
7652
7653   if (!target_stream)
7654     return -1;
7655
7656   GST_LOG_OBJECT (demux,
7657       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7658       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7659
7660   stream = target_stream;
7661   sample = &stream->samples[stream->sample_index];
7662
7663   if (sample->offset >= demux->offset) {
7664     demux->todrop = sample->offset - demux->offset;
7665     return sample->size + demux->todrop;
7666   }
7667
7668   GST_DEBUG_OBJECT (demux,
7669       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7670   return -1;
7671 }
7672
7673 static void
7674 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7675 {
7676   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7677
7678   gst_element_post_message (GST_ELEMENT_CAST (demux),
7679       gst_message_new_element (GST_OBJECT_CAST (demux),
7680           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7681 }
7682
7683 static gboolean
7684 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7685 {
7686   GstEvent *event;
7687   gboolean res = 0;
7688
7689   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7690
7691   event =
7692       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7693       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7694       GST_SEEK_TYPE_NONE, -1);
7695
7696   /* store seqnum to drop flush events, they don't need to reach downstream */
7697   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7698   res = gst_pad_push_event (demux->sinkpad, event);
7699   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7700
7701   return res;
7702 }
7703
7704 /* check for seekable upstream, above and beyond a mere query */
7705 static void
7706 gst_qtdemux_check_seekability (GstQTDemux * demux)
7707 {
7708   GstQuery *query;
7709   gboolean seekable = FALSE;
7710   gint64 start = -1, stop = -1;
7711
7712   if (demux->upstream_size)
7713     return;
7714
7715   if (demux->upstream_format_is_time)
7716     return;
7717
7718   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7719   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7720     GST_DEBUG_OBJECT (demux, "seeking query failed");
7721     goto done;
7722   }
7723
7724   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7725
7726   /* try harder to query upstream size if we didn't get it the first time */
7727   if (seekable && stop == -1) {
7728     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7729     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7730   }
7731
7732   /* if upstream doesn't know the size, it's likely that it's not seekable in
7733    * practice even if it technically may be seekable */
7734   if (seekable && (start != 0 || stop <= start)) {
7735     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7736     seekable = FALSE;
7737   }
7738
7739 done:
7740   gst_query_unref (query);
7741
7742   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7743       G_GUINT64_FORMAT ")", seekable, start, stop);
7744   demux->upstream_seekable = seekable;
7745   demux->upstream_size = seekable ? stop : -1;
7746 }
7747
7748 static void
7749 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7750 {
7751   g_return_if_fail (bytes <= demux->todrop);
7752
7753   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7754   gst_adapter_flush (demux->adapter, bytes);
7755   demux->neededbytes -= bytes;
7756   demux->offset += bytes;
7757   demux->todrop -= bytes;
7758 }
7759
7760 /* PUSH-MODE only: Send a segment, if not done already. */
7761 static void
7762 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7763 {
7764   if (G_UNLIKELY (demux->need_segment)) {
7765     gint i;
7766
7767     if (!demux->upstream_format_is_time) {
7768       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7769     } else {
7770       GstEvent *segment_event;
7771       segment_event = gst_event_new_segment (&demux->segment);
7772       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7773         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7774       gst_qtdemux_push_event (demux, segment_event);
7775     }
7776
7777     demux->need_segment = FALSE;
7778
7779     /* clear to send tags on all streams */
7780     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7781       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7782       gst_qtdemux_push_tags (demux, stream);
7783       if (CUR_STREAM (stream)->sparse) {
7784         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7785         gst_pad_push_event (stream->pad,
7786             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7787       }
7788     }
7789   }
7790 }
7791
7792 /* Used for push mode only. */
7793 static void
7794 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7795     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7796 {
7797   GstClockTime ts, dur;
7798
7799   ts = pos;
7800   dur =
7801       stream->segments[segment_index].duration - (pos -
7802       stream->segments[segment_index].time);
7803   stream->time_position += dur;
7804
7805   /* Only gaps with a duration of at least one second are propagated.
7806    * Same workaround as in pull mode.
7807    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7808   if (dur >= GST_SECOND) {
7809     GstEvent *gap;
7810     gap = gst_event_new_gap (ts, dur);
7811
7812     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7813         "segment: %" GST_PTR_FORMAT, gap);
7814     gst_pad_push_event (stream->pad, gap);
7815   }
7816 }
7817
7818 static GstFlowReturn
7819 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7820 {
7821   GstQTDemux *demux;
7822
7823   demux = GST_QTDEMUX (parent);
7824
7825   GST_DEBUG_OBJECT (demux,
7826       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7827       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7828       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7829       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7830       gst_buffer_get_size (inbuf), demux->offset);
7831
7832   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7833     gboolean is_gap_input = FALSE;
7834     gint i;
7835
7836     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7837
7838     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7839       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7840     }
7841
7842     /* Check if we can land back on our feet in the case where upstream is
7843      * handling the seeking/pushing of samples with gaps in between (like
7844      * in the case of trick-mode DASH for example) */
7845     if (demux->upstream_format_is_time
7846         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7847       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7848         guint32 res;
7849         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7850         GST_LOG_OBJECT (demux,
7851             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7852             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7853         res =
7854             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7855             stream, GST_BUFFER_OFFSET (inbuf));
7856         if (res != -1) {
7857           QtDemuxSample *sample = &stream->samples[res];
7858           GST_LOG_OBJECT (demux,
7859               "Checking if sample %d from track-id %u is valid (offset:%"
7860               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7861               stream->track_id, sample->offset, sample->size);
7862           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7863             GST_LOG_OBJECT (demux,
7864                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7865                 res);
7866             is_gap_input = TRUE;
7867             /* We can go back to standard playback mode */
7868             demux->state = QTDEMUX_STATE_MOVIE;
7869             /* Remember which sample this stream is at */
7870             stream->sample_index = res;
7871             /* Finally update all push-based values to the expected values */
7872             demux->neededbytes = stream->samples[res].size;
7873             demux->offset = GST_BUFFER_OFFSET (inbuf);
7874             demux->mdatleft =
7875                 demux->mdatsize - demux->offset + demux->mdatoffset;
7876             demux->todrop = 0;
7877           }
7878         }
7879       }
7880       if (!is_gap_input) {
7881         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7882         /* Reset state if it's a real discont */
7883         demux->neededbytes = 16;
7884         demux->state = QTDEMUX_STATE_INITIAL;
7885         demux->offset = GST_BUFFER_OFFSET (inbuf);
7886         gst_adapter_clear (demux->adapter);
7887       }
7888     }
7889     /* Reverse fragmented playback, need to flush all we have before
7890      * consuming a new fragment.
7891      * The samples array have the timestamps calculated by accumulating the
7892      * durations but this won't work for reverse playback of fragments as
7893      * the timestamps of a subsequent fragment should be smaller than the
7894      * previously received one. */
7895     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7896       gst_qtdemux_process_adapter (demux, TRUE);
7897       g_ptr_array_foreach (demux->active_streams,
7898           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7899     }
7900   }
7901
7902   gst_adapter_push (demux->adapter, inbuf);
7903
7904   GST_DEBUG_OBJECT (demux,
7905       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7906       demux->neededbytes, gst_adapter_available (demux->adapter));
7907
7908   return gst_qtdemux_process_adapter (demux, FALSE);
7909 }
7910
7911 static guint64
7912 gst_segment_to_stream_time_clamped (const GstSegment * segment,
7913     guint64 position)
7914 {
7915   guint64 segment_stream_time_start;
7916   guint64 segment_stream_time_stop = GST_CLOCK_TIME_NONE;
7917   guint64 stream_pts_unsigned;
7918   int ret;
7919
7920   g_return_val_if_fail (segment != NULL, GST_CLOCK_TIME_NONE);
7921   g_return_val_if_fail (segment->format == GST_FORMAT_TIME,
7922       GST_CLOCK_TIME_NONE);
7923
7924   segment_stream_time_start = segment->time;
7925   if (segment->stop != GST_CLOCK_TIME_NONE)
7926     segment_stream_time_stop =
7927         gst_segment_to_stream_time (segment, GST_FORMAT_TIME, segment->stop);
7928
7929   ret =
7930       gst_segment_to_stream_time_full (segment, GST_FORMAT_TIME, position,
7931       &stream_pts_unsigned);
7932   /* ret == 0 if the segment is invalid (either position, segment->time or the segment start are -1). */
7933   g_return_val_if_fail (ret != 0, GST_CLOCK_TIME_NONE);
7934
7935   if (ret == -1 || stream_pts_unsigned < segment_stream_time_start) {
7936     /* Negative or prior to segment start stream time, clamp to segment start. */
7937     return segment_stream_time_start;
7938   } else if (segment_stream_time_stop != GST_CLOCK_TIME_NONE
7939       && stream_pts_unsigned > segment_stream_time_stop) {
7940     /* Clamp to segment end. */
7941     return segment_stream_time_stop;
7942   } else {
7943     return stream_pts_unsigned;
7944   }
7945 }
7946
7947 static GstFlowReturn
7948 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7949 {
7950   GstFlowReturn ret = GST_FLOW_OK;
7951
7952   /* we never really mean to buffer that much */
7953   if (demux->neededbytes == -1) {
7954     goto eos;
7955   }
7956
7957   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7958       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7959
7960 #ifndef GST_DISABLE_GST_DEBUG
7961     {
7962       guint64 discont_offset, distance_from_discont;
7963
7964       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7965       distance_from_discont =
7966           gst_adapter_distance_from_discont (demux->adapter);
7967
7968       GST_DEBUG_OBJECT (demux,
7969           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7970           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7971           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7972           demux->offset, discont_offset, distance_from_discont);
7973     }
7974 #endif
7975
7976     switch (demux->state) {
7977       case QTDEMUX_STATE_INITIAL:{
7978         const guint8 *data;
7979         guint32 fourcc;
7980         guint64 size;
7981
7982         gst_qtdemux_check_seekability (demux);
7983
7984         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7985
7986         /* get fourcc/length, set neededbytes */
7987         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7988             &size, &fourcc);
7989         gst_adapter_unmap (demux->adapter);
7990         data = NULL;
7991         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7992             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7993         if (size == 0) {
7994           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7995               (_("This file is invalid and cannot be played.")),
7996               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7997                   GST_FOURCC_ARGS (fourcc)));
7998           ret = GST_FLOW_ERROR;
7999           break;
8000         }
8001         if (fourcc == FOURCC_mdat) {
8002           gint next_entry = next_entry_size (demux);
8003           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
8004                   || !demux->fragmented)) {
8005             /* we have the headers, start playback */
8006             demux->state = QTDEMUX_STATE_MOVIE;
8007             demux->neededbytes = next_entry;
8008             demux->mdatleft = size;
8009             demux->mdatsize = demux->mdatleft;
8010           } else {
8011             /* no headers yet, try to get them */
8012             guint bs;
8013             gboolean res;
8014             guint64 old, target;
8015
8016           buffer_data:
8017             old = demux->offset;
8018             target = old + size;
8019
8020             /* try to jump over the atom with a seek */
8021             /* only bother if it seems worth doing so,
8022              * and avoids possible upstream/server problems */
8023             if (demux->upstream_seekable &&
8024                 demux->upstream_size > 4 * (1 << 20)) {
8025               res = qtdemux_seek_offset (demux, target);
8026             } else {
8027               GST_DEBUG_OBJECT (demux, "skipping seek");
8028               res = FALSE;
8029             }
8030
8031             if (res) {
8032               GST_DEBUG_OBJECT (demux, "seek success");
8033               /* remember the offset fo the first mdat so we can seek back to it
8034                * after we have the headers */
8035               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
8036                 demux->first_mdat = old;
8037                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
8038                     demux->first_mdat);
8039               }
8040               /* seek worked, continue reading */
8041               demux->offset = target;
8042               demux->neededbytes = 16;
8043               demux->state = QTDEMUX_STATE_INITIAL;
8044             } else {
8045               /* seek failed, need to buffer */
8046               demux->offset = old;
8047               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
8048               /* there may be multiple mdat (or alike) buffers */
8049               /* sanity check */
8050               if (demux->mdatbuffer)
8051                 bs = gst_buffer_get_size (demux->mdatbuffer);
8052               else
8053                 bs = 0;
8054               if (size + bs > 10 * (1 << 20))
8055                 goto no_moov;
8056               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
8057               demux->neededbytes = size;
8058               if (!demux->mdatbuffer)
8059                 demux->mdatoffset = demux->offset;
8060             }
8061           }
8062         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
8063           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8064               (_("This file is invalid and cannot be played.")),
8065               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
8066                   GST_FOURCC_ARGS (fourcc), size));
8067           ret = GST_FLOW_ERROR;
8068           break;
8069         } else {
8070           /* this means we already started buffering and still no moov header,
8071            * let's continue buffering everything till we get moov */
8072           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
8073                   || fourcc == FOURCC_moof))
8074             goto buffer_data;
8075           demux->neededbytes = size;
8076           demux->state = QTDEMUX_STATE_HEADER;
8077         }
8078         break;
8079       }
8080       case QTDEMUX_STATE_HEADER:{
8081         const guint8 *data;
8082         guint32 fourcc;
8083
8084         GST_DEBUG_OBJECT (demux, "In header");
8085
8086         data = gst_adapter_map (demux->adapter, demux->neededbytes);
8087
8088         /* parse the header */
8089         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
8090             &fourcc);
8091         if (fourcc == FOURCC_moov) {
8092           /* in usual fragmented setup we could try to scan for more
8093            * and end up at the the moov (after mdat) again */
8094           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
8095               (!demux->fragmented
8096                   || demux->last_moov_offset == demux->offset)) {
8097             GST_DEBUG_OBJECT (demux,
8098                 "Skipping moov atom as we have (this) one already");
8099           } else {
8100             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
8101
8102             if (demux->got_moov && demux->fragmented) {
8103               GST_DEBUG_OBJECT (demux,
8104                   "Got a second moov, clean up data from old one");
8105               if (demux->moov_node_compressed) {
8106                 g_node_destroy (demux->moov_node_compressed);
8107                 if (demux->moov_node)
8108                   g_free (demux->moov_node->data);
8109               }
8110               demux->moov_node_compressed = NULL;
8111               if (demux->moov_node)
8112                 g_node_destroy (demux->moov_node);
8113               demux->moov_node = NULL;
8114               demux->start_utc_time = GST_CLOCK_TIME_NONE;
8115             }
8116
8117             demux->last_moov_offset = demux->offset;
8118
8119             /* Update streams with new moov */
8120             gst_qtdemux_stream_concat (demux,
8121                 demux->old_streams, demux->active_streams);
8122
8123             qtdemux_parse_moov (demux, data, demux->neededbytes);
8124             qtdemux_node_dump (demux, demux->moov_node);
8125             qtdemux_parse_tree (demux);
8126             qtdemux_prepare_streams (demux);
8127             QTDEMUX_EXPOSE_LOCK (demux);
8128             qtdemux_expose_streams (demux);
8129             QTDEMUX_EXPOSE_UNLOCK (demux);
8130
8131             demux->got_moov = TRUE;
8132
8133             gst_qtdemux_check_send_pending_segment (demux);
8134
8135             if (demux->moov_node_compressed) {
8136               g_node_destroy (demux->moov_node_compressed);
8137               g_free (demux->moov_node->data);
8138             }
8139             demux->moov_node_compressed = NULL;
8140             g_node_destroy (demux->moov_node);
8141             demux->moov_node = NULL;
8142             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
8143           }
8144         } else if (fourcc == FOURCC_moof) {
8145           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
8146             guint64 dist = 0;
8147             GstClockTime prev_pts;
8148             guint64 prev_offset;
8149             guint64 adapter_discont_offset, adapter_discont_dist;
8150
8151             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
8152
8153             /*
8154              * The timestamp of the moof buffer is relevant as some scenarios
8155              * won't have the initial timestamp in the atoms. Whenever a new
8156              * buffer has started, we get that buffer's PTS and use it as a base
8157              * timestamp for the trun entries.
8158              *
8159              * To keep track of the current buffer timestamp and starting point
8160              * we use gst_adapter_prev_pts that gives us the PTS and the distance
8161              * from the beginning of the buffer, with the distance and demux->offset
8162              * we know if it is still the same buffer or not.
8163              */
8164             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
8165             prev_offset = demux->offset - dist;
8166             if (demux->fragment_start_offset == -1
8167                 || prev_offset > demux->fragment_start_offset) {
8168               demux->fragment_start_offset = prev_offset;
8169               demux->fragment_start = prev_pts;
8170               GST_DEBUG_OBJECT (demux,
8171                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
8172                   GST_TIME_FORMAT, demux->fragment_start_offset,
8173                   GST_TIME_ARGS (demux->fragment_start));
8174             }
8175
8176             /* We can't use prev_offset() here because this would require
8177              * upstream to set consistent and correct offsets on all buffers
8178              * since the discont. Nothing ever did that in the past and we
8179              * would break backwards compatibility here then.
8180              * Instead take the offset we had at the last discont and count
8181              * the bytes from there. This works with old code as there would
8182              * be no discont between moov and moof, and also works with
8183              * adaptivedemux which correctly sets offset and will set the
8184              * DISCONT flag accordingly when needed.
8185              *
8186              * We also only do this for upstream TIME segments as otherwise
8187              * there are potential backwards compatibility problems with
8188              * seeking in PUSH mode and upstream providing inconsistent
8189              * timestamps. */
8190             adapter_discont_offset =
8191                 gst_adapter_offset_at_discont (demux->adapter);
8192             adapter_discont_dist =
8193                 gst_adapter_distance_from_discont (demux->adapter);
8194
8195             GST_DEBUG_OBJECT (demux,
8196                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
8197                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
8198                 demux->offset, adapter_discont_offset, adapter_discont_dist);
8199
8200             if (demux->upstream_format_is_time) {
8201               demux->moof_offset = adapter_discont_offset;
8202               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
8203                 demux->moof_offset += adapter_discont_dist;
8204               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
8205                 demux->moof_offset = demux->offset;
8206             } else {
8207               demux->moof_offset = demux->offset;
8208             }
8209
8210             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
8211                     demux->moof_offset, NULL)) {
8212               gst_adapter_unmap (demux->adapter);
8213               ret = GST_FLOW_ERROR;
8214               goto done;
8215             }
8216
8217             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
8218             if (demux->variant == VARIANT_MSS_FRAGMENTED && !demux->exposed) {
8219               QTDEMUX_EXPOSE_LOCK (demux);
8220               qtdemux_expose_streams (demux);
8221               QTDEMUX_EXPOSE_UNLOCK (demux);
8222             }
8223
8224             gst_qtdemux_check_send_pending_segment (demux);
8225           } else {
8226             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
8227           }
8228         } else if (fourcc == FOURCC_ftyp) {
8229           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
8230           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
8231         } else if (fourcc == FOURCC_uuid) {
8232           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
8233           qtdemux_parse_uuid (demux, data, demux->neededbytes);
8234         } else if (fourcc == FOURCC_sidx) {
8235           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
8236           qtdemux_parse_sidx (demux, data, demux->neededbytes);
8237         } else if (fourcc == FOURCC_meta) {
8238           GNode *node, *child;
8239           GstByteReader child_data;
8240
8241           node = g_node_new ((gpointer) data);
8242           qtdemux_parse_node (demux, node, data, demux->neededbytes);
8243
8244           /* Parse ONVIF Export File Format CorrectStartTime box if available */
8245           if ((child =
8246                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
8247                       &child_data))) {
8248             qtdemux_parse_cstb (demux, &child_data);
8249           }
8250
8251           g_node_destroy (node);
8252         } else {
8253           switch (fourcc) {
8254             case FOURCC_styp:
8255               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
8256                * FALLTHROUGH */
8257             case FOURCC_skip:
8258             case FOURCC_free:
8259               /* [free] and [skip] are padding atoms */
8260               GST_DEBUG_OBJECT (demux,
8261                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
8262                   GST_FOURCC_ARGS (fourcc));
8263               break;
8264             default:
8265               GST_WARNING_OBJECT (demux,
8266                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
8267                   GST_FOURCC_ARGS (fourcc));
8268               /* Let's jump that one and go back to initial state */
8269               break;
8270           }
8271         }
8272         gst_adapter_unmap (demux->adapter);
8273         data = NULL;
8274
8275         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
8276           gsize remaining_data_size = 0;
8277
8278           /* the mdat was before the header */
8279           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
8280               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
8281           /* restore our adapter/offset view of things with upstream;
8282            * put preceding buffered data ahead of current moov data.
8283            * This should also handle evil mdat, moov, mdat cases and alike */
8284           gst_adapter_flush (demux->adapter, demux->neededbytes);
8285
8286           /* Store any remaining data after the mdat for later usage */
8287           remaining_data_size = gst_adapter_available (demux->adapter);
8288           if (remaining_data_size > 0) {
8289             g_assert (demux->restoredata_buffer == NULL);
8290             demux->restoredata_buffer =
8291                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
8292             demux->restoredata_offset = demux->offset + demux->neededbytes;
8293             GST_DEBUG_OBJECT (demux,
8294                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
8295                 G_GUINT64_FORMAT, remaining_data_size,
8296                 demux->restoredata_offset);
8297           }
8298
8299           gst_adapter_push (demux->adapter, demux->mdatbuffer);
8300           demux->mdatbuffer = NULL;
8301           demux->offset = demux->mdatoffset;
8302           demux->neededbytes = next_entry_size (demux);
8303           demux->state = QTDEMUX_STATE_MOVIE;
8304           demux->mdatleft = gst_adapter_available (demux->adapter);
8305           demux->mdatsize = demux->mdatleft;
8306         } else {
8307           GST_DEBUG_OBJECT (demux, "Carrying on normally");
8308           gst_adapter_flush (demux->adapter, demux->neededbytes);
8309
8310           /* only go back to the mdat if there are samples to play */
8311           if (demux->got_moov && demux->first_mdat != -1
8312               && has_next_entry (demux)) {
8313             gboolean res;
8314
8315             /* we need to seek back */
8316             res = qtdemux_seek_offset (demux, demux->first_mdat);
8317             if (res) {
8318               demux->offset = demux->first_mdat;
8319             } else {
8320               GST_DEBUG_OBJECT (demux, "Seek back failed");
8321             }
8322           } else {
8323             demux->offset += demux->neededbytes;
8324           }
8325           demux->neededbytes = 16;
8326           demux->state = QTDEMUX_STATE_INITIAL;
8327         }
8328
8329         break;
8330       }
8331       case QTDEMUX_STATE_BUFFER_MDAT:{
8332         GstBuffer *buf;
8333         guint8 fourcc[4];
8334
8335         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
8336             demux->offset);
8337         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
8338         gst_buffer_extract (buf, 0, fourcc, 4);
8339         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
8340             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
8341         if (demux->mdatbuffer)
8342           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
8343         else
8344           demux->mdatbuffer = buf;
8345         demux->offset += demux->neededbytes;
8346         demux->neededbytes = 16;
8347         demux->state = QTDEMUX_STATE_INITIAL;
8348         gst_qtdemux_post_progress (demux, 1, 1);
8349
8350         break;
8351       }
8352       case QTDEMUX_STATE_MOVIE:{
8353         QtDemuxStream *stream = NULL;
8354         QtDemuxSample *sample;
8355         GstClockTime dts, pts, stream_pts, duration;
8356         gboolean keyframe;
8357         gint i;
8358
8359         GST_DEBUG_OBJECT (demux,
8360             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
8361
8362         if (demux->fragmented) {
8363           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
8364               demux->mdatleft);
8365           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
8366             /* if needed data starts within this atom,
8367              * then it should not exceed this atom */
8368             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
8369               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8370                   (_("This file is invalid and cannot be played.")),
8371                   ("sample data crosses atom boundary"));
8372               ret = GST_FLOW_ERROR;
8373               break;
8374             }
8375             demux->mdatleft -= demux->neededbytes;
8376           } else {
8377             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
8378             /* so we are dropping more than left in this atom */
8379             gst_qtdemux_drop_data (demux, demux->mdatleft);
8380             demux->mdatleft = 0;
8381
8382             /* need to resume atom parsing so we do not miss any other pieces */
8383             demux->state = QTDEMUX_STATE_INITIAL;
8384             demux->neededbytes = 16;
8385
8386             /* check if there was any stored post mdat data from previous buffers */
8387             if (demux->restoredata_buffer) {
8388               g_assert (gst_adapter_available (demux->adapter) == 0);
8389
8390               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
8391               demux->restoredata_buffer = NULL;
8392               demux->offset = demux->restoredata_offset;
8393             }
8394
8395             break;
8396           }
8397         }
8398
8399         if (demux->todrop) {
8400           if (demux->cenc_aux_info_offset > 0) {
8401             GstByteReader br;
8402             const guint8 *data;
8403
8404             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
8405             data = gst_adapter_map (demux->adapter, demux->todrop);
8406             gst_byte_reader_init (&br, data + 8, demux->todrop);
8407             if (!qtdemux_parse_cenc_aux_info (demux,
8408                     QTDEMUX_NTH_STREAM (demux, 0), &br,
8409                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
8410               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
8411               ret = GST_FLOW_ERROR;
8412               gst_adapter_unmap (demux->adapter);
8413               g_free (demux->cenc_aux_info_sizes);
8414               demux->cenc_aux_info_sizes = NULL;
8415               goto done;
8416             }
8417             demux->cenc_aux_info_offset = 0;
8418             g_free (demux->cenc_aux_info_sizes);
8419             demux->cenc_aux_info_sizes = NULL;
8420             gst_adapter_unmap (demux->adapter);
8421           }
8422           gst_qtdemux_drop_data (demux, demux->todrop);
8423         }
8424
8425         /* first buffer? */
8426         /* initial newsegment sent here after having added pads,
8427          * possible others in sink_event */
8428         gst_qtdemux_check_send_pending_segment (demux);
8429
8430         /* Figure out which stream this packet belongs to */
8431         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
8432           stream = QTDEMUX_NTH_STREAM (demux, i);
8433           if (stream->sample_index >= stream->n_samples) {
8434             /* reset to be checked below G_UNLIKELY (stream == NULL) */
8435             stream = NULL;
8436             continue;
8437           }
8438           GST_LOG_OBJECT (demux,
8439               "Checking track-id %u (sample_index:%d / offset:%"
8440               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
8441               stream->sample_index,
8442               stream->samples[stream->sample_index].offset,
8443               stream->samples[stream->sample_index].size);
8444
8445           if (stream->samples[stream->sample_index].offset == demux->offset)
8446             break;
8447         }
8448
8449         if (G_UNLIKELY (stream == NULL))
8450           goto unknown_stream;
8451
8452         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
8453
8454         if (stream->new_caps) {
8455           gst_qtdemux_configure_stream (demux, stream);
8456         }
8457
8458         /* Put data in a buffer, set timestamps, caps, ... */
8459         sample = &stream->samples[stream->sample_index];
8460
8461         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
8462           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
8463               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
8464
8465           dts = QTSAMPLE_DTS (stream, sample);
8466           pts = QTSAMPLE_PTS (stream, sample);
8467           stream_pts =
8468               gst_segment_to_stream_time_clamped (&stream->segment, pts);
8469           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
8470           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
8471
8472           /* check for segment end */
8473           if (G_UNLIKELY (demux->segment.stop != -1
8474                   && demux->segment.stop <= stream_pts && keyframe)
8475               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
8476             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
8477             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
8478
8479             /* skip this data, stream is EOS */
8480             gst_adapter_flush (demux->adapter, demux->neededbytes);
8481             demux->offset += demux->neededbytes;
8482
8483             /* check if all streams are eos */
8484             ret = GST_FLOW_EOS;
8485             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
8486               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
8487                 ret = GST_FLOW_OK;
8488                 break;
8489               }
8490             }
8491           } else {
8492             GstBuffer *outbuf;
8493
8494             outbuf =
8495                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
8496
8497             /* FIXME: should either be an assert or a plain check */
8498             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
8499
8500             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
8501                 dts, pts, duration, keyframe, dts, demux->offset);
8502           }
8503
8504           /* combine flows */
8505           GST_OBJECT_LOCK (demux);
8506           ret = gst_qtdemux_combine_flows (demux, stream, ret);
8507           GST_OBJECT_UNLOCK (demux);
8508         } else {
8509           /* skip this data, stream is EOS */
8510           gst_adapter_flush (demux->adapter, demux->neededbytes);
8511         }
8512
8513         stream->sample_index++;
8514         stream->offset_in_sample = 0;
8515
8516         /* update current offset and figure out size of next buffer */
8517         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
8518             demux->offset, demux->neededbytes);
8519         demux->offset += demux->neededbytes;
8520         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
8521             demux->offset);
8522
8523
8524         if (ret == GST_FLOW_EOS) {
8525           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
8526           demux->neededbytes = -1;
8527           goto eos;
8528         }
8529
8530         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
8531           if (demux->fragmented) {
8532             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
8533             /* there may be more to follow, only finish this atom */
8534             demux->todrop = demux->mdatleft;
8535             demux->neededbytes = demux->todrop;
8536             break;
8537           }
8538           goto eos;
8539         }
8540         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
8541           goto non_ok_unlinked_flow;
8542         }
8543         break;
8544       }
8545       default:
8546         goto invalid_state;
8547     }
8548   }
8549
8550   /* when buffering movie data, at least show user something is happening */
8551   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
8552       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
8553     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
8554         demux->neededbytes);
8555   }
8556 done:
8557
8558   return ret;
8559
8560   /* ERRORS */
8561 non_ok_unlinked_flow:
8562   {
8563     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
8564         gst_flow_get_name (ret));
8565     return ret;
8566   }
8567 unknown_stream:
8568   {
8569     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
8570     ret = GST_FLOW_ERROR;
8571     goto done;
8572   }
8573 eos:
8574   {
8575     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
8576     ret = GST_FLOW_EOS;
8577     goto done;
8578   }
8579 invalid_state:
8580   {
8581     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
8582         (NULL), ("qtdemuxer invalid state %d", demux->state));
8583     ret = GST_FLOW_ERROR;
8584     goto done;
8585   }
8586 no_moov:
8587   {
8588     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
8589         (NULL), ("no 'moov' atom within the first 10 MB"));
8590     ret = GST_FLOW_ERROR;
8591     goto done;
8592   }
8593 }
8594
8595 static gboolean
8596 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
8597 {
8598   GstQuery *query;
8599   gboolean pull_mode;
8600
8601   query = gst_query_new_scheduling ();
8602
8603   if (!gst_pad_peer_query (sinkpad, query)) {
8604     gst_query_unref (query);
8605     goto activate_push;
8606   }
8607
8608   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
8609       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
8610   gst_query_unref (query);
8611
8612   if (!pull_mode)
8613     goto activate_push;
8614
8615   GST_DEBUG_OBJECT (sinkpad, "activating pull");
8616   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
8617
8618 activate_push:
8619   {
8620     GST_DEBUG_OBJECT (sinkpad, "activating push");
8621     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
8622   }
8623 }
8624
8625 static gboolean
8626 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
8627     GstPadMode mode, gboolean active)
8628 {
8629   gboolean res;
8630   GstQTDemux *demux = GST_QTDEMUX (parent);
8631
8632   switch (mode) {
8633     case GST_PAD_MODE_PUSH:
8634       demux->pullbased = FALSE;
8635       res = TRUE;
8636       break;
8637     case GST_PAD_MODE_PULL:
8638       if (active) {
8639         demux->pullbased = TRUE;
8640         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
8641             sinkpad, NULL);
8642       } else {
8643         res = gst_pad_stop_task (sinkpad);
8644       }
8645       break;
8646     default:
8647       res = FALSE;
8648       break;
8649   }
8650   return res;
8651 }
8652
8653 #ifdef HAVE_ZLIB
8654 static void *
8655 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
8656 {
8657   guint8 *buffer;
8658   z_stream z;
8659   int ret;
8660
8661   memset (&z, 0, sizeof (z));
8662   z.zalloc = NULL;
8663   z.zfree = NULL;
8664   z.opaque = NULL;
8665
8666   if ((ret = inflateInit (&z)) != Z_OK) {
8667     GST_ERROR ("inflateInit() returned %d", ret);
8668     return NULL;
8669   }
8670
8671   z.next_in = z_buffer;
8672   z.avail_in = z_length;
8673
8674   buffer = (guint8 *) g_malloc (*length);
8675   z.avail_out = *length;
8676   z.next_out = (Bytef *) buffer;
8677   do {
8678     ret = inflate (&z, Z_NO_FLUSH);
8679     if (ret == Z_STREAM_END) {
8680       break;
8681     } else if (ret != Z_OK) {
8682       GST_WARNING ("inflate() returned %d", ret);
8683       break;
8684     }
8685
8686     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8687       GST_WARNING ("too big decompressed data");
8688       ret = Z_MEM_ERROR;
8689       break;
8690     }
8691
8692     *length += 4096;
8693     buffer = (guint8 *) g_realloc (buffer, *length);
8694     z.next_out = (Bytef *) (buffer + z.total_out);
8695     z.avail_out += *length - z.total_out;
8696   } while (z.avail_in > 0);
8697
8698   if (ret != Z_STREAM_END) {
8699     g_free (buffer);
8700     buffer = NULL;
8701     *length = 0;
8702   } else {
8703     *length = z.total_out;
8704   }
8705
8706   inflateEnd (&z);
8707
8708   return buffer;
8709 }
8710 #endif /* HAVE_ZLIB */
8711
8712 static gboolean
8713 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8714 {
8715   GNode *cmov;
8716
8717   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8718
8719   /* counts as header data */
8720   qtdemux->header_size += length;
8721
8722   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8723   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8724
8725   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8726   if (cmov) {
8727     guint32 method;
8728     GNode *dcom;
8729     GNode *cmvd;
8730     guint32 dcom_len;
8731
8732     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8733     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8734     if (dcom == NULL || cmvd == NULL)
8735       goto invalid_compression;
8736
8737     dcom_len = QT_UINT32 (dcom->data);
8738     if (dcom_len < 12)
8739       goto invalid_compression;
8740
8741     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8742     switch (method) {
8743 #ifdef HAVE_ZLIB
8744       case FOURCC_zlib:{
8745         guint uncompressed_length;
8746         guint compressed_length;
8747         guint8 *buf;
8748         guint32 cmvd_len;
8749
8750         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8751         if (cmvd_len < 12)
8752           goto invalid_compression;
8753
8754         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8755         compressed_length = cmvd_len - 12;
8756         GST_LOG ("length = %u", uncompressed_length);
8757
8758         buf =
8759             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8760             compressed_length, &uncompressed_length);
8761
8762         if (buf) {
8763           qtdemux->moov_node_compressed = qtdemux->moov_node;
8764           qtdemux->moov_node = g_node_new (buf);
8765
8766           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8767               uncompressed_length);
8768         }
8769         break;
8770       }
8771 #endif /* HAVE_ZLIB */
8772       default:
8773         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8774             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8775         break;
8776     }
8777   }
8778   return TRUE;
8779
8780   /* ERRORS */
8781 invalid_compression:
8782   {
8783     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8784     return FALSE;
8785   }
8786 }
8787
8788 static gboolean
8789 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8790     const guint8 * end)
8791 {
8792   while (G_UNLIKELY (buf < end)) {
8793     GNode *child;
8794     guint32 len;
8795
8796     if (G_UNLIKELY (buf + 4 > end)) {
8797       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8798       break;
8799     }
8800     len = QT_UINT32 (buf);
8801     if (G_UNLIKELY (len == 0)) {
8802       GST_LOG_OBJECT (qtdemux, "empty container");
8803       break;
8804     }
8805     if (G_UNLIKELY (len < 8)) {
8806       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8807       break;
8808     }
8809     if (G_UNLIKELY (len > (end - buf))) {
8810       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8811           (gint) (end - buf));
8812       break;
8813     }
8814
8815     child = g_node_new ((guint8 *) buf);
8816     g_node_append (node, child);
8817     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8818     qtdemux_parse_node (qtdemux, child, buf, len);
8819
8820     buf += len;
8821   }
8822   return TRUE;
8823 }
8824
8825 static gboolean
8826 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8827     GNode * xdxt)
8828 {
8829   int len = QT_UINT32 (xdxt->data);
8830   guint8 *buf = xdxt->data;
8831   guint8 *end = buf + len;
8832   GstBuffer *buffer;
8833
8834   /* skip size and type */
8835   buf += 8;
8836   end -= 8;
8837
8838   while (buf < end) {
8839     gint size;
8840     guint32 type;
8841
8842     size = QT_UINT32 (buf);
8843     type = QT_FOURCC (buf + 4);
8844
8845     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8846
8847     if (buf + size > end || size <= 0)
8848       break;
8849
8850     buf += 8;
8851     size -= 8;
8852
8853     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8854         GST_FOURCC_ARGS (type));
8855
8856     switch (type) {
8857       case FOURCC_tCtH:
8858         buffer = gst_buffer_new_and_alloc (size);
8859         gst_buffer_fill (buffer, 0, buf, size);
8860         stream->buffers = g_slist_append (stream->buffers, buffer);
8861         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8862         break;
8863       case FOURCC_tCt_:
8864         buffer = gst_buffer_new_and_alloc (size);
8865         gst_buffer_fill (buffer, 0, buf, size);
8866         stream->buffers = g_slist_append (stream->buffers, buffer);
8867         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8868         break;
8869       case FOURCC_tCtC:
8870         buffer = gst_buffer_new_and_alloc (size);
8871         gst_buffer_fill (buffer, 0, buf, size);
8872         stream->buffers = g_slist_append (stream->buffers, buffer);
8873         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8874         break;
8875       default:
8876         GST_WARNING_OBJECT (qtdemux,
8877             "unknown theora cookie %" GST_FOURCC_FORMAT,
8878             GST_FOURCC_ARGS (type));
8879         break;
8880     }
8881     buf += size;
8882   }
8883   return TRUE;
8884 }
8885
8886 static gboolean
8887 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8888     guint length)
8889 {
8890   guint32 fourcc = 0;
8891   guint32 node_length = 0;
8892   const QtNodeType *type;
8893   const guint8 *end;
8894
8895   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8896
8897   if (G_UNLIKELY (length < 8))
8898     goto not_enough_data;
8899
8900   node_length = QT_UINT32 (buffer);
8901   fourcc = QT_FOURCC (buffer + 4);
8902
8903   /* ignore empty nodes */
8904   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8905     return TRUE;
8906
8907   type = qtdemux_type_get (fourcc);
8908
8909   end = buffer + length;
8910
8911   GST_LOG_OBJECT (qtdemux,
8912       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8913       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8914
8915   if (node_length > length)
8916     goto broken_atom_size;
8917
8918   if (type->flags & QT_FLAG_CONTAINER) {
8919     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8920   } else {
8921     switch (fourcc) {
8922       case FOURCC_stsd:
8923       {
8924         if (node_length < 20) {
8925           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8926           break;
8927         }
8928         GST_DEBUG_OBJECT (qtdemux,
8929             "parsing stsd (sample table, sample description) atom");
8930         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8931         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8932         break;
8933       }
8934       case FOURCC_mp4a:
8935       case FOURCC_alac:
8936       case FOURCC_fLaC:
8937       case FOURCC_aavd:
8938       case FOURCC_opus:
8939       {
8940         guint32 version;
8941         guint32 offset;
8942         guint min_size;
8943
8944         /* also read alac (or whatever) in stead of mp4a in the following,
8945          * since a similar layout is used in other cases as well */
8946         if (fourcc == FOURCC_mp4a)
8947           min_size = 20;
8948         else if (fourcc == FOURCC_fLaC)
8949           min_size = 86;
8950         else if (fourcc == FOURCC_opus)
8951           min_size = 55;
8952         else
8953           min_size = 40;
8954
8955         /* There are two things we might encounter here: a true mp4a atom, and
8956            an mp4a entry in an stsd atom. The latter is what we're interested
8957            in, and it looks like an atom, but isn't really one. The true mp4a
8958            atom is short, so we detect it based on length here. */
8959         if (length < min_size) {
8960           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8961               GST_FOURCC_ARGS (fourcc));
8962           break;
8963         }
8964
8965         /* 'version' here is the sound sample description version. Types 0 and
8966            1 are documented in the QTFF reference, but type 2 is not: it's
8967            described in Apple header files instead (struct SoundDescriptionV2
8968            in Movies.h) */
8969         version = QT_UINT16 (buffer + 16);
8970
8971         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8972             GST_FOURCC_ARGS (fourcc), version);
8973
8974         /* parse any esds descriptors */
8975         switch (version) {
8976           case 0:
8977             offset = 0x24;
8978             break;
8979           case 1:
8980             offset = 0x34;
8981             break;
8982           case 2:
8983             offset = 0x48;
8984             break;
8985           default:
8986             GST_WARNING_OBJECT (qtdemux,
8987                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8988                 GST_FOURCC_ARGS (fourcc), version);
8989             offset = 0;
8990             break;
8991         }
8992         if (offset)
8993           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8994         break;
8995       }
8996       case FOURCC_mp4v:
8997       case FOURCC_MP4V:
8998       case FOURCC_fmp4:
8999       case FOURCC_FMP4:
9000       case FOURCC_apcs:
9001       case FOURCC_apch:
9002       case FOURCC_apcn:
9003       case FOURCC_apco:
9004       case FOURCC_ap4h:
9005       case FOURCC_xvid:
9006       case FOURCC_XVID:
9007       case FOURCC_H264:
9008       case FOURCC_avc1:
9009       case FOURCC_avc3:
9010       case FOURCC_H265:
9011       case FOURCC_hvc1:
9012       case FOURCC_hev1:
9013       case FOURCC_dvh1:
9014       case FOURCC_dvhe:
9015       case FOURCC_mjp2:
9016       case FOURCC_encv:
9017       {
9018         guint32 version;
9019         guint32 str_len;
9020
9021         /* codec_data is contained inside these atoms, which all have
9022          * the same format. */
9023         /* video sample description size is 86 bytes without extension.
9024          * node_length have to be bigger than 86 bytes because video sample
9025          * description can include extensions such as esds, fiel, glbl, etc. */
9026         if (node_length < 86) {
9027           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
9028               " sample description length too short (%u < 86)",
9029               GST_FOURCC_ARGS (fourcc), node_length);
9030           break;
9031         }
9032
9033         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
9034             GST_FOURCC_ARGS (fourcc));
9035
9036         /* version (2 bytes) : this is set to 0, unless a compressor has changed
9037          *              its data format.
9038          * revision level (2 bytes) : must be set to 0. */
9039         version = QT_UINT32 (buffer + 16);
9040         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
9041
9042         /* compressor name : PASCAL string and informative purposes
9043          * first byte : the number of bytes to be displayed.
9044          *              it has to be less than 32 because it is reserved
9045          *              space of 32 bytes total including itself. */
9046         str_len = QT_UINT8 (buffer + 50);
9047         if (str_len < 32)
9048           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
9049               (char *) buffer + 51);
9050         else
9051           GST_WARNING_OBJECT (qtdemux,
9052               "compressorname length too big (%u > 31)", str_len);
9053
9054         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
9055             end - buffer);
9056         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
9057         break;
9058       }
9059       case FOURCC_meta:
9060       {
9061         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
9062
9063         /* You are reading this correctly. QTFF specifies that the
9064          * metadata atom is a short atom, whereas ISO BMFF specifies
9065          * it's a full atom. But since so many people are doing things
9066          * differently, we actually peek into the atom to see which
9067          * variant it is */
9068         if (length < 16) {
9069           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
9070               GST_FOURCC_ARGS (fourcc));
9071           break;
9072         }
9073         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
9074           /* Variant 1: What QTFF specifies. 'meta' is a short header which
9075            * starts with a 'hdlr' atom */
9076           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
9077         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
9078           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
9079            * with version/flags both set to zero */
9080           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
9081         } else
9082           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
9083         break;
9084       }
9085       case FOURCC_mp4s:
9086       {
9087         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
9088         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
9089         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
9090         break;
9091       }
9092       case FOURCC_XiTh:
9093       {
9094         guint32 version;
9095         guint32 offset;
9096
9097         if (length < 16) {
9098           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
9099               GST_FOURCC_ARGS (fourcc));
9100           break;
9101         }
9102
9103         version = QT_UINT32 (buffer + 12);
9104         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
9105
9106         switch (version) {
9107           case 0x00000001:
9108             offset = 0x62;
9109             break;
9110           default:
9111             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
9112             offset = 0;
9113             break;
9114         }
9115         if (offset) {
9116           if (length < offset) {
9117             GST_WARNING_OBJECT (qtdemux,
9118                 "skipping too small %" GST_FOURCC_FORMAT " box",
9119                 GST_FOURCC_ARGS (fourcc));
9120             break;
9121           }
9122           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
9123         }
9124         break;
9125       }
9126       case FOURCC_in24:
9127       {
9128         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
9129         break;
9130       }
9131       case FOURCC_uuid:
9132       {
9133         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
9134         break;
9135       }
9136       case FOURCC_enca:
9137       {
9138         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
9139         break;
9140       }
9141 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
9142       case FOURCC_SA3D:
9143       {
9144         qtdemux_parse_SA3D (qtdemux, buffer, end - buffer);
9145         break;
9146       }
9147 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
9148       default:
9149         if (!strcmp (type->name, "unknown"))
9150           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
9151         break;
9152     }
9153   }
9154   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
9155       GST_FOURCC_ARGS (fourcc));
9156   return TRUE;
9157
9158 /* ERRORS */
9159 not_enough_data:
9160   {
9161     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9162         (_("This file is corrupt and cannot be played.")),
9163         ("Not enough data for an atom header, got only %u bytes", length));
9164     return FALSE;
9165   }
9166 broken_atom_size:
9167   {
9168     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9169         (_("This file is corrupt and cannot be played.")),
9170         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
9171             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
9172             length));
9173     return FALSE;
9174   }
9175 }
9176
9177 static void
9178 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
9179 {
9180 /* FIXME: This can only reliably work if demuxers have a
9181  * separate streaming thread per srcpad. This should be
9182  * done in a demuxer base class, which integrates parts
9183  * of multiqueue
9184  *
9185  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
9186  */
9187 #if 0
9188   GstQuery *query;
9189
9190   query = gst_query_new_allocation (stream->caps, FALSE);
9191
9192   if (!gst_pad_peer_query (stream->pad, query)) {
9193     /* not a problem, just debug a little */
9194     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
9195   }
9196
9197   if (stream->allocator)
9198     gst_object_unref (stream->allocator);
9199
9200   if (gst_query_get_n_allocation_params (query) > 0) {
9201     /* try the allocator */
9202     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
9203         &stream->params);
9204     stream->use_allocator = TRUE;
9205   } else {
9206     stream->allocator = NULL;
9207     gst_allocation_params_init (&stream->params);
9208     stream->use_allocator = FALSE;
9209   }
9210   gst_query_unref (query);
9211 #endif
9212 }
9213
9214 static gboolean
9215 pad_query (const GValue * item, GValue * value, gpointer user_data)
9216 {
9217   GstPad *pad = g_value_get_object (item);
9218   GstQuery *query = user_data;
9219   gboolean res;
9220
9221   res = gst_pad_peer_query (pad, query);
9222
9223   if (res) {
9224     g_value_set_boolean (value, TRUE);
9225     return FALSE;
9226   }
9227
9228   GST_INFO_OBJECT (pad, "pad peer query failed");
9229   return TRUE;
9230 }
9231
9232 static gboolean
9233 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
9234     GstPadDirection direction)
9235 {
9236   GstIterator *it;
9237   GstIteratorFoldFunction func = pad_query;
9238   GValue res = { 0, };
9239
9240   g_value_init (&res, G_TYPE_BOOLEAN);
9241   g_value_set_boolean (&res, FALSE);
9242
9243   /* Ask neighbor */
9244   if (direction == GST_PAD_SRC)
9245     it = gst_element_iterate_src_pads (element);
9246   else
9247     it = gst_element_iterate_sink_pads (element);
9248
9249   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
9250     gst_iterator_resync (it);
9251
9252   gst_iterator_free (it);
9253
9254   return g_value_get_boolean (&res);
9255 }
9256
9257 static void
9258 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
9259     QtDemuxStream * stream)
9260 {
9261   GstQuery *query;
9262   GstContext *ctxt;
9263   GstElement *element = GST_ELEMENT (qtdemux);
9264   GstStructure *st;
9265   gchar **filtered_sys_ids;
9266   GValue event_list = G_VALUE_INIT;
9267   GList *walk;
9268
9269   /* 1. Check if we already have the context. */
9270   if (qtdemux->preferred_protection_system_id != NULL) {
9271     GST_LOG_OBJECT (element,
9272         "already have the protection context, no need to request it again");
9273     return;
9274   }
9275
9276   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
9277   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
9278       (const gchar **) qtdemux->protection_system_ids->pdata);
9279
9280   g_ptr_array_remove_index (qtdemux->protection_system_ids,
9281       qtdemux->protection_system_ids->len - 1);
9282   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
9283       "decryptors for %u of them, running context request",
9284       qtdemux->protection_system_ids->len,
9285       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
9286
9287
9288   if (stream->protection_scheme_event_queue.length) {
9289     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
9290         stream->protection_scheme_event_queue.length);
9291     walk = stream->protection_scheme_event_queue.tail;
9292   } else {
9293     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
9294         qtdemux->protection_event_queue.length);
9295     walk = qtdemux->protection_event_queue.tail;
9296   }
9297
9298   g_value_init (&event_list, GST_TYPE_LIST);
9299   for (; walk; walk = g_list_previous (walk)) {
9300     GValue event_value = G_VALUE_INIT;
9301     g_value_init (&event_value, GST_TYPE_EVENT);
9302     g_value_set_boxed (&event_value, walk->data);
9303     gst_value_list_append_and_take_value (&event_list, &event_value);
9304   }
9305
9306   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
9307    *      check if downstream already has a context of the specific type
9308    *  2b) Query upstream as above.
9309    */
9310   query = gst_query_new_context ("drm-preferred-decryption-system-id");
9311   st = gst_query_writable_structure (query);
9312   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
9313       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
9314       NULL);
9315   gst_structure_set_value (st, "stream-encryption-events", &event_list);
9316   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
9317     gst_query_parse_context (query, &ctxt);
9318     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
9319     gst_element_set_context (element, ctxt);
9320   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
9321     gst_query_parse_context (query, &ctxt);
9322     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
9323     gst_element_set_context (element, ctxt);
9324   } else {
9325     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
9326      *    the required context type and afterwards check if a
9327      *    usable context was set now as in 1). The message could
9328      *    be handled by the parent bins of the element and the
9329      *    application.
9330      */
9331     GstMessage *msg;
9332
9333     GST_INFO_OBJECT (element, "posting need context message");
9334     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
9335         "drm-preferred-decryption-system-id");
9336     st = (GstStructure *) gst_message_get_structure (msg);
9337     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
9338         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
9339         NULL);
9340
9341     gst_structure_set_value (st, "stream-encryption-events", &event_list);
9342     gst_element_post_message (element, msg);
9343   }
9344
9345   g_strfreev (filtered_sys_ids);
9346   g_value_unset (&event_list);
9347   gst_query_unref (query);
9348 }
9349
9350 static gboolean
9351 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
9352     QtDemuxStream * stream)
9353 {
9354   GstStructure *s;
9355   const gchar *selected_system = NULL;
9356
9357   g_return_val_if_fail (qtdemux != NULL, FALSE);
9358   g_return_val_if_fail (stream != NULL, FALSE);
9359   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
9360       FALSE);
9361
9362   if (stream->protection_scheme_type == FOURCC_aavd) {
9363     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
9364     if (!gst_structure_has_name (s, "application/x-aavd")) {
9365       gst_structure_set (s,
9366           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
9367           NULL);
9368       gst_structure_set_name (s, "application/x-aavd");
9369     }
9370     return TRUE;
9371   }
9372
9373   if (stream->protection_scheme_type != FOURCC_cenc
9374       && stream->protection_scheme_type != FOURCC_cbcs) {
9375     GST_ERROR_OBJECT (qtdemux,
9376         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
9377         GST_FOURCC_ARGS (stream->protection_scheme_type));
9378     return FALSE;
9379   }
9380
9381   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
9382   if (!gst_structure_has_name (s, "application/x-cenc")) {
9383     gst_structure_set (s,
9384         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
9385     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
9386         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
9387         NULL);
9388     gst_structure_set_name (s, "application/x-cenc");
9389   }
9390
9391   if (qtdemux->protection_system_ids == NULL) {
9392     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
9393         "cenc protection system information has been found, not setting a "
9394         "protection system UUID");
9395     return TRUE;
9396   }
9397
9398   gst_qtdemux_request_protection_context (qtdemux, stream);
9399   if (qtdemux->preferred_protection_system_id != NULL) {
9400     const gchar *preferred_system_array[] =
9401         { qtdemux->preferred_protection_system_id, NULL };
9402
9403     selected_system = gst_protection_select_system (preferred_system_array);
9404
9405     if (selected_system) {
9406       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
9407           qtdemux->preferred_protection_system_id);
9408     } else {
9409       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
9410           "because there is no available decryptor",
9411           qtdemux->preferred_protection_system_id);
9412     }
9413   }
9414
9415   if (!selected_system) {
9416     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
9417     selected_system = gst_protection_select_system ((const gchar **)
9418         qtdemux->protection_system_ids->pdata);
9419     g_ptr_array_remove_index (qtdemux->protection_system_ids,
9420         qtdemux->protection_system_ids->len - 1);
9421   }
9422
9423   if (!selected_system) {
9424     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
9425         "suitable decryptor element has been found");
9426     return FALSE;
9427   }
9428
9429   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
9430       selected_system);
9431
9432   gst_structure_set (s,
9433       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
9434       NULL);
9435
9436   return TRUE;
9437 }
9438
9439 static gboolean
9440 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
9441 {
9442   /* fps is calculated base on the duration of the average framerate since
9443    * qt does not have a fixed framerate. */
9444   gboolean fps_available = TRUE;
9445   guint32 first_duration = 0;
9446
9447   if (stream->n_samples > 0)
9448     first_duration = stream->samples[0].duration;
9449
9450   if ((stream->n_samples == 1 && first_duration == 0)
9451       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
9452     /* still frame */
9453     CUR_STREAM (stream)->fps_n = 0;
9454     CUR_STREAM (stream)->fps_d = 1;
9455   } else {
9456     if (stream->duration == 0 || stream->n_samples < 2) {
9457       CUR_STREAM (stream)->fps_n = stream->timescale;
9458       CUR_STREAM (stream)->fps_d = 1;
9459       fps_available = FALSE;
9460     } else {
9461       GstClockTime avg_duration;
9462       guint64 duration;
9463       guint32 n_samples;
9464
9465       /* duration and n_samples can be updated for fragmented format
9466        * so, framerate of fragmented format is calculated using data in a moof */
9467       if (qtdemux->fragmented && stream->n_samples_moof > 0
9468           && stream->duration_moof > 0) {
9469         n_samples = stream->n_samples_moof;
9470         duration = stream->duration_moof;
9471       } else {
9472         n_samples = stream->n_samples;
9473         duration = stream->duration;
9474       }
9475
9476       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
9477       /* stream->duration is guint64, timescale, n_samples are guint32 */
9478       avg_duration =
9479           gst_util_uint64_scale_round (duration -
9480           first_duration, GST_SECOND,
9481           (guint64) (stream->timescale) * (n_samples - 1));
9482
9483       GST_LOG_OBJECT (qtdemux,
9484           "Calculating avg sample duration based on stream (or moof) duration %"
9485           G_GUINT64_FORMAT
9486           " minus first sample %u, leaving %d samples gives %"
9487           GST_TIME_FORMAT, duration, first_duration,
9488           n_samples - 1, GST_TIME_ARGS (avg_duration));
9489
9490 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
9491       gst_video_guess_framerate (avg_duration,
9492         &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
9493       if (CUR_STREAM (stream)->fps_d == 0)
9494         fps_available = FALSE;
9495 #else
9496       fps_available =
9497           gst_video_guess_framerate (avg_duration,
9498           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
9499 #endif
9500
9501       GST_DEBUG_OBJECT (qtdemux,
9502           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
9503           stream->timescale, CUR_STREAM (stream)->fps_n,
9504           CUR_STREAM (stream)->fps_d);
9505     }
9506   }
9507
9508   return fps_available;
9509 }
9510
9511 static gboolean
9512 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
9513 {
9514   if (stream->subtype == FOURCC_vide) {
9515     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
9516
9517     if (CUR_STREAM (stream)->caps) {
9518       CUR_STREAM (stream)->caps =
9519           gst_caps_make_writable (CUR_STREAM (stream)->caps);
9520
9521       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
9522         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9523             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
9524             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
9525
9526       /* set framerate if calculated framerate is reliable */
9527       if (fps_available) {
9528         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9529             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
9530             CUR_STREAM (stream)->fps_d, NULL);
9531       }
9532
9533       /* calculate pixel-aspect-ratio using display width and height */
9534       GST_DEBUG_OBJECT (qtdemux,
9535           "video size %dx%d, target display size %dx%d",
9536           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
9537           stream->display_width, stream->display_height);
9538       /* qt file might have pasp atom */
9539       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
9540         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
9541             CUR_STREAM (stream)->par_h);
9542         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
9543             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
9544             CUR_STREAM (stream)->par_h, NULL);
9545       } else if (stream->display_width > 0 && stream->display_height > 0
9546           && CUR_STREAM (stream)->width > 0
9547           && CUR_STREAM (stream)->height > 0) {
9548         gint n, d;
9549
9550         /* calculate the pixel aspect ratio using the display and pixel w/h */
9551         n = stream->display_width * CUR_STREAM (stream)->height;
9552         d = stream->display_height * CUR_STREAM (stream)->width;
9553         if (n == d)
9554           n = d = 1;
9555         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
9556         CUR_STREAM (stream)->par_w = n;
9557         CUR_STREAM (stream)->par_h = d;
9558         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
9559             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
9560             CUR_STREAM (stream)->par_h, NULL);
9561       }
9562
9563       if (CUR_STREAM (stream)->interlace_mode > 0) {
9564         if (CUR_STREAM (stream)->interlace_mode == 1) {
9565           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
9566               G_TYPE_STRING, "progressive", NULL);
9567         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
9568           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
9569               G_TYPE_STRING, "interleaved", NULL);
9570           if (CUR_STREAM (stream)->field_order == 9) {
9571             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
9572                 G_TYPE_STRING, "top-field-first", NULL);
9573           } else if (CUR_STREAM (stream)->field_order == 14) {
9574             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
9575                 G_TYPE_STRING, "bottom-field-first", NULL);
9576           }
9577         }
9578       }
9579
9580       /* Create incomplete colorimetry here if needed */
9581       if (CUR_STREAM (stream)->colorimetry.range ||
9582           CUR_STREAM (stream)->colorimetry.matrix ||
9583           CUR_STREAM (stream)->colorimetry.transfer
9584           || CUR_STREAM (stream)->colorimetry.primaries) {
9585         gchar *colorimetry =
9586             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
9587         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
9588             G_TYPE_STRING, colorimetry, NULL);
9589         g_free (colorimetry);
9590       }
9591
9592       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
9593         guint par_w = 1, par_h = 1;
9594
9595         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
9596           par_w = CUR_STREAM (stream)->par_w;
9597           par_h = CUR_STREAM (stream)->par_h;
9598         }
9599
9600         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
9601                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
9602                 par_h)) {
9603           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
9604         }
9605
9606         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9607             "multiview-mode", G_TYPE_STRING,
9608             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
9609             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
9610             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
9611       }
9612     }
9613   }
9614
9615   else if (stream->subtype == FOURCC_soun) {
9616     if (CUR_STREAM (stream)->caps) {
9617       CUR_STREAM (stream)->caps =
9618           gst_caps_make_writable (CUR_STREAM (stream)->caps);
9619       if (CUR_STREAM (stream)->rate > 0)
9620         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9621             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
9622       if (CUR_STREAM (stream)->n_channels > 0)
9623         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9624             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
9625       if (CUR_STREAM (stream)->n_channels > 2) {
9626         /* FIXME: Need to parse the 'chan' atom to get channel layouts
9627          * correctly; this is just the minimum we can do - assume
9628          * we don't actually have any channel positions. */
9629         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9630             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
9631       }
9632     }
9633   }
9634
9635   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
9636     const GstStructure *s;
9637     QtDemuxStream *fps_stream = NULL;
9638     gboolean fps_available = FALSE;
9639
9640     /* CEA608 closed caption tracks are a bit special in that each sample
9641      * can contain CCs for multiple frames, and CCs can be omitted and have to
9642      * be inferred from the duration of the sample then.
9643      *
9644      * As such we take the framerate from the (first) video track here for
9645      * CEA608 as there must be one CC byte pair for every video frame
9646      * according to the spec.
9647      *
9648      * For CEA708 all is fine and there is one sample per frame.
9649      */
9650
9651     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
9652     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
9653       gint i;
9654
9655       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
9656         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
9657
9658         if (tmp->subtype == FOURCC_vide) {
9659           fps_stream = tmp;
9660           break;
9661         }
9662       }
9663
9664       if (fps_stream) {
9665         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
9666         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
9667         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
9668       }
9669     } else {
9670       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
9671       fps_stream = stream;
9672     }
9673
9674     CUR_STREAM (stream)->caps =
9675         gst_caps_make_writable (CUR_STREAM (stream)->caps);
9676
9677     /* set framerate if calculated framerate is reliable */
9678     if (fps_available) {
9679       gst_caps_set_simple (CUR_STREAM (stream)->caps,
9680           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
9681           CUR_STREAM (stream)->fps_d, NULL);
9682     }
9683   }
9684
9685   if (stream->pad) {
9686     gboolean forward_collection = FALSE;
9687     GstCaps *prev_caps = NULL;
9688
9689     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9690     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9691     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9692     gst_pad_set_active (stream->pad, TRUE);
9693
9694     gst_pad_use_fixed_caps (stream->pad);
9695
9696     if (stream->protected) {
9697       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9698         GST_ERROR_OBJECT (qtdemux,
9699             "Failed to configure protected stream caps.");
9700         return FALSE;
9701       }
9702     }
9703
9704     if (stream->new_stream) {
9705       GstEvent *event;
9706       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9707
9708       event =
9709           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9710           0);
9711       if (event) {
9712         gst_event_parse_stream_flags (event, &stream_flags);
9713         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9714           qtdemux->have_group_id = TRUE;
9715         else
9716           qtdemux->have_group_id = FALSE;
9717         gst_event_unref (event);
9718       } else if (!qtdemux->have_group_id) {
9719         qtdemux->have_group_id = TRUE;
9720         qtdemux->group_id = gst_util_group_id_next ();
9721       }
9722
9723       stream->new_stream = FALSE;
9724       event = gst_event_new_stream_start (stream->stream_id);
9725       if (qtdemux->have_group_id)
9726         gst_event_set_group_id (event, qtdemux->group_id);
9727       if (stream->disabled)
9728         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9729       if (CUR_STREAM (stream)->sparse) {
9730         stream_flags |= GST_STREAM_FLAG_SPARSE;
9731       } else {
9732         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9733       }
9734       gst_event_set_stream_flags (event, stream_flags);
9735       gst_pad_push_event (stream->pad, event);
9736
9737       forward_collection = TRUE;
9738     }
9739
9740     prev_caps = gst_pad_get_current_caps (stream->pad);
9741
9742     if (CUR_STREAM (stream)->caps) {
9743       if (!prev_caps
9744           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9745         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9746             CUR_STREAM (stream)->caps);
9747         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9748       } else {
9749         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9750       }
9751     } else {
9752       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9753     }
9754
9755     if (prev_caps)
9756       gst_caps_unref (prev_caps);
9757     stream->new_caps = FALSE;
9758
9759     if (forward_collection) {
9760       /* Forward upstream collection and selection if any */
9761       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9762           GST_EVENT_STREAM_COLLECTION, 0);
9763       if (upstream_event)
9764         gst_pad_push_event (stream->pad, upstream_event);
9765     }
9766   }
9767   return TRUE;
9768 }
9769
9770 static void
9771 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9772     QtDemuxStream * stream)
9773 {
9774   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9775     return;
9776
9777   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9778       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9779   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9780           stream->stsd_entries_length)) {
9781     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9782         (_("This file is invalid and cannot be played.")),
9783         ("New sample description id is out of bounds (%d >= %d)",
9784             stream->stsd_sample_description_id, stream->stsd_entries_length));
9785   } else {
9786     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9787     stream->new_caps = TRUE;
9788   }
9789 }
9790
9791 static gboolean
9792 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9793     QtDemuxStream * stream, GstTagList * list)
9794 {
9795   gboolean ret = TRUE;
9796
9797   if (stream->subtype == FOURCC_vide) {
9798     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9799
9800     stream->pad =
9801         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9802     g_free (name);
9803
9804     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9805       gst_object_unref (stream->pad);
9806       stream->pad = NULL;
9807       ret = FALSE;
9808       goto done;
9809     }
9810
9811     qtdemux->n_video_streams++;
9812   } else if (stream->subtype == FOURCC_soun) {
9813     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9814
9815     stream->pad =
9816         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9817     g_free (name);
9818     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9819       gst_object_unref (stream->pad);
9820       stream->pad = NULL;
9821       ret = FALSE;
9822       goto done;
9823     }
9824     qtdemux->n_audio_streams++;
9825   } else if (stream->subtype == FOURCC_strm) {
9826     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9827   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9828       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9829       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9830     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9831
9832     stream->pad =
9833         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9834     g_free (name);
9835     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9836       gst_object_unref (stream->pad);
9837       stream->pad = NULL;
9838       ret = FALSE;
9839       goto done;
9840     }
9841     qtdemux->n_sub_streams++;
9842   } else if (stream->subtype == FOURCC_meta) {
9843     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9844
9845     stream->pad =
9846         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9847     g_free (name);
9848     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9849       gst_object_unref (stream->pad);
9850       stream->pad = NULL;
9851       ret = FALSE;
9852       goto done;
9853     }
9854     qtdemux->n_meta_streams++;
9855   } else if (CUR_STREAM (stream)->caps) {
9856     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9857
9858     stream->pad =
9859         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9860     g_free (name);
9861     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9862       gst_object_unref (stream->pad);
9863       stream->pad = NULL;
9864       ret = FALSE;
9865       goto done;
9866     }
9867     qtdemux->n_video_streams++;
9868   } else {
9869     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9870     goto done;
9871   }
9872
9873   if (stream->pad) {
9874     GList *l;
9875
9876     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9877         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9878     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9879     GST_OBJECT_LOCK (qtdemux);
9880     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9881     GST_OBJECT_UNLOCK (qtdemux);
9882
9883     if (stream->stream_tags)
9884       gst_tag_list_unref (stream->stream_tags);
9885     stream->stream_tags = list;
9886     list = NULL;
9887     /* global tags go on each pad anyway */
9888     stream->send_global_tags = TRUE;
9889     /* send upstream GST_EVENT_PROTECTION events that were received before
9890        this source pad was created */
9891     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9892       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9893   }
9894 done:
9895   if (list)
9896     gst_tag_list_unref (list);
9897   return ret;
9898 }
9899
9900 /* find next atom with @fourcc starting at @offset */
9901 static GstFlowReturn
9902 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9903     guint64 * length, guint32 fourcc)
9904 {
9905   GstFlowReturn ret;
9906   guint32 lfourcc;
9907   GstBuffer *buf;
9908
9909   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9910       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9911
9912   while (TRUE) {
9913     GstMapInfo map;
9914
9915     buf = NULL;
9916     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9917     if (G_UNLIKELY (ret != GST_FLOW_OK))
9918       goto locate_failed;
9919     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9920       /* likely EOF */
9921       ret = GST_FLOW_EOS;
9922       gst_buffer_unref (buf);
9923       goto locate_failed;
9924     }
9925     gst_buffer_map (buf, &map, GST_MAP_READ);
9926     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9927     gst_buffer_unmap (buf, &map);
9928     gst_buffer_unref (buf);
9929
9930     if (G_UNLIKELY (*length == 0)) {
9931       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9932       ret = GST_FLOW_ERROR;
9933       goto locate_failed;
9934     }
9935
9936     if (lfourcc == fourcc) {
9937       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9938           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9939       break;
9940     } else {
9941       GST_LOG_OBJECT (qtdemux,
9942           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9943           GST_FOURCC_ARGS (lfourcc), *offset);
9944       if (*offset == G_MAXUINT64)
9945         goto locate_failed;
9946       *offset += *length;
9947     }
9948   }
9949
9950   return GST_FLOW_OK;
9951
9952 locate_failed:
9953   {
9954     /* might simply have had last one */
9955     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9956     return ret;
9957   }
9958 }
9959
9960 /* should only do something in pull mode */
9961 /* call with OBJECT lock */
9962 static GstFlowReturn
9963 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9964 {
9965   guint64 length, offset;
9966   GstBuffer *buf = NULL;
9967   GstFlowReturn ret = GST_FLOW_OK;
9968   GstFlowReturn res = GST_FLOW_OK;
9969   GstMapInfo map;
9970
9971   offset = qtdemux->moof_offset;
9972   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9973
9974   if (!offset) {
9975     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9976     return GST_FLOW_EOS;
9977   }
9978
9979   /* best not do pull etc with lock held */
9980   GST_OBJECT_UNLOCK (qtdemux);
9981
9982   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9983   if (ret != GST_FLOW_OK)
9984     goto flow_failed;
9985
9986   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9987   if (G_UNLIKELY (ret != GST_FLOW_OK))
9988     goto flow_failed;
9989   gst_buffer_map (buf, &map, GST_MAP_READ);
9990   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9991     gst_buffer_unmap (buf, &map);
9992     gst_buffer_unref (buf);
9993     buf = NULL;
9994     goto parse_failed;
9995   }
9996
9997   gst_buffer_unmap (buf, &map);
9998   gst_buffer_unref (buf);
9999   buf = NULL;
10000
10001   offset += length;
10002   /* look for next moof */
10003   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
10004   if (G_UNLIKELY (ret != GST_FLOW_OK))
10005     goto flow_failed;
10006
10007 exit:
10008   GST_OBJECT_LOCK (qtdemux);
10009
10010   qtdemux->moof_offset = offset;
10011
10012   return res;
10013
10014 parse_failed:
10015   {
10016     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
10017     offset = 0;
10018     res = GST_FLOW_ERROR;
10019     goto exit;
10020   }
10021 flow_failed:
10022   {
10023     /* maybe upstream temporarily flushing */
10024     if (ret != GST_FLOW_FLUSHING) {
10025       GST_DEBUG_OBJECT (qtdemux, "no next moof");
10026       offset = 0;
10027     } else {
10028       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
10029       /* resume at current position next time */
10030     }
10031     res = ret;
10032     goto exit;
10033   }
10034 }
10035
10036 static void
10037 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
10038 {
10039   guint i;
10040   guint32 num_chunks;
10041   gint32 stts_duration;
10042   GstByteWriter stsc, stts, stsz;
10043
10044   /* Each sample has a different size, which we don't support for merging */
10045   if (stream->sample_size == 0) {
10046     GST_DEBUG_OBJECT (qtdemux,
10047         "Not all samples have the same size, not merging");
10048     return;
10049   }
10050
10051   /* The stream has a ctts table, we don't support that */
10052   if (stream->ctts_present) {
10053     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
10054     return;
10055   }
10056
10057   /* If there's a sync sample table also ignore this stream */
10058   if (stream->stps_present || stream->stss_present) {
10059     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
10060     return;
10061   }
10062
10063   /* If chunks are considered samples already ignore this stream */
10064   if (stream->chunks_are_samples) {
10065     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
10066     return;
10067   }
10068
10069   /* Require that all samples have the same duration */
10070   if (stream->n_sample_times > 1) {
10071     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
10072     return;
10073   }
10074
10075   /* Parse the stts to get the sample duration and number of samples */
10076   gst_byte_reader_skip_unchecked (&stream->stts, 4);
10077   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10078
10079   /* Parse the number of chunks from the stco manually because the
10080    * reader is already behind that */
10081   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
10082
10083   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
10084       num_chunks);
10085
10086   /* Now parse stsc, convert chunks into single samples and generate a
10087    * new stsc, stts and stsz from this information */
10088   gst_byte_writer_init (&stsc);
10089   gst_byte_writer_init (&stts);
10090   gst_byte_writer_init (&stsz);
10091
10092   /* Note: we skip fourccs, size, version, flags and other fields of the new
10093    * atoms as the byte readers with them are already behind that position
10094    * anyway and only update the values of those inside the stream directly.
10095    */
10096   stream->n_sample_times = 0;
10097   stream->n_samples = 0;
10098   for (i = 0; i < stream->n_samples_per_chunk; i++) {
10099     guint j;
10100     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
10101
10102     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10103     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10104     sample_description_id =
10105         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10106
10107     if (i == stream->n_samples_per_chunk - 1) {
10108       /* +1 because first_chunk is 1-based */
10109       last_chunk = num_chunks + 1;
10110     } else {
10111       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
10112     }
10113
10114     GST_DEBUG_OBJECT (qtdemux,
10115         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
10116         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
10117
10118     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
10119     /* One sample in this chunk */
10120     gst_byte_writer_put_uint32_be (&stsc, 1);
10121     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
10122
10123     /* For each chunk write a stts and stsz entry now */
10124     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
10125     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
10126     for (j = first_chunk; j < last_chunk; j++) {
10127       gst_byte_writer_put_uint32_be (&stsz,
10128           stream->sample_size * samples_per_chunk);
10129     }
10130
10131     stream->n_sample_times += 1;
10132     stream->n_samples += last_chunk - first_chunk;
10133   }
10134
10135   g_assert_cmpint (stream->n_samples, ==, num_chunks);
10136
10137   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
10138       stream->n_samples, stream->n_sample_times);
10139
10140   /* We don't have a fixed sample size anymore */
10141   stream->sample_size = 0;
10142
10143   /* Free old data for the atoms */
10144   g_free ((gpointer) stream->stsz.data);
10145   stream->stsz.data = NULL;
10146   g_free ((gpointer) stream->stsc.data);
10147   stream->stsc.data = NULL;
10148   g_free ((gpointer) stream->stts.data);
10149   stream->stts.data = NULL;
10150
10151   /* Store new data and replace byte readers */
10152   stream->stsz.size = gst_byte_writer_get_size (&stsz);
10153   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
10154   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
10155   stream->stts.size = gst_byte_writer_get_size (&stts);
10156   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
10157   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
10158   stream->stsc.size = gst_byte_writer_get_size (&stsc);
10159   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
10160   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
10161 }
10162
10163 /* initialise bytereaders for stbl sub-atoms */
10164 static gboolean
10165 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
10166 {
10167   stream->stbl_index = -1;      /* no samples have yet been parsed */
10168   stream->sample_index = -1;
10169
10170   /* time-to-sample atom */
10171   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
10172     goto corrupt_file;
10173
10174   /* copy atom data into a new buffer for later use */
10175   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
10176
10177   /* skip version + flags */
10178   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
10179       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
10180     goto corrupt_file;
10181   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
10182
10183   /* make sure there's enough data */
10184   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
10185     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
10186     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
10187         stream->n_sample_times);
10188     if (!stream->n_sample_times)
10189       goto corrupt_file;
10190   }
10191
10192   /* sync sample atom */
10193   stream->stps_present = FALSE;
10194   if ((stream->stss_present =
10195           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
10196               &stream->stss) ? TRUE : FALSE) == TRUE) {
10197     /* copy atom data into a new buffer for later use */
10198     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
10199
10200     /* skip version + flags */
10201     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
10202         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
10203       goto corrupt_file;
10204
10205     if (stream->n_sample_syncs) {
10206       /* make sure there's enough data */
10207       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
10208         goto corrupt_file;
10209     }
10210
10211     /* partial sync sample atom */
10212     if ((stream->stps_present =
10213             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
10214                 &stream->stps) ? TRUE : FALSE) == TRUE) {
10215       /* copy atom data into a new buffer for later use */
10216       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
10217
10218       /* skip version + flags */
10219       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
10220           !gst_byte_reader_get_uint32_be (&stream->stps,
10221               &stream->n_sample_partial_syncs))
10222         goto corrupt_file;
10223
10224       /* if there are no entries, the stss table contains the real
10225        * sync samples */
10226       if (stream->n_sample_partial_syncs) {
10227         /* make sure there's enough data */
10228         if (!qt_atom_parser_has_chunks (&stream->stps,
10229                 stream->n_sample_partial_syncs, 4))
10230           goto corrupt_file;
10231       }
10232     }
10233   }
10234
10235   /* sample size */
10236   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
10237     goto no_samples;
10238
10239   /* copy atom data into a new buffer for later use */
10240   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
10241
10242   /* skip version + flags */
10243   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
10244       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
10245     goto corrupt_file;
10246
10247   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
10248     goto corrupt_file;
10249
10250   if (!stream->n_samples)
10251     goto no_samples;
10252
10253   /* sample-to-chunk atom */
10254   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
10255     goto corrupt_file;
10256
10257   /* copy atom data into a new buffer for later use */
10258   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
10259
10260   /* skip version + flags */
10261   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
10262       !gst_byte_reader_get_uint32_be (&stream->stsc,
10263           &stream->n_samples_per_chunk))
10264     goto corrupt_file;
10265
10266   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
10267       stream->n_samples_per_chunk);
10268
10269   /* make sure there's enough data */
10270   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
10271           12))
10272     goto corrupt_file;
10273
10274
10275   /* chunk offset */
10276   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
10277     stream->co_size = sizeof (guint32);
10278   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
10279           &stream->stco))
10280     stream->co_size = sizeof (guint64);
10281   else
10282     goto corrupt_file;
10283
10284   /* copy atom data into a new buffer for later use */
10285   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
10286
10287   /* skip version + flags */
10288   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
10289     goto corrupt_file;
10290
10291   /* chunks_are_samples == TRUE means treat chunks as samples */
10292   stream->chunks_are_samples = stream->sample_size
10293       && !CUR_STREAM (stream)->sampled;
10294   if (stream->chunks_are_samples) {
10295     /* treat chunks as samples */
10296     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
10297       goto corrupt_file;
10298   } else {
10299     /* skip number of entries */
10300     if (!gst_byte_reader_skip (&stream->stco, 4))
10301       goto corrupt_file;
10302
10303     /* make sure there are enough data in the stsz atom */
10304     if (!stream->sample_size) {
10305       /* different sizes for each sample */
10306       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
10307         goto corrupt_file;
10308     }
10309   }
10310
10311   /* composition time-to-sample */
10312   if ((stream->ctts_present =
10313           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
10314               &stream->ctts) ? TRUE : FALSE) == TRUE) {
10315     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
10316     guint8 ctts_version;
10317     gboolean checked_ctts = FALSE;
10318
10319     /* copy atom data into a new buffer for later use */
10320     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
10321
10322     /* version 1 has signed offsets */
10323     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
10324       goto corrupt_file;
10325
10326     /* flags */
10327     if (!gst_byte_reader_skip (&stream->ctts, 3)
10328         || !gst_byte_reader_get_uint32_be (&stream->ctts,
10329             &stream->n_composition_times))
10330       goto corrupt_file;
10331
10332     /* make sure there's enough data */
10333     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
10334             4 + 4))
10335       goto corrupt_file;
10336
10337     /* This is optional, if missing we iterate the ctts */
10338     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
10339       guint8 cslg_version;
10340
10341       /* cslg version 1 has 64 bit fields */
10342       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
10343         goto corrupt_file;
10344
10345       /* skip flags */
10346       if (!gst_byte_reader_skip (&cslg, 3))
10347         goto corrupt_file;
10348
10349       if (cslg_version == 0) {
10350         gint32 composition_to_dts_shift;
10351
10352         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
10353           goto corrupt_file;
10354
10355         stream->cslg_shift = MAX (0, composition_to_dts_shift);
10356       } else {
10357         gint64 composition_to_dts_shift;
10358
10359         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
10360           goto corrupt_file;
10361
10362         stream->cslg_shift = MAX (0, composition_to_dts_shift);
10363       }
10364     } else {
10365       gint32 cslg_least = 0;
10366       guint num_entries, pos;
10367       gint i;
10368
10369       pos = gst_byte_reader_get_pos (&stream->ctts);
10370       num_entries = stream->n_composition_times;
10371
10372       checked_ctts = TRUE;
10373
10374       stream->cslg_shift = 0;
10375
10376       for (i = 0; i < num_entries; i++) {
10377         gint32 offset;
10378
10379         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
10380         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10381         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
10382          * slightly inaccurate PTS could be more usable than corrupted one */
10383         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
10384                 && ABS (offset) / 2 > stream->duration)) {
10385           GST_WARNING_OBJECT (qtdemux,
10386               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
10387               " larger than duration %" G_GUINT64_FORMAT, offset,
10388               stream->duration);
10389
10390           stream->cslg_shift = 0;
10391           stream->ctts_present = FALSE;
10392           goto done;
10393         }
10394
10395         /* Don't consider "no decode samples" with offset G_MININT32
10396          * for the DTS/PTS shift */
10397         if (offset != G_MININT32 && offset < cslg_least)
10398           cslg_least = offset;
10399       }
10400
10401       if (cslg_least < 0)
10402         stream->cslg_shift = -cslg_least;
10403       else
10404         stream->cslg_shift = 0;
10405
10406       /* reset the reader so we can generate sample table */
10407       gst_byte_reader_set_pos (&stream->ctts, pos);
10408     }
10409
10410     /* Check if ctts values are looking reasonable if that didn't happen above */
10411     if (!checked_ctts) {
10412       guint num_entries, pos;
10413       gint i;
10414
10415       pos = gst_byte_reader_get_pos (&stream->ctts);
10416       num_entries = stream->n_composition_times;
10417
10418       for (i = 0; i < num_entries; i++) {
10419         gint32 offset;
10420
10421         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
10422         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10423         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
10424          * slightly inaccurate PTS could be more usable than corrupted one */
10425         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
10426                 && ABS (offset) / 2 > stream->duration)) {
10427           GST_WARNING_OBJECT (qtdemux,
10428               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
10429               " larger than duration %" G_GUINT64_FORMAT, offset,
10430               stream->duration);
10431
10432           stream->cslg_shift = 0;
10433           stream->ctts_present = FALSE;
10434           goto done;
10435         }
10436       }
10437
10438       /* reset the reader so we can generate sample table */
10439       gst_byte_reader_set_pos (&stream->ctts, pos);
10440     }
10441   } else {
10442     /* Ensure the cslg_shift value is consistent so we can use it
10443      * unconditionally to produce TS and Segment */
10444     stream->cslg_shift = 0;
10445   }
10446
10447   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
10448       stream->cslg_shift);
10449
10450   /* For raw audio streams especially we might want to merge the samples
10451    * to not output one audio sample per buffer. We're doing this here
10452    * before allocating the sample tables so that from this point onwards
10453    * the number of container samples are static */
10454   if (stream->min_buffer_size > 0) {
10455     qtdemux_merge_sample_table (qtdemux, stream);
10456   }
10457
10458 done:
10459   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
10460       stream->n_samples, (guint) sizeof (QtDemuxSample),
10461       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
10462
10463   if (stream->n_samples >=
10464       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
10465     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
10466         "be larger than %uMB (broken file?)", stream->n_samples,
10467         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
10468     return FALSE;
10469   }
10470
10471   g_assert (stream->samples == NULL);
10472   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
10473   if (!stream->samples) {
10474     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
10475         stream->n_samples);
10476     return FALSE;
10477   }
10478
10479   return TRUE;
10480
10481 corrupt_file:
10482   {
10483     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10484         (_("This file is corrupt and cannot be played.")), (NULL));
10485     return FALSE;
10486   }
10487 no_samples:
10488   {
10489     gst_qtdemux_stbl_free (stream);
10490     if (!qtdemux->fragmented) {
10491       /* not quite good */
10492       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
10493       return FALSE;
10494     } else {
10495       /* may pick up samples elsewhere */
10496       return TRUE;
10497     }
10498   }
10499 }
10500
10501 /* collect samples from the next sample to be parsed up to sample @n for @stream
10502  * by reading the info from @stbl
10503  *
10504  * This code can be executed from both the streaming thread and the seeking
10505  * thread so it takes the object lock to protect itself
10506  */
10507 static gboolean
10508 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
10509 {
10510   gint i, j, k;
10511   QtDemuxSample *samples, *first, *cur, *last;
10512   guint32 n_samples_per_chunk;
10513   guint32 n_samples;
10514
10515   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
10516       GST_FOURCC_FORMAT ", pad %s",
10517       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
10518       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
10519
10520   n_samples = stream->n_samples;
10521
10522   if (n >= n_samples)
10523     goto out_of_samples;
10524
10525   GST_OBJECT_LOCK (qtdemux);
10526   if (n <= stream->stbl_index)
10527     goto already_parsed;
10528
10529   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
10530
10531   if (!stream->stsz.data) {
10532     /* so we already parsed and passed all the moov samples;
10533      * onto fragmented ones */
10534     g_assert (qtdemux->fragmented);
10535     goto done;
10536   }
10537
10538   /* pointer to the sample table */
10539   samples = stream->samples;
10540
10541   /* starts from -1, moves to the next sample index to parse */
10542   stream->stbl_index++;
10543
10544   /* keep track of the first and last sample to fill */
10545   first = &samples[stream->stbl_index];
10546   last = &samples[n];
10547
10548   if (!stream->chunks_are_samples) {
10549     /* set the sample sizes */
10550     if (stream->sample_size == 0) {
10551       /* different sizes for each sample */
10552       for (cur = first; cur <= last; cur++) {
10553         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
10554         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
10555             (guint) (cur - samples), cur->size);
10556       }
10557     } else {
10558       /* samples have the same size */
10559       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
10560       for (cur = first; cur <= last; cur++)
10561         cur->size = stream->sample_size;
10562     }
10563   }
10564
10565   n_samples_per_chunk = stream->n_samples_per_chunk;
10566   cur = first;
10567
10568   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
10569     guint32 last_chunk;
10570
10571     if (stream->stsc_chunk_index >= stream->last_chunk
10572         || stream->stsc_chunk_index < stream->first_chunk) {
10573       stream->first_chunk =
10574           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10575       stream->samples_per_chunk =
10576           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10577       /* starts from 1 */
10578       stream->stsd_sample_description_id =
10579           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
10580
10581       /* chunk numbers are counted from 1 it seems */
10582       if (G_UNLIKELY (stream->first_chunk == 0))
10583         goto corrupt_file;
10584
10585       --stream->first_chunk;
10586
10587       /* the last chunk of each entry is calculated by taking the first chunk
10588        * of the next entry; except if there is no next, where we fake it with
10589        * INT_MAX */
10590       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
10591         stream->last_chunk = G_MAXUINT32;
10592       } else {
10593         stream->last_chunk =
10594             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
10595         if (G_UNLIKELY (stream->last_chunk == 0))
10596           goto corrupt_file;
10597
10598         --stream->last_chunk;
10599       }
10600
10601       GST_LOG_OBJECT (qtdemux,
10602           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
10603           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
10604           stream->samples_per_chunk, stream->stsd_sample_description_id);
10605
10606       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
10607         goto corrupt_file;
10608
10609       if (stream->last_chunk != G_MAXUINT32) {
10610         if (!qt_atom_parser_peek_sub (&stream->stco,
10611                 stream->first_chunk * stream->co_size,
10612                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
10613                 &stream->co_chunk))
10614           goto corrupt_file;
10615
10616       } else {
10617         stream->co_chunk = stream->stco;
10618         if (!gst_byte_reader_skip (&stream->co_chunk,
10619                 stream->first_chunk * stream->co_size))
10620           goto corrupt_file;
10621       }
10622
10623       stream->stsc_chunk_index = stream->first_chunk;
10624     }
10625
10626     last_chunk = stream->last_chunk;
10627
10628     if (stream->chunks_are_samples) {
10629       cur = &samples[stream->stsc_chunk_index];
10630
10631       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
10632         if (j > n) {
10633           /* save state */
10634           stream->stsc_chunk_index = j;
10635           goto done;
10636         }
10637
10638         cur->offset =
10639             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
10640             stream->co_size);
10641
10642         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
10643             "%" G_GUINT64_FORMAT, j, cur->offset);
10644
10645         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
10646             CUR_STREAM (stream)->bytes_per_frame > 0) {
10647           cur->size =
10648               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
10649               CUR_STREAM (stream)->samples_per_frame *
10650               CUR_STREAM (stream)->bytes_per_frame;
10651         } else {
10652           cur->size = stream->samples_per_chunk;
10653         }
10654
10655         GST_DEBUG_OBJECT (qtdemux,
10656             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
10657             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
10658                     stream->stco_sample_index)), cur->size);
10659
10660         cur->timestamp = stream->stco_sample_index;
10661         cur->duration = stream->samples_per_chunk;
10662         cur->keyframe = TRUE;
10663         cur++;
10664
10665         stream->stco_sample_index += stream->samples_per_chunk;
10666       }
10667       stream->stsc_chunk_index = j;
10668     } else {
10669       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
10670         guint32 samples_per_chunk;
10671         guint64 chunk_offset;
10672
10673         if (!stream->stsc_sample_index
10674             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
10675                 &stream->chunk_offset))
10676           goto corrupt_file;
10677
10678         samples_per_chunk = stream->samples_per_chunk;
10679         chunk_offset = stream->chunk_offset;
10680
10681         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
10682           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
10683               G_GUINT64_FORMAT " and size %d",
10684               (guint) (cur - samples), chunk_offset, cur->size);
10685
10686           cur->offset = chunk_offset;
10687           chunk_offset += cur->size;
10688           cur++;
10689
10690           if (G_UNLIKELY (cur > last)) {
10691             /* save state */
10692             stream->stsc_sample_index = k + 1;
10693             stream->chunk_offset = chunk_offset;
10694             stream->stsc_chunk_index = j;
10695             goto done2;
10696           }
10697         }
10698         stream->stsc_sample_index = 0;
10699       }
10700       stream->stsc_chunk_index = j;
10701     }
10702     stream->stsc_index++;
10703   }
10704
10705   if (stream->chunks_are_samples)
10706     goto ctts;
10707 done2:
10708   {
10709     guint32 n_sample_times;
10710
10711     n_sample_times = stream->n_sample_times;
10712     cur = first;
10713
10714     for (i = stream->stts_index; i < n_sample_times; i++) {
10715       guint32 stts_samples;
10716       gint32 stts_duration;
10717       gint64 stts_time;
10718
10719       if (stream->stts_sample_index >= stream->stts_samples
10720           || !stream->stts_sample_index) {
10721
10722         stream->stts_samples =
10723             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10724         stream->stts_duration =
10725             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10726
10727         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10728             i, stream->stts_samples, stream->stts_duration);
10729
10730         stream->stts_sample_index = 0;
10731       }
10732
10733       stts_samples = stream->stts_samples;
10734       stts_duration = stream->stts_duration;
10735       stts_time = stream->stts_time;
10736
10737       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10738         GST_DEBUG_OBJECT (qtdemux,
10739             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10740             (guint) (cur - samples), j,
10741             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10742
10743         cur->timestamp = stts_time;
10744         cur->duration = stts_duration;
10745
10746         /* avoid 32-bit wrap-around,
10747          * but still mind possible 'negative' duration */
10748         stts_time += (gint64) stts_duration;
10749         cur++;
10750
10751         if (G_UNLIKELY (cur > last)) {
10752           /* save values */
10753           stream->stts_time = stts_time;
10754           stream->stts_sample_index = j + 1;
10755           if (stream->stts_sample_index >= stream->stts_samples)
10756             stream->stts_index++;
10757           goto done3;
10758         }
10759       }
10760       stream->stts_sample_index = 0;
10761       stream->stts_time = stts_time;
10762       stream->stts_index++;
10763     }
10764     /* fill up empty timestamps with the last timestamp, this can happen when
10765      * the last samples do not decode and so we don't have timestamps for them.
10766      * We however look at the last timestamp to estimate the track length so we
10767      * need something in here. */
10768     for (; cur < last; cur++) {
10769       GST_DEBUG_OBJECT (qtdemux,
10770           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10771           (guint) (cur - samples),
10772           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10773       cur->timestamp = stream->stts_time;
10774       cur->duration = -1;
10775     }
10776   }
10777 done3:
10778   {
10779     /* sample sync, can be NULL */
10780     if (stream->stss_present == TRUE) {
10781       guint32 n_sample_syncs;
10782
10783       n_sample_syncs = stream->n_sample_syncs;
10784
10785       if (!n_sample_syncs) {
10786         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10787         stream->all_keyframe = TRUE;
10788       } else {
10789         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10790           /* note that the first sample is index 1, not 0 */
10791           guint32 index;
10792
10793           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10794
10795           if (G_LIKELY (index > 0 && index <= n_samples)) {
10796             index -= 1;
10797             samples[index].keyframe = TRUE;
10798             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10799             /* and exit if we have enough samples */
10800             if (G_UNLIKELY (index >= n)) {
10801               i++;
10802               break;
10803             }
10804           }
10805         }
10806         /* save state */
10807         stream->stss_index = i;
10808       }
10809
10810       /* stps marks partial sync frames like open GOP I-Frames */
10811       if (stream->stps_present == TRUE) {
10812         guint32 n_sample_partial_syncs;
10813
10814         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10815
10816         /* if there are no entries, the stss table contains the real
10817          * sync samples */
10818         if (n_sample_partial_syncs) {
10819           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10820             /* note that the first sample is index 1, not 0 */
10821             guint32 index;
10822
10823             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10824
10825             if (G_LIKELY (index > 0 && index <= n_samples)) {
10826               index -= 1;
10827               samples[index].keyframe = TRUE;
10828               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10829               /* and exit if we have enough samples */
10830               if (G_UNLIKELY (index >= n)) {
10831                 i++;
10832                 break;
10833               }
10834             }
10835           }
10836           /* save state */
10837           stream->stps_index = i;
10838         }
10839       }
10840     } else {
10841       /* no stss, all samples are keyframes */
10842       stream->all_keyframe = TRUE;
10843       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10844     }
10845   }
10846
10847 ctts:
10848   /* composition time to sample */
10849   if (stream->ctts_present == TRUE) {
10850     guint32 n_composition_times;
10851     guint32 ctts_count;
10852     gint32 ctts_soffset;
10853
10854     /* Fill in the pts_offsets */
10855     cur = first;
10856     n_composition_times = stream->n_composition_times;
10857
10858     for (i = stream->ctts_index; i < n_composition_times; i++) {
10859       if (stream->ctts_sample_index >= stream->ctts_count
10860           || !stream->ctts_sample_index) {
10861         stream->ctts_count =
10862             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10863         stream->ctts_soffset =
10864             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10865         stream->ctts_sample_index = 0;
10866       }
10867
10868       ctts_count = stream->ctts_count;
10869       ctts_soffset = stream->ctts_soffset;
10870
10871       /* FIXME: Set offset to 0 for "no decode samples". This needs
10872        * to be handled in a codec specific manner ideally. */
10873       if (ctts_soffset == G_MININT32)
10874         ctts_soffset = 0;
10875
10876       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10877         cur->pts_offset = ctts_soffset;
10878         cur++;
10879
10880         if (G_UNLIKELY (cur > last)) {
10881           /* save state */
10882           stream->ctts_sample_index = j + 1;
10883           goto done;
10884         }
10885       }
10886       stream->ctts_sample_index = 0;
10887       stream->ctts_index++;
10888     }
10889   }
10890 done:
10891   stream->stbl_index = n;
10892   /* if index has been completely parsed, free data that is no-longer needed */
10893   if (n + 1 == stream->n_samples) {
10894     gst_qtdemux_stbl_free (stream);
10895     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10896     if (qtdemux->pullbased) {
10897       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10898       while (n + 1 == stream->n_samples)
10899         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10900           break;
10901     }
10902   }
10903   GST_OBJECT_UNLOCK (qtdemux);
10904
10905   return TRUE;
10906
10907   /* SUCCESS */
10908 already_parsed:
10909   {
10910     GST_LOG_OBJECT (qtdemux,
10911         "Tried to parse up to sample %u but this sample has already been parsed",
10912         n);
10913     /* if fragmented, there may be more */
10914     if (qtdemux->fragmented && n == stream->stbl_index)
10915       goto done;
10916     GST_OBJECT_UNLOCK (qtdemux);
10917     return TRUE;
10918   }
10919   /* ERRORS */
10920 out_of_samples:
10921   {
10922     GST_LOG_OBJECT (qtdemux,
10923         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10924         stream->n_samples);
10925     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10926         (_("This file is corrupt and cannot be played.")), (NULL));
10927     return FALSE;
10928   }
10929 corrupt_file:
10930   {
10931     GST_OBJECT_UNLOCK (qtdemux);
10932     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10933         (_("This file is corrupt and cannot be played.")), (NULL));
10934     return FALSE;
10935   }
10936 }
10937
10938 /* collect all segment info for @stream.
10939  */
10940 static gboolean
10941 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10942     GNode * trak)
10943 {
10944   GNode *edts;
10945   /* accept edts if they contain gaps at start and there is only
10946    * one media segment */
10947   gboolean allow_pushbased_edts = TRUE;
10948   gint media_segments_count = 0;
10949
10950   /* parse and prepare segment info from the edit list */
10951   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10952   stream->n_segments = 0;
10953   stream->segments = NULL;
10954   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10955     GNode *elst;
10956     guint n_segments;
10957     guint segment_number, entry_size;
10958     guint64 time;
10959     GstClockTime stime;
10960     const guint8 *buffer;
10961     guint8 version;
10962     guint32 size;
10963
10964     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10965     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10966       goto done;
10967
10968     buffer = elst->data;
10969
10970     size = QT_UINT32 (buffer);
10971     /* version, flags, n_segments */
10972     if (size < 16) {
10973       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10974       goto done;
10975     }
10976     version = QT_UINT8 (buffer + 8);
10977     entry_size = (version == 1) ? 20 : 12;
10978
10979     n_segments = QT_UINT32 (buffer + 12);
10980
10981     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10982       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10983       goto done;
10984     }
10985
10986     /* we might allocate a bit too much, at least allocate 1 segment */
10987     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10988
10989     /* segments always start from 0 */
10990     time = 0;
10991     stime = 0;
10992     buffer += 16;
10993     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10994       guint64 duration;
10995       guint64 media_time;
10996       gboolean empty_edit = FALSE;
10997       QtDemuxSegment *segment;
10998       guint32 rate_int;
10999       GstClockTime media_start = GST_CLOCK_TIME_NONE;
11000
11001       if (version == 1) {
11002         media_time = QT_UINT64 (buffer + 8);
11003         duration = QT_UINT64 (buffer);
11004         if (media_time == G_MAXUINT64)
11005           empty_edit = TRUE;
11006       } else {
11007         media_time = QT_UINT32 (buffer + 4);
11008         duration = QT_UINT32 (buffer);
11009         if (media_time == G_MAXUINT32)
11010           empty_edit = TRUE;
11011       }
11012
11013       if (!empty_edit)
11014         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
11015
11016       segment = &stream->segments[segment_number];
11017
11018       /* time and duration expressed in global timescale */
11019       segment->time = stime;
11020       if (duration != 0 || empty_edit) {
11021         /* edge case: empty edits with duration=zero are treated here.
11022          * (files should not have these anyway). */
11023
11024         /* add non scaled values so we don't cause roundoff errors */
11025         time += duration;
11026         stime = QTTIME_TO_GSTTIME (qtdemux, time);
11027         segment->duration = stime - segment->time;
11028       } else {
11029         /* zero duration does not imply media_start == media_stop
11030          * but, only specify media_start. The edit ends with the track. */
11031         stime = segment->duration = GST_CLOCK_TIME_NONE;
11032         /* Don't allow more edits after this one. */
11033         n_segments = segment_number + 1;
11034       }
11035       segment->stop_time = stime;
11036
11037       segment->trak_media_start = media_time;
11038       /* media_time expressed in stream timescale */
11039       if (!empty_edit) {
11040         segment->media_start = media_start;
11041         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
11042             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
11043         media_segments_count++;
11044       } else {
11045         segment->media_start = GST_CLOCK_TIME_NONE;
11046         segment->media_stop = GST_CLOCK_TIME_NONE;
11047       }
11048       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
11049
11050       if (rate_int <= 1) {
11051         /* 0 is not allowed, some programs write 1 instead of the floating point
11052          * value */
11053         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
11054             rate_int);
11055         segment->rate = 1;
11056       } else {
11057         segment->rate = rate_int / 65536.0;
11058       }
11059
11060       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
11061           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
11062           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
11063           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
11064           segment_number, GST_TIME_ARGS (segment->time),
11065           GST_TIME_ARGS (segment->duration),
11066           GST_TIME_ARGS (segment->media_start), media_time,
11067           GST_TIME_ARGS (segment->media_stop),
11068           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
11069           stream->timescale);
11070       if (segment->stop_time > qtdemux->segment.stop &&
11071           !qtdemux->upstream_format_is_time) {
11072         GST_WARNING_OBJECT (qtdemux, "Segment %d "
11073             " extends to %" GST_TIME_FORMAT
11074             " past the end of the declared movie duration %" GST_TIME_FORMAT
11075             " movie segment will be extended", segment_number,
11076             GST_TIME_ARGS (segment->stop_time),
11077             GST_TIME_ARGS (qtdemux->segment.stop));
11078         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
11079       }
11080
11081       buffer += entry_size;
11082     }
11083     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
11084     stream->n_segments = n_segments;
11085     if (media_segments_count != 1)
11086       allow_pushbased_edts = FALSE;
11087   }
11088 done:
11089
11090   /* push based does not handle segments, so act accordingly here,
11091    * and warn if applicable */
11092   if (!qtdemux->pullbased && !allow_pushbased_edts) {
11093     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
11094     /* remove and use default one below, we stream like it anyway */
11095     g_free (stream->segments);
11096     stream->segments = NULL;
11097     stream->n_segments = 0;
11098   }
11099
11100   /* no segments, create one to play the complete trak */
11101   if (stream->n_segments == 0) {
11102     GstClockTime stream_duration =
11103         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
11104
11105     if (stream->segments == NULL)
11106       stream->segments = g_new (QtDemuxSegment, 1);
11107
11108     /* represent unknown our way */
11109     if (stream_duration == 0)
11110       stream_duration = GST_CLOCK_TIME_NONE;
11111
11112     stream->segments[0].time = 0;
11113     stream->segments[0].stop_time = stream_duration;
11114     stream->segments[0].duration = stream_duration;
11115     stream->segments[0].media_start = 0;
11116     stream->segments[0].media_stop = stream_duration;
11117     stream->segments[0].rate = 1.0;
11118     stream->segments[0].trak_media_start = 0;
11119
11120     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
11121         GST_TIME_ARGS (stream_duration));
11122     stream->n_segments = 1;
11123     stream->dummy_segment = TRUE;
11124   }
11125   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
11126
11127   return TRUE;
11128 }
11129
11130 /*
11131  * Parses the stsd atom of a svq3 trak looking for
11132  * the SMI and gama atoms.
11133  */
11134 static void
11135 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
11136     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
11137 {
11138   const guint8 *_gamma = NULL;
11139   GstBuffer *_seqh = NULL;
11140   const guint8 *stsd_data = stsd_entry_data;
11141   guint32 length = QT_UINT32 (stsd_data);
11142   guint16 version;
11143
11144   if (length < 32) {
11145     GST_WARNING_OBJECT (qtdemux, "stsd too short");
11146     goto end;
11147   }
11148
11149   stsd_data += 16;
11150   length -= 16;
11151   version = QT_UINT16 (stsd_data);
11152   if (version == 3) {
11153     if (length >= 70) {
11154       length -= 70;
11155       stsd_data += 70;
11156       while (length > 8) {
11157         guint32 fourcc, size;
11158         const guint8 *data;
11159         size = QT_UINT32 (stsd_data);
11160         fourcc = QT_FOURCC (stsd_data + 4);
11161         data = stsd_data + 8;
11162
11163         if (size == 0) {
11164           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
11165               "svq3 atom parsing");
11166           goto end;
11167         }
11168
11169         switch (fourcc) {
11170           case FOURCC_gama:{
11171             if (size == 12) {
11172               _gamma = data;
11173             } else {
11174               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
11175                   " for gama atom, expected 12", size);
11176             }
11177             break;
11178           }
11179           case FOURCC_SMI_:{
11180             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
11181               guint32 seqh_size;
11182               if (_seqh != NULL) {
11183                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
11184                     " found, ignoring");
11185               } else {
11186                 seqh_size = QT_UINT32 (data + 4);
11187                 if (seqh_size > 0) {
11188                   _seqh = gst_buffer_new_and_alloc (seqh_size);
11189                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
11190                 }
11191               }
11192             }
11193             break;
11194           }
11195           default:{
11196             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
11197                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
11198           }
11199         }
11200
11201         if (size <= length) {
11202           length -= size;
11203           stsd_data += size;
11204         }
11205       }
11206     } else {
11207       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
11208     }
11209   } else {
11210     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
11211         G_GUINT16_FORMAT, version);
11212     goto end;
11213   }
11214
11215 end:
11216   if (gamma) {
11217     *gamma = _gamma;
11218   }
11219   if (seqh) {
11220     *seqh = _seqh;
11221   } else if (_seqh) {
11222     gst_buffer_unref (_seqh);
11223   }
11224 }
11225
11226 static gchar *
11227 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
11228 {
11229   GNode *dinf;
11230   GstByteReader dref;
11231   gchar *uri = NULL;
11232
11233   /*
11234    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
11235    * atom that might contain a 'data' atom with the rtsp uri.
11236    * This case was reported in bug #597497, some info about
11237    * the hndl atom can be found in TN1195
11238    */
11239   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
11240   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
11241
11242   if (dinf) {
11243     guint32 dref_num_entries = 0;
11244     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
11245         gst_byte_reader_skip (&dref, 4) &&
11246         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
11247       gint i;
11248
11249       /* search dref entries for hndl atom */
11250       for (i = 0; i < dref_num_entries; i++) {
11251         guint32 size = 0, type;
11252         guint8 string_len = 0;
11253         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
11254             qt_atom_parser_get_fourcc (&dref, &type)) {
11255           if (type == FOURCC_hndl) {
11256             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
11257
11258             /* skip data reference handle bytes and the
11259              * following pascal string and some extra 4
11260              * bytes I have no idea what are */
11261             if (!gst_byte_reader_skip (&dref, 4) ||
11262                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
11263                 !gst_byte_reader_skip (&dref, string_len + 4)) {
11264               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
11265               break;
11266             }
11267
11268             /* iterate over the atoms to find the data atom */
11269             while (gst_byte_reader_get_remaining (&dref) >= 8) {
11270               guint32 atom_size;
11271               guint32 atom_type;
11272
11273               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
11274                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
11275                 if (atom_type == FOURCC_data) {
11276                   const guint8 *uri_aux = NULL;
11277
11278                   /* found the data atom that might contain the rtsp uri */
11279                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
11280                       "hndl atom, interpreting it as an URI");
11281                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
11282                           &uri_aux)) {
11283                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
11284                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
11285                     else
11286                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
11287                           "didn't contain a rtsp address");
11288                   } else {
11289                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
11290                         "atom contents");
11291                   }
11292                   break;
11293                 }
11294                 /* skipping to the next entry */
11295                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
11296                   break;
11297               } else {
11298                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
11299                     "atom header");
11300                 break;
11301               }
11302             }
11303             break;
11304           }
11305           /* skip to the next entry */
11306           if (!gst_byte_reader_skip (&dref, size - 8))
11307             break;
11308         } else {
11309           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
11310         }
11311       }
11312       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
11313     }
11314   }
11315   return uri;
11316 }
11317
11318 #define AMR_NB_ALL_MODES        0x81ff
11319 #define AMR_WB_ALL_MODES        0x83ff
11320 static guint
11321 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
11322 {
11323   /* The 'damr' atom is of the form:
11324    *
11325    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
11326    *    32 b       8 b          16 b           8 b                 8 b
11327    *
11328    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
11329    * represents the highest mode used in the stream (and thus the maximum
11330    * bitrate), with a couple of special cases as seen below.
11331    */
11332
11333   /* Map of frame type ID -> bitrate */
11334   static const guint nb_bitrates[] = {
11335     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
11336   };
11337   static const guint wb_bitrates[] = {
11338     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
11339   };
11340   GstMapInfo map;
11341   gsize max_mode;
11342   guint16 mode_set;
11343
11344   gst_buffer_map (buf, &map, GST_MAP_READ);
11345
11346   if (map.size != 0x11) {
11347     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
11348     goto bad_data;
11349   }
11350
11351   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
11352     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
11353         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
11354     goto bad_data;
11355   }
11356
11357   mode_set = QT_UINT16 (map.data + 13);
11358
11359   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
11360     max_mode = 7 + (wb ? 1 : 0);
11361   else
11362     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
11363     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
11364
11365   if (max_mode == -1) {
11366     GST_DEBUG ("No mode indication was found (mode set) = %x",
11367         (guint) mode_set);
11368     goto bad_data;
11369   }
11370
11371   gst_buffer_unmap (buf, &map);
11372   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
11373
11374 bad_data:
11375   gst_buffer_unmap (buf, &map);
11376   return 0;
11377 }
11378
11379 static gboolean
11380 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
11381     GstByteReader * reader, guint32 * matrix, const gchar * atom)
11382 {
11383   /*
11384    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
11385    * [0 1 2]
11386    * [3 4 5]
11387    * [6 7 8]
11388    */
11389
11390   if (gst_byte_reader_get_remaining (reader) < 36)
11391     return FALSE;
11392
11393   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
11394   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
11395   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
11396   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
11397   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
11398   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
11399   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
11400   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
11401   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
11402
11403   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
11404   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
11405       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
11406       matrix[2] & 0xFF);
11407   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
11408       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
11409       matrix[5] & 0xFF);
11410   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
11411       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
11412       matrix[8] & 0xFF);
11413
11414   return TRUE;
11415 }
11416
11417 static void
11418 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
11419     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
11420 {
11421
11422 /* [a b c]
11423  * [d e f]
11424  * [g h i]
11425  *
11426  * This macro will only compare value abdegh, it expects cfi to have already
11427  * been checked
11428  */
11429 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
11430                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
11431
11432   /* only handle the cases where the last column has standard values */
11433   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
11434     const gchar *rotation_tag = NULL;
11435
11436     /* no rotation needed */
11437     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
11438       /* NOP */
11439     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
11440       rotation_tag = "rotate-90";
11441     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
11442       rotation_tag = "rotate-180";
11443     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
11444       rotation_tag = "rotate-270";
11445     } else {
11446       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
11447     }
11448
11449     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
11450         GST_STR_NULL (rotation_tag));
11451     if (rotation_tag != NULL) {
11452       if (*taglist == NULL)
11453         *taglist = gst_tag_list_new_empty ();
11454       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
11455           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
11456     }
11457   } else {
11458     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
11459   }
11460 }
11461
11462 static gboolean
11463 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
11464     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
11465 {
11466   GNode *adrm;
11467   guint32 adrm_size;
11468   GstBuffer *adrm_buf = NULL;
11469   QtDemuxAavdEncryptionInfo *info;
11470
11471   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
11472   if (G_UNLIKELY (!adrm)) {
11473     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
11474     return FALSE;
11475   }
11476   adrm_size = QT_UINT32 (adrm->data);
11477   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
11478
11479   stream->protection_scheme_type = FOURCC_aavd;
11480
11481   if (!stream->protection_scheme_info)
11482     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
11483
11484   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
11485
11486   if (info->default_properties)
11487     gst_structure_free (info->default_properties);
11488   info->default_properties = gst_structure_new ("application/x-aavd",
11489       "encrypted", G_TYPE_BOOLEAN, TRUE,
11490       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
11491   gst_buffer_unref (adrm_buf);
11492
11493   *original_fmt = FOURCC_mp4a;
11494   return TRUE;
11495 }
11496
11497 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
11498  * protected streams (sinf, frma, schm and schi); if the protection scheme is
11499  * Common Encryption (cenc), the function will also parse the tenc box (defined
11500  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
11501  * (typically an enc[v|a|t|s] sample entry); the function will set
11502  * @original_fmt to the fourcc of the original unencrypted stream format.
11503  * Returns TRUE if successful; FALSE otherwise. */
11504 static gboolean
11505 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
11506     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
11507 {
11508   GNode *sinf;
11509   GNode *frma;
11510   GNode *schm;
11511   GNode *schi;
11512   QtDemuxCencSampleSetInfo *info;
11513   GNode *tenc;
11514   const guint8 *tenc_data;
11515
11516   g_return_val_if_fail (qtdemux != NULL, FALSE);
11517   g_return_val_if_fail (stream != NULL, FALSE);
11518   g_return_val_if_fail (container != NULL, FALSE);
11519   g_return_val_if_fail (original_fmt != NULL, FALSE);
11520
11521   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
11522   if (G_UNLIKELY (!sinf)) {
11523     if (stream->protection_scheme_type == FOURCC_cenc
11524         || stream->protection_scheme_type == FOURCC_cbcs) {
11525       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
11526           "mandatory for Common Encryption");
11527       return FALSE;
11528     }
11529     return TRUE;
11530   }
11531
11532   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
11533   if (G_UNLIKELY (!frma)) {
11534     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
11535     return FALSE;
11536   }
11537
11538   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
11539   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
11540       GST_FOURCC_ARGS (*original_fmt));
11541
11542   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
11543   if (!schm) {
11544     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
11545     return FALSE;
11546   }
11547   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
11548   stream->protection_scheme_version =
11549       QT_UINT32 ((const guint8 *) schm->data + 16);
11550
11551   GST_DEBUG_OBJECT (qtdemux,
11552       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
11553       "protection_scheme_version: %#010x",
11554       GST_FOURCC_ARGS (stream->protection_scheme_type),
11555       stream->protection_scheme_version);
11556
11557   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
11558   if (!schi) {
11559     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
11560     return FALSE;
11561   }
11562   if (stream->protection_scheme_type != FOURCC_cenc &&
11563       stream->protection_scheme_type != FOURCC_piff &&
11564       stream->protection_scheme_type != FOURCC_cbcs) {
11565     GST_ERROR_OBJECT (qtdemux,
11566         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
11567         GST_FOURCC_ARGS (stream->protection_scheme_type));
11568     return FALSE;
11569   }
11570
11571   if (G_UNLIKELY (!stream->protection_scheme_info))
11572     stream->protection_scheme_info =
11573         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
11574
11575   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
11576
11577   if (stream->protection_scheme_type == FOURCC_cenc
11578       || stream->protection_scheme_type == FOURCC_cbcs) {
11579     guint8 is_encrypted;
11580     guint8 iv_size;
11581     guint8 constant_iv_size = 0;
11582     const guint8 *default_kid;
11583     guint8 crypt_byte_block = 0;
11584     guint8 skip_byte_block = 0;
11585     const guint8 *constant_iv = NULL;
11586
11587     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
11588     if (!tenc) {
11589       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
11590           "which is mandatory for Common Encryption");
11591       return FALSE;
11592     }
11593     tenc_data = (const guint8 *) tenc->data + 12;
11594     is_encrypted = QT_UINT8 (tenc_data + 2);
11595     iv_size = QT_UINT8 (tenc_data + 3);
11596     default_kid = (tenc_data + 4);
11597     if (stream->protection_scheme_type == FOURCC_cbcs) {
11598       guint8 possible_pattern_info;
11599       if (iv_size == 0) {
11600         constant_iv_size = QT_UINT8 (tenc_data + 20);
11601         if (constant_iv_size != 8 && constant_iv_size != 16) {
11602           GST_ERROR_OBJECT (qtdemux,
11603               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
11604           return FALSE;
11605         }
11606         constant_iv = (tenc_data + 21);
11607       }
11608       possible_pattern_info = QT_UINT8 (tenc_data + 1);
11609       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
11610       skip_byte_block = possible_pattern_info & 0x0f;
11611     }
11612     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
11613         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
11614         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
11615   } else if (stream->protection_scheme_type == FOURCC_piff) {
11616     GstByteReader br;
11617     static const guint8 piff_track_encryption_uuid[] = {
11618       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
11619       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
11620     };
11621
11622     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
11623     if (!tenc) {
11624       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
11625           "which is mandatory for Common Encryption");
11626       return FALSE;
11627     }
11628
11629     tenc_data = (const guint8 *) tenc->data + 8;
11630     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
11631       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
11632       GST_ERROR_OBJECT (qtdemux,
11633           "Unsupported track encryption box with uuid: %s", box_uuid);
11634       g_free (box_uuid);
11635       return FALSE;
11636     }
11637     tenc_data = (const guint8 *) tenc->data + 16 + 12;
11638     gst_byte_reader_init (&br, tenc_data, 20);
11639     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
11640       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
11641       return FALSE;
11642     }
11643     stream->protection_scheme_type = FOURCC_cenc;
11644   }
11645
11646   return TRUE;
11647 }
11648
11649 static gint
11650 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
11651     QtDemuxStream ** stream2)
11652 {
11653   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
11654 }
11655
11656 static gboolean
11657 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
11658     GNode * stbl)
11659 {
11660   GNode *svmi;
11661
11662   /*parse svmi header if existing */
11663   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
11664   if (svmi) {
11665     guint32 len = QT_UINT32 ((guint8 *) svmi->data);
11666     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
11667     if (!version) {
11668       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
11669       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
11670       guint8 frame_type, frame_layout;
11671       guint32 stereo_mono_change_count;
11672
11673       if (len < 18)
11674         return FALSE;
11675
11676       /* MPEG-A stereo video */
11677       if (qtdemux->major_brand == FOURCC_ss02)
11678         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
11679
11680       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
11681       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
11682       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
11683
11684       switch (frame_type) {
11685         case 0:
11686           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
11687           break;
11688         case 1:
11689           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11690           break;
11691         case 2:
11692           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11693           break;
11694         case 3:
11695           /* mode 3 is primary/secondary view sequence, ie
11696            * left/right views in separate tracks. See section 7.2
11697            * of ISO/IEC 23000-11:2009 */
11698           /* In the future this might be supported using related
11699            * streams, like an enhancement track - if files like this
11700            * ever exist */
11701           GST_FIXME_OBJECT (qtdemux,
11702               "Implement stereo video in separate streams");
11703       }
11704
11705       if ((frame_layout & 0x1) == 0)
11706         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11707
11708       GST_LOG_OBJECT (qtdemux,
11709           "StereoVideo: composition type: %u, is_left_first: %u",
11710           frame_type, frame_layout);
11711
11712       if (stereo_mono_change_count > 1) {
11713         GST_FIXME_OBJECT (qtdemux,
11714             "Mixed-mono flags are not yet supported in qtdemux.");
11715       }
11716
11717       stream->multiview_mode = mode;
11718       stream->multiview_flags = flags;
11719     }
11720   }
11721
11722   return TRUE;
11723 }
11724
11725 /* parse the traks.
11726  * With each track we associate a new QtDemuxStream that contains all the info
11727  * about the trak.
11728  * traks that do not decode to something (like strm traks) will not have a pad.
11729  */
11730 static gboolean
11731 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11732 {
11733   GstByteReader tkhd;
11734   int offset;
11735   GNode *mdia;
11736   GNode *mdhd;
11737   GNode *hdlr;
11738   GNode *minf;
11739   GNode *stbl;
11740   GNode *stsd;
11741   GNode *mp4a;
11742   GNode *mp4v;
11743   GNode *esds;
11744   GNode *tref;
11745   GNode *udta;
11746
11747   QtDemuxStream *stream = NULL;
11748   const guint8 *stsd_data;
11749   const guint8 *stsd_entry_data;
11750   guint remaining_stsd_len;
11751   guint stsd_entry_count;
11752   guint stsd_index;
11753   guint16 lang_code;            /* quicktime lang code or packed iso code */
11754   guint32 version;
11755   guint32 tkhd_flags = 0;
11756   guint8 tkhd_version = 0;
11757   guint32 w = 0, h = 0;
11758   guint value_size, stsd_len, len;
11759   guint32 track_id;
11760   guint32 dummy;
11761
11762   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11763
11764   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11765       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11766       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11767     goto corrupt_file;
11768
11769   /* pick between 64 or 32 bits */
11770   value_size = tkhd_version == 1 ? 8 : 4;
11771   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11772       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11773     goto corrupt_file;
11774
11775   /* Check if current moov has duplicated track_id */
11776   if (qtdemux_find_stream (qtdemux, track_id))
11777     goto existing_stream;
11778
11779   stream = _create_stream (qtdemux, track_id);
11780   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11781
11782 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
11783   if (!gst_byte_reader_skip (&tkhd, 4))
11784     goto corrupt_file;
11785
11786   if (tkhd_version == 1) {
11787     if (!gst_byte_reader_get_uint64_be (&tkhd, &stream->tkhd_duration))
11788       goto corrupt_file;
11789   } else {
11790     guint32 dur = 0;
11791     if (!gst_byte_reader_get_uint32_be (&tkhd, &dur))
11792       goto corrupt_file;
11793     stream->tkhd_duration = dur;
11794   }
11795   GST_INFO_OBJECT (qtdemux, "tkhd duration: %" G_GUINT64_FORMAT,
11796       stream->tkhd_duration);
11797 #endif
11798   /* need defaults for fragments */
11799   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11800
11801   if ((tkhd_flags & 1) == 0)
11802     stream->disabled = TRUE;
11803
11804   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11805       tkhd_version, tkhd_flags, stream->track_id);
11806
11807   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11808     goto corrupt_file;
11809
11810   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11811     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11812     if (qtdemux->major_brand != FOURCC_mjp2 ||
11813         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11814       goto corrupt_file;
11815   }
11816
11817   len = QT_UINT32 ((guint8 *) mdhd->data);
11818   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11819   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11820   if (version == 0x01000000) {
11821     if (len < 42)
11822       goto corrupt_file;
11823     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11824     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11825     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11826   } else {
11827     if (len < 30)
11828       goto corrupt_file;
11829     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11830     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11831     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11832   }
11833
11834   if (lang_code < 0x400) {
11835     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11836   } else if (lang_code == 0x7fff) {
11837     stream->lang_id[0] = 0;     /* unspecified */
11838   } else {
11839     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11840     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11841     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11842     stream->lang_id[3] = 0;
11843   }
11844
11845   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11846       stream->timescale);
11847   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11848       stream->duration);
11849   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11850       lang_code, stream->lang_id);
11851
11852   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11853     goto corrupt_file;
11854
11855   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11856     /* chapters track reference */
11857     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11858     if (chap) {
11859       gsize length = GST_READ_UINT32_BE (chap->data);
11860       if (qtdemux->chapters_track_id)
11861         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11862
11863       if (length >= 12) {
11864         qtdemux->chapters_track_id =
11865             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11866       }
11867     }
11868   }
11869
11870   /* fragmented files may have bogus duration in moov */
11871   if (!qtdemux->fragmented &&
11872       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11873     guint64 tdur1, tdur2;
11874
11875     /* don't overflow */
11876     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11877     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11878
11879     /* HACK:
11880      * some of those trailers, nowadays, have prologue images that are
11881      * themselves video tracks as well. I haven't really found a way to
11882      * identify those yet, except for just looking at their duration. */
11883     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11884       GST_WARNING_OBJECT (qtdemux,
11885           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11886           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11887           "found, assuming preview image or something; skipping track",
11888           stream->duration, stream->timescale, qtdemux->duration,
11889           qtdemux->timescale);
11890       gst_qtdemux_stream_unref (stream);
11891       return TRUE;
11892     }
11893   }
11894
11895   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11896     goto corrupt_file;
11897
11898   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11899       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11900
11901   len = QT_UINT32 ((guint8 *) hdlr->data);
11902   if (len >= 20)
11903     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11904   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11905       GST_FOURCC_ARGS (stream->subtype));
11906
11907   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11908     goto corrupt_file;
11909
11910   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11911     goto corrupt_file;
11912
11913   /* Parse out svmi (and later st3d/sv3d) atoms */
11914   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11915     goto corrupt_file;
11916
11917   /* parse rest of tkhd */
11918   if (stream->subtype == FOURCC_vide) {
11919     guint32 matrix[9];
11920
11921     /* version 1 uses some 64-bit ints */
11922 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
11923     if (!gst_byte_reader_skip (&tkhd, 16))
11924 #else
11925     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11926 #endif
11927       goto corrupt_file;
11928
11929     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11930       goto corrupt_file;
11931
11932     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11933         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11934       goto corrupt_file;
11935
11936     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11937         &stream->stream_tags);
11938   }
11939
11940   /* parse stsd */
11941   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11942     goto corrupt_file;
11943   stsd_data = (const guint8 *) stsd->data;
11944
11945   /* stsd should at least have one entry */
11946   stsd_len = QT_UINT32 (stsd_data);
11947   if (stsd_len < 24) {
11948     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11949     if (stream->subtype == FOURCC_vivo) {
11950       gst_qtdemux_stream_unref (stream);
11951       return TRUE;
11952     } else {
11953       goto corrupt_file;
11954     }
11955   }
11956
11957   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11958   /* each stsd entry must contain at least 8 bytes */
11959   if (stream->stsd_entries_length == 0
11960       || stream->stsd_entries_length > stsd_len / 8) {
11961     stream->stsd_entries_length = 0;
11962     goto corrupt_file;
11963   }
11964   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11965   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11966   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11967
11968   stsd_entry_data = stsd_data + 16;
11969   remaining_stsd_len = stsd_len - 16;
11970   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11971     guint32 fourcc;
11972     gchar *codec = NULL;
11973     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11974
11975     /* and that entry should fit within stsd */
11976     len = QT_UINT32 (stsd_entry_data);
11977     if (len > remaining_stsd_len)
11978       goto corrupt_file;
11979
11980     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11981     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11982         GST_FOURCC_ARGS (entry->fourcc));
11983     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11984
11985     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11986       goto error_encrypted;
11987
11988     if (fourcc == FOURCC_aavd) {
11989       if (stream->subtype != FOURCC_soun) {
11990         GST_ERROR_OBJECT (qtdemux,
11991             "Unexpeced stsd type 'aavd' outside 'soun' track");
11992       } else {
11993         /* encrypted audio with sound sample description v0 */
11994         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11995         stream->protected = TRUE;
11996         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11997           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11998       }
11999     }
12000
12001     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
12002       /* FIXME this looks wrong, there might be multiple children
12003        * with the same type */
12004       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
12005       stream->protected = TRUE;
12006       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
12007         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
12008     }
12009
12010     if (stream->subtype == FOURCC_vide) {
12011       GNode *colr;
12012       GNode *fiel;
12013       GNode *pasp;
12014       gboolean gray;
12015       gint depth, palette_size, palette_count;
12016       guint32 *palette_data = NULL;
12017
12018       entry->sampled = TRUE;
12019
12020       stream->display_width = w >> 16;
12021       stream->display_height = h >> 16;
12022
12023       offset = 16;
12024       if (len < 86)             /* TODO verify */
12025         goto corrupt_file;
12026
12027       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
12028       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
12029       entry->fps_n = 0;         /* this is filled in later */
12030       entry->fps_d = 0;         /* this is filled in later */
12031       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
12032       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
12033
12034       /* if color_table_id is 0, ctab atom must follow; however some files
12035        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
12036        * if color table is not present we'll correct the value */
12037       if (entry->color_table_id == 0 &&
12038           (len < 90
12039               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
12040         entry->color_table_id = -1;
12041       }
12042
12043       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
12044           entry->width, entry->height, entry->bits_per_sample,
12045           entry->color_table_id);
12046
12047       depth = entry->bits_per_sample;
12048
12049       /* more than 32 bits means grayscale */
12050       gray = (depth > 32);
12051       /* low 32 bits specify the depth  */
12052       depth &= 0x1F;
12053
12054       /* different number of palette entries is determined by depth. */
12055       palette_count = 0;
12056       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
12057         palette_count = (1 << depth);
12058       palette_size = palette_count * 4;
12059
12060       if (entry->color_table_id) {
12061         switch (palette_count) {
12062           case 0:
12063             break;
12064           case 2:
12065             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
12066             break;
12067           case 4:
12068             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
12069             break;
12070           case 16:
12071             if (gray)
12072               palette_data =
12073                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
12074             else
12075               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
12076             break;
12077           case 256:
12078             if (gray)
12079               palette_data =
12080                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
12081             else
12082               palette_data =
12083                   g_memdup2 (ff_qt_default_palette_256, palette_size);
12084             break;
12085           default:
12086             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
12087                 (_("The video in this file might not play correctly.")),
12088                 ("unsupported palette depth %d", depth));
12089             break;
12090         }
12091       } else {
12092         guint i, j, start, end;
12093
12094         if (len < 94)
12095           goto corrupt_file;
12096
12097         /* read table */
12098         start = QT_UINT32 (stsd_entry_data + offset + 70);
12099         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
12100         end = QT_UINT16 (stsd_entry_data + offset + 76);
12101
12102         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
12103             start, end, palette_count);
12104
12105         if (end > 255)
12106           end = 255;
12107         if (start > end)
12108           start = end;
12109
12110         if (len < 94 + (end - start) * 8)
12111           goto corrupt_file;
12112
12113         /* palette is always the same size */
12114         palette_data = g_malloc0 (256 * 4);
12115         palette_size = 256 * 4;
12116
12117         for (j = 0, i = start; i <= end; j++, i++) {
12118           guint32 a, r, g, b;
12119
12120           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
12121           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
12122           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
12123           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
12124
12125           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
12126               (g & 0xff00) | (b >> 8);
12127         }
12128       }
12129
12130       if (entry->caps)
12131         gst_caps_unref (entry->caps);
12132
12133       entry->caps =
12134           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12135           &codec);
12136       if (G_UNLIKELY (!entry->caps)) {
12137         g_free (palette_data);
12138         goto unknown_stream;
12139       }
12140
12141       if (codec) {
12142         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12143             GST_TAG_VIDEO_CODEC, codec, NULL);
12144         g_free (codec);
12145         codec = NULL;
12146       }
12147
12148       if (palette_data) {
12149         GstStructure *s;
12150
12151         if (entry->rgb8_palette)
12152           gst_memory_unref (entry->rgb8_palette);
12153         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
12154             palette_data, palette_size, 0, palette_size, palette_data, g_free);
12155
12156         s = gst_caps_get_structure (entry->caps, 0);
12157
12158         /* non-raw video has a palette_data property. raw video has the palette as
12159          * an extra plane that we append to the output buffers before we push
12160          * them*/
12161         if (!gst_structure_has_name (s, "video/x-raw")) {
12162           GstBuffer *palette;
12163
12164           palette = gst_buffer_new ();
12165           gst_buffer_append_memory (palette, entry->rgb8_palette);
12166           entry->rgb8_palette = NULL;
12167
12168           gst_caps_set_simple (entry->caps, "palette_data",
12169               GST_TYPE_BUFFER, palette, NULL);
12170           gst_buffer_unref (palette);
12171         }
12172       } else if (palette_count != 0) {
12173         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
12174             (NULL), ("Unsupported palette depth %d", depth));
12175       }
12176
12177       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
12178           QT_UINT16 (stsd_entry_data + offset + 32));
12179
12180       esds = NULL;
12181       pasp = NULL;
12182       colr = NULL;
12183       fiel = NULL;
12184       /* pick 'the' stsd child */
12185       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12186       // We should skip parsing the stsd for non-protected streams if
12187       // the entry doesn't match the fourcc, since they don't change
12188       // format. However, for protected streams we can have partial
12189       // encryption, where parts of the stream are encrypted and parts
12190       // not. For both parts of such streams, we should ensure the
12191       // esds overrides are parsed for both from the stsd.
12192       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
12193         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
12194           mp4v = NULL;
12195         else if (!stream->protected)
12196           mp4v = NULL;
12197       }
12198
12199       if (mp4v) {
12200         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
12201         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
12202         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
12203         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
12204       }
12205
12206       if (pasp) {
12207         const guint8 *pasp_data = (const guint8 *) pasp->data;
12208         guint len = QT_UINT32 (pasp_data);
12209
12210         if (len == 16) {
12211           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
12212           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
12213         } else {
12214           CUR_STREAM (stream)->par_w = 0;
12215           CUR_STREAM (stream)->par_h = 0;
12216         }
12217       } else {
12218         CUR_STREAM (stream)->par_w = 0;
12219         CUR_STREAM (stream)->par_h = 0;
12220       }
12221
12222       if (fiel) {
12223         const guint8 *fiel_data = (const guint8 *) fiel->data;
12224         guint len = QT_UINT32 (fiel_data);
12225
12226         if (len == 10) {
12227           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
12228           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
12229         }
12230       }
12231
12232       if (colr) {
12233         const guint8 *colr_data = (const guint8 *) colr->data;
12234         guint len = QT_UINT32 (colr_data);
12235
12236         if (len == 19 || len == 18) {
12237           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
12238
12239           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
12240             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
12241             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
12242             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
12243             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
12244
12245             CUR_STREAM (stream)->colorimetry.primaries =
12246                 gst_video_color_primaries_from_iso (primaries);
12247             CUR_STREAM (stream)->colorimetry.transfer =
12248                 gst_video_transfer_function_from_iso (transfer_function);
12249             CUR_STREAM (stream)->colorimetry.matrix =
12250                 gst_video_color_matrix_from_iso (matrix);
12251             CUR_STREAM (stream)->colorimetry.range =
12252                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
12253                 GST_VIDEO_COLOR_RANGE_16_235;
12254           } else {
12255             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
12256           }
12257         } else {
12258           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
12259         }
12260       }
12261
12262       if (esds) {
12263         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12264             stream->stream_tags);
12265       } else {
12266         switch (fourcc) {
12267           case FOURCC_H264:
12268           case FOURCC_avc1:
12269           case FOURCC_avc3:
12270           {
12271             guint len = QT_UINT32 (stsd_entry_data);
12272             len = len <= 0x56 ? 0 : len - 0x56;
12273             const guint8 *avc_data = stsd_entry_data + 0x56;
12274
12275             /* find avcC */
12276             while (len >= 0x8) {
12277               guint size;
12278
12279               if (QT_UINT32 (avc_data) <= 0x8)
12280                 size = 0;
12281               else if (QT_UINT32 (avc_data) <= len)
12282                 size = QT_UINT32 (avc_data) - 0x8;
12283               else
12284                 size = len - 0x8;
12285
12286               if (size < 1)
12287                 /* No real data, so break out */
12288                 break;
12289
12290               switch (QT_FOURCC (avc_data + 0x4)) {
12291                 case FOURCC_avcC:
12292                 {
12293                   /* parse, if found */
12294                   GstBuffer *buf;
12295
12296                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
12297
12298                   /* First 4 bytes are the length of the atom, the next 4 bytes
12299                    * are the fourcc, the next 1 byte is the version, and the
12300                    * subsequent bytes are profile_tier_level structure like data. */
12301                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
12302                       avc_data + 8 + 1, size - 1);
12303                   buf = gst_buffer_new_and_alloc (size);
12304                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
12305                   gst_caps_set_simple (entry->caps,
12306                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12307                   gst_buffer_unref (buf);
12308
12309                   break;
12310                 }
12311                 case FOURCC_strf:
12312                 {
12313                   GstBuffer *buf;
12314
12315                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
12316
12317                   /* First 4 bytes are the length of the atom, the next 4 bytes
12318                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
12319                    * next 1 byte is the version, and the
12320                    * subsequent bytes are sequence parameter set like data. */
12321
12322                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
12323                   if (size > 1) {
12324                     gst_codec_utils_h264_caps_set_level_and_profile
12325                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
12326
12327                     buf = gst_buffer_new_and_alloc (size);
12328                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
12329                     gst_caps_set_simple (entry->caps,
12330                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12331                     gst_buffer_unref (buf);
12332                   }
12333                   break;
12334                 }
12335                 case FOURCC_btrt:
12336                 {
12337                   guint avg_bitrate, max_bitrate;
12338
12339                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
12340                   if (size < 12)
12341                     break;
12342
12343                   max_bitrate = QT_UINT32 (avc_data + 0xc);
12344                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
12345
12346                   if (!max_bitrate && !avg_bitrate)
12347                     break;
12348
12349                   /* Some muxers seem to swap the average and maximum bitrates
12350                    * (I'm looking at you, YouTube), so we swap for sanity. */
12351                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
12352                     guint temp = avg_bitrate;
12353
12354                     avg_bitrate = max_bitrate;
12355                     max_bitrate = temp;
12356                   }
12357
12358                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12359                     gst_tag_list_add (stream->stream_tags,
12360                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
12361                         max_bitrate, NULL);
12362                   }
12363                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12364                     gst_tag_list_add (stream->stream_tags,
12365                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
12366                         NULL);
12367                   }
12368
12369                   break;
12370                 }
12371
12372                 default:
12373                   break;
12374               }
12375
12376               len -= size + 8;
12377               avc_data += size + 8;
12378             }
12379
12380             break;
12381           }
12382           case FOURCC_H265:
12383           case FOURCC_hvc1:
12384           case FOURCC_hev1:
12385           case FOURCC_dvh1:
12386           case FOURCC_dvhe:
12387           {
12388             guint len = QT_UINT32 (stsd_entry_data);
12389             len = len <= 0x56 ? 0 : len - 0x56;
12390             const guint8 *hevc_data = stsd_entry_data + 0x56;
12391
12392             /* find hevc */
12393             while (len >= 0x8) {
12394               guint size;
12395
12396               if (QT_UINT32 (hevc_data) <= 0x8)
12397                 size = 0;
12398               else if (QT_UINT32 (hevc_data) <= len)
12399                 size = QT_UINT32 (hevc_data) - 0x8;
12400               else
12401                 size = len - 0x8;
12402
12403               if (size < 1)
12404                 /* No real data, so break out */
12405                 break;
12406
12407               switch (QT_FOURCC (hevc_data + 0x4)) {
12408                 case FOURCC_hvcC:
12409                 {
12410                   /* parse, if found */
12411                   GstBuffer *buf;
12412
12413                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
12414
12415                   /* First 4 bytes are the length of the atom, the next 4 bytes
12416                    * are the fourcc, the next 1 byte is the version, and the
12417                    * subsequent bytes are sequence parameter set like data. */
12418                   gst_codec_utils_h265_caps_set_level_tier_and_profile
12419                       (entry->caps, hevc_data + 8 + 1, size - 1);
12420
12421                   buf = gst_buffer_new_and_alloc (size);
12422                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
12423                   gst_caps_set_simple (entry->caps,
12424                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12425                   gst_buffer_unref (buf);
12426                   break;
12427                 }
12428                 default:
12429                   break;
12430               }
12431               len -= size + 8;
12432               hevc_data += size + 8;
12433             }
12434             break;
12435           }
12436           case FOURCC_mp4v:
12437           case FOURCC_MP4V:
12438           case FOURCC_fmp4:
12439           case FOURCC_FMP4:
12440           case FOURCC_xvid:
12441           case FOURCC_XVID:
12442           {
12443             GNode *glbl;
12444
12445             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
12446                 GST_FOURCC_ARGS (fourcc));
12447
12448             /* codec data might be in glbl extension atom */
12449             glbl = mp4v ?
12450                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
12451             if (glbl) {
12452               guint8 *data;
12453               GstBuffer *buf;
12454               guint len;
12455
12456               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
12457               data = glbl->data;
12458               len = QT_UINT32 (data);
12459               if (len > 0x8) {
12460                 len -= 0x8;
12461                 buf = gst_buffer_new_and_alloc (len);
12462                 gst_buffer_fill (buf, 0, data + 8, len);
12463                 gst_caps_set_simple (entry->caps,
12464                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12465                 gst_buffer_unref (buf);
12466               }
12467             }
12468             break;
12469           }
12470           case FOURCC_mjp2:
12471           {
12472             /* see annex I of the jpeg2000 spec */
12473             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
12474             const guint8 *data;
12475             const gchar *colorspace = NULL;
12476             gint ncomp = 0;
12477             guint32 ncomp_map = 0;
12478             gint32 *comp_map = NULL;
12479             guint32 nchan_def = 0;
12480             gint32 *chan_def = NULL;
12481
12482             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
12483             /* some required atoms */
12484             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12485             if (!mjp2)
12486               break;
12487             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
12488             if (!jp2h)
12489               break;
12490
12491             /* number of components; redundant with info in codestream, but useful
12492                to a muxer */
12493             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
12494             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
12495               break;
12496             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
12497
12498             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
12499             if (!colr)
12500               break;
12501             GST_DEBUG_OBJECT (qtdemux, "found colr");
12502             /* extract colour space info */
12503             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
12504               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
12505                 case 16:
12506                   colorspace = "sRGB";
12507                   break;
12508                 case 17:
12509                   colorspace = "GRAY";
12510                   break;
12511                 case 18:
12512                   colorspace = "sYUV";
12513                   break;
12514                 default:
12515                   colorspace = NULL;
12516                   break;
12517               }
12518             }
12519             if (!colorspace)
12520               /* colr is required, and only values 16, 17, and 18 are specified,
12521                  so error if we have no colorspace */
12522               break;
12523
12524             /* extract component mapping */
12525             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
12526             if (cmap) {
12527               guint32 cmap_len = 0;
12528               int i;
12529               cmap_len = QT_UINT32 (cmap->data);
12530               if (cmap_len >= 8) {
12531                 /* normal box, subtract off header */
12532                 cmap_len -= 8;
12533                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
12534                 if (cmap_len % 4 == 0) {
12535                   ncomp_map = (cmap_len / 4);
12536                   comp_map = g_new0 (gint32, ncomp_map);
12537                   for (i = 0; i < ncomp_map; i++) {
12538                     guint16 cmp;
12539                     guint8 mtyp, pcol;
12540                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
12541                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
12542                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
12543                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
12544                   }
12545                 }
12546               }
12547             }
12548             /* extract channel definitions */
12549             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
12550             if (cdef) {
12551               guint32 cdef_len = 0;
12552               int i;
12553               cdef_len = QT_UINT32 (cdef->data);
12554               if (cdef_len >= 10) {
12555                 /* normal box, subtract off header and len */
12556                 cdef_len -= 10;
12557                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
12558                 if (cdef_len % 6 == 0) {
12559                   nchan_def = (cdef_len / 6);
12560                   chan_def = g_new0 (gint32, nchan_def);
12561                   for (i = 0; i < nchan_def; i++)
12562                     chan_def[i] = -1;
12563                   for (i = 0; i < nchan_def; i++) {
12564                     guint16 cn, typ, asoc;
12565                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
12566                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
12567                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
12568                     if (cn < nchan_def) {
12569                       switch (typ) {
12570                         case 0:
12571                           chan_def[cn] = asoc;
12572                           break;
12573                         case 1:
12574                           chan_def[cn] = 0;     /* alpha */
12575                           break;
12576                         default:
12577                           chan_def[cn] = -typ;
12578                       }
12579                     }
12580                   }
12581                 }
12582               }
12583             }
12584
12585             gst_caps_set_simple (entry->caps,
12586                 "num-components", G_TYPE_INT, ncomp, NULL);
12587             gst_caps_set_simple (entry->caps,
12588                 "colorspace", G_TYPE_STRING, colorspace, NULL);
12589
12590             if (comp_map) {
12591               GValue arr = { 0, };
12592               GValue elt = { 0, };
12593               int i;
12594               g_value_init (&arr, GST_TYPE_ARRAY);
12595               g_value_init (&elt, G_TYPE_INT);
12596               for (i = 0; i < ncomp_map; i++) {
12597                 g_value_set_int (&elt, comp_map[i]);
12598                 gst_value_array_append_value (&arr, &elt);
12599               }
12600               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
12601                   "component-map", &arr);
12602               g_value_unset (&elt);
12603               g_value_unset (&arr);
12604               g_free (comp_map);
12605             }
12606
12607             if (chan_def) {
12608               GValue arr = { 0, };
12609               GValue elt = { 0, };
12610               int i;
12611               g_value_init (&arr, GST_TYPE_ARRAY);
12612               g_value_init (&elt, G_TYPE_INT);
12613               for (i = 0; i < nchan_def; i++) {
12614                 g_value_set_int (&elt, chan_def[i]);
12615                 gst_value_array_append_value (&arr, &elt);
12616               }
12617               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
12618                   "channel-definitions", &arr);
12619               g_value_unset (&elt);
12620               g_value_unset (&arr);
12621               g_free (chan_def);
12622             }
12623
12624             /* some optional atoms */
12625             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
12626             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
12627
12628             /* indicate possible fields in caps */
12629             if (field) {
12630               data = (guint8 *) field->data + 8;
12631               if (*data != 1)
12632                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
12633                     (gint) * data, NULL);
12634             }
12635             /* add codec_data if provided */
12636             if (prefix) {
12637               GstBuffer *buf;
12638               guint len;
12639
12640               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
12641               data = prefix->data;
12642               len = QT_UINT32 (data);
12643               if (len > 0x8) {
12644                 len -= 0x8;
12645                 buf = gst_buffer_new_and_alloc (len);
12646                 gst_buffer_fill (buf, 0, data + 8, len);
12647                 gst_caps_set_simple (entry->caps,
12648                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12649                 gst_buffer_unref (buf);
12650               }
12651             }
12652             break;
12653           }
12654           case FOURCC_SVQ3:
12655           case FOURCC_VP31:
12656           {
12657             GstBuffer *buf;
12658             GstBuffer *seqh = NULL;
12659             const guint8 *gamma_data = NULL;
12660             guint len = QT_UINT32 (stsd_data);  /* FIXME review - why put the whole stsd in codec data? */
12661
12662             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
12663                 &seqh);
12664             if (gamma_data) {
12665               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
12666                   QT_FP32 (gamma_data), NULL);
12667             }
12668             if (seqh) {
12669               /* sorry for the bad name, but we don't know what this is, other
12670                * than its own fourcc */
12671               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
12672                   NULL);
12673               gst_buffer_unref (seqh);
12674             }
12675
12676             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
12677             buf = gst_buffer_new_and_alloc (len);
12678             gst_buffer_fill (buf, 0, stsd_data, len);
12679             gst_caps_set_simple (entry->caps,
12680                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12681             gst_buffer_unref (buf);
12682             break;
12683           }
12684           case FOURCC_jpeg:
12685           {
12686             /* https://developer.apple.com/standards/qtff-2001.pdf,
12687              * page 92, "Video Sample Description", under table 3.1 */
12688             GstByteReader br;
12689
12690             const gint compressor_offset =
12691                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
12692             const gint min_size = compressor_offset + 32 + 2 + 2;
12693             GNode *jpeg;
12694             guint32 len;
12695             guint16 color_table_id = 0;
12696             gboolean ok;
12697
12698             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
12699
12700             /* recover information on interlaced/progressive */
12701             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
12702             if (!jpeg)
12703               break;
12704
12705             len = QT_UINT32 (jpeg->data);
12706             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
12707                 min_size);
12708             if (len >= min_size) {
12709               gst_byte_reader_init (&br, jpeg->data, len);
12710
12711               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
12712               gst_byte_reader_get_uint16_le (&br, &color_table_id);
12713               if (color_table_id != 0) {
12714                 /* the spec says there can be concatenated chunks in the data, and we want
12715                  * to find one called field. Walk through them. */
12716                 gint offset = min_size;
12717                 while (offset + 8 < len) {
12718                   guint32 size = 0, tag;
12719                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12720                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12721                   if (!ok || size < 8) {
12722                     GST_WARNING_OBJECT (qtdemux,
12723                         "Failed to walk optional chunk list");
12724                     break;
12725                   }
12726                   GST_DEBUG_OBJECT (qtdemux,
12727                       "Found optional %4.4s chunk, size %u",
12728                       (const char *) &tag, size);
12729                   if (tag == FOURCC_fiel) {
12730                     guint8 n_fields = 0, ordering = 0;
12731                     gst_byte_reader_get_uint8 (&br, &n_fields);
12732                     gst_byte_reader_get_uint8 (&br, &ordering);
12733                     if (n_fields == 1 || n_fields == 2) {
12734                       GST_DEBUG_OBJECT (qtdemux,
12735                           "Found fiel tag with %u fields, ordering %u",
12736                           n_fields, ordering);
12737                       if (n_fields == 2)
12738                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12739                             "interlace-mode", G_TYPE_STRING, "interleaved",
12740                             NULL);
12741                     } else {
12742                       GST_WARNING_OBJECT (qtdemux,
12743                           "Found fiel tag with invalid fields (%u)", n_fields);
12744                     }
12745                   }
12746                   offset += size;
12747                 }
12748               } else {
12749                 GST_DEBUG_OBJECT (qtdemux,
12750                     "Color table ID is 0, not trying to get interlacedness");
12751               }
12752             } else {
12753               GST_WARNING_OBJECT (qtdemux,
12754                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12755             }
12756
12757             break;
12758           }
12759           case FOURCC_rle_:
12760           case FOURCC_WRLE:
12761           {
12762             gst_caps_set_simple (entry->caps,
12763                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12764                 NULL);
12765             break;
12766           }
12767           case FOURCC_XiTh:
12768           {
12769             GNode *xith, *xdxt;
12770
12771             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12772             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12773             if (!xith)
12774               break;
12775
12776             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12777             if (!xdxt)
12778               break;
12779
12780             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12781             /* collect the headers and store them in a stream list so that we can
12782              * send them out first */
12783             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12784             break;
12785           }
12786           case FOURCC_ovc1:
12787           {
12788             GNode *ovc1;
12789             guint8 *ovc1_data;
12790             guint ovc1_len;
12791             GstBuffer *buf;
12792
12793             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12794             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12795             if (!ovc1)
12796               break;
12797             ovc1_data = ovc1->data;
12798             ovc1_len = QT_UINT32 (ovc1_data);
12799             if (ovc1_len <= 198) {
12800               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12801               break;
12802             }
12803             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12804             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12805             gst_caps_set_simple (entry->caps,
12806                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12807             gst_buffer_unref (buf);
12808             break;
12809           }
12810           case FOURCC_vc_1:
12811           {
12812             guint len = QT_UINT32 (stsd_entry_data);
12813             len = len <= 0x56 ? 0 : len - 0x56;
12814             const guint8 *vc1_data = stsd_entry_data + 0x56;
12815
12816             /* find dvc1 */
12817             while (len >= 8) {
12818               guint size;
12819
12820               if (QT_UINT32 (vc1_data) <= 8)
12821                 size = 0;
12822               else if (QT_UINT32 (vc1_data) <= len)
12823                 size = QT_UINT32 (vc1_data) - 8;
12824               else
12825                 size = len - 8;
12826
12827               if (size < 1)
12828                 /* No real data, so break out */
12829                 break;
12830
12831               switch (QT_FOURCC (vc1_data + 0x4)) {
12832                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12833                 {
12834                   GstBuffer *buf;
12835
12836                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12837                   buf = gst_buffer_new_and_alloc (size);
12838                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12839                   gst_caps_set_simple (entry->caps,
12840                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12841                   gst_buffer_unref (buf);
12842                   break;
12843                 }
12844                 default:
12845                   break;
12846               }
12847               len -= size + 8;
12848               vc1_data += size + 8;
12849             }
12850             break;
12851           }
12852           case FOURCC_av01:
12853           {
12854             guint len = QT_UINT32 (stsd_entry_data);
12855             len = len <= 0x56 ? 0 : len - 0x56;
12856             const guint8 *av1_data = stsd_entry_data + 0x56;
12857
12858             /* find av1C */
12859             while (len >= 0x8) {
12860               guint size;
12861
12862               if (QT_UINT32 (av1_data) <= 0x8)
12863                 size = 0;
12864               else if (QT_UINT32 (av1_data) <= len)
12865                 size = QT_UINT32 (av1_data) - 0x8;
12866               else
12867                 size = len - 0x8;
12868
12869               if (size < 1)
12870                 /* No real data, so break out */
12871                 break;
12872
12873               switch (QT_FOURCC (av1_data + 0x4)) {
12874                 case FOURCC_av1C:
12875                 {
12876                   /* parse, if found */
12877                   GstBuffer *buf;
12878
12879                   GST_DEBUG_OBJECT (qtdemux,
12880                       "found av1C codec_data in stsd of size %d", size);
12881
12882                   /* not enough data, just ignore and hope for the best */
12883                   if (size < 4)
12884                     break;
12885
12886                   /* Content is:
12887                    * 4 bytes: atom length
12888                    * 4 bytes: fourcc
12889                    *
12890                    * version 1 (marker=1):
12891                    *
12892                    *  unsigned int (1) marker = 1;
12893                    *  unsigned int (7) version = 1;
12894                    *  unsigned int (3) seq_profile;
12895                    *  unsigned int (5) seq_level_idx_0;
12896                    *  unsigned int (1) seq_tier_0;
12897                    *  unsigned int (1) high_bitdepth;
12898                    *  unsigned int (1) twelve_bit;
12899                    *  unsigned int (1) monochrome;
12900                    *  unsigned int (1) chroma_subsampling_x;
12901                    *  unsigned int (1) chroma_subsampling_y;
12902                    *  unsigned int (2) chroma_sample_position;
12903                    *  unsigned int (3) reserved = 0;
12904                    *
12905                    *  unsigned int (1) initial_presentation_delay_present;
12906                    *  if (initial_presentation_delay_present) {
12907                    *    unsigned int (4) initial_presentation_delay_minus_one;
12908                    *  } else {
12909                    *    unsigned int (4) reserved = 0;
12910                    *  }
12911                    *
12912                    *  unsigned int (8) configOBUs[];
12913                    *
12914                    * rest: OBUs.
12915                    */
12916
12917                   switch (av1_data[8]) {
12918                     case 0x81:{
12919                       guint8 pres_delay_field;
12920
12921                       /* We let profile and the other parts be figured out by
12922                        * av1parse and only include the presentation delay here
12923                        * if present */
12924                       /* We skip initial_presentation_delay* for now */
12925                       pres_delay_field = *(av1_data + 11);
12926                       if (pres_delay_field & (1 << 5)) {
12927                         gst_caps_set_simple (entry->caps,
12928                             "presentation-delay", G_TYPE_INT,
12929                             (gint) (pres_delay_field & 0x0F) + 1, NULL);
12930                       }
12931
12932                       buf = gst_buffer_new_and_alloc (size);
12933                       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12934                       gst_buffer_fill (buf, 0, av1_data + 8, size);
12935                       gst_caps_set_simple (entry->caps,
12936                           "codec_data", GST_TYPE_BUFFER, buf, NULL);
12937                       gst_buffer_unref (buf);
12938                       break;
12939                     }
12940                     default:
12941                       GST_WARNING ("Unknown version 0x%02x of av1C box",
12942                           av1_data[8]);
12943                       break;
12944                   }
12945
12946                   break;
12947                 }
12948                 default:
12949                   break;
12950               }
12951
12952               len -= size + 8;
12953               av1_data += size + 8;
12954             }
12955
12956             break;
12957           }
12958
12959             /* TODO: Need to parse vpcC for VP8 codec too.
12960              * Note that VPCodecConfigurationBox (vpcC) is defined for
12961              * vp08, vp09, and vp10 fourcc. */
12962           case FOURCC_vp09:
12963           {
12964             guint len = QT_UINT32 (stsd_entry_data);
12965             len = len <= 0x56 ? 0 : len - 0x56;
12966             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12967
12968             /* find vpcC */
12969             while (len >= 0x8) {
12970               guint size;
12971
12972               if (QT_UINT32 (vpcc_data) <= 0x8)
12973                 size = 0;
12974               else if (QT_UINT32 (vpcc_data) <= len)
12975                 size = QT_UINT32 (vpcc_data) - 0x8;
12976               else
12977                 size = len - 0x8;
12978
12979               if (size < 1)
12980                 /* No real data, so break out */
12981                 break;
12982
12983               switch (QT_FOURCC (vpcc_data + 0x4)) {
12984                 case FOURCC_vpcC:
12985                 {
12986                   const gchar *profile_str = NULL;
12987                   const gchar *chroma_format_str = NULL;
12988                   guint8 profile;
12989                   guint8 bitdepth;
12990                   guint8 chroma_format;
12991                   GstVideoColorimetry cinfo;
12992
12993                   /* parse, if found */
12994                   GST_DEBUG_OBJECT (qtdemux,
12995                       "found vp codec_data in stsd of size %d", size);
12996
12997                   /* the meaning of "size" is length of the atom body, excluding
12998                    * atom length and fourcc fields */
12999                   if (size < 12)
13000                     break;
13001
13002                   /* Content is:
13003                    * 4 bytes: atom length
13004                    * 4 bytes: fourcc
13005                    * 1 byte: version
13006                    * 3 bytes: flags
13007                    * 1 byte: profile
13008                    * 1 byte: level
13009                    * 4 bits: bitDepth
13010                    * 3 bits: chromaSubsampling
13011                    * 1 bit: videoFullRangeFlag
13012                    * 1 byte: colourPrimaries
13013                    * 1 byte: transferCharacteristics
13014                    * 1 byte: matrixCoefficients
13015                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
13016                    * rest: codecIntializationData (not used for vp8 and vp9)
13017                    */
13018
13019                   if (vpcc_data[8] != 1) {
13020                     GST_WARNING_OBJECT (qtdemux,
13021                         "unknown vpcC version %d", vpcc_data[8]);
13022                     break;
13023                   }
13024
13025                   profile = vpcc_data[12];
13026                   switch (profile) {
13027                     case 0:
13028                       profile_str = "0";
13029                       break;
13030                     case 1:
13031                       profile_str = "1";
13032                       break;
13033                     case 2:
13034                       profile_str = "2";
13035                       break;
13036                     case 3:
13037                       profile_str = "3";
13038                       break;
13039                     default:
13040                       break;
13041                   }
13042
13043                   if (profile_str) {
13044                     gst_caps_set_simple (entry->caps,
13045                         "profile", G_TYPE_STRING, profile_str, NULL);
13046                   }
13047
13048                   /* skip level, the VP9 spec v0.6 defines only one level atm,
13049                    * but webm spec define various ones. Add level to caps
13050                    * if we really need it then */
13051
13052                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
13053                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
13054                     gst_caps_set_simple (entry->caps,
13055                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
13056                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
13057                   }
13058
13059                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
13060                   switch (chroma_format) {
13061                     case 0:
13062                     case 1:
13063                       chroma_format_str = "4:2:0";
13064                       break;
13065                     case 2:
13066                       chroma_format_str = "4:2:2";
13067                       break;
13068                     case 3:
13069                       chroma_format_str = "4:4:4";
13070                       break;
13071                     default:
13072                       break;
13073                   }
13074
13075                   if (chroma_format_str) {
13076                     gst_caps_set_simple (entry->caps,
13077                         "chroma-format", G_TYPE_STRING, chroma_format_str,
13078                         NULL);
13079                   }
13080
13081                   if ((vpcc_data[14] & 0x1) != 0)
13082                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
13083                   else
13084                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
13085                   cinfo.primaries =
13086                       gst_video_color_primaries_from_iso (vpcc_data[15]);
13087                   cinfo.transfer =
13088                       gst_video_transfer_function_from_iso (vpcc_data[16]);
13089                   cinfo.matrix =
13090                       gst_video_color_matrix_from_iso (vpcc_data[17]);
13091
13092                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
13093                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
13094                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
13095                     /* set this only if all values are known, otherwise this
13096                      * might overwrite valid ones parsed from other color box */
13097                     CUR_STREAM (stream)->colorimetry = cinfo;
13098                   }
13099                   break;
13100                 }
13101                 default:
13102                   break;
13103               }
13104
13105               len -= size + 8;
13106               vpcc_data += size + 8;
13107             }
13108
13109             break;
13110           }
13111           default:
13112             break;
13113         }
13114       }
13115
13116       GST_INFO_OBJECT (qtdemux,
13117           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13118           GST_FOURCC_ARGS (fourcc), entry->caps);
13119
13120     } else if (stream->subtype == FOURCC_soun) {
13121       GNode *wave;
13122       guint version, samplesize;
13123       guint16 compression_id;
13124       gboolean amrwb = FALSE;
13125
13126       offset = 16;
13127       /* sample description entry (16) + sound sample description v0 (20) */
13128       if (len < 36)
13129         goto corrupt_file;
13130
13131       version = QT_UINT32 (stsd_entry_data + offset);
13132       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
13133       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
13134       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
13135       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
13136
13137       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
13138       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
13139           QT_UINT32 (stsd_entry_data + offset + 4));
13140       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
13141       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
13142       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
13143       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
13144           QT_UINT16 (stsd_entry_data + offset + 14));
13145       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
13146
13147       if (compression_id == 0xfffe)
13148         entry->sampled = TRUE;
13149
13150       /* first assume uncompressed audio */
13151       entry->bytes_per_sample = samplesize / 8;
13152       entry->samples_per_frame = entry->n_channels;
13153       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
13154       entry->samples_per_packet = entry->samples_per_frame;
13155       entry->bytes_per_packet = entry->bytes_per_sample;
13156
13157       offset = 36;
13158
13159       if (version == 0x00010000) {
13160         /* sample description entry (16) + sound sample description v1 (20+16) */
13161         if (len < 52)
13162           goto corrupt_file;
13163
13164         /* take information from here over the normal sample description */
13165         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
13166         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
13167         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
13168         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
13169
13170         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
13171         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
13172             entry->samples_per_packet);
13173         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
13174             entry->bytes_per_packet);
13175         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
13176             entry->bytes_per_frame);
13177         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
13178             entry->bytes_per_sample);
13179
13180         if (!entry->sampled && entry->bytes_per_packet) {
13181           entry->samples_per_frame = (entry->bytes_per_frame /
13182               entry->bytes_per_packet) * entry->samples_per_packet;
13183           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
13184               entry->samples_per_frame);
13185         }
13186       } else if (version == 0x00020000) {
13187         /* sample description entry (16) + sound sample description v2 (56) */
13188         if (len < 72)
13189           goto corrupt_file;
13190
13191         /* take information from here over the normal sample description */
13192         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
13193         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
13194         entry->samples_per_frame = entry->n_channels;
13195         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
13196         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
13197         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
13198         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
13199
13200         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
13201         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
13202         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
13203         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
13204             entry->bytes_per_sample * 8);
13205         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
13206             QT_UINT32 (stsd_entry_data + offset + 24));
13207         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
13208             entry->bytes_per_packet);
13209         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
13210             entry->samples_per_packet);
13211       } else if (version != 0x00000) {
13212         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
13213             version);
13214       }
13215
13216       switch (fourcc) {
13217           /* Yes, these have to be hard-coded */
13218         case FOURCC_MAC6:
13219         {
13220           entry->samples_per_packet = 6;
13221           entry->bytes_per_packet = 1;
13222           entry->bytes_per_frame = 1 * entry->n_channels;
13223           entry->bytes_per_sample = 1;
13224           entry->samples_per_frame = 6 * entry->n_channels;
13225           break;
13226         }
13227         case FOURCC_MAC3:
13228         {
13229           entry->samples_per_packet = 3;
13230           entry->bytes_per_packet = 1;
13231           entry->bytes_per_frame = 1 * entry->n_channels;
13232           entry->bytes_per_sample = 1;
13233           entry->samples_per_frame = 3 * entry->n_channels;
13234           break;
13235         }
13236         case FOURCC_ima4:
13237         {
13238           entry->samples_per_packet = 64;
13239           entry->bytes_per_packet = 34;
13240           entry->bytes_per_frame = 34 * entry->n_channels;
13241           entry->bytes_per_sample = 2;
13242           entry->samples_per_frame = 64 * entry->n_channels;
13243           break;
13244         }
13245         case FOURCC_ulaw:
13246         case FOURCC_alaw:
13247         {
13248           entry->samples_per_packet = 1;
13249           entry->bytes_per_packet = 1;
13250           entry->bytes_per_frame = 1 * entry->n_channels;
13251           entry->bytes_per_sample = 1;
13252           entry->samples_per_frame = 1 * entry->n_channels;
13253           break;
13254         }
13255         case FOURCC_agsm:
13256         {
13257           entry->samples_per_packet = 160;
13258           entry->bytes_per_packet = 33;
13259           entry->bytes_per_frame = 33 * entry->n_channels;
13260           entry->bytes_per_sample = 2;
13261           entry->samples_per_frame = 160 * entry->n_channels;
13262           break;
13263         }
13264           /* fix up any invalid header information from above */
13265         case FOURCC_twos:
13266         case FOURCC_sowt:
13267         case FOURCC_raw_:
13268         case FOURCC_lpcm:
13269           /* Sometimes these are set to 0 in the sound sample descriptions so
13270            * let's try to infer useful values from the other information we
13271            * have available */
13272           if (entry->bytes_per_sample == 0)
13273             entry->bytes_per_sample =
13274                 entry->bytes_per_frame / entry->n_channels;
13275           if (entry->bytes_per_sample == 0)
13276             entry->bytes_per_sample = samplesize / 8;
13277
13278           if (entry->bytes_per_frame == 0)
13279             entry->bytes_per_frame =
13280                 entry->bytes_per_sample * entry->n_channels;
13281
13282           if (entry->bytes_per_packet == 0)
13283             entry->bytes_per_packet = entry->bytes_per_sample;
13284
13285           if (entry->samples_per_frame == 0)
13286             entry->samples_per_frame = entry->n_channels;
13287
13288           if (entry->samples_per_packet == 0)
13289             entry->samples_per_packet = entry->samples_per_frame;
13290
13291           break;
13292         case FOURCC_in24:
13293         case FOURCC_in32:
13294         case FOURCC_fl32:
13295         case FOURCC_fl64:
13296         case FOURCC_s16l:{
13297           switch (fourcc) {
13298             case FOURCC_in24:
13299               entry->bytes_per_sample = 3;
13300               break;
13301             case FOURCC_in32:
13302             case FOURCC_fl32:
13303               entry->bytes_per_sample = 4;
13304               break;
13305             case FOURCC_fl64:
13306               entry->bytes_per_sample = 8;
13307               break;
13308             case FOURCC_s16l:
13309               entry->bytes_per_sample = 2;
13310               break;
13311             default:
13312               g_assert_not_reached ();
13313               break;
13314           }
13315           entry->samples_per_frame = entry->n_channels;
13316           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
13317           entry->samples_per_packet = entry->samples_per_frame;
13318           entry->bytes_per_packet = entry->bytes_per_sample;
13319           break;
13320         }
13321
13322           /* According to TS 102 366, the channel count in
13323            * a (E)AC3SampleEntry box is to be ignored */
13324         case 0x20736d:
13325         case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13326         case GST_MAKE_FOURCC ('s', 'a', 'c', '3'):     // Nero Recode
13327         case FOURCC_ac_3:
13328           entry->n_channels = 0;
13329           break;
13330
13331         default:
13332           break;
13333       }
13334
13335       if (entry->caps)
13336         gst_caps_unref (entry->caps);
13337
13338       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
13339           stsd_entry_data + 32, len - 16, &codec);
13340
13341       switch (fourcc) {
13342         case FOURCC_in24:
13343         case FOURCC_in32:
13344         case FOURCC_fl32:
13345         case FOURCC_fl64:
13346         {
13347           GNode *enda;
13348           GNode *fmt;
13349
13350           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
13351
13352           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
13353           if (!enda) {
13354             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
13355             if (wave)
13356               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
13357           }
13358           if (enda) {
13359             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
13360             const gchar *format_str;
13361
13362             switch (fourcc) {
13363               case FOURCC_in24:
13364                 format_str = (enda_value) ? "S24LE" : "S24BE";
13365                 break;
13366               case FOURCC_in32:
13367                 format_str = (enda_value) ? "S32LE" : "S32BE";
13368                 break;
13369               case FOURCC_fl32:
13370                 format_str = (enda_value) ? "F32LE" : "F32BE";
13371                 break;
13372               case FOURCC_fl64:
13373                 format_str = (enda_value) ? "F64LE" : "F64BE";
13374                 break;
13375               default:
13376                 g_assert_not_reached ();
13377                 break;
13378             }
13379             gst_caps_set_simple (entry->caps,
13380                 "format", G_TYPE_STRING, format_str, NULL);
13381           }
13382           break;
13383         }
13384         case FOURCC_owma:
13385         {
13386           const guint8 *owma_data;
13387           const gchar *codec_name = NULL;
13388           guint owma_len;
13389           GstBuffer *buf;
13390           gint version = 1;
13391           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
13392           /* FIXME this should also be gst_riff_strf_auds,
13393            * but the latter one is actually missing bits-per-sample :( */
13394           typedef struct
13395           {
13396             gint16 wFormatTag;
13397             gint16 nChannels;
13398             gint32 nSamplesPerSec;
13399             gint32 nAvgBytesPerSec;
13400             gint16 nBlockAlign;
13401             gint16 wBitsPerSample;
13402             gint16 cbSize;
13403           } WAVEFORMATEX;
13404           WAVEFORMATEX *wfex;
13405
13406           GST_DEBUG_OBJECT (qtdemux, "parse owma");
13407           owma_data = stsd_entry_data;
13408           owma_len = QT_UINT32 (owma_data);
13409           if (owma_len <= 54) {
13410             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
13411             break;
13412           }
13413           wfex = (WAVEFORMATEX *) (owma_data + 36);
13414           buf = gst_buffer_new_and_alloc (owma_len - 54);
13415           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
13416           if (wfex->wFormatTag == 0x0161) {
13417             codec_name = "Windows Media Audio";
13418             version = 2;
13419           } else if (wfex->wFormatTag == 0x0162) {
13420             codec_name = "Windows Media Audio 9 Pro";
13421             version = 3;
13422           } else if (wfex->wFormatTag == 0x0163) {
13423             codec_name = "Windows Media Audio 9 Lossless";
13424             /* is that correct? gstffmpegcodecmap.c is missing it, but
13425              * fluendo codec seems to support it */
13426             version = 4;
13427           }
13428
13429           gst_caps_set_simple (entry->caps,
13430               "codec_data", GST_TYPE_BUFFER, buf,
13431               "wmaversion", G_TYPE_INT, version,
13432               "block_align", G_TYPE_INT,
13433               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
13434               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
13435               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
13436               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
13437           gst_buffer_unref (buf);
13438
13439           if (codec_name) {
13440             g_free (codec);
13441             codec = g_strdup (codec_name);
13442           }
13443           break;
13444         }
13445         case FOURCC_wma_:
13446         {
13447           guint len = QT_UINT32 (stsd_entry_data);
13448           len = len <= offset ? 0 : len - offset;
13449           const guint8 *wfex_data = stsd_entry_data + offset;
13450           const gchar *codec_name = NULL;
13451           gint version = 1;
13452           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
13453           /* FIXME this should also be gst_riff_strf_auds,
13454            * but the latter one is actually missing bits-per-sample :( */
13455           typedef struct
13456           {
13457             gint16 wFormatTag;
13458             gint16 nChannels;
13459             gint32 nSamplesPerSec;
13460             gint32 nAvgBytesPerSec;
13461             gint16 nBlockAlign;
13462             gint16 wBitsPerSample;
13463             gint16 cbSize;
13464           } WAVEFORMATEX;
13465           WAVEFORMATEX wfex;
13466
13467           /* FIXME: unify with similar wavformatex parsing code above */
13468           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
13469
13470           /* find wfex */
13471           while (len >= 8) {
13472             guint size;
13473
13474             if (QT_UINT32 (wfex_data) <= 0x8)
13475               size = 0;
13476             else if (QT_UINT32 (wfex_data) <= len)
13477               size = QT_UINT32 (wfex_data) - 8;
13478             else
13479               size = len - 8;
13480
13481             if (size < 1)
13482               /* No real data, so break out */
13483               break;
13484
13485             switch (QT_FOURCC (wfex_data + 4)) {
13486               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
13487               {
13488                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
13489
13490                 if (size < 8 + 18)
13491                   break;
13492
13493                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
13494                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
13495                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
13496                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
13497                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
13498                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
13499                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
13500
13501                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
13502                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
13503                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
13504                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
13505                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
13506                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
13507
13508                 if (wfex.wFormatTag == 0x0161) {
13509                   codec_name = "Windows Media Audio";
13510                   version = 2;
13511                 } else if (wfex.wFormatTag == 0x0162) {
13512                   codec_name = "Windows Media Audio 9 Pro";
13513                   version = 3;
13514                 } else if (wfex.wFormatTag == 0x0163) {
13515                   codec_name = "Windows Media Audio 9 Lossless";
13516                   /* is that correct? gstffmpegcodecmap.c is missing it, but
13517                    * fluendo codec seems to support it */
13518                   version = 4;
13519                 }
13520
13521                 gst_caps_set_simple (entry->caps,
13522                     "wmaversion", G_TYPE_INT, version,
13523                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
13524                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
13525                     "width", G_TYPE_INT, wfex.wBitsPerSample,
13526                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
13527
13528                 if (size > wfex.cbSize) {
13529                   GstBuffer *buf;
13530
13531                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
13532                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
13533                       size - wfex.cbSize);
13534                   gst_caps_set_simple (entry->caps,
13535                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
13536                   gst_buffer_unref (buf);
13537                 } else {
13538                   GST_WARNING_OBJECT (qtdemux, "no codec data");
13539                 }
13540
13541                 if (codec_name) {
13542                   g_free (codec);
13543                   codec = g_strdup (codec_name);
13544                 }
13545                 break;
13546               }
13547               default:
13548                 break;
13549             }
13550             len -= size + 8;
13551             wfex_data += size + 8;
13552           }
13553           break;
13554         }
13555         case FOURCC_opus:
13556         {
13557           guint8 *channel_mapping = NULL;
13558           guint32 dops_len, rate;
13559           guint8 n_channels;
13560           guint8 channel_mapping_family;
13561           guint8 stream_count;
13562           guint8 coupled_count;
13563           guint8 i;
13564
13565           GNode *opus;
13566           GNode *dops;
13567
13568           opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
13569           if (opus == NULL) {
13570             GST_WARNING_OBJECT (qtdemux, "Opus Sample Entry not found");
13571             goto corrupt_file;
13572           }
13573
13574           dops = qtdemux_tree_get_child_by_type (opus, FOURCC_dops);
13575           if (dops == NULL) {
13576             GST_WARNING_OBJECT (qtdemux, "Opus Specific Box not found");
13577             goto corrupt_file;
13578           }
13579
13580           /* Opus Specific Box content:
13581            * 4 bytes: length
13582            * 4 bytes: "dOps"
13583            * 1 byte: Version;
13584            * 1 byte: OutputChannelCount;
13585            * 2 bytes: PreSkip (big-endians);
13586            * 4 bytes: InputSampleRate (big-endians);
13587            * 2 bytes: OutputGain (big-endians);
13588            * 1 byte: ChannelMappingFamily;
13589            * if (ChannelMappingFamily != 0) {
13590            *   1 byte: StreamCount;
13591            *   1 byte: CoupledCount;
13592            *   for (OutputChannel in 0..OutputChannelCount) {
13593            *     1 byte: ChannelMapping;
13594            *   }
13595            * }
13596            */
13597
13598           dops_len = QT_UINT32 ((guint8 *) dops->data);
13599           if (len < offset + dops_len) {
13600             GST_WARNING_OBJECT (qtdemux,
13601                 "Opus Sample Entry has bogus size %" G_GUINT32_FORMAT, len);
13602             goto corrupt_file;
13603           }
13604           if (dops_len < 19) {
13605             GST_WARNING_OBJECT (qtdemux,
13606                 "Opus Specific Box has bogus size %" G_GUINT32_FORMAT,
13607                 dops_len);
13608             goto corrupt_file;
13609           }
13610
13611           n_channels = GST_READ_UINT8 ((guint8 *) dops->data + 9);
13612           rate = GST_READ_UINT32_BE ((guint8 *) dops->data + 12);
13613           channel_mapping_family = GST_READ_UINT8 ((guint8 *) dops->data + 18);
13614
13615           if (channel_mapping_family != 0) {
13616             if (dops_len < 21 + n_channels) {
13617               GST_WARNING_OBJECT (qtdemux,
13618                   "Opus Specific Box has bogus size %" G_GUINT32_FORMAT,
13619                   dops_len);
13620               goto corrupt_file;
13621             }
13622
13623             stream_count = GST_READ_UINT8 ((guint8 *) dops->data + 19);
13624             coupled_count = GST_READ_UINT8 ((guint8 *) dops->data + 20);
13625
13626             if (n_channels > 0) {
13627               channel_mapping = g_malloc (n_channels * sizeof (guint8));
13628               for (i = 0; i < n_channels; i++)
13629                 channel_mapping[i] =
13630                     GST_READ_UINT8 ((guint8 *) dops->data + i + 21);
13631             }
13632           } else if (n_channels == 1) {
13633             stream_count = 1;
13634             coupled_count = 0;
13635           } else if (n_channels == 2) {
13636             stream_count = 1;
13637             coupled_count = 1;
13638           } else {
13639             GST_WARNING_OBJECT (qtdemux,
13640                 "Opus unexpected nb of channels %d without channel mapping",
13641                 n_channels);
13642             goto corrupt_file;
13643           }
13644
13645           entry->caps = gst_codec_utils_opus_create_caps (rate, n_channels,
13646               channel_mapping_family, stream_count, coupled_count,
13647               channel_mapping);
13648           g_free (channel_mapping);
13649
13650           entry->sampled = TRUE;
13651
13652           break;
13653         }
13654         default:
13655           break;
13656       }
13657
13658       if (codec) {
13659         GstStructure *s;
13660         gint bitrate = 0;
13661
13662         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13663             GST_TAG_AUDIO_CODEC, codec, NULL);
13664         g_free (codec);
13665         codec = NULL;
13666
13667         /* some bitrate info may have ended up in caps */
13668         s = gst_caps_get_structure (entry->caps, 0);
13669         gst_structure_get_int (s, "bitrate", &bitrate);
13670         if (bitrate > 0)
13671           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13672               GST_TAG_BITRATE, bitrate, NULL);
13673       }
13674
13675       esds = NULL;
13676       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
13677       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
13678         if (stream->protected) {
13679           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
13680             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
13681           }
13682           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
13683             mp4a = NULL;
13684           }
13685         } else {
13686           mp4a = NULL;
13687         }
13688       }
13689
13690       wave = NULL;
13691       if (mp4a) {
13692         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
13693         if (wave)
13694           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
13695         if (!esds)
13696           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
13697       }
13698
13699
13700       /* If the fourcc's bottom 16 bits gives 'sm', then the top
13701          16 bits is a byte-swapped wave-style codec identifier,
13702          and we can find a WAVE header internally to a 'wave' atom here.
13703          This can more clearly be thought of as 'ms' as the top 16 bits, and a
13704          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
13705          is big-endian).
13706        */
13707       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
13708         if (len < offset + 20) {
13709           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
13710         } else {
13711           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
13712           const guint8 *data = stsd_entry_data + offset + 16;
13713           GNode *wavenode;
13714           GNode *waveheadernode;
13715
13716           wavenode = g_node_new ((guint8 *) data);
13717           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
13718             const guint8 *waveheader;
13719             guint32 headerlen;
13720
13721             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
13722             if (waveheadernode) {
13723               waveheader = (const guint8 *) waveheadernode->data;
13724               headerlen = QT_UINT32 (waveheader);
13725
13726               if (headerlen > 8) {
13727                 gst_riff_strf_auds *header = NULL;
13728                 GstBuffer *headerbuf;
13729                 GstBuffer *extra;
13730
13731                 waveheader += 8;
13732                 headerlen -= 8;
13733
13734                 headerbuf = gst_buffer_new_and_alloc (headerlen);
13735                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
13736
13737                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
13738                         headerbuf, &header, &extra)) {
13739                   gst_caps_unref (entry->caps);
13740                   /* FIXME: Need to do something with the channel reorder map */
13741                   entry->caps =
13742                       gst_riff_create_audio_caps (header->format, NULL, header,
13743                       extra, NULL, NULL, NULL);
13744
13745                   if (extra)
13746                     gst_buffer_unref (extra);
13747                   g_free (header);
13748                 }
13749               }
13750             } else
13751               GST_DEBUG ("Didn't find waveheadernode for this codec");
13752           }
13753           g_node_destroy (wavenode);
13754         }
13755       } else if (esds) {
13756         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13757             stream->stream_tags);
13758       } else {
13759         switch (fourcc) {
13760 #if 0
13761             /* FIXME: what is in the chunk? */
13762           case FOURCC_QDMC:
13763           {
13764             gint len = QT_UINT32 (stsd_data);
13765
13766             /* seems to be always = 116 = 0x74 */
13767             break;
13768           }
13769 #endif
13770           case FOURCC_QDM2:
13771           {
13772             gint len = QT_UINT32 (stsd_entry_data);
13773
13774             if (len > 0x3C) {
13775               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
13776
13777               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
13778               gst_caps_set_simple (entry->caps,
13779                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13780               gst_buffer_unref (buf);
13781             }
13782             gst_caps_set_simple (entry->caps,
13783                 "samplesize", G_TYPE_INT, samplesize, NULL);
13784             break;
13785           }
13786           case FOURCC_alac:
13787           {
13788             GNode *alac, *wave = NULL;
13789
13790             /* apparently, m4a has this atom appended directly in the stsd entry,
13791              * while mov has it in a wave atom */
13792             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
13793             if (alac) {
13794               /* alac now refers to stsd entry atom */
13795               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
13796               if (wave)
13797                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
13798               else
13799                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
13800             }
13801             if (alac) {
13802               const guint8 *alac_data = alac->data;
13803               gint len = QT_UINT32 (alac->data);
13804               GstBuffer *buf;
13805
13806               if (len < 36) {
13807                 GST_DEBUG_OBJECT (qtdemux,
13808                     "discarding alac atom with unexpected len %d", len);
13809               } else {
13810                 /* codec-data contains alac atom size and prefix,
13811                  * ffmpeg likes it that way, not quite gst-ish though ...*/
13812                 buf = gst_buffer_new_and_alloc (len);
13813                 gst_buffer_fill (buf, 0, alac->data, len);
13814                 gst_caps_set_simple (entry->caps,
13815                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
13816                 gst_buffer_unref (buf);
13817
13818                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
13819                 entry->n_channels = QT_UINT8 (alac_data + 21);
13820                 entry->rate = QT_UINT32 (alac_data + 32);
13821                 samplesize = QT_UINT8 (alac_data + 16 + 1);
13822               }
13823             }
13824             gst_caps_set_simple (entry->caps,
13825                 "samplesize", G_TYPE_INT, samplesize, NULL);
13826             break;
13827           }
13828           case FOURCC_fLaC:
13829           {
13830             /* The codingname of the sample entry is 'fLaC' */
13831             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13832
13833             if (flac) {
13834               /* The 'dfLa' box is added to the sample entry to convey
13835                  initializing information for the decoder. */
13836               const GNode *dfla =
13837                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13838
13839               if (dfla) {
13840                 const guint32 len = QT_UINT32 (dfla->data);
13841
13842                 /* Must contain at least dfLa box header (12),
13843                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13844                 if (len < 50) {
13845                   GST_DEBUG_OBJECT (qtdemux,
13846                       "discarding dfla atom with unexpected len %d", len);
13847                 } else {
13848                   /* skip dfLa header to get the METADATA_BLOCKs */
13849                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13850                   const guint32 metadata_blocks_len = len - 12;
13851
13852                   gchar *stream_marker = g_strdup ("fLaC");
13853                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13854                       strlen (stream_marker));
13855
13856                   guint32 index = 0;
13857                   guint32 remainder = 0;
13858                   guint32 block_size = 0;
13859                   gboolean is_last = FALSE;
13860
13861                   GValue array = G_VALUE_INIT;
13862                   GValue value = G_VALUE_INIT;
13863
13864                   g_value_init (&array, GST_TYPE_ARRAY);
13865                   g_value_init (&value, GST_TYPE_BUFFER);
13866
13867                   gst_value_set_buffer (&value, block);
13868                   gst_value_array_append_value (&array, &value);
13869                   g_value_reset (&value);
13870
13871                   gst_buffer_unref (block);
13872
13873                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13874                    * of data, and we haven't already finished parsing */
13875                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13876                     remainder = metadata_blocks_len - index;
13877
13878                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13879                     block_size = 4 +
13880                         (metadata_blocks[index + 1] << 16) +
13881                         (metadata_blocks[index + 2] << 8) +
13882                         metadata_blocks[index + 3];
13883
13884                     /* be careful not to read off end of box */
13885                     if (block_size > remainder) {
13886                       break;
13887                     }
13888
13889                     is_last = metadata_blocks[index] >> 7;
13890
13891                     block = gst_buffer_new_and_alloc (block_size);
13892
13893                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13894                         block_size);
13895
13896                     gst_value_set_buffer (&value, block);
13897                     gst_value_array_append_value (&array, &value);
13898                     g_value_reset (&value);
13899
13900                     gst_buffer_unref (block);
13901
13902                     index += block_size;
13903                   }
13904
13905                   /* only append the metadata if we successfully read all of it */
13906                   if (is_last) {
13907                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13908                             (stream)->caps, 0), "streamheader", &array);
13909                   } else {
13910                     GST_WARNING_OBJECT (qtdemux,
13911                         "discarding all METADATA_BLOCKs due to invalid "
13912                         "block_size %d at idx %d, rem %d", block_size, index,
13913                         remainder);
13914                   }
13915
13916                   g_value_unset (&value);
13917                   g_value_unset (&array);
13918
13919                   /* The sample rate obtained from the stsd may not be accurate
13920                    * since it cannot represent rates greater than 65535Hz, so
13921                    * override that value with the sample rate from the
13922                    * METADATA_BLOCK_STREAMINFO block */
13923                   CUR_STREAM (stream)->rate =
13924                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13925                 }
13926               }
13927             }
13928             break;
13929           }
13930           case FOURCC_sawb:
13931             /* Fallthrough! */
13932             amrwb = TRUE;
13933           case FOURCC_samr:
13934           {
13935             gint len = QT_UINT32 (stsd_entry_data);
13936
13937             if (len > 0x24) {
13938               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13939               guint bitrate;
13940
13941               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13942
13943               /* If we have enough data, let's try to get the 'damr' atom. See
13944                * the 3GPP container spec (26.244) for more details. */
13945               if ((len - 0x34) > 8 &&
13946                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13947                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13948                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13949               }
13950
13951               gst_caps_set_simple (entry->caps,
13952                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13953               gst_buffer_unref (buf);
13954             }
13955             break;
13956           }
13957           case FOURCC_mp4a:
13958           {
13959             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13960             gint len = QT_UINT32 (stsd_entry_data);
13961             guint16 sound_version = 0;
13962             /* FIXME: Can this be determined somehow? There doesn't seem to be
13963              * anything in mp4a atom that specifis compression */
13964             gint profile = 2;
13965             guint16 channels = entry->n_channels;
13966             guint32 time_scale = (guint32) entry->rate;
13967             gint sample_rate_index = -1;
13968
13969             if (len >= 34) {
13970               sound_version = QT_UINT16 (stsd_entry_data + 16);
13971
13972               if (sound_version == 1) {
13973                 channels = QT_UINT16 (stsd_entry_data + 24);
13974                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13975               } else {
13976                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13977                     sound_version);
13978               }
13979             } else {
13980               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13981                   len);
13982             }
13983
13984             sample_rate_index =
13985                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13986             if (sample_rate_index >= 0 && channels > 0) {
13987               guint8 codec_data[2];
13988               GstBuffer *buf;
13989
13990               /* build AAC codec data */
13991               codec_data[0] = profile << 3;
13992               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13993               codec_data[1] = (sample_rate_index & 0x01) << 7;
13994               codec_data[1] |= (channels & 0xF) << 3;
13995
13996               buf = gst_buffer_new_and_alloc (2);
13997               gst_buffer_fill (buf, 0, codec_data, 2);
13998               gst_caps_set_simple (entry->caps,
13999                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
14000               gst_buffer_unref (buf);
14001             }
14002             break;
14003           }
14004           case FOURCC_opus:
14005           case FOURCC_lpcm:
14006           case FOURCC_in24:
14007           case FOURCC_in32:
14008           case FOURCC_fl32:
14009           case FOURCC_fl64:
14010           case FOURCC_s16l:
14011             /* Fully handled elsewhere */
14012             break;
14013           default:
14014             GST_INFO_OBJECT (qtdemux,
14015                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14016             break;
14017         }
14018       }
14019       GST_INFO_OBJECT (qtdemux,
14020           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
14021           GST_FOURCC_ARGS (fourcc), entry->caps);
14022
14023     } else if (stream->subtype == FOURCC_strm) {
14024       if (fourcc == FOURCC_rtsp) {
14025         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
14026       } else {
14027         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
14028             GST_FOURCC_ARGS (fourcc));
14029         goto unknown_stream;
14030       }
14031       entry->sampled = TRUE;
14032     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
14033         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
14034         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
14035
14036       entry->sampled = TRUE;
14037       entry->sparse = TRUE;
14038
14039       entry->caps =
14040           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
14041           &codec);
14042       if (codec) {
14043         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
14044             GST_TAG_SUBTITLE_CODEC, codec, NULL);
14045         g_free (codec);
14046         codec = NULL;
14047       }
14048
14049       /* hunt for sort-of codec data */
14050       switch (fourcc) {
14051         case FOURCC_mp4s:
14052         {
14053           GNode *mp4s = NULL;
14054           GNode *esds = NULL;
14055
14056           /* look for palette in a stsd->mp4s->esds sub-atom */
14057           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
14058           if (mp4s)
14059             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
14060           if (esds == NULL) {
14061             /* Invalid STSD */
14062             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
14063             break;
14064           }
14065
14066           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
14067               stream->stream_tags);
14068           break;
14069         }
14070         default:
14071           GST_INFO_OBJECT (qtdemux,
14072               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14073           break;
14074       }
14075       GST_INFO_OBJECT (qtdemux,
14076           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
14077           GST_FOURCC_ARGS (fourcc), entry->caps);
14078     } else if (stream->subtype == FOURCC_meta) {
14079       entry->sampled = TRUE;
14080       entry->sparse = TRUE;
14081
14082       entry->caps =
14083           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
14084           &codec);
14085       if (codec) {
14086         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
14087             GST_TAG_CODEC, codec, NULL);
14088         g_free (codec);
14089         codec = NULL;
14090       }
14091
14092       GST_INFO_OBJECT (qtdemux,
14093           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
14094           GST_FOURCC_ARGS (fourcc), entry->caps);
14095     } else {
14096       /* everything in 1 sample */
14097       entry->sampled = TRUE;
14098
14099       entry->caps =
14100           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
14101           &codec);
14102
14103       if (entry->caps == NULL)
14104         goto unknown_stream;
14105
14106       if (codec) {
14107         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
14108             GST_TAG_SUBTITLE_CODEC, codec, NULL);
14109         g_free (codec);
14110         codec = NULL;
14111       }
14112     }
14113
14114     /* promote to sampled format */
14115     if (entry->fourcc == FOURCC_samr) {
14116       /* force mono 8000 Hz for AMR */
14117       entry->sampled = TRUE;
14118       entry->n_channels = 1;
14119       entry->rate = 8000;
14120     } else if (entry->fourcc == FOURCC_sawb) {
14121       /* force mono 16000 Hz for AMR-WB */
14122       entry->sampled = TRUE;
14123       entry->n_channels = 1;
14124       entry->rate = 16000;
14125     } else if (entry->fourcc == FOURCC_mp4a) {
14126       entry->sampled = TRUE;
14127     }
14128
14129
14130     stsd_entry_data += len;
14131     remaining_stsd_len -= len;
14132
14133   }
14134
14135   /* collect sample information */
14136   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
14137     goto samples_failed;
14138
14139   if (qtdemux->fragmented) {
14140     guint64 offset;
14141
14142     /* need all moov samples as basis; probably not many if any at all */
14143     /* prevent moof parsing taking of at this time */
14144     offset = qtdemux->moof_offset;
14145     qtdemux->moof_offset = 0;
14146     if (stream->n_samples &&
14147         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
14148       qtdemux->moof_offset = offset;
14149       goto samples_failed;
14150     }
14151     qtdemux->moof_offset = offset;
14152     /* movie duration more reliable in this case (e.g. mehd) */
14153     if (qtdemux->segment.duration &&
14154         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
14155       stream->duration =
14156           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
14157   }
14158
14159   /* configure segments */
14160   if (!qtdemux_parse_segments (qtdemux, stream, trak))
14161     goto segments_failed;
14162
14163   /* add some language tag, if useful */
14164   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
14165       strcmp (stream->lang_id, "und")) {
14166     const gchar *lang_code;
14167
14168     /* convert ISO 639-2 code to ISO 639-1 */
14169     lang_code = gst_tag_get_language_code (stream->lang_id);
14170     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
14171         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
14172   }
14173
14174   /* Check for UDTA tags */
14175   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
14176     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
14177   }
14178
14179   /* Insert and sort new stream in track-id order.
14180    * This will help in comparing old/new streams during stream update check */
14181   g_ptr_array_add (qtdemux->active_streams, stream);
14182   g_ptr_array_sort (qtdemux->active_streams,
14183       (GCompareFunc) qtdemux_track_id_compare_func);
14184   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
14185       QTDEMUX_N_STREAMS (qtdemux));
14186
14187   return TRUE;
14188
14189 /* ERRORS */
14190 corrupt_file:
14191   {
14192     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
14193         (_("This file is corrupt and cannot be played.")), (NULL));
14194     if (stream)
14195       gst_qtdemux_stream_unref (stream);
14196     return FALSE;
14197   }
14198 error_encrypted:
14199   {
14200     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
14201     gst_qtdemux_stream_unref (stream);
14202     return FALSE;
14203   }
14204 samples_failed:
14205 segments_failed:
14206   {
14207     /* we posted an error already */
14208     /* free stbl sub-atoms */
14209     gst_qtdemux_stbl_free (stream);
14210     gst_qtdemux_stream_unref (stream);
14211     return FALSE;
14212   }
14213 existing_stream:
14214   {
14215     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
14216         track_id);
14217     return TRUE;
14218   }
14219 unknown_stream:
14220   {
14221     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
14222         GST_FOURCC_ARGS (stream->subtype));
14223     gst_qtdemux_stream_unref (stream);
14224     return TRUE;
14225   }
14226 }
14227
14228 /* If we can estimate the overall bitrate, and don't have information about the
14229  * stream bitrate for exactly one stream, this guesses the stream bitrate as
14230  * the overall bitrate minus the sum of the bitrates of all other streams. This
14231  * should be useful for the common case where we have one audio and one video
14232  * stream and can estimate the bitrate of one, but not the other. */
14233 static void
14234 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
14235 {
14236   QtDemuxStream *stream = NULL;
14237   gint64 size, sys_bitrate, sum_bitrate = 0;
14238   GstClockTime duration;
14239   guint bitrate;
14240   gint i;
14241
14242   if (qtdemux->fragmented)
14243     return;
14244
14245   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
14246
14247   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
14248       || size <= 0) {
14249     GST_DEBUG_OBJECT (qtdemux,
14250         "Size in bytes of the stream not known - bailing");
14251     return;
14252   }
14253
14254   /* Subtract the header size */
14255   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
14256       size, qtdemux->header_size);
14257
14258   if (size < qtdemux->header_size)
14259     return;
14260
14261   size = size - qtdemux->header_size;
14262
14263   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
14264     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
14265     return;
14266   }
14267
14268   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14269     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
14270     switch (str->subtype) {
14271       case FOURCC_soun:
14272       case FOURCC_vide:
14273         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
14274             CUR_STREAM (str)->caps);
14275         /* retrieve bitrate, prefer avg then max */
14276         bitrate = 0;
14277         if (str->stream_tags) {
14278           if (gst_tag_list_get_uint (str->stream_tags,
14279                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
14280             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
14281           if (gst_tag_list_get_uint (str->stream_tags,
14282                   GST_TAG_NOMINAL_BITRATE, &bitrate))
14283             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
14284           if (gst_tag_list_get_uint (str->stream_tags,
14285                   GST_TAG_BITRATE, &bitrate))
14286             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
14287         }
14288         if (bitrate)
14289           sum_bitrate += bitrate;
14290         else {
14291           if (stream) {
14292             GST_DEBUG_OBJECT (qtdemux,
14293                 ">1 stream with unknown bitrate - bailing");
14294             return;
14295           } else
14296             stream = str;
14297         }
14298
14299       default:
14300         /* For other subtypes, we assume no significant impact on bitrate */
14301         break;
14302     }
14303   }
14304
14305   if (!stream) {
14306     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
14307     return;
14308   }
14309
14310   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
14311
14312   if (sys_bitrate < sum_bitrate) {
14313     /* This can happen, since sum_bitrate might be derived from maximum
14314      * bitrates and not average bitrates */
14315     GST_DEBUG_OBJECT (qtdemux,
14316         "System bitrate less than sum bitrate - bailing");
14317     return;
14318   }
14319
14320   bitrate = sys_bitrate - sum_bitrate;
14321   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
14322       ", Stream bitrate = %u", sys_bitrate, bitrate);
14323
14324   if (!stream->stream_tags)
14325     stream->stream_tags = gst_tag_list_new_empty ();
14326   else
14327     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
14328
14329   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
14330       GST_TAG_BITRATE, bitrate, NULL);
14331 }
14332
14333 static GstFlowReturn
14334 qtdemux_prepare_streams (GstQTDemux * qtdemux)
14335 {
14336   GstFlowReturn ret = GST_FLOW_OK;
14337 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
14338   guint64 tkhd_max_duration = 0;
14339 #endif
14340   gint i;
14341
14342   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
14343
14344   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14345     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14346     guint32 sample_num = 0;
14347
14348     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
14349         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
14350
14351     if (qtdemux->fragmented && qtdemux->pullbased) {
14352       /* need all moov samples first */
14353       GST_OBJECT_LOCK (qtdemux);
14354       while (stream->n_samples == 0)
14355         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
14356           break;
14357       GST_OBJECT_UNLOCK (qtdemux);
14358     } else {
14359       /* discard any stray moof */
14360       qtdemux->moof_offset = 0;
14361 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
14362       if (tkhd_max_duration < stream->tkhd_duration)
14363         tkhd_max_duration = stream->tkhd_duration;
14364 #endif
14365     }
14366
14367     /* prepare braking */
14368     if (ret != GST_FLOW_ERROR)
14369       ret = GST_FLOW_OK;
14370
14371     /* in pull mode, we should have parsed some sample info by now;
14372      * and quite some code will not handle no samples.
14373      * in push mode, we'll just have to deal with it */
14374     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
14375       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
14376       g_ptr_array_remove_index (qtdemux->active_streams, i);
14377       i--;
14378       continue;
14379     } else if (stream->track_id == qtdemux->chapters_track_id &&
14380         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
14381       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
14382          so that it doesn't look like a subtitle track */
14383       g_ptr_array_remove_index (qtdemux->active_streams, i);
14384       i--;
14385       continue;
14386     }
14387
14388     /* parse the initial sample for use in setting the frame rate cap */
14389     while (sample_num == 0 && sample_num < stream->n_samples) {
14390       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
14391         break;
14392       ++sample_num;
14393     }
14394   }
14395
14396 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
14397   if (!qtdemux->fragmented && (qtdemux->duration > tkhd_max_duration)) {
14398     GST_INFO_OBJECT (qtdemux,
14399         "Update duration: %" G_GUINT64_FORMAT " -> %" G_GUINT64_FORMAT,
14400         qtdemux->duration, tkhd_max_duration);
14401     qtdemux->duration = tkhd_max_duration;
14402   }
14403 #endif
14404
14405   return ret;
14406 }
14407
14408 static gboolean
14409 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
14410 {
14411   return g_strcmp0 (stream->stream_id, stream_id) == 0;
14412 }
14413
14414 static gboolean
14415 qtdemux_is_streams_update (GstQTDemux * qtdemux)
14416 {
14417   gint i;
14418
14419   /* Different length, updated */
14420   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
14421     return TRUE;
14422
14423   /* streams in list are sorted in track-id order */
14424   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14425     /* Different stream-id, updated */
14426     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
14427             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
14428       return TRUE;
14429   }
14430
14431   return FALSE;
14432 }
14433
14434 static gboolean
14435 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
14436     QtDemuxStream * oldstream, QtDemuxStream * newstream)
14437 {
14438   /* Connect old stream's srcpad to new stream */
14439   newstream->pad = oldstream->pad;
14440   oldstream->pad = NULL;
14441
14442   /* unset new_stream to prevent stream-start event, unless we are EOS in which
14443    * case we need to force one through */
14444   newstream->new_stream = newstream->pad != NULL
14445       && GST_PAD_IS_EOS (newstream->pad);
14446
14447   return gst_qtdemux_configure_stream (qtdemux, newstream);
14448 }
14449
14450 static gboolean
14451 qtdemux_update_streams (GstQTDemux * qtdemux)
14452 {
14453   gint i;
14454   g_assert (qtdemux->streams_aware);
14455
14456   /* At below, figure out which stream in active_streams has identical stream-id
14457    * with that of in old_streams. If there is matching stream-id,
14458    * corresponding newstream will not be exposed again,
14459    * but demux will reuse srcpad of matched old stream
14460    *
14461    * active_streams : newly created streams from the latest moov
14462    * old_streams : existing streams (belong to previous moov)
14463    */
14464
14465   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14466     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14467     QtDemuxStream *oldstream = NULL;
14468     guint target;
14469
14470     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
14471         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
14472
14473     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
14474             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
14475       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
14476
14477       /* null pad stream cannot be reused */
14478       if (oldstream->pad == NULL)
14479         oldstream = NULL;
14480     }
14481
14482     if (oldstream) {
14483       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
14484
14485       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
14486         return FALSE;
14487
14488       /* we don't need to preserve order of old streams */
14489       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
14490     } else {
14491       GstTagList *list;
14492
14493       /* now we have all info and can expose */
14494       list = stream->stream_tags;
14495       stream->stream_tags = NULL;
14496       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
14497         return FALSE;
14498     }
14499   }
14500
14501   return TRUE;
14502 }
14503
14504 /* Must be called with expose lock */
14505 static GstFlowReturn
14506 qtdemux_expose_streams (GstQTDemux * qtdemux)
14507 {
14508   gint i;
14509
14510   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
14511
14512   if (!qtdemux_is_streams_update (qtdemux)) {
14513     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
14514     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14515       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14516       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
14517       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
14518         return GST_FLOW_ERROR;
14519     }
14520
14521     g_ptr_array_set_size (qtdemux->old_streams, 0);
14522     qtdemux->need_segment = TRUE;
14523
14524     return GST_FLOW_OK;
14525   }
14526
14527   if (qtdemux->streams_aware) {
14528     if (!qtdemux_update_streams (qtdemux))
14529       return GST_FLOW_ERROR;
14530   } else {
14531     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14532       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14533       GstTagList *list;
14534
14535       /* now we have all info and can expose */
14536       list = stream->stream_tags;
14537       stream->stream_tags = NULL;
14538       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
14539         return GST_FLOW_ERROR;
14540
14541     }
14542   }
14543
14544   gst_qtdemux_guess_bitrate (qtdemux);
14545
14546   /* If we have still old_streams, it's no more used stream */
14547   for (i = 0; i < qtdemux->old_streams->len; i++) {
14548     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
14549
14550     if (stream->pad) {
14551       GstEvent *event;
14552
14553       event = gst_event_new_eos ();
14554       if (qtdemux->segment_seqnum)
14555         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
14556
14557       gst_pad_push_event (stream->pad, event);
14558     }
14559   }
14560
14561   g_ptr_array_set_size (qtdemux->old_streams, 0);
14562
14563   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
14564
14565   /* check if we should post a redirect in case there is a single trak
14566    * and it is a redirecting trak */
14567   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
14568       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
14569     GstMessage *m;
14570
14571     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
14572         "an external content");
14573     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
14574         gst_structure_new ("redirect",
14575             "new-location", G_TYPE_STRING,
14576             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
14577     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
14578     g_free (qtdemux->redirect_location);
14579     qtdemux->redirect_location =
14580         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
14581   }
14582
14583   g_ptr_array_foreach (qtdemux->active_streams,
14584       (GFunc) qtdemux_do_allocation, qtdemux);
14585
14586   qtdemux->need_segment = TRUE;
14587
14588   qtdemux->exposed = TRUE;
14589   return GST_FLOW_OK;
14590 }
14591
14592 typedef struct
14593 {
14594   GstStructure *structure;      /* helper for sort function */
14595   gchar *location;
14596   guint min_req_bitrate;
14597   guint min_req_qt_version;
14598 } GstQtReference;
14599
14600 static gint
14601 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
14602 {
14603   GstQtReference *ref_a = (GstQtReference *) a;
14604   GstQtReference *ref_b = (GstQtReference *) b;
14605
14606   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
14607     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
14608
14609   /* known bitrates go before unknown; higher bitrates go first */
14610   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
14611 }
14612
14613 /* sort the redirects and post a message for the application.
14614  */
14615 static void
14616 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
14617 {
14618   GstQtReference *best;
14619   GstStructure *s;
14620   GstMessage *msg;
14621   GValue list_val = { 0, };
14622   GList *l;
14623
14624   g_assert (references != NULL);
14625
14626   references = g_list_sort (references, qtdemux_redirects_sort_func);
14627
14628   best = (GstQtReference *) references->data;
14629
14630   g_value_init (&list_val, GST_TYPE_LIST);
14631
14632   for (l = references; l != NULL; l = l->next) {
14633     GstQtReference *ref = (GstQtReference *) l->data;
14634     GValue struct_val = { 0, };
14635
14636     ref->structure = gst_structure_new ("redirect",
14637         "new-location", G_TYPE_STRING, ref->location, NULL);
14638
14639     if (ref->min_req_bitrate > 0) {
14640       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
14641           ref->min_req_bitrate, NULL);
14642     }
14643
14644     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
14645     g_value_set_boxed (&struct_val, ref->structure);
14646     gst_value_list_append_value (&list_val, &struct_val);
14647     g_value_unset (&struct_val);
14648     /* don't free anything here yet, since we need best->structure below */
14649   }
14650
14651   g_assert (best != NULL);
14652   s = gst_structure_copy (best->structure);
14653
14654   if (g_list_length (references) > 1) {
14655     gst_structure_set_value (s, "locations", &list_val);
14656   }
14657
14658   g_value_unset (&list_val);
14659
14660   for (l = references; l != NULL; l = l->next) {
14661     GstQtReference *ref = (GstQtReference *) l->data;
14662
14663     gst_structure_free (ref->structure);
14664     g_free (ref->location);
14665     g_free (ref);
14666   }
14667   g_list_free (references);
14668
14669   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
14670   g_free (qtdemux->redirect_location);
14671   qtdemux->redirect_location =
14672       g_strdup (gst_structure_get_string (s, "new-location"));
14673   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
14674   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
14675 }
14676
14677 /* look for redirect nodes, collect all redirect information and
14678  * process it.
14679  */
14680 static gboolean
14681 qtdemux_parse_redirects (GstQTDemux * qtdemux)
14682 {
14683   GNode *rmra, *rmda, *rdrf;
14684
14685   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
14686   if (rmra) {
14687     GList *redirects = NULL;
14688
14689     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
14690     while (rmda) {
14691       GstQtReference ref = { NULL, NULL, 0, 0 };
14692       GNode *rmdr, *rmvc;
14693
14694       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
14695         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
14696         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
14697             ref.min_req_bitrate);
14698       }
14699
14700       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
14701         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
14702         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
14703
14704 #ifndef GST_DISABLE_GST_DEBUG
14705         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
14706 #endif
14707         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
14708
14709         GST_LOG_OBJECT (qtdemux,
14710             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
14711             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
14712             bitmask, check_type);
14713         if (package == FOURCC_qtim && check_type == 0) {
14714           ref.min_req_qt_version = version;
14715         }
14716       }
14717
14718       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
14719       if (rdrf) {
14720         guint32 ref_type;
14721         guint8 *ref_data;
14722         guint ref_len;
14723
14724         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
14725         if (ref_len > 20) {
14726           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
14727           ref_data = (guint8 *) rdrf->data + 20;
14728           if (ref_type == FOURCC_alis) {
14729             guint record_len, record_version, fn_len;
14730
14731             if (ref_len > 70) {
14732               /* MacOSX alias record, google for alias-layout.txt */
14733               record_len = QT_UINT16 (ref_data + 4);
14734               record_version = QT_UINT16 (ref_data + 4 + 2);
14735               fn_len = QT_UINT8 (ref_data + 50);
14736               if (record_len > 50 && record_version == 2 && fn_len > 0) {
14737                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
14738               }
14739             } else {
14740               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
14741                   ref_len);
14742             }
14743           } else if (ref_type == FOURCC_url_) {
14744             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
14745           } else {
14746             GST_DEBUG_OBJECT (qtdemux,
14747                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
14748                 GST_FOURCC_ARGS (ref_type));
14749           }
14750           if (ref.location != NULL) {
14751             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
14752             redirects =
14753                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
14754           } else {
14755             GST_WARNING_OBJECT (qtdemux,
14756                 "Failed to extract redirect location from rdrf atom");
14757           }
14758         } else {
14759           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
14760         }
14761       }
14762
14763       /* look for others */
14764       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
14765     }
14766
14767     if (redirects != NULL) {
14768       qtdemux_process_redirects (qtdemux, redirects);
14769     }
14770   }
14771   return TRUE;
14772 }
14773
14774 static GstTagList *
14775 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
14776 {
14777   const gchar *fmt;
14778
14779   if (tags == NULL) {
14780     tags = gst_tag_list_new_empty ();
14781     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
14782   }
14783
14784   if (qtdemux->major_brand == FOURCC_mjp2)
14785     fmt = "Motion JPEG 2000";
14786   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
14787     fmt = "3GP";
14788   else if (qtdemux->major_brand == FOURCC_qt__)
14789     fmt = "Quicktime";
14790   else if (qtdemux->fragmented)
14791     fmt = "ISO fMP4";
14792   else
14793     fmt = "ISO MP4/M4A";
14794
14795   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
14796       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
14797
14798   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
14799       fmt, NULL);
14800
14801   return tags;
14802 }
14803
14804 /* we have read the complete moov node now.
14805  * This function parses all of the relevant info, creates the traks and
14806  * prepares all data structures for playback
14807  */
14808 static gboolean
14809 qtdemux_parse_tree (GstQTDemux * qtdemux)
14810 {
14811   GNode *mvhd;
14812   GNode *trak;
14813   GNode *udta;
14814   GNode *mvex;
14815   GNode *pssh;
14816   guint64 creation_time;
14817   GstDateTime *datetime = NULL;
14818   gint version;
14819
14820   /* make sure we have a usable taglist */
14821   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14822
14823   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14824   if (mvhd == NULL) {
14825     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14826     return qtdemux_parse_redirects (qtdemux);
14827   }
14828
14829   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14830   if (version == 1) {
14831     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14832     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14833     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14834   } else if (version == 0) {
14835     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14836     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14837     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14838   } else {
14839     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14840     return FALSE;
14841   }
14842
14843   /* Moving qt creation time (secs since 1904) to unix time */
14844   if (creation_time != 0) {
14845     /* Try to use epoch first as it should be faster and more commonly found */
14846     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14847       gint64 now_s;
14848
14849       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14850       /* some data cleansing sanity */
14851       now_s = g_get_real_time () / G_USEC_PER_SEC;
14852       if (now_s + 24 * 3600 < creation_time) {
14853         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14854       } else {
14855         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14856       }
14857     } else {
14858       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14859       GDateTime *dt, *dt_local;
14860
14861       dt = g_date_time_add_seconds (base_dt, creation_time);
14862       dt_local = g_date_time_to_local (dt);
14863       datetime = gst_date_time_new_from_g_date_time (dt_local);
14864
14865       g_date_time_unref (base_dt);
14866       g_date_time_unref (dt);
14867     }
14868   }
14869   if (datetime) {
14870     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14871     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14872         datetime, NULL);
14873     gst_date_time_unref (datetime);
14874   }
14875
14876   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14877   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14878
14879   /* check for fragmented file and get some (default) data */
14880   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14881   if (mvex) {
14882     GNode *mehd;
14883     GstByteReader mehd_data;
14884
14885     /* let track parsing or anyone know weird stuff might happen ... */
14886     qtdemux->fragmented = TRUE;
14887
14888     /* compensate for total duration */
14889     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14890     if (mehd)
14891       qtdemux_parse_mehd (qtdemux, &mehd_data);
14892   }
14893
14894   /* Update the movie segment duration, unless it was directly given to us
14895    * by upstream. Otherwise let it as is, as we don't want to mangle the
14896    * duration provided by upstream that may come e.g. from a MPD file. */
14897   if (!qtdemux->upstream_format_is_time) {
14898     GstClockTime duration;
14899     /* set duration in the segment info */
14900     gst_qtdemux_get_duration (qtdemux, &duration);
14901     qtdemux->segment.duration = duration;
14902     /* also do not exceed duration; stop is set that way post seek anyway,
14903      * and segment activation falls back to duration,
14904      * whereas loop only checks stop, so let's align this here as well */
14905     qtdemux->segment.stop = duration;
14906   }
14907
14908   /* parse all traks */
14909   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14910   while (trak) {
14911     qtdemux_parse_trak (qtdemux, trak);
14912     /* iterate all siblings */
14913     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14914   }
14915
14916   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14917
14918   /* find tags */
14919   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14920   if (udta) {
14921     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14922   } else {
14923     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14924   }
14925
14926   /* maybe also some tags in meta box */
14927   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14928   if (udta) {
14929     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14930     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14931   } else {
14932     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14933   }
14934
14935   /* parse any protection system info */
14936   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14937   if (pssh) {
14938     /* Unref old protection events if we are going to receive new ones. */
14939     qtdemux_clear_protection_events_on_all_streams (qtdemux);
14940   }
14941   while (pssh) {
14942     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14943     qtdemux_parse_pssh (qtdemux, pssh);
14944     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14945   }
14946
14947   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14948
14949   return TRUE;
14950 }
14951
14952 /* taken from ffmpeg */
14953 static int
14954 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14955 {
14956   int count = 4;
14957   int len = 0;
14958
14959   while (count--) {
14960     int c;
14961
14962     if (ptr >= end)
14963       return -1;
14964
14965     c = *ptr++;
14966     len = (len << 7) | (c & 0x7f);
14967     if (!(c & 0x80))
14968       break;
14969   }
14970   *end_out = ptr;
14971   return len;
14972 }
14973
14974 static GList *
14975 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14976     gsize codec_data_size)
14977 {
14978   GList *list = NULL;
14979   guint8 *p = codec_data;
14980   gint i, offset, num_packets;
14981   guint *length, last;
14982
14983   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14984
14985   if (codec_data == NULL || codec_data_size == 0)
14986     goto error;
14987
14988   /* start of the stream and vorbis audio or theora video, need to
14989    * send the codec_priv data as first three packets */
14990   num_packets = p[0] + 1;
14991   GST_DEBUG_OBJECT (qtdemux,
14992       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14993       (guint) num_packets, codec_data_size);
14994
14995   /* Let's put some limits, Don't think there even is a xiph codec
14996    * with more than 3-4 headers */
14997   if (G_UNLIKELY (num_packets > 16)) {
14998     GST_WARNING_OBJECT (qtdemux,
14999         "Unlikely number of xiph headers, most likely not valid");
15000     goto error;
15001   }
15002
15003   length = g_alloca (num_packets * sizeof (guint));
15004   last = 0;
15005   offset = 1;
15006
15007   /* first packets, read length values */
15008   for (i = 0; i < num_packets - 1; i++) {
15009     length[i] = 0;
15010     while (offset < codec_data_size) {
15011       length[i] += p[offset];
15012       if (p[offset++] != 0xff)
15013         break;
15014     }
15015     last += length[i];
15016   }
15017   if (offset + last > codec_data_size)
15018     goto error;
15019
15020   /* last packet is the remaining size */
15021   length[i] = codec_data_size - offset - last;
15022
15023   for (i = 0; i < num_packets; i++) {
15024     GstBuffer *hdr;
15025
15026     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
15027
15028     if (offset + length[i] > codec_data_size)
15029       goto error;
15030
15031     hdr = gst_buffer_new_memdup (p + offset, length[i]);
15032     list = g_list_append (list, hdr);
15033
15034     offset += length[i];
15035   }
15036
15037   return list;
15038
15039   /* ERRORS */
15040 error:
15041   {
15042     if (list != NULL)
15043       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
15044     return NULL;
15045   }
15046
15047 }
15048
15049 /* this can change the codec originally present in @list */
15050 static void
15051 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
15052     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
15053 {
15054   int len = QT_UINT32 (esds->data);
15055   guint8 *ptr = esds->data;
15056   guint8 *end = ptr + len;
15057   int tag;
15058   guint8 *data_ptr = NULL;
15059   int data_len = 0;
15060   guint8 object_type_id = 0;
15061   guint8 stream_type = 0;
15062   const char *codec_name = NULL;
15063   GstCaps *caps = NULL;
15064
15065   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
15066   ptr += 8;
15067   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
15068   ptr += 4;
15069   while (ptr + 1 < end) {
15070     tag = QT_UINT8 (ptr);
15071     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
15072     ptr++;
15073     len = read_descr_size (ptr, end, &ptr);
15074     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
15075
15076     /* Check the stated amount of data is available for reading */
15077     if (len < 0 || ptr + len > end)
15078       break;
15079
15080     switch (tag) {
15081       case ES_DESCRIPTOR_TAG:
15082         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
15083         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
15084         ptr += 3;
15085         break;
15086       case DECODER_CONFIG_DESC_TAG:{
15087         guint max_bitrate, avg_bitrate;
15088
15089         object_type_id = QT_UINT8 (ptr);
15090         stream_type = QT_UINT8 (ptr + 1) >> 2;
15091         max_bitrate = QT_UINT32 (ptr + 5);
15092         avg_bitrate = QT_UINT32 (ptr + 9);
15093         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
15094         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
15095         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
15096         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
15097         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
15098         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
15099           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
15100               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
15101         }
15102         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
15103           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
15104               avg_bitrate, NULL);
15105         }
15106         ptr += 13;
15107         break;
15108       }
15109       case DECODER_SPECIFIC_INFO_TAG:
15110         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
15111         if (object_type_id == 0xe0 && len == 0x40) {
15112           guint8 *data;
15113           GstStructure *s;
15114           guint32 clut[16];
15115           gint i;
15116
15117           GST_DEBUG_OBJECT (qtdemux,
15118               "Have VOBSUB palette. Creating palette event");
15119           /* move to decConfigDescr data and read palette */
15120           data = ptr;
15121           for (i = 0; i < 16; i++) {
15122             clut[i] = QT_UINT32 (data);
15123             data += 4;
15124           }
15125
15126           s = gst_structure_new ("application/x-gst-dvd", "event",
15127               G_TYPE_STRING, "dvd-spu-clut-change",
15128               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
15129               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
15130               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
15131               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
15132               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
15133               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
15134               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
15135               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
15136               NULL);
15137
15138           /* store event and trigger custom processing */
15139           stream->pending_event =
15140               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
15141         } else {
15142           /* Generic codec_data handler puts it on the caps */
15143           data_ptr = ptr;
15144           data_len = len;
15145         }
15146
15147         ptr += len;
15148         break;
15149       case SL_CONFIG_DESC_TAG:
15150         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
15151         ptr += 1;
15152         break;
15153       default:
15154         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
15155             tag);
15156         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
15157         ptr += len;
15158         break;
15159     }
15160   }
15161
15162   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
15163    * in use, and should also be used to override some other parameters for some
15164    * codecs. */
15165   switch (object_type_id) {
15166     case 0x20:                 /* MPEG-4 */
15167       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
15168        * profile_and_level_indication */
15169       if (data_ptr != NULL && data_len >= 5 &&
15170           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
15171         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
15172             data_ptr + 4, data_len - 4);
15173       }
15174       break;                    /* Nothing special needed here */
15175     case 0x21:                 /* H.264 */
15176       codec_name = "H.264 / AVC";
15177       caps = gst_caps_new_simple ("video/x-h264",
15178           "stream-format", G_TYPE_STRING, "avc",
15179           "alignment", G_TYPE_STRING, "au", NULL);
15180       break;
15181     case 0x40:                 /* AAC (any) */
15182     case 0x66:                 /* AAC Main */
15183     case 0x67:                 /* AAC LC */
15184     case 0x68:                 /* AAC SSR */
15185       /* Override channels and rate based on the codec_data, as it's often
15186        * wrong. */
15187       /* Only do so for basic setup without HE-AAC extension */
15188       if (data_ptr && data_len == 2) {
15189         guint channels, rate;
15190
15191         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
15192         if (channels > 0)
15193           entry->n_channels = channels;
15194
15195         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
15196         if (rate > 0)
15197           entry->rate = rate;
15198       }
15199
15200       /* Set level and profile if possible */
15201       if (data_ptr != NULL && data_len >= 2) {
15202         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
15203             data_ptr, data_len);
15204       } else {
15205         const gchar *profile_str = NULL;
15206         GstBuffer *buffer;
15207         GstMapInfo map;
15208         guint8 *codec_data;
15209         gint rate_idx, profile;
15210
15211         /* No codec_data, let's invent something.
15212          * FIXME: This is wrong for SBR! */
15213
15214         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
15215
15216         buffer = gst_buffer_new_and_alloc (2);
15217         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
15218         codec_data = map.data;
15219
15220         rate_idx =
15221             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
15222             (stream)->rate);
15223
15224         switch (object_type_id) {
15225           case 0x66:
15226             profile_str = "main";
15227             profile = 0;
15228             break;
15229           case 0x67:
15230             profile_str = "lc";
15231             profile = 1;
15232             break;
15233           case 0x68:
15234             profile_str = "ssr";
15235             profile = 2;
15236             break;
15237           default:
15238             profile = 3;
15239             break;
15240         }
15241
15242         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
15243         codec_data[1] =
15244             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
15245
15246         gst_buffer_unmap (buffer, &map);
15247         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
15248             GST_TYPE_BUFFER, buffer, NULL);
15249         gst_buffer_unref (buffer);
15250
15251         if (profile_str) {
15252           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
15253               G_TYPE_STRING, profile_str, NULL);
15254         }
15255       }
15256       break;
15257     case 0x60:                 /* MPEG-2, various profiles */
15258     case 0x61:
15259     case 0x62:
15260     case 0x63:
15261     case 0x64:
15262     case 0x65:
15263       codec_name = "MPEG-2 video";
15264       caps = gst_caps_new_simple ("video/mpeg",
15265           "mpegversion", G_TYPE_INT, 2,
15266           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15267       break;
15268     case 0x69:                 /* MPEG-2 BC audio */
15269     case 0x6B:                 /* MPEG-1 audio */
15270       caps = gst_caps_new_simple ("audio/mpeg",
15271           "mpegversion", G_TYPE_INT, 1, NULL);
15272       codec_name = "MPEG-1 audio";
15273       break;
15274     case 0x6A:                 /* MPEG-1 */
15275       codec_name = "MPEG-1 video";
15276       caps = gst_caps_new_simple ("video/mpeg",
15277           "mpegversion", G_TYPE_INT, 1,
15278           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15279       break;
15280     case 0x6C:                 /* MJPEG */
15281       caps =
15282           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
15283           NULL);
15284       codec_name = "Motion-JPEG";
15285       break;
15286     case 0x6D:                 /* PNG */
15287       caps =
15288           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
15289           NULL);
15290       codec_name = "PNG still images";
15291       break;
15292     case 0x6E:                 /* JPEG2000 */
15293       codec_name = "JPEG-2000";
15294       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
15295       break;
15296     case 0xA4:                 /* Dirac */
15297       codec_name = "Dirac";
15298       caps = gst_caps_new_empty_simple ("video/x-dirac");
15299       break;
15300     case 0xA5:                 /* AC3 */
15301       codec_name = "AC-3 audio";
15302       caps = gst_caps_new_simple ("audio/x-ac3",
15303           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15304       break;
15305     case 0xA9:                 /* AC3 */
15306       codec_name = "DTS audio";
15307       caps = gst_caps_new_simple ("audio/x-dts",
15308           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15309       break;
15310     case 0xDD:
15311       if (stream_type == 0x05 && data_ptr) {
15312         GList *headers =
15313             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
15314         if (headers) {
15315           GList *tmp;
15316           GValue arr_val = G_VALUE_INIT;
15317           GValue buf_val = G_VALUE_INIT;
15318           GstStructure *s;
15319
15320           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
15321           codec_name = "Vorbis";
15322           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
15323           g_value_init (&arr_val, GST_TYPE_ARRAY);
15324           g_value_init (&buf_val, GST_TYPE_BUFFER);
15325           for (tmp = headers; tmp; tmp = tmp->next) {
15326             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
15327             gst_value_array_append_value (&arr_val, &buf_val);
15328           }
15329           s = gst_caps_get_structure (caps, 0);
15330           gst_structure_take_value (s, "streamheader", &arr_val);
15331           g_value_unset (&buf_val);
15332           g_list_free (headers);
15333
15334           data_ptr = NULL;
15335           data_len = 0;
15336         }
15337       }
15338       break;
15339     case 0xE1:                 /* QCELP */
15340       /* QCELP, the codec_data is a riff tag (little endian) with
15341        * 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). */
15342       caps = gst_caps_new_empty_simple ("audio/qcelp");
15343       codec_name = "QCELP";
15344       break;
15345     default:
15346       break;
15347   }
15348
15349   /* If we have a replacement caps, then change our caps for this stream */
15350   if (caps) {
15351     gst_caps_unref (entry->caps);
15352     entry->caps = caps;
15353   }
15354
15355   if (codec_name && list)
15356     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
15357         GST_TAG_AUDIO_CODEC, codec_name, NULL);
15358
15359   /* Add the codec_data attribute to caps, if we have it */
15360   if (data_ptr) {
15361     GstBuffer *buffer;
15362
15363     buffer = gst_buffer_new_and_alloc (data_len);
15364     gst_buffer_fill (buffer, 0, data_ptr, data_len);
15365
15366     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
15367     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
15368
15369     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
15370         buffer, NULL);
15371     gst_buffer_unref (buffer);
15372   }
15373
15374 }
15375
15376 static inline GstCaps *
15377 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
15378 {
15379   GstCaps *caps;
15380   guint i;
15381   char *s, fourstr[5];
15382
15383   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
15384   for (i = 0; i < 4; i++) {
15385     if (!g_ascii_isalnum (fourstr[i]))
15386       fourstr[i] = '_';
15387   }
15388   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
15389   caps = gst_caps_new_empty_simple (s);
15390   g_free (s);
15391   return caps;
15392 }
15393
15394 #define _codec(name) \
15395   do { \
15396     if (codec_name) { \
15397       *codec_name = g_strdup (name); \
15398     } \
15399   } while (0)
15400
15401 static GstCaps *
15402 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15403     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15404     const guint8 * stsd_entry_data, gchar ** codec_name)
15405 {
15406   GstCaps *caps = NULL;
15407   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
15408
15409   switch (fourcc) {
15410     case FOURCC_png:
15411       _codec ("PNG still images");
15412       caps = gst_caps_new_empty_simple ("image/png");
15413       break;
15414     case FOURCC_jpeg:
15415       _codec ("JPEG still images");
15416       caps =
15417           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
15418           NULL);
15419       break;
15420     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
15421     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
15422     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
15423     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
15424       _codec ("Motion-JPEG");
15425       caps =
15426           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
15427           NULL);
15428       break;
15429     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
15430       _codec ("Motion-JPEG format B");
15431       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
15432       break;
15433     case FOURCC_mjp2:
15434       _codec ("JPEG-2000");
15435       /* override to what it should be according to spec, avoid palette_data */
15436       entry->bits_per_sample = 24;
15437       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
15438       break;
15439     case FOURCC_SVQ3:
15440       _codec ("Sorensen video v.3");
15441       caps = gst_caps_new_simple ("video/x-svq",
15442           "svqversion", G_TYPE_INT, 3, NULL);
15443       break;
15444     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
15445     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
15446       _codec ("Sorensen video v.1");
15447       caps = gst_caps_new_simple ("video/x-svq",
15448           "svqversion", G_TYPE_INT, 1, NULL);
15449       break;
15450     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
15451       caps = gst_caps_new_empty_simple ("video/x-raw");
15452       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
15453       _codec ("Windows Raw RGB");
15454       stream->alignment = 32;
15455       break;
15456     case FOURCC_raw_:
15457     {
15458       guint16 bps;
15459
15460       bps = QT_UINT16 (stsd_entry_data + 82);
15461       switch (bps) {
15462         case 15:
15463           format = GST_VIDEO_FORMAT_RGB15;
15464           break;
15465         case 16:
15466           format = GST_VIDEO_FORMAT_RGB16;
15467           break;
15468         case 24:
15469           format = GST_VIDEO_FORMAT_RGB;
15470           break;
15471         case 32:
15472           format = GST_VIDEO_FORMAT_ARGB;
15473           break;
15474         default:
15475           /* unknown */
15476           break;
15477       }
15478       break;
15479     }
15480     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
15481       format = GST_VIDEO_FORMAT_I420;
15482       break;
15483     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
15484     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
15485       format = GST_VIDEO_FORMAT_I420;
15486       break;
15487     case FOURCC_2vuy:
15488     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
15489       format = GST_VIDEO_FORMAT_UYVY;
15490       break;
15491     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
15492       format = GST_VIDEO_FORMAT_v308;
15493       break;
15494     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
15495       format = GST_VIDEO_FORMAT_v216;
15496       break;
15497     case FOURCC_v210:
15498       format = GST_VIDEO_FORMAT_v210;
15499       break;
15500     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
15501       format = GST_VIDEO_FORMAT_r210;
15502       break;
15503       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
15504          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
15505          format = GST_VIDEO_FORMAT_v410;
15506          break;
15507        */
15508       /* Packed YUV 4:4:4:4 8 bit in 32 bits
15509        * but different order than AYUV
15510        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
15511        format = GST_VIDEO_FORMAT_v408;
15512        break;
15513        */
15514     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
15515     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
15516       _codec ("MPEG-1 video");
15517       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15518           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15519       break;
15520     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
15521     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
15522     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
15523     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
15524     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
15525     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
15526     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
15527     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
15528     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
15529     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
15530     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
15531     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
15532     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
15533     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
15534     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
15535     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
15536     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
15537     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
15538     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
15539     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
15540     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
15541     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
15542     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
15543     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
15544     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
15545     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
15546     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
15547     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
15548     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
15549     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
15550     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
15551     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
15552     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
15553     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
15554     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
15555     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
15556     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
15557     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
15558     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
15559     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
15560     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
15561     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
15562     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
15563     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
15564     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
15565     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
15566     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
15567       _codec ("MPEG-2 video");
15568       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
15569           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15570       break;
15571     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
15572       _codec ("GIF still images");
15573       caps = gst_caps_new_empty_simple ("image/gif");
15574       break;
15575     case FOURCC_h263:
15576     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
15577     case FOURCC_s263:
15578     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
15579       _codec ("H.263");
15580       /* ffmpeg uses the height/width props, don't know why */
15581       caps = gst_caps_new_simple ("video/x-h263",
15582           "variant", G_TYPE_STRING, "itu", NULL);
15583       break;
15584     case FOURCC_mp4v:
15585     case FOURCC_MP4V:
15586       _codec ("MPEG-4 video");
15587       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
15588           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15589       break;
15590     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
15591     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
15592       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
15593       caps = gst_caps_new_simple ("video/x-msmpeg",
15594           "msmpegversion", G_TYPE_INT, 43, NULL);
15595       break;
15596     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
15597       _codec ("DivX 3");
15598       caps = gst_caps_new_simple ("video/x-divx",
15599           "divxversion", G_TYPE_INT, 3, NULL);
15600       break;
15601     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
15602     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
15603       _codec ("DivX 4");
15604       caps = gst_caps_new_simple ("video/x-divx",
15605           "divxversion", G_TYPE_INT, 4, NULL);
15606       break;
15607     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
15608       _codec ("DivX 5");
15609       caps = gst_caps_new_simple ("video/x-divx",
15610           "divxversion", G_TYPE_INT, 5, NULL);
15611       break;
15612
15613     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
15614       _codec ("FFV1");
15615       caps = gst_caps_new_simple ("video/x-ffv",
15616           "ffvversion", G_TYPE_INT, 1, NULL);
15617       break;
15618
15619     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
15620     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
15621     case FOURCC_XVID:
15622     case FOURCC_xvid:
15623     case FOURCC_FMP4:
15624     case FOURCC_fmp4:
15625     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
15626       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
15627           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15628       _codec ("MPEG-4");
15629       break;
15630
15631     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
15632       _codec ("Cinepak");
15633       caps = gst_caps_new_empty_simple ("video/x-cinepak");
15634       break;
15635     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
15636       _codec ("Apple QuickDraw");
15637       caps = gst_caps_new_empty_simple ("video/x-qdrw");
15638       break;
15639     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
15640       _codec ("Apple video");
15641       caps = gst_caps_new_empty_simple ("video/x-apple-video");
15642       break;
15643     case FOURCC_H264:
15644     case FOURCC_avc1:
15645     case FOURCC_dva1:
15646       _codec ("H.264 / AVC");
15647       caps = gst_caps_new_simple ("video/x-h264",
15648           "stream-format", G_TYPE_STRING, "avc",
15649           "alignment", G_TYPE_STRING, "au", NULL);
15650       break;
15651     case FOURCC_avc3:
15652     case FOURCC_dvav:
15653       _codec ("H.264 / AVC");
15654       caps = gst_caps_new_simple ("video/x-h264",
15655           "stream-format", G_TYPE_STRING, "avc3",
15656           "alignment", G_TYPE_STRING, "au", NULL);
15657       break;
15658     case FOURCC_ai12:
15659     case FOURCC_ai13:
15660     case FOURCC_ai15:
15661     case FOURCC_ai16:
15662     case FOURCC_ai1p:
15663     case FOURCC_ai1q:
15664     case FOURCC_ai52:
15665     case FOURCC_ai53:
15666     case FOURCC_ai55:
15667     case FOURCC_ai56:
15668     case FOURCC_ai5p:
15669     case FOURCC_ai5q:
15670       _codec ("H.264 / AVC");
15671       caps = gst_caps_new_simple ("video/x-h264",
15672           "stream-format", G_TYPE_STRING, "byte-stream",
15673           "alignment", G_TYPE_STRING, "au", NULL);
15674       break;
15675     case FOURCC_H265:
15676     case FOURCC_hvc1:
15677     case FOURCC_dvh1:
15678       _codec ("H.265 / HEVC");
15679       caps = gst_caps_new_simple ("video/x-h265",
15680           "stream-format", G_TYPE_STRING, "hvc1",
15681           "alignment", G_TYPE_STRING, "au", NULL);
15682       break;
15683     case FOURCC_hev1:
15684     case FOURCC_dvhe:
15685       _codec ("H.265 / HEVC");
15686       caps = gst_caps_new_simple ("video/x-h265",
15687           "stream-format", G_TYPE_STRING, "hev1",
15688           "alignment", G_TYPE_STRING, "au", NULL);
15689       break;
15690     case FOURCC_rle_:
15691       _codec ("Run-length encoding");
15692       caps = gst_caps_new_simple ("video/x-rle",
15693           "layout", G_TYPE_STRING, "quicktime", NULL);
15694       break;
15695     case FOURCC_WRLE:
15696       _codec ("Run-length encoding");
15697       caps = gst_caps_new_simple ("video/x-rle",
15698           "layout", G_TYPE_STRING, "microsoft", NULL);
15699       break;
15700     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
15701     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
15702       _codec ("Indeo Video 3");
15703       caps = gst_caps_new_simple ("video/x-indeo",
15704           "indeoversion", G_TYPE_INT, 3, NULL);
15705       break;
15706     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
15707     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
15708       _codec ("Intel Video 4");
15709       caps = gst_caps_new_simple ("video/x-indeo",
15710           "indeoversion", G_TYPE_INT, 4, NULL);
15711       break;
15712     case FOURCC_dvcp:
15713     case FOURCC_dvc_:
15714     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
15715     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
15716     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
15717     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
15718     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
15719     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
15720       _codec ("DV Video");
15721       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
15722           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15723       break;
15724     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
15725     case FOURCC_dv5p:          /* DVCPRO50 PAL */
15726       _codec ("DVCPro50 Video");
15727       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
15728           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15729       break;
15730     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
15731     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
15732       _codec ("DVCProHD Video");
15733       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
15734           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15735       break;
15736     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
15737       _codec ("Apple Graphics (SMC)");
15738       caps = gst_caps_new_empty_simple ("video/x-smc");
15739       break;
15740     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
15741       _codec ("VP3");
15742       caps = gst_caps_new_empty_simple ("video/x-vp3");
15743       break;
15744     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
15745       _codec ("VP6 Flash");
15746       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
15747       break;
15748     case FOURCC_XiTh:
15749       _codec ("Theora");
15750       caps = gst_caps_new_empty_simple ("video/x-theora");
15751       /* theora uses one byte of padding in the data stream because it does not
15752        * allow 0 sized packets while theora does */
15753       entry->padding = 1;
15754       break;
15755     case FOURCC_drac:
15756       _codec ("Dirac");
15757       caps = gst_caps_new_empty_simple ("video/x-dirac");
15758       break;
15759     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
15760       _codec ("TIFF still images");
15761       caps = gst_caps_new_empty_simple ("image/tiff");
15762       break;
15763     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
15764       _codec ("Apple Intermediate Codec");
15765       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
15766       break;
15767     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
15768       _codec ("AVID DNxHD");
15769       caps = gst_caps_from_string ("video/x-dnxhd");
15770       break;
15771     case FOURCC_VP80:
15772     case FOURCC_vp08:
15773       _codec ("On2 VP8");
15774       caps = gst_caps_from_string ("video/x-vp8");
15775       break;
15776     case FOURCC_vp09:
15777       _codec ("Google VP9");
15778       caps = gst_caps_from_string ("video/x-vp9");
15779       break;
15780     case FOURCC_apcs:
15781       _codec ("Apple ProRes LT");
15782       caps =
15783           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
15784           NULL);
15785       break;
15786     case FOURCC_apch:
15787       _codec ("Apple ProRes HQ");
15788       caps =
15789           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
15790           NULL);
15791       break;
15792     case FOURCC_apcn:
15793       _codec ("Apple ProRes");
15794       caps =
15795           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15796           "standard", NULL);
15797       break;
15798     case FOURCC_apco:
15799       _codec ("Apple ProRes Proxy");
15800       caps =
15801           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15802           "proxy", NULL);
15803       break;
15804     case FOURCC_ap4h:
15805       _codec ("Apple ProRes 4444");
15806       caps =
15807           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15808           "4444", NULL);
15809
15810       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
15811       if (entry->bits_per_sample > 0) {
15812         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
15813             NULL);
15814       }
15815       break;
15816     case FOURCC_ap4x:
15817       _codec ("Apple ProRes 4444 XQ");
15818       caps =
15819           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15820           "4444xq", NULL);
15821
15822       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
15823       if (entry->bits_per_sample > 0) {
15824         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
15825             NULL);
15826       }
15827       break;
15828     case FOURCC_cfhd:
15829       _codec ("GoPro CineForm");
15830       caps = gst_caps_from_string ("video/x-cineform");
15831       break;
15832     case FOURCC_vc_1:
15833     case FOURCC_ovc1:
15834       _codec ("VC-1");
15835       caps = gst_caps_new_simple ("video/x-wmv",
15836           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
15837       break;
15838     case FOURCC_av01:
15839       _codec ("AV1");
15840       caps = gst_caps_new_simple ("video/x-av1",
15841           "stream-format", G_TYPE_STRING, "obu-stream",
15842           "alignment", G_TYPE_STRING, "tu", NULL);
15843       break;
15844     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15845     default:
15846     {
15847       caps = _get_unknown_codec_name ("video", fourcc);
15848       break;
15849     }
15850   }
15851
15852   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15853     GstVideoInfo info;
15854
15855     gst_video_info_init (&info);
15856     gst_video_info_set_format (&info, format, entry->width, entry->height);
15857
15858     caps = gst_video_info_to_caps (&info);
15859     *codec_name = gst_pb_utils_get_codec_description (caps);
15860
15861     /* enable clipping for raw video streams */
15862     stream->need_clip = TRUE;
15863     stream->alignment = 32;
15864   }
15865
15866   return caps;
15867 }
15868
15869 static guint
15870 round_up_pow2 (guint n)
15871 {
15872   n = n - 1;
15873   n = n | (n >> 1);
15874   n = n | (n >> 2);
15875   n = n | (n >> 4);
15876   n = n | (n >> 8);
15877   n = n | (n >> 16);
15878   return n + 1;
15879 }
15880
15881 static GstCaps *
15882 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15883     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15884     int len, gchar ** codec_name)
15885 {
15886   GstCaps *caps;
15887   const GstStructure *s;
15888   const gchar *name;
15889   gint endian = 0;
15890   GstAudioFormat format = 0;
15891   gint depth;
15892
15893   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15894
15895   depth = entry->bytes_per_packet * 8;
15896
15897   switch (fourcc) {
15898     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15899     case FOURCC_raw_:
15900       /* 8-bit audio is unsigned */
15901       if (depth == 8)
15902         format = GST_AUDIO_FORMAT_U8;
15903       /* otherwise it's signed and big-endian just like 'twos' */
15904     case FOURCC_twos:
15905       endian = G_BIG_ENDIAN;
15906       /* fall-through */
15907     case FOURCC_sowt:
15908     {
15909       gchar *str;
15910
15911       if (!endian)
15912         endian = G_LITTLE_ENDIAN;
15913
15914       if (!format)
15915         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15916
15917       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15918       _codec (str);
15919       g_free (str);
15920
15921       caps = gst_caps_new_simple ("audio/x-raw",
15922           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15923           "layout", G_TYPE_STRING, "interleaved", NULL);
15924       stream->alignment = GST_ROUND_UP_8 (depth);
15925       stream->alignment = round_up_pow2 (stream->alignment);
15926       break;
15927     }
15928     case FOURCC_fl64:
15929       _codec ("Raw 64-bit floating-point audio");
15930       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15931        * endian later */
15932       caps = gst_caps_new_simple ("audio/x-raw",
15933           "format", G_TYPE_STRING, "F64BE",
15934           "layout", G_TYPE_STRING, "interleaved", NULL);
15935       stream->alignment = 8;
15936       break;
15937     case FOURCC_fl32:
15938       _codec ("Raw 32-bit floating-point audio");
15939       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15940        * endian later */
15941       caps = gst_caps_new_simple ("audio/x-raw",
15942           "format", G_TYPE_STRING, "F32BE",
15943           "layout", G_TYPE_STRING, "interleaved", NULL);
15944       stream->alignment = 4;
15945       break;
15946     case FOURCC_in24:
15947       _codec ("Raw 24-bit PCM audio");
15948       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15949        * endian later */
15950       caps = gst_caps_new_simple ("audio/x-raw",
15951           "format", G_TYPE_STRING, "S24BE",
15952           "layout", G_TYPE_STRING, "interleaved", NULL);
15953       stream->alignment = 4;
15954       break;
15955     case FOURCC_in32:
15956       _codec ("Raw 32-bit PCM audio");
15957       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15958        * endian later */
15959       caps = gst_caps_new_simple ("audio/x-raw",
15960           "format", G_TYPE_STRING, "S32BE",
15961           "layout", G_TYPE_STRING, "interleaved", NULL);
15962       stream->alignment = 4;
15963       break;
15964     case FOURCC_s16l:
15965       _codec ("Raw 16-bit PCM audio");
15966       caps = gst_caps_new_simple ("audio/x-raw",
15967           "format", G_TYPE_STRING, "S16LE",
15968           "layout", G_TYPE_STRING, "interleaved", NULL);
15969       stream->alignment = 2;
15970       break;
15971     case FOURCC_ulaw:
15972       _codec ("Mu-law audio");
15973       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15974       break;
15975     case FOURCC_alaw:
15976       _codec ("A-law audio");
15977       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15978       break;
15979     case 0x0200736d:
15980     case 0x6d730002:
15981       _codec ("Microsoft ADPCM");
15982       /* Microsoft ADPCM-ACM code 2 */
15983       caps = gst_caps_new_simple ("audio/x-adpcm",
15984           "layout", G_TYPE_STRING, "microsoft", NULL);
15985       break;
15986     case 0x1100736d:
15987     case 0x6d730011:
15988       _codec ("DVI/IMA ADPCM");
15989       caps = gst_caps_new_simple ("audio/x-adpcm",
15990           "layout", G_TYPE_STRING, "dvi", NULL);
15991       break;
15992     case 0x1700736d:
15993     case 0x6d730017:
15994       _codec ("DVI/Intel IMA ADPCM");
15995       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15996       caps = gst_caps_new_simple ("audio/x-adpcm",
15997           "layout", G_TYPE_STRING, "quicktime", NULL);
15998       break;
15999     case 0x5500736d:
16000     case 0x6d730055:
16001       /* MPEG layer 3, CBR only (pre QT4.1) */
16002     case FOURCC__mp3:
16003     case FOURCC_mp3_:
16004       _codec ("MPEG-1 layer 3");
16005       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
16006       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
16007           "mpegversion", G_TYPE_INT, 1, NULL);
16008       break;
16009     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
16010       _codec ("MPEG-1 layer 2");
16011       /* MPEG layer 2 */
16012       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
16013           "mpegversion", G_TYPE_INT, 1, NULL);
16014       break;
16015     case 0x20736d:
16016     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
16017       _codec ("EAC-3 audio");
16018       caps = gst_caps_new_simple ("audio/x-eac3",
16019           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
16020       entry->sampled = TRUE;
16021       break;
16022     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
16023     case FOURCC_ac_3:
16024       _codec ("AC-3 audio");
16025       caps = gst_caps_new_simple ("audio/x-ac3",
16026           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
16027       entry->sampled = TRUE;
16028       break;
16029     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
16030     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
16031       _codec ("DTS audio");
16032       caps = gst_caps_new_simple ("audio/x-dts",
16033           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
16034       entry->sampled = TRUE;
16035       break;
16036     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
16037     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
16038       _codec ("DTS-HD audio");
16039       caps = gst_caps_new_simple ("audio/x-dts",
16040           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
16041       entry->sampled = TRUE;
16042       break;
16043     case FOURCC_MAC3:
16044       _codec ("MACE-3");
16045       caps = gst_caps_new_simple ("audio/x-mace",
16046           "maceversion", G_TYPE_INT, 3, NULL);
16047       break;
16048     case FOURCC_MAC6:
16049       _codec ("MACE-6");
16050       caps = gst_caps_new_simple ("audio/x-mace",
16051           "maceversion", G_TYPE_INT, 6, NULL);
16052       break;
16053     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
16054       /* ogg/vorbis */
16055       caps = gst_caps_new_empty_simple ("application/ogg");
16056       break;
16057     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
16058       _codec ("DV audio");
16059       caps = gst_caps_new_empty_simple ("audio/x-dv");
16060       break;
16061     case FOURCC_mp4a:
16062       _codec ("MPEG-4 AAC audio");
16063       caps = gst_caps_new_simple ("audio/mpeg",
16064           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
16065           "stream-format", G_TYPE_STRING, "raw", NULL);
16066       break;
16067     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
16068       _codec ("QDesign Music");
16069       caps = gst_caps_new_empty_simple ("audio/x-qdm");
16070       break;
16071     case FOURCC_QDM2:
16072       _codec ("QDesign Music v.2");
16073       /* FIXME: QDesign music version 2 (no constant) */
16074       if (FALSE && data) {
16075         caps = gst_caps_new_simple ("audio/x-qdm2",
16076             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
16077             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
16078             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
16079       } else {
16080         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
16081       }
16082       break;
16083     case FOURCC_agsm:
16084       _codec ("GSM audio");
16085       caps = gst_caps_new_empty_simple ("audio/x-gsm");
16086       break;
16087     case FOURCC_samr:
16088       _codec ("AMR audio");
16089       caps = gst_caps_new_empty_simple ("audio/AMR");
16090       break;
16091     case FOURCC_sawb:
16092       _codec ("AMR-WB audio");
16093       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
16094       break;
16095     case FOURCC_ima4:
16096       _codec ("Quicktime IMA ADPCM");
16097       caps = gst_caps_new_simple ("audio/x-adpcm",
16098           "layout", G_TYPE_STRING, "quicktime", NULL);
16099       break;
16100     case FOURCC_alac:
16101       _codec ("Apple lossless audio");
16102       caps = gst_caps_new_empty_simple ("audio/x-alac");
16103       break;
16104     case FOURCC_fLaC:
16105       _codec ("Free Lossless Audio Codec");
16106       caps = gst_caps_new_simple ("audio/x-flac",
16107           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
16108       break;
16109     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
16110       _codec ("QualComm PureVoice");
16111       caps = gst_caps_from_string ("audio/qcelp");
16112       break;
16113     case FOURCC_wma_:
16114     case FOURCC_owma:
16115       _codec ("WMA");
16116       caps = gst_caps_new_empty_simple ("audio/x-wma");
16117       break;
16118     case FOURCC_opus:
16119       _codec ("Opus");
16120       caps = gst_caps_new_empty_simple ("audio/x-opus");
16121       break;
16122     case FOURCC_lpcm:
16123     {
16124       guint32 flags = 0;
16125       guint32 depth = 0;
16126       guint32 width = 0;
16127       GstAudioFormat format;
16128       enum
16129       {
16130         FLAG_IS_FLOAT = 0x1,
16131         FLAG_IS_BIG_ENDIAN = 0x2,
16132         FLAG_IS_SIGNED = 0x4,
16133         FLAG_IS_PACKED = 0x8,
16134         FLAG_IS_ALIGNED_HIGH = 0x10,
16135         FLAG_IS_NON_INTERLEAVED = 0x20
16136       };
16137       _codec ("Raw LPCM audio");
16138
16139       if (data && len >= 36) {
16140         depth = QT_UINT32 (data + 24);
16141         flags = QT_UINT32 (data + 28);
16142         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
16143       }
16144       if ((flags & FLAG_IS_FLOAT) == 0) {
16145         if (depth == 0)
16146           depth = 16;
16147         if (width == 0)
16148           width = 16;
16149         if ((flags & FLAG_IS_ALIGNED_HIGH))
16150           depth = width;
16151
16152         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
16153             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
16154             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
16155         caps = gst_caps_new_simple ("audio/x-raw",
16156             "format", G_TYPE_STRING,
16157             format !=
16158             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
16159             "UNKNOWN", "layout", G_TYPE_STRING,
16160             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
16161             "interleaved", NULL);
16162         stream->alignment = GST_ROUND_UP_8 (depth);
16163         stream->alignment = round_up_pow2 (stream->alignment);
16164       } else {
16165         if (width == 0)
16166           width = 32;
16167         if (width == 64) {
16168           if (flags & FLAG_IS_BIG_ENDIAN)
16169             format = GST_AUDIO_FORMAT_F64BE;
16170           else
16171             format = GST_AUDIO_FORMAT_F64LE;
16172         } else {
16173           if (flags & FLAG_IS_BIG_ENDIAN)
16174             format = GST_AUDIO_FORMAT_F32BE;
16175           else
16176             format = GST_AUDIO_FORMAT_F32LE;
16177         }
16178         caps = gst_caps_new_simple ("audio/x-raw",
16179             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
16180             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
16181             "non-interleaved" : "interleaved", NULL);
16182         stream->alignment = width / 8;
16183       }
16184       break;
16185     }
16186     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
16187     {
16188       _codec ("AC4");
16189       caps = gst_caps_new_empty_simple ("audio/x-ac4");
16190       break;
16191     }
16192     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
16193       /* ? */
16194     default:
16195     {
16196       caps = _get_unknown_codec_name ("audio", fourcc);
16197       break;
16198     }
16199   }
16200
16201   if (caps) {
16202     GstCaps *templ_caps =
16203         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
16204     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
16205     gst_caps_unref (caps);
16206     gst_caps_unref (templ_caps);
16207     caps = intersection;
16208   }
16209
16210   /* enable clipping for raw audio streams */
16211   s = gst_caps_get_structure (caps, 0);
16212   name = gst_structure_get_name (s);
16213   if (g_str_has_prefix (name, "audio/x-raw")) {
16214     stream->need_clip = TRUE;
16215     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
16216     stream->max_buffer_size = entry->rate * entry->bytes_per_frame;
16217     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
16218         stream->max_buffer_size);
16219   }
16220   return caps;
16221 }
16222
16223 static GstCaps *
16224 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
16225     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
16226     const guint8 * stsd_entry_data, gchar ** codec_name)
16227 {
16228   GstCaps *caps;
16229
16230   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
16231
16232   switch (fourcc) {
16233     case FOURCC_mp4s:
16234       _codec ("DVD subtitle");
16235       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
16236       stream->process_func = gst_qtdemux_process_buffer_dvd;
16237       break;
16238     case FOURCC_text:
16239       _codec ("Quicktime timed text");
16240       goto text;
16241     case FOURCC_tx3g:
16242       _codec ("3GPP timed text");
16243     text:
16244       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
16245           "utf8", NULL);
16246       /* actual text piece needs to be extracted */
16247       stream->process_func = gst_qtdemux_process_buffer_text;
16248       break;
16249     case FOURCC_stpp:
16250       _codec ("XML subtitles");
16251       caps = gst_caps_new_empty_simple ("application/ttml+xml");
16252       break;
16253     case FOURCC_wvtt:
16254     {
16255       GstBuffer *buffer;
16256       const gchar *buf = "WEBVTT\n\n";
16257
16258       _codec ("WebVTT subtitles");
16259       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
16260       stream->process_func = gst_qtdemux_process_buffer_wvtt;
16261
16262       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
16263       buffer = gst_buffer_new_and_alloc (8);
16264       gst_buffer_fill (buffer, 0, buf, 8);
16265       stream->buffers = g_slist_append (stream->buffers, buffer);
16266
16267       break;
16268     }
16269     case FOURCC_c608:
16270       _codec ("CEA 608 Closed Caption");
16271       caps =
16272           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
16273           G_TYPE_STRING, "s334-1a", NULL);
16274       stream->process_func = gst_qtdemux_process_buffer_clcp;
16275       stream->need_split = TRUE;
16276       break;
16277     case FOURCC_c708:
16278       _codec ("CEA 708 Closed Caption");
16279       caps =
16280           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
16281           G_TYPE_STRING, "cdp", NULL);
16282       stream->process_func = gst_qtdemux_process_buffer_clcp;
16283       break;
16284
16285     default:
16286     {
16287       caps = _get_unknown_codec_name ("text", fourcc);
16288       break;
16289     }
16290   }
16291   return caps;
16292 }
16293
16294 static GstCaps *
16295 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
16296     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
16297     const guint8 * stsd_entry_data, gchar ** codec_name)
16298 {
16299   GstCaps *caps = NULL;
16300
16301   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
16302
16303   switch (fourcc) {
16304     case FOURCC_metx:{
16305       gsize size = QT_UINT32 (stsd_entry_data);
16306       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
16307       const gchar *content_encoding;
16308       const gchar *namespaces;
16309       const gchar *schema_locations;
16310
16311       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
16312         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
16313         break;
16314       }
16315
16316       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
16317           !gst_byte_reader_get_string (&reader, &namespaces) ||
16318           !gst_byte_reader_get_string (&reader, &schema_locations)) {
16319         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
16320         break;
16321       }
16322
16323       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
16324         if (content_encoding == NULL || *content_encoding == '\0'
16325             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
16326           _codec ("ONVIF Timed XML MetaData");
16327           caps =
16328               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
16329               G_TYPE_BOOLEAN, TRUE, NULL);
16330         } else {
16331           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
16332               content_encoding);
16333         }
16334       } else {
16335         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
16336             namespaces);
16337       }
16338
16339       break;
16340     }
16341     default:
16342       break;
16343   }
16344
16345   if (!caps)
16346     caps = _get_unknown_codec_name ("meta", fourcc);
16347
16348   return caps;
16349 }
16350
16351 static GstCaps *
16352 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
16353     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
16354     const guint8 * stsd_entry_data, gchar ** codec_name)
16355 {
16356   GstCaps *caps;
16357
16358   switch (fourcc) {
16359     case FOURCC_m1v:
16360       _codec ("MPEG 1 video");
16361       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
16362           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
16363       break;
16364     default:
16365       caps = NULL;
16366       break;
16367   }
16368   return caps;
16369 }
16370
16371 static void
16372 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
16373     const gchar * system_id)
16374 {
16375   gint i;
16376
16377   if (!qtdemux->protection_system_ids)
16378     qtdemux->protection_system_ids =
16379         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
16380   /* Check whether we already have an entry for this system ID. */
16381   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
16382     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
16383     if (g_ascii_strcasecmp (system_id, id) == 0) {
16384       return;
16385     }
16386   }
16387   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
16388   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
16389           -1));
16390 }