Merge branch 'tizen_gst_1.19.3' into tizen_gst_1.20.0
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 #include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 #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 #define gst_qtdemux_parent_class parent_class
321 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
322 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
323     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
324
325 static void gst_qtdemux_dispose (GObject * object);
326 static void gst_qtdemux_finalize (GObject * object);
327
328 static guint32
329 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
330     GstClockTime media_time);
331 static guint32
332 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
333     QtDemuxStream * str, gint64 media_offset);
334
335 #if 0
336 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
337 static GstIndex *gst_qtdemux_get_index (GstElement * element);
338 #endif
339 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
340     GstStateChange transition);
341 static void gst_qtdemux_set_context (GstElement * element,
342     GstContext * context);
343 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
344 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
345     GstObject * parent, GstPadMode mode, gboolean active);
346
347 static void gst_qtdemux_loop (GstPad * pad);
348 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
349     GstBuffer * inbuf);
350 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
351     GstEvent * event);
352 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
353     GstQuery * query);
354 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
355 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
356     QtDemuxStream * stream);
357 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
358     QtDemuxStream * stream);
359 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
360     gboolean force);
361
362 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
363
364 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
365     const guint8 * buffer, guint length);
366 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
367     const guint8 * buffer, guint length);
368 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
369
370 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
371     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
372     GstTagList * list);
373 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
374     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
375     const guint8 * stsd_entry_data, gchar ** codec_name);
376 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
378     const guint8 * data, int len, gchar ** codec_name);
379 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
380     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
381     gchar ** codec_name);
382 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
383     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
384     const guint8 * stsd_entry_data, gchar ** codec_name);
385
386 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
387     QtDemuxStream * stream, guint32 n);
388 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
389 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
390 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
391 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
392 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
393 static void qtdemux_do_allocation (QtDemuxStream * stream,
394     GstQTDemux * qtdemux);
395 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
396     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
397 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
398     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
399     GstClockTime * _start, GstClockTime * _stop);
400 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
401     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
402
403 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
404 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
405
406 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
407
408 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
409     QtDemuxStream * stream, guint sample_index);
410 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
411     const gchar * id);
412 static void qtdemux_gst_structure_free (GstStructure * gststructure);
413 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
414
415 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
416 static void gst_tag_register_spherical_tags (void);
417 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
418
419 static void
420 gst_qtdemux_class_init (GstQTDemuxClass * klass)
421 {
422   GObjectClass *gobject_class;
423   GstElementClass *gstelement_class;
424
425   gobject_class = (GObjectClass *) klass;
426   gstelement_class = (GstElementClass *) klass;
427
428   parent_class = g_type_class_peek_parent (klass);
429
430   gobject_class->dispose = gst_qtdemux_dispose;
431   gobject_class->finalize = gst_qtdemux_finalize;
432
433   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
434 #if 0
435   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
436   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
437 #endif
438   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
439
440   gst_tag_register_musicbrainz_tags ();
441
442 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
443   gst_tag_register_spherical_tags ();
444 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
445
446   gst_element_class_add_static_pad_template (gstelement_class,
447       &gst_qtdemux_sink_template);
448   gst_element_class_add_static_pad_template (gstelement_class,
449       &gst_qtdemux_videosrc_template);
450   gst_element_class_add_static_pad_template (gstelement_class,
451       &gst_qtdemux_audiosrc_template);
452   gst_element_class_add_static_pad_template (gstelement_class,
453       &gst_qtdemux_subsrc_template);
454   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
455       "Codec/Demuxer",
456       "Demultiplex a QuickTime file into audio and video streams",
457       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
458
459   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
460   gst_riff_init ();
461 }
462
463 static void
464 gst_qtdemux_init (GstQTDemux * qtdemux)
465 {
466   qtdemux->sinkpad =
467       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
468   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
469   gst_pad_set_activatemode_function (qtdemux->sinkpad,
470       qtdemux_sink_activate_mode);
471   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
472   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
473   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
474   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
475
476   qtdemux->adapter = gst_adapter_new ();
477   g_queue_init (&qtdemux->protection_event_queue);
478   qtdemux->flowcombiner = gst_flow_combiner_new ();
479   g_mutex_init (&qtdemux->expose_lock);
480
481   qtdemux->active_streams = g_ptr_array_new_with_free_func
482       ((GDestroyNotify) gst_qtdemux_stream_unref);
483   qtdemux->old_streams = g_ptr_array_new_with_free_func
484       ((GDestroyNotify) gst_qtdemux_stream_unref);
485
486 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
487   qtdemux->spherical_metadata = (QtDemuxSphericalMetadata *)
488       malloc (sizeof (QtDemuxSphericalMetadata));
489
490   if (qtdemux->spherical_metadata) {
491     qtdemux->spherical_metadata->is_spherical = FALSE;
492     qtdemux->spherical_metadata->is_stitched = FALSE;
493     qtdemux->spherical_metadata->stitching_software = NULL;
494     qtdemux->spherical_metadata->projection_type = NULL;
495     qtdemux->spherical_metadata->stereo_mode = NULL;
496     qtdemux->spherical_metadata->source_count = 0;
497     qtdemux->spherical_metadata->init_view_heading = 0;
498     qtdemux->spherical_metadata->init_view_pitch = 0;
499     qtdemux->spherical_metadata->init_view_roll = 0;
500     qtdemux->spherical_metadata->timestamp = 0;
501     qtdemux->spherical_metadata->full_pano_width_pixels = 0;
502     qtdemux->spherical_metadata->full_pano_height_pixels = 0;
503     qtdemux->spherical_metadata->cropped_area_image_width = 0;
504     qtdemux->spherical_metadata->cropped_area_image_height = 0;
505     qtdemux->spherical_metadata->cropped_area_left = 0;
506     qtdemux->spherical_metadata->cropped_area_top = 0;
507     qtdemux->spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_UNKNOWN;
508     qtdemux->spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_UNKNOWN;
509     qtdemux->spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_UNKNOWN;
510   }
511 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
512
513   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
514
515   gst_qtdemux_reset (qtdemux, TRUE);
516 }
517
518 static void
519 gst_qtdemux_finalize (GObject * object)
520 {
521   GstQTDemux *qtdemux = GST_QTDEMUX (object);
522
523   g_free (qtdemux->redirect_location);
524
525   G_OBJECT_CLASS (parent_class)->finalize (object);
526 }
527
528 static void
529 gst_qtdemux_dispose (GObject * object)
530 {
531   GstQTDemux *qtdemux = GST_QTDEMUX (object);
532
533 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
534   if (qtdemux->spherical_metadata) {
535     if (qtdemux->spherical_metadata->stitching_software)
536       free(qtdemux->spherical_metadata->stitching_software);
537     if (qtdemux->spherical_metadata->projection_type)
538       free(qtdemux->spherical_metadata->projection_type);
539     if (qtdemux->spherical_metadata->stereo_mode)
540       free(qtdemux->spherical_metadata->stereo_mode);
541
542     free(qtdemux->spherical_metadata);
543     qtdemux->spherical_metadata = NULL;
544   }
545 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
546
547   if (qtdemux->adapter) {
548     g_object_unref (G_OBJECT (qtdemux->adapter));
549     qtdemux->adapter = NULL;
550   }
551   gst_tag_list_unref (qtdemux->tag_list);
552   gst_flow_combiner_free (qtdemux->flowcombiner);
553   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
554       NULL);
555   g_queue_clear (&qtdemux->protection_event_queue);
556
557   g_free (qtdemux->cenc_aux_info_sizes);
558   qtdemux->cenc_aux_info_sizes = NULL;
559   g_mutex_clear (&qtdemux->expose_lock);
560
561   g_ptr_array_free (qtdemux->active_streams, TRUE);
562   g_ptr_array_free (qtdemux->old_streams, TRUE);
563
564   G_OBJECT_CLASS (parent_class)->dispose (object);
565 }
566
567 static void
568 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
569 {
570   if (qtdemux->redirect_location) {
571     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
572         (_("This file contains no playable streams.")),
573         ("no known streams found, a redirect message has been posted"),
574         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
575   } else {
576     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
577         (_("This file contains no playable streams.")),
578         ("no known streams found"));
579   }
580 }
581
582 static GstBuffer *
583 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
584 {
585   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
586       mem, size, 0, size, mem, free_func);
587 }
588
589 static GstFlowReturn
590 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
591     GstBuffer ** buf)
592 {
593   GstFlowReturn flow;
594   GstMapInfo map;
595   gsize bsize;
596
597   if (G_UNLIKELY (size == 0)) {
598     GstFlowReturn ret;
599     GstBuffer *tmp = NULL;
600
601     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
602     if (ret != GST_FLOW_OK)
603       return ret;
604
605     gst_buffer_map (tmp, &map, GST_MAP_READ);
606     size = QT_UINT32 (map.data);
607     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
608
609     gst_buffer_unmap (tmp, &map);
610     gst_buffer_unref (tmp);
611   }
612
613   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
614   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
615     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
616       /* we're pulling header but already got most interesting bits,
617        * so never mind the rest (e.g. tags) (that much) */
618       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
619           size);
620       return GST_FLOW_EOS;
621     } else {
622       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
623           (_("This file is invalid and cannot be played.")),
624           ("atom has bogus size %" G_GUINT64_FORMAT, size));
625       return GST_FLOW_ERROR;
626     }
627   }
628
629   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
630
631   if (G_UNLIKELY (flow != GST_FLOW_OK))
632     return flow;
633
634   bsize = gst_buffer_get_size (*buf);
635   /* Catch short reads - we don't want any partial atoms */
636   if (G_UNLIKELY (bsize < size)) {
637     GST_WARNING_OBJECT (qtdemux,
638         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
639     gst_buffer_unref (*buf);
640     *buf = NULL;
641     return GST_FLOW_EOS;
642   }
643
644   return flow;
645 }
646
647 #if 1
648 static gboolean
649 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
650     GstFormat src_format, gint64 src_value, GstFormat dest_format,
651     gint64 * dest_value)
652 {
653   gboolean res = TRUE;
654   QtDemuxStream *stream = gst_pad_get_element_private (pad);
655   gint32 index;
656
657   if (stream->subtype != FOURCC_vide) {
658     res = FALSE;
659     goto done;
660   }
661
662   switch (src_format) {
663     case GST_FORMAT_TIME:
664       switch (dest_format) {
665         case GST_FORMAT_BYTES:{
666           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
667           if (-1 == index) {
668             res = FALSE;
669             goto done;
670           }
671
672           *dest_value = stream->samples[index].offset;
673
674           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
675               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
676               GST_TIME_ARGS (src_value), *dest_value);
677           break;
678         }
679         default:
680           res = FALSE;
681           break;
682       }
683       break;
684     case GST_FORMAT_BYTES:
685       switch (dest_format) {
686         case GST_FORMAT_TIME:{
687           index =
688               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
689               stream, src_value);
690
691           if (-1 == index) {
692             res = FALSE;
693             goto done;
694           }
695
696           *dest_value =
697               QTSTREAMTIME_TO_GSTTIME (stream,
698               stream->samples[index].timestamp);
699           GST_DEBUG_OBJECT (qtdemux,
700               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
701               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
702           break;
703         }
704         default:
705           res = FALSE;
706           break;
707       }
708       break;
709     default:
710       res = FALSE;
711       break;
712   }
713
714 done:
715   return res;
716 }
717 #endif
718
719 static gboolean
720 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
721 {
722   gboolean res = FALSE;
723
724   *duration = GST_CLOCK_TIME_NONE;
725
726   if (qtdemux->duration != 0 &&
727       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
728     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
729     res = TRUE;
730   } else {
731     *duration = GST_CLOCK_TIME_NONE;
732   }
733
734   return res;
735 }
736
737 static gboolean
738 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
739     GstQuery * query)
740 {
741   gboolean res = FALSE;
742   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
743
744   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
745
746   switch (GST_QUERY_TYPE (query)) {
747     case GST_QUERY_POSITION:{
748       GstFormat fmt;
749
750       gst_query_parse_position (query, &fmt, NULL);
751       if (fmt == GST_FORMAT_TIME
752           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
753         gst_query_set_position (query, GST_FORMAT_TIME,
754             qtdemux->segment.position);
755         res = TRUE;
756       }
757     }
758       break;
759     case GST_QUERY_DURATION:{
760       GstFormat fmt;
761
762       gst_query_parse_duration (query, &fmt, NULL);
763       if (fmt == GST_FORMAT_TIME) {
764         /* First try to query upstream */
765         res = gst_pad_query_default (pad, parent, query);
766         if (!res) {
767           GstClockTime duration;
768           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
769             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
770             res = TRUE;
771           }
772         }
773       }
774       break;
775     }
776     case GST_QUERY_CONVERT:{
777       GstFormat src_fmt, dest_fmt;
778       gint64 src_value, dest_value = 0;
779
780       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
781
782       res = gst_qtdemux_src_convert (qtdemux, pad,
783           src_fmt, src_value, dest_fmt, &dest_value);
784       if (res)
785         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
786
787       break;
788     }
789     case GST_QUERY_FORMATS:
790       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
791       res = TRUE;
792       break;
793     case GST_QUERY_SEEKING:{
794       GstFormat fmt;
795       gboolean seekable;
796
797       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
798
799       if (fmt == GST_FORMAT_BYTES) {
800         /* We always refuse BYTES seeks from downstream */
801         break;
802       }
803
804       /* try upstream first */
805       res = gst_pad_query_default (pad, parent, query);
806
807       if (!res) {
808         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
809         if (fmt == GST_FORMAT_TIME) {
810           GstClockTime duration;
811
812           gst_qtdemux_get_duration (qtdemux, &duration);
813           seekable = TRUE;
814           if (!qtdemux->pullbased) {
815             GstQuery *q;
816
817             /* we might be able with help from upstream */
818             seekable = FALSE;
819             q = gst_query_new_seeking (GST_FORMAT_BYTES);
820             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
821               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
822               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
823             }
824             gst_query_unref (q);
825           }
826           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
827           res = TRUE;
828         }
829       }
830       break;
831     }
832     case GST_QUERY_SEGMENT:
833     {
834       GstFormat format;
835       gint64 start, stop;
836
837       format = qtdemux->segment.format;
838
839       start =
840           gst_segment_to_stream_time (&qtdemux->segment, format,
841           qtdemux->segment.start);
842       if ((stop = qtdemux->segment.stop) == -1)
843         stop = qtdemux->segment.duration;
844       else
845         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
846
847       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
848       res = TRUE;
849       break;
850     }
851     default:
852       res = gst_pad_query_default (pad, parent, query);
853       break;
854   }
855
856   return res;
857 }
858
859 static void
860 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
861 {
862   if (G_LIKELY (stream->pad)) {
863     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
864         GST_DEBUG_PAD_NAME (stream->pad));
865
866     if (!gst_tag_list_is_empty (stream->stream_tags)) {
867       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
868           stream->stream_tags);
869       gst_pad_push_event (stream->pad,
870           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
871 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
872       /* post message qtdemux tag (for early recive application) */
873       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
874             gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
875                   gst_tag_list_copy (stream->stream_tags)));
876 #endif
877     }
878
879     if (G_UNLIKELY (stream->send_global_tags)) {
880       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
881           qtdemux->tag_list);
882       gst_pad_push_event (stream->pad,
883           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
884       stream->send_global_tags = FALSE;
885     }
886   }
887 }
888
889 /* push event on all source pads; takes ownership of the event */
890 static void
891 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
892 {
893   gboolean has_valid_stream = FALSE;
894   GstEventType etype = GST_EVENT_TYPE (event);
895   guint i;
896
897   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
898       GST_EVENT_TYPE_NAME (event));
899
900   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
901     GstPad *pad;
902     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
903     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
904
905     if ((pad = stream->pad)) {
906       has_valid_stream = TRUE;
907
908       if (etype == GST_EVENT_EOS) {
909         /* let's not send twice */
910         if (stream->sent_eos)
911           continue;
912         stream->sent_eos = TRUE;
913       }
914
915       gst_pad_push_event (pad, gst_event_ref (event));
916     }
917   }
918
919   gst_event_unref (event);
920
921   /* if it is EOS and there are no pads, post an error */
922   if (!has_valid_stream && etype == GST_EVENT_EOS) {
923     gst_qtdemux_post_no_playable_stream_error (qtdemux);
924   }
925 }
926
927 typedef struct
928 {
929   guint64 media_time;
930 } FindData;
931
932 static gint
933 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
934 {
935   if ((gint64) s1->timestamp > *media_time)
936     return 1;
937   if ((gint64) s1->timestamp == *media_time)
938     return 0;
939
940   return -1;
941 }
942
943 /* find the index of the sample that includes the data for @media_time using a
944  * binary search.  Only to be called in optimized cases of linear search below.
945  *
946  * Returns the index of the sample with the corresponding *DTS*.
947  */
948 static guint32
949 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
950     guint64 media_time)
951 {
952   QtDemuxSample *result;
953   guint32 index;
954
955   /* convert media_time to mov format */
956   media_time =
957       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
958
959   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
960       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
961       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
962
963   if (G_LIKELY (result))
964     index = result - str->samples;
965   else
966     index = 0;
967
968   return index;
969 }
970
971
972
973 /* find the index of the sample that includes the data for @media_offset using a
974  * linear search
975  *
976  * Returns the index of the sample.
977  */
978 static guint32
979 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
980     QtDemuxStream * str, gint64 media_offset)
981 {
982   QtDemuxSample *result = str->samples;
983   guint32 index = 0;
984
985   if (result == NULL || str->n_samples == 0)
986     return -1;
987
988   if (media_offset == result->offset)
989     return index;
990
991   result++;
992   while (index < str->n_samples - 1) {
993     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
994       goto parse_failed;
995
996     if (media_offset < result->offset)
997       break;
998
999     index++;
1000     result++;
1001   }
1002   return index;
1003
1004   /* ERRORS */
1005 parse_failed:
1006   {
1007     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1008     return -1;
1009   }
1010 }
1011
1012 /* find the index of the sample that includes the data for @media_time using a
1013  * linear search, and keeping in mind that not all samples may have been parsed
1014  * yet.  If possible, it will delegate to binary search.
1015  *
1016  * Returns the index of the sample.
1017  */
1018 static guint32
1019 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1020     GstClockTime media_time)
1021 {
1022   guint32 index = 0;
1023   guint64 mov_time;
1024   QtDemuxSample *sample;
1025
1026   /* convert media_time to mov format */
1027   mov_time =
1028       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1029
1030   sample = str->samples;
1031   if (mov_time == sample->timestamp + sample->pts_offset)
1032     return index;
1033
1034   /* use faster search if requested time in already parsed range */
1035   sample = str->samples + str->stbl_index;
1036   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1037     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1038     sample = str->samples + index;
1039   } else {
1040     while (index < str->n_samples - 1) {
1041       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1042         goto parse_failed;
1043
1044       sample = str->samples + index + 1;
1045       if (mov_time < sample->timestamp) {
1046         sample = str->samples + index;
1047         break;
1048       }
1049
1050       index++;
1051     }
1052   }
1053
1054   /* sample->timestamp is now <= media_time, need to find the corresponding
1055    * PTS now by looking backwards */
1056   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1057     index--;
1058     sample = str->samples + index;
1059   }
1060
1061   return index;
1062
1063   /* ERRORS */
1064 parse_failed:
1065   {
1066     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1067     return -1;
1068   }
1069 }
1070
1071 /* find the index of the keyframe needed to decode the sample at @index
1072  * of stream @str, or of a subsequent keyframe (depending on @next)
1073  *
1074  * Returns the index of the keyframe.
1075  */
1076 static guint32
1077 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1078     guint32 index, gboolean next)
1079 {
1080   guint32 new_index = index;
1081
1082   if (index >= str->n_samples) {
1083     new_index = str->n_samples;
1084     goto beach;
1085   }
1086
1087   /* all keyframes, return index */
1088   if (str->all_keyframe) {
1089     new_index = index;
1090     goto beach;
1091   }
1092
1093   /* else search until we have a keyframe */
1094   while (new_index < str->n_samples) {
1095     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1096       goto parse_failed;
1097
1098     if (str->samples[new_index].keyframe)
1099       break;
1100
1101     if (new_index == 0)
1102       break;
1103
1104     if (next)
1105       new_index++;
1106     else
1107       new_index--;
1108   }
1109
1110   if (new_index == str->n_samples) {
1111     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1112     new_index = -1;
1113   }
1114
1115 beach:
1116   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1117       "gave %u", next ? "after" : "before", index, new_index);
1118
1119   return new_index;
1120
1121   /* ERRORS */
1122 parse_failed:
1123   {
1124     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1125     return -1;
1126   }
1127 }
1128
1129 /* find the segment for @time_position for @stream
1130  *
1131  * Returns the index of the segment containing @time_position.
1132  * Returns the last segment and sets the @eos variable to TRUE
1133  * if the time is beyond the end. @eos may be NULL
1134  */
1135 static guint32
1136 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1137     GstClockTime time_position)
1138 {
1139   gint i;
1140   guint32 seg_idx;
1141
1142   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1143       GST_TIME_ARGS (time_position));
1144
1145   seg_idx = -1;
1146   for (i = 0; i < stream->n_segments; i++) {
1147     QtDemuxSegment *segment = &stream->segments[i];
1148
1149     GST_LOG_OBJECT (stream->pad,
1150         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1151         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1152
1153     /* For the last segment we include stop_time in the last segment */
1154     if (i < stream->n_segments - 1) {
1155       if (segment->time <= time_position && time_position < segment->stop_time) {
1156         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1157         seg_idx = i;
1158         break;
1159       }
1160     } else {
1161       /* Last segment always matches */
1162       seg_idx = i;
1163       break;
1164     }
1165   }
1166   return seg_idx;
1167 }
1168
1169 /* move the stream @str to the sample position @index.
1170  *
1171  * Updates @str->sample_index and marks discontinuity if needed.
1172  */
1173 static void
1174 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1175     guint32 index)
1176 {
1177   /* no change needed */
1178   if (index == str->sample_index)
1179     return;
1180
1181   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1182       str->n_samples);
1183
1184   /* position changed, we have a discont */
1185   str->sample_index = index;
1186   str->offset_in_sample = 0;
1187   /* Each time we move in the stream we store the position where we are
1188    * starting from */
1189   str->from_sample = index;
1190   str->discont = TRUE;
1191 }
1192
1193 static void
1194 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1195     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1196 {
1197   guint64 min_offset;
1198   gint64 min_byte_offset = -1;
1199   guint i;
1200
1201   min_offset = desired_time;
1202
1203   /* for each stream, find the index of the sample in the segment
1204    * and move back to the previous keyframe. */
1205   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1206     QtDemuxStream *str;
1207     guint32 index, kindex;
1208     guint32 seg_idx;
1209     GstClockTime media_start;
1210     GstClockTime media_time;
1211     GstClockTime seg_time;
1212     QtDemuxSegment *seg;
1213     gboolean empty_segment = FALSE;
1214
1215     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1216
1217     if (CUR_STREAM (str)->sparse && !use_sparse)
1218       continue;
1219
1220     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1221     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1222
1223     /* get segment and time in the segment */
1224     seg = &str->segments[seg_idx];
1225     seg_time = (desired_time - seg->time) * seg->rate;
1226
1227     while (QTSEGMENT_IS_EMPTY (seg)) {
1228       seg_time = 0;
1229       empty_segment = TRUE;
1230       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1231           seg_idx);
1232       seg_idx++;
1233       if (seg_idx == str->n_segments)
1234         break;
1235       seg = &str->segments[seg_idx];
1236     }
1237
1238     if (seg_idx == str->n_segments) {
1239       /* FIXME track shouldn't have the last segment as empty, but if it
1240        * happens we better handle it */
1241       continue;
1242     }
1243
1244     /* get the media time in the segment */
1245     media_start = seg->media_start + seg_time;
1246
1247     /* get the index of the sample with media time */
1248     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1249     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1250         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1251         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1252         empty_segment);
1253
1254     /* shift to next frame if we are looking for next keyframe */
1255     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1256         && index < str->stbl_index)
1257       index++;
1258
1259     if (!empty_segment) {
1260       /* find previous keyframe */
1261       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1262
1263       /* we will settle for one before if none found after */
1264       if (next && kindex == -1)
1265         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1266
1267       /* Update the requested time whenever a keyframe was found, to make it
1268        * accurate and avoid having the first buffer fall outside of the segment
1269        */
1270       if (kindex != -1) {
1271         index = kindex;
1272
1273         /* get timestamp of keyframe */
1274         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1275         GST_DEBUG_OBJECT (qtdemux,
1276             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1277             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1278             str->samples[kindex].offset);
1279
1280         /* keyframes in the segment get a chance to change the
1281          * desired_offset. keyframes out of the segment are
1282          * ignored. */
1283         if (media_time >= seg->media_start) {
1284           GstClockTime seg_time;
1285
1286           /* this keyframe is inside the segment, convert back to
1287            * segment time */
1288           seg_time = (media_time - seg->media_start) + seg->time;
1289           if ((!next && (seg_time < min_offset)) ||
1290               (next && (seg_time > min_offset)))
1291             min_offset = seg_time;
1292         }
1293       }
1294     }
1295
1296     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1297       min_byte_offset = str->samples[index].offset;
1298   }
1299
1300   if (key_time)
1301     *key_time = min_offset;
1302   if (key_offset)
1303     *key_offset = min_byte_offset;
1304 }
1305
1306 static gboolean
1307 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1308     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1309 {
1310   gboolean res;
1311
1312   g_return_val_if_fail (format != NULL, FALSE);
1313   g_return_val_if_fail (cur != NULL, FALSE);
1314   g_return_val_if_fail (stop != NULL, FALSE);
1315
1316   if (*format == GST_FORMAT_TIME)
1317     return TRUE;
1318
1319   res = TRUE;
1320   if (cur_type != GST_SEEK_TYPE_NONE)
1321     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1322   if (res && stop_type != GST_SEEK_TYPE_NONE)
1323     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1324
1325   if (res)
1326     *format = GST_FORMAT_TIME;
1327
1328   return res;
1329 }
1330
1331 /* perform seek in push based mode:
1332    find BYTE position to move to based on time and delegate to upstream
1333 */
1334 static gboolean
1335 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1336 {
1337   gdouble rate;
1338   GstFormat format;
1339   GstSeekFlags flags;
1340   GstSeekType cur_type, stop_type;
1341   gint64 cur, stop, key_cur;
1342   gboolean res;
1343   gint64 byte_cur;
1344   gint64 original_stop;
1345   guint32 seqnum;
1346
1347   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1348
1349   gst_event_parse_seek (event, &rate, &format, &flags,
1350       &cur_type, &cur, &stop_type, &stop);
1351   seqnum = gst_event_get_seqnum (event);
1352
1353   /* Directly send the instant-rate-change event here before taking the
1354    * stream-lock so that it can be applied as soon as possible */
1355   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1356     GstEvent *ev;
1357
1358     /* instant rate change only supported if direction does not change. All
1359      * other requirements are already checked before creating the seek event
1360      * but let's double-check here to be sure */
1361     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1362         (qtdemux->segment.rate < 0 && rate > 0) ||
1363         cur_type != GST_SEEK_TYPE_NONE ||
1364         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1365       GST_ERROR_OBJECT (qtdemux,
1366           "Instant rate change seeks only supported in the "
1367           "same direction, without flushing and position change");
1368       return FALSE;
1369     }
1370
1371     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1372         (GstSegmentFlags) flags);
1373     gst_event_set_seqnum (ev, seqnum);
1374     gst_qtdemux_push_event (qtdemux, ev);
1375     return TRUE;
1376   }
1377
1378   /* only forward streaming and seeking is possible */
1379   if (rate <= 0)
1380     goto unsupported_seek;
1381
1382   /* convert to TIME if needed and possible */
1383   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1384           stop_type, &stop))
1385     goto no_format;
1386
1387   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1388    * the original stop position to use when upstream pushes the new segment
1389    * for this seek */
1390   original_stop = stop;
1391   stop = -1;
1392
1393   /* find reasonable corresponding BYTE position,
1394    * also try to mind about keyframes, since we can not go back a bit for them
1395    * later on */
1396   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1397    * mostly just work, but let's not yet boldly go there  ... */
1398   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1399
1400   if (byte_cur == -1)
1401     goto abort_seek;
1402
1403   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1404       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1405       stop);
1406
1407   GST_OBJECT_LOCK (qtdemux);
1408   qtdemux->seek_offset = byte_cur;
1409   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1410     qtdemux->push_seek_start = cur;
1411   } else {
1412     qtdemux->push_seek_start = key_cur;
1413   }
1414
1415   if (stop_type == GST_SEEK_TYPE_NONE) {
1416     qtdemux->push_seek_stop = qtdemux->segment.stop;
1417   } else {
1418     qtdemux->push_seek_stop = original_stop;
1419   }
1420   GST_OBJECT_UNLOCK (qtdemux);
1421
1422   qtdemux->segment_seqnum = seqnum;
1423   /* BYTE seek event */
1424   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1425       stop_type, stop);
1426   gst_event_set_seqnum (event, seqnum);
1427   res = gst_pad_push_event (qtdemux->sinkpad, event);
1428
1429   return res;
1430
1431   /* ERRORS */
1432 abort_seek:
1433   {
1434     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1435         "seek aborted.");
1436     return FALSE;
1437   }
1438 unsupported_seek:
1439   {
1440     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1441     return FALSE;
1442   }
1443 no_format:
1444   {
1445     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1446     return FALSE;
1447   }
1448 }
1449
1450 /* perform the seek.
1451  *
1452  * We set all segment_indexes in the streams to unknown and
1453  * adjust the time_position to the desired position. this is enough
1454  * to trigger a segment switch in the streaming thread to start
1455  * streaming from the desired position.
1456  *
1457  * Keyframe seeking is a little more complicated when dealing with
1458  * segments. Ideally we want to move to the previous keyframe in
1459  * the segment but there might not be a keyframe in the segment. In
1460  * fact, none of the segments could contain a keyframe. We take a
1461  * practical approach: seek to the previous keyframe in the segment,
1462  * if there is none, seek to the beginning of the segment.
1463  *
1464  * Called with STREAM_LOCK
1465  */
1466 static gboolean
1467 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1468     guint32 seqnum, GstSeekFlags flags)
1469 {
1470   gint64 desired_offset;
1471   guint i;
1472
1473   desired_offset = segment->position;
1474
1475   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1476       GST_TIME_ARGS (desired_offset));
1477
1478   /* may not have enough fragmented info to do this adjustment,
1479    * and we can't scan (and probably should not) at this time with
1480    * possibly flushing upstream */
1481   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1482     gint64 min_offset;
1483     gboolean next, before, after;
1484
1485     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1486     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1487     next = after && !before;
1488     if (segment->rate < 0)
1489       next = !next;
1490
1491     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1492         NULL);
1493     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1494         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1495     desired_offset = min_offset;
1496   }
1497
1498   /* and set all streams to the final position */
1499   GST_OBJECT_LOCK (qtdemux);
1500   gst_flow_combiner_reset (qtdemux->flowcombiner);
1501   GST_OBJECT_UNLOCK (qtdemux);
1502   qtdemux->segment_seqnum = seqnum;
1503   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1504     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1505
1506     stream->time_position = desired_offset;
1507     stream->accumulated_base = 0;
1508     stream->sample_index = -1;
1509     stream->offset_in_sample = 0;
1510     stream->segment_index = -1;
1511     stream->sent_eos = FALSE;
1512     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1513
1514     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1515       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1516   }
1517   segment->position = desired_offset;
1518   if (segment->rate >= 0) {
1519     segment->start = desired_offset;
1520     /* We need to update time as we update start in that direction */
1521     segment->time = desired_offset;
1522
1523     /* we stop at the end */
1524     if (segment->stop == -1)
1525       segment->stop = segment->duration;
1526   } else {
1527     segment->stop = desired_offset;
1528   }
1529
1530   if (qtdemux->fragmented)
1531     qtdemux->fragmented_seek_pending = TRUE;
1532
1533   return TRUE;
1534 }
1535
1536 /* do a seek in pull based mode */
1537 static gboolean
1538 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1539 {
1540   gdouble rate = 1.0;
1541   GstFormat format;
1542   GstSeekFlags flags;
1543   GstSeekType cur_type, stop_type;
1544   gint64 cur, stop;
1545   gboolean flush, instant_rate_change;
1546   gboolean update;
1547   GstSegment seeksegment;
1548   guint32 seqnum = GST_SEQNUM_INVALID;
1549   GstEvent *flush_event;
1550   gboolean ret;
1551
1552   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1553
1554   gst_event_parse_seek (event, &rate, &format, &flags,
1555       &cur_type, &cur, &stop_type, &stop);
1556   seqnum = gst_event_get_seqnum (event);
1557
1558   /* we have to have a format as the segment format. Try to convert
1559    * if not. */
1560   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1561           stop_type, &stop))
1562     goto no_format;
1563
1564   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1565
1566   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1567   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1568
1569   /* Directly send the instant-rate-change event here before taking the
1570    * stream-lock so that it can be applied as soon as possible */
1571   if (instant_rate_change) {
1572     GstEvent *ev;
1573
1574     /* instant rate change only supported if direction does not change. All
1575      * other requirements are already checked before creating the seek event
1576      * but let's double-check here to be sure */
1577     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1578         (qtdemux->segment.rate < 0 && rate > 0) ||
1579         cur_type != GST_SEEK_TYPE_NONE ||
1580         stop_type != GST_SEEK_TYPE_NONE || flush) {
1581       GST_ERROR_OBJECT (qtdemux,
1582           "Instant rate change seeks only supported in the "
1583           "same direction, without flushing and position change");
1584       return FALSE;
1585     }
1586
1587     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1588         (GstSegmentFlags) flags);
1589     gst_event_set_seqnum (ev, seqnum);
1590     gst_qtdemux_push_event (qtdemux, ev);
1591     return TRUE;
1592   }
1593
1594   /* stop streaming, either by flushing or by pausing the task */
1595   if (flush) {
1596     flush_event = gst_event_new_flush_start ();
1597     if (seqnum != GST_SEQNUM_INVALID)
1598       gst_event_set_seqnum (flush_event, seqnum);
1599     /* unlock upstream pull_range */
1600     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1601     /* make sure out loop function exits */
1602     gst_qtdemux_push_event (qtdemux, flush_event);
1603   } else {
1604     /* non flushing seek, pause the task */
1605     gst_pad_pause_task (qtdemux->sinkpad);
1606   }
1607
1608   /* wait for streaming to finish */
1609   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1610
1611   /* copy segment, we need this because we still need the old
1612    * segment when we close the current segment. */
1613   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1614
1615   /* configure the segment with the seek variables */
1616   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1617   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1618           cur_type, cur, stop_type, stop, &update)) {
1619     ret = FALSE;
1620     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1621   } else {
1622     /* now do the seek */
1623     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1624   }
1625
1626   /* prepare for streaming again */
1627   if (flush) {
1628     flush_event = gst_event_new_flush_stop (TRUE);
1629     if (seqnum != GST_SEQNUM_INVALID)
1630       gst_event_set_seqnum (flush_event, seqnum);
1631
1632     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1633     gst_qtdemux_push_event (qtdemux, flush_event);
1634   }
1635
1636   /* commit the new segment */
1637   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1638
1639   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1640     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1641         qtdemux->segment.format, qtdemux->segment.position);
1642     if (seqnum != GST_SEQNUM_INVALID)
1643       gst_message_set_seqnum (msg, seqnum);
1644     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1645   }
1646
1647   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1648   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1649       qtdemux->sinkpad, NULL);
1650
1651   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1652
1653   return ret;
1654
1655   /* ERRORS */
1656 no_format:
1657   {
1658     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1659     return FALSE;
1660   }
1661 }
1662
1663 static gboolean
1664 qtdemux_ensure_index (GstQTDemux * qtdemux)
1665 {
1666   guint i;
1667
1668   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1669
1670   /* Build complete index */
1671   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1672     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1673
1674     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1675       GST_LOG_OBJECT (qtdemux,
1676           "Building complete index of track-id %u for seeking failed!",
1677           stream->track_id);
1678       return FALSE;
1679     }
1680   }
1681
1682   return TRUE;
1683 }
1684
1685 static gboolean
1686 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1687     GstEvent * event)
1688 {
1689   gboolean res = TRUE;
1690   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1691
1692   switch (GST_EVENT_TYPE (event)) {
1693     case GST_EVENT_RECONFIGURE:
1694       GST_OBJECT_LOCK (qtdemux);
1695       gst_flow_combiner_reset (qtdemux->flowcombiner);
1696       GST_OBJECT_UNLOCK (qtdemux);
1697       res = gst_pad_event_default (pad, parent, event);
1698       break;
1699     case GST_EVENT_SEEK:
1700     {
1701       GstSeekFlags flags = 0;
1702       GstFormat seek_format;
1703       gboolean instant_rate_change;
1704
1705 #ifndef GST_DISABLE_GST_DEBUG
1706       GstClockTime ts = gst_util_get_timestamp ();
1707 #endif
1708       guint32 seqnum = gst_event_get_seqnum (event);
1709
1710       qtdemux->received_seek = TRUE;
1711
1712       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1713           NULL);
1714       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1715
1716       if (seqnum == qtdemux->segment_seqnum) {
1717         GST_LOG_OBJECT (pad,
1718             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1719         gst_event_unref (event);
1720         return TRUE;
1721       }
1722
1723       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1724         /* seek should be handled by upstream, we might need to re-download fragments */
1725         GST_DEBUG_OBJECT (qtdemux,
1726             "let upstream handle seek for fragmented playback");
1727         goto upstream;
1728       }
1729
1730       if (seek_format == GST_FORMAT_BYTES) {
1731         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1732         gst_event_unref (event);
1733         return FALSE;
1734       }
1735
1736       gst_event_parse_seek_trickmode_interval (event,
1737           &qtdemux->trickmode_interval);
1738
1739       /* Build complete index for seeking;
1740        * if not a fragmented file at least and we're really doing a seek,
1741        * not just an instant-rate-change */
1742       if (!qtdemux->fragmented && !instant_rate_change) {
1743         if (!qtdemux_ensure_index (qtdemux))
1744           goto index_failed;
1745       }
1746 #ifndef GST_DISABLE_GST_DEBUG
1747       ts = gst_util_get_timestamp () - ts;
1748       GST_INFO_OBJECT (qtdemux,
1749           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1750 #endif
1751       if (qtdemux->pullbased) {
1752         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1753       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1754         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1755         res = TRUE;
1756       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1757           && QTDEMUX_N_STREAMS (qtdemux)
1758           && !qtdemux->fragmented) {
1759         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1760       } else {
1761         GST_DEBUG_OBJECT (qtdemux,
1762             "ignoring seek in push mode in current state");
1763         res = FALSE;
1764       }
1765       gst_event_unref (event);
1766     }
1767       break;
1768     default:
1769     upstream:
1770       res = gst_pad_event_default (pad, parent, event);
1771       break;
1772   }
1773
1774 done:
1775   return res;
1776
1777   /* ERRORS */
1778 index_failed:
1779   {
1780     GST_ERROR_OBJECT (qtdemux, "Index failed");
1781     gst_event_unref (event);
1782     res = FALSE;
1783     goto done;
1784   }
1785 }
1786
1787 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1788  *
1789  * If @fw is false, the coding order is explored backwards.
1790  *
1791  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1792  * sample is found for that track.
1793  *
1794  * The stream and sample index of the sample with the minimum offset in the direction explored
1795  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1796  *
1797  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1798  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1799  * @_stream and @_index. */
1800 static void
1801 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1802     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1803 {
1804   gint i, index;
1805   gint64 time, min_time;
1806   QtDemuxStream *stream;
1807   gint iter;
1808
1809   min_time = -1;
1810   stream = NULL;
1811   index = -1;
1812
1813   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1814     QtDemuxStream *str;
1815     gint inc;
1816     gboolean set_sample;
1817
1818     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1819     set_sample = !set;
1820
1821     if (fw) {
1822       i = 0;
1823       inc = 1;
1824     } else {
1825       i = str->n_samples - 1;
1826       inc = -1;
1827     }
1828
1829     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1830       if (str->samples[i].size == 0)
1831         continue;
1832
1833       if (fw && (str->samples[i].offset < byte_pos))
1834         continue;
1835
1836       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1837         continue;
1838
1839       /* move stream to first available sample */
1840       if (set) {
1841         gst_qtdemux_move_stream (qtdemux, str, i);
1842         set_sample = TRUE;
1843       }
1844
1845       /* avoid index from sparse streams since they might be far away */
1846       if (!CUR_STREAM (str)->sparse) {
1847         /* determine min/max time */
1848         time = QTSAMPLE_PTS (str, &str->samples[i]);
1849         if (min_time == -1 || (!fw && time > min_time) ||
1850             (fw && time < min_time)) {
1851           min_time = time;
1852         }
1853
1854         /* determine stream with leading sample, to get its position */
1855         if (!stream ||
1856             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1857             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1858           stream = str;
1859           index = i;
1860         }
1861       }
1862       break;
1863     }
1864
1865     /* no sample for this stream, mark eos */
1866     if (!set_sample)
1867       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1868   }
1869
1870   if (_time)
1871     *_time = min_time;
1872   if (_stream)
1873     *_stream = stream;
1874   if (_index)
1875     *_index = index;
1876 }
1877
1878 /* Copied from mpegtsbase code */
1879 /* FIXME: replace this function when we add new util function for stream-id creation */
1880 static gchar *
1881 _get_upstream_id (GstQTDemux * demux)
1882 {
1883   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1884
1885   if (!upstream_id) {
1886     /* Try to create one from the upstream URI, else use a randome number */
1887     GstQuery *query;
1888     gchar *uri = NULL;
1889
1890     /* Try to generate one from the URI query and
1891      * if it fails take a random number instead */
1892     query = gst_query_new_uri ();
1893     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1894       gst_query_parse_uri (query, &uri);
1895     }
1896
1897     if (uri) {
1898       GChecksum *cs;
1899
1900       /* And then generate an SHA256 sum of the URI */
1901       cs = g_checksum_new (G_CHECKSUM_SHA256);
1902       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1903       g_free (uri);
1904       upstream_id = g_strdup (g_checksum_get_string (cs));
1905       g_checksum_free (cs);
1906     } else {
1907       /* Just get some random number if the URI query fails */
1908       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1909           "implementing a deterministic way of creating a stream-id");
1910       upstream_id =
1911           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1912           g_random_int (), g_random_int ());
1913     }
1914
1915     gst_query_unref (query);
1916   }
1917   return upstream_id;
1918 }
1919
1920 static QtDemuxStream *
1921 _create_stream (GstQTDemux * demux, guint32 track_id)
1922 {
1923   QtDemuxStream *stream;
1924   gchar *upstream_id;
1925
1926   stream = g_new0 (QtDemuxStream, 1);
1927   stream->demux = demux;
1928   stream->track_id = track_id;
1929   upstream_id = _get_upstream_id (demux);
1930   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1931   g_free (upstream_id);
1932   /* new streams always need a discont */
1933   stream->discont = TRUE;
1934   /* we enable clipping for raw audio/video streams */
1935   stream->need_clip = FALSE;
1936   stream->process_func = NULL;
1937   stream->segment_index = -1;
1938   stream->time_position = 0;
1939   stream->sample_index = -1;
1940   stream->offset_in_sample = 0;
1941   stream->new_stream = TRUE;
1942   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1943   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1944   stream->protected = FALSE;
1945   stream->protection_scheme_type = 0;
1946   stream->protection_scheme_version = 0;
1947   stream->protection_scheme_info = NULL;
1948   stream->n_samples_moof = 0;
1949   stream->duration_moof = 0;
1950   stream->duration_last_moof = 0;
1951   stream->alignment = 1;
1952   stream->stream_tags = gst_tag_list_new_empty ();
1953   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1954   g_queue_init (&stream->protection_scheme_event_queue);
1955   stream->ref_count = 1;
1956   /* consistent default for push based mode */
1957   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1958   return stream;
1959 }
1960
1961 static gboolean
1962 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1963 {
1964   GstStructure *structure;
1965   const gchar *variant;
1966   const GstCaps *mediacaps = NULL;
1967
1968   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1969
1970   structure = gst_caps_get_structure (caps, 0);
1971   variant = gst_structure_get_string (structure, "variant");
1972
1973   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1974     QtDemuxStream *stream;
1975     const GValue *value;
1976
1977     demux->fragmented = TRUE;
1978     demux->mss_mode = TRUE;
1979
1980     if (QTDEMUX_N_STREAMS (demux) > 1) {
1981       /* can't do this, we can only renegotiate for another mss format */
1982       return FALSE;
1983     }
1984
1985     value = gst_structure_get_value (structure, "media-caps");
1986     /* create stream */
1987     if (value) {
1988       const GValue *timescale_v;
1989
1990       /* TODO update when stream changes during playback */
1991
1992       if (QTDEMUX_N_STREAMS (demux) == 0) {
1993         stream = _create_stream (demux, 1);
1994         g_ptr_array_add (demux->active_streams, stream);
1995         /* mss has no stsd/stsd entry, use id 0 as default */
1996         stream->stsd_entries_length = 1;
1997         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1998         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1999       } else {
2000         stream = QTDEMUX_NTH_STREAM (demux, 0);
2001       }
2002
2003       timescale_v = gst_structure_get_value (structure, "timescale");
2004       if (timescale_v) {
2005         stream->timescale = g_value_get_uint64 (timescale_v);
2006       } else {
2007         /* default mss timescale */
2008         stream->timescale = 10000000;
2009       }
2010       demux->timescale = stream->timescale;
2011
2012       mediacaps = gst_value_get_caps (value);
2013       if (!CUR_STREAM (stream)->caps
2014           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2015         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2016             mediacaps);
2017         stream->new_caps = TRUE;
2018       }
2019       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2020       structure = gst_caps_get_structure (mediacaps, 0);
2021       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2022         stream->subtype = FOURCC_vide;
2023
2024         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2025         gst_structure_get_int (structure, "height",
2026             &CUR_STREAM (stream)->height);
2027         gst_structure_get_fraction (structure, "framerate",
2028             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2029       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2030         gint rate = 0;
2031         stream->subtype = FOURCC_soun;
2032         gst_structure_get_int (structure, "channels",
2033             &CUR_STREAM (stream)->n_channels);
2034         gst_structure_get_int (structure, "rate", &rate);
2035         CUR_STREAM (stream)->rate = rate;
2036       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
2037         if (gst_structure_has_field (structure, "original-media-type")) {
2038           const gchar *media_type =
2039               gst_structure_get_string (structure, "original-media-type");
2040           if (g_str_has_prefix (media_type, "video")) {
2041             stream->subtype = FOURCC_vide;
2042           } else if (g_str_has_prefix (media_type, "audio")) {
2043             stream->subtype = FOURCC_soun;
2044           }
2045         }
2046       }
2047     }
2048     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2049   } else {
2050     demux->mss_mode = FALSE;
2051   }
2052
2053   return TRUE;
2054 }
2055
2056 static void
2057 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2058 {
2059   gint i;
2060
2061   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2062   gst_pad_stop_task (qtdemux->sinkpad);
2063
2064   if (hard || qtdemux->upstream_format_is_time) {
2065     qtdemux->state = QTDEMUX_STATE_INITIAL;
2066     qtdemux->neededbytes = 16;
2067     qtdemux->todrop = 0;
2068     qtdemux->pullbased = FALSE;
2069     g_clear_pointer (&qtdemux->redirect_location, g_free);
2070     qtdemux->first_mdat = -1;
2071     qtdemux->header_size = 0;
2072     qtdemux->mdatoffset = -1;
2073     qtdemux->restoredata_offset = -1;
2074     if (qtdemux->mdatbuffer)
2075       gst_buffer_unref (qtdemux->mdatbuffer);
2076     if (qtdemux->restoredata_buffer)
2077       gst_buffer_unref (qtdemux->restoredata_buffer);
2078     qtdemux->mdatbuffer = NULL;
2079     qtdemux->restoredata_buffer = NULL;
2080     qtdemux->mdatleft = 0;
2081     qtdemux->mdatsize = 0;
2082     if (qtdemux->comp_brands)
2083       gst_buffer_unref (qtdemux->comp_brands);
2084     qtdemux->comp_brands = NULL;
2085     qtdemux->last_moov_offset = -1;
2086     if (qtdemux->moov_node_compressed) {
2087       g_node_destroy (qtdemux->moov_node_compressed);
2088       if (qtdemux->moov_node)
2089         g_free (qtdemux->moov_node->data);
2090     }
2091     qtdemux->moov_node_compressed = NULL;
2092     if (qtdemux->moov_node)
2093       g_node_destroy (qtdemux->moov_node);
2094     qtdemux->moov_node = NULL;
2095     if (qtdemux->tag_list)
2096       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2097     qtdemux->tag_list = gst_tag_list_new_empty ();
2098     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2099 #if 0
2100     if (qtdemux->element_index)
2101       gst_object_unref (qtdemux->element_index);
2102     qtdemux->element_index = NULL;
2103 #endif
2104     qtdemux->major_brand = 0;
2105     qtdemux->upstream_format_is_time = FALSE;
2106     qtdemux->upstream_seekable = FALSE;
2107     qtdemux->upstream_size = 0;
2108
2109     qtdemux->fragment_start = -1;
2110     qtdemux->fragment_start_offset = -1;
2111     qtdemux->duration = 0;
2112     qtdemux->moof_offset = 0;
2113     qtdemux->chapters_track_id = 0;
2114     qtdemux->have_group_id = FALSE;
2115     qtdemux->group_id = G_MAXUINT;
2116
2117     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2118         NULL);
2119     g_queue_clear (&qtdemux->protection_event_queue);
2120
2121     qtdemux->received_seek = FALSE;
2122     qtdemux->first_moof_already_parsed = FALSE;
2123   }
2124   qtdemux->offset = 0;
2125   gst_adapter_clear (qtdemux->adapter);
2126   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2127   qtdemux->need_segment = TRUE;
2128
2129   if (hard) {
2130     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2131     qtdemux->trickmode_interval = 0;
2132     g_ptr_array_set_size (qtdemux->active_streams, 0);
2133     g_ptr_array_set_size (qtdemux->old_streams, 0);
2134     qtdemux->n_video_streams = 0;
2135     qtdemux->n_audio_streams = 0;
2136     qtdemux->n_sub_streams = 0;
2137     qtdemux->exposed = FALSE;
2138     qtdemux->fragmented = FALSE;
2139     qtdemux->mss_mode = FALSE;
2140     gst_caps_replace (&qtdemux->media_caps, NULL);
2141     qtdemux->timescale = 0;
2142     qtdemux->got_moov = FALSE;
2143     qtdemux->cenc_aux_info_offset = 0;
2144     qtdemux->cenc_aux_info_sizes = NULL;
2145     qtdemux->cenc_aux_sample_count = 0;
2146     if (qtdemux->protection_system_ids) {
2147       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2148       qtdemux->protection_system_ids = NULL;
2149     }
2150     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2151         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2152         GST_BIN_FLAG_STREAMS_AWARE);
2153
2154     if (qtdemux->preferred_protection_system_id) {
2155       g_free (qtdemux->preferred_protection_system_id);
2156       qtdemux->preferred_protection_system_id = NULL;
2157     }
2158   } else if (qtdemux->mss_mode) {
2159     gst_flow_combiner_reset (qtdemux->flowcombiner);
2160     g_ptr_array_foreach (qtdemux->active_streams,
2161         (GFunc) gst_qtdemux_stream_clear, NULL);
2162   } else {
2163     gst_flow_combiner_reset (qtdemux->flowcombiner);
2164     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2165       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2166       stream->sent_eos = FALSE;
2167       stream->time_position = 0;
2168       stream->accumulated_base = 0;
2169       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2170     }
2171   }
2172 }
2173
2174
2175 /* Maps the @segment to the qt edts internal segments and pushes
2176  * the corresponding segment event.
2177  *
2178  * If it ends up being at a empty segment, a gap will be pushed and the next
2179  * edts segment will be activated in sequence.
2180  *
2181  * To be used in push-mode only */
2182 static void
2183 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2184 {
2185   gint i, iter;
2186
2187   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2188     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2189
2190     stream->time_position = segment->start;
2191
2192     /* in push mode we should be guaranteed that we will have empty segments
2193      * at the beginning and then one segment after, other scenarios are not
2194      * supported and are discarded when parsing the edts */
2195     for (i = 0; i < stream->n_segments; i++) {
2196       if (stream->segments[i].stop_time > segment->start) {
2197         /* push the empty segment and move to the next one */
2198         gst_qtdemux_activate_segment (qtdemux, stream, i,
2199             stream->time_position);
2200         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2201           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2202               stream->time_position);
2203
2204           /* accumulate previous segments */
2205           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2206             stream->accumulated_base +=
2207                 (stream->segment.stop -
2208                 stream->segment.start) / ABS (stream->segment.rate);
2209           continue;
2210         }
2211
2212         g_assert (i == stream->n_segments - 1);
2213       }
2214     }
2215   }
2216 }
2217
2218 static void
2219 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2220     GPtrArray * src)
2221 {
2222   guint i;
2223   guint len;
2224
2225   len = src->len;
2226
2227   if (len == 0)
2228     return;
2229
2230   for (i = 0; i < len; i++) {
2231     QtDemuxStream *stream = g_ptr_array_index (src, i);
2232
2233 #ifndef GST_DISABLE_GST_DEBUG
2234     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2235         stream, GST_STR_NULL (stream->stream_id), dest);
2236 #endif
2237     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2238   }
2239
2240   g_ptr_array_set_size (src, 0);
2241 }
2242
2243 static gboolean
2244 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2245     GstEvent * event)
2246 {
2247   GstQTDemux *demux = GST_QTDEMUX (parent);
2248   gboolean res = TRUE;
2249
2250   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2251
2252   switch (GST_EVENT_TYPE (event)) {
2253     case GST_EVENT_SEGMENT:
2254     {
2255       gint64 offset = 0;
2256       QtDemuxStream *stream;
2257       gint idx;
2258       GstSegment segment;
2259
2260       /* some debug output */
2261       gst_event_copy_segment (event, &segment);
2262       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2263           &segment);
2264
2265       if (segment.format == GST_FORMAT_TIME) {
2266         demux->upstream_format_is_time = TRUE;
2267         demux->segment_seqnum = gst_event_get_seqnum (event);
2268       } else {
2269         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2270             "not in time format");
2271
2272         /* chain will send initial newsegment after pads have been added */
2273         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2274           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2275           goto exit;
2276         }
2277       }
2278
2279       /* check if this matches a time seek we received previously
2280        * FIXME for backwards compatibility reasons we use the
2281        * seek_offset here to compare. In the future we might want to
2282        * change this to use the seqnum as it uniquely should identify
2283        * the segment that corresponds to the seek. */
2284       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2285           ", received segment offset %" G_GINT64_FORMAT,
2286           demux->seek_offset, segment.start);
2287       if (segment.format == GST_FORMAT_BYTES
2288           && demux->seek_offset == segment.start) {
2289         GST_OBJECT_LOCK (demux);
2290         offset = segment.start;
2291
2292         segment.format = GST_FORMAT_TIME;
2293         segment.start = demux->push_seek_start;
2294         segment.stop = demux->push_seek_stop;
2295         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2296             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2297             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2298         GST_OBJECT_UNLOCK (demux);
2299       }
2300
2301       /* we only expect a BYTE segment, e.g. following a seek */
2302       if (segment.format == GST_FORMAT_BYTES) {
2303         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2304           offset = segment.start;
2305
2306           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2307               NULL, (gint64 *) & segment.start);
2308           if ((gint64) segment.start < 0)
2309             segment.start = 0;
2310         }
2311         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2312           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2313               NULL, (gint64 *) & segment.stop);
2314           /* keyframe seeking should already arrange for start >= stop,
2315            * but make sure in other rare cases */
2316           segment.stop = MAX (segment.stop, segment.start);
2317         }
2318       } else if (segment.format == GST_FORMAT_TIME) {
2319         /* push all data on the adapter before starting this
2320          * new segment */
2321         gst_qtdemux_process_adapter (demux, TRUE);
2322       } else {
2323         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2324         goto exit;
2325       }
2326
2327       /* We shouldn't modify upstream driven TIME FORMAT segment */
2328       if (!demux->upstream_format_is_time) {
2329         /* accept upstream's notion of segment and distribute along */
2330         segment.format = GST_FORMAT_TIME;
2331         segment.position = segment.time = segment.start;
2332         segment.duration = demux->segment.duration;
2333         segment.base = gst_segment_to_running_time (&demux->segment,
2334             GST_FORMAT_TIME, demux->segment.position);
2335       }
2336
2337       gst_segment_copy_into (&segment, &demux->segment);
2338       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2339
2340       /* map segment to internal qt segments and push on each stream */
2341       if (QTDEMUX_N_STREAMS (demux)) {
2342         demux->need_segment = TRUE;
2343         gst_qtdemux_check_send_pending_segment (demux);
2344       }
2345
2346       /* clear leftover in current segment, if any */
2347       gst_adapter_clear (demux->adapter);
2348
2349       /* set up streaming thread */
2350       demux->offset = offset;
2351       if (demux->upstream_format_is_time) {
2352         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2353             "set values to restart reading from a new atom");
2354         demux->neededbytes = 16;
2355         demux->todrop = 0;
2356       } else {
2357         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2358             NULL);
2359         if (stream) {
2360           demux->todrop = stream->samples[idx].offset - offset;
2361           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2362         } else {
2363           /* set up for EOS */
2364           demux->neededbytes = -1;
2365           demux->todrop = 0;
2366         }
2367       }
2368     exit:
2369       gst_event_unref (event);
2370       res = TRUE;
2371       goto drop;
2372     }
2373     case GST_EVENT_FLUSH_START:
2374     {
2375       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2376         gst_event_unref (event);
2377         goto drop;
2378       }
2379       QTDEMUX_EXPOSE_LOCK (demux);
2380       res = gst_pad_event_default (demux->sinkpad, parent, event);
2381       QTDEMUX_EXPOSE_UNLOCK (demux);
2382       goto drop;
2383     }
2384     case GST_EVENT_FLUSH_STOP:
2385     {
2386       guint64 dur;
2387
2388       dur = demux->segment.duration;
2389       gst_qtdemux_reset (demux, FALSE);
2390       demux->segment.duration = dur;
2391
2392       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2393         gst_event_unref (event);
2394         goto drop;
2395       }
2396       break;
2397     }
2398     case GST_EVENT_EOS:
2399       /* If we are in push mode, and get an EOS before we've seen any streams,
2400        * then error out - we have nowhere to send the EOS */
2401       if (!demux->pullbased) {
2402         gint i;
2403         gboolean has_valid_stream = FALSE;
2404         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2405           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2406             has_valid_stream = TRUE;
2407             break;
2408           }
2409         }
2410         if (!has_valid_stream)
2411           gst_qtdemux_post_no_playable_stream_error (demux);
2412         else {
2413           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2414               (guint) gst_adapter_available (demux->adapter));
2415           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2416             res = FALSE;
2417           }
2418         }
2419       }
2420       break;
2421     case GST_EVENT_CAPS:{
2422       GstCaps *caps = NULL;
2423
2424       gst_event_parse_caps (event, &caps);
2425       gst_qtdemux_setcaps (demux, caps);
2426       res = TRUE;
2427       gst_event_unref (event);
2428       goto drop;
2429     }
2430     case GST_EVENT_PROTECTION:
2431     {
2432       const gchar *system_id = NULL;
2433
2434       gst_event_parse_protection (event, &system_id, NULL, NULL);
2435       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2436           system_id);
2437       gst_qtdemux_append_protection_system_id (demux, system_id);
2438       /* save the event for later, for source pads that have not been created */
2439       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2440       /* send it to all pads that already exist */
2441       gst_qtdemux_push_event (demux, event);
2442       res = TRUE;
2443       goto drop;
2444     }
2445     case GST_EVENT_STREAM_START:
2446     {
2447       res = TRUE;
2448       gst_event_unref (event);
2449
2450       /* Drain all the buffers */
2451       gst_qtdemux_process_adapter (demux, TRUE);
2452       gst_qtdemux_reset (demux, FALSE);
2453       /* We expect new moov box after new stream-start event */
2454       if (demux->exposed) {
2455         gst_qtdemux_stream_concat (demux,
2456             demux->old_streams, demux->active_streams);
2457       }
2458
2459       goto drop;
2460     }
2461     default:
2462       break;
2463   }
2464
2465   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2466
2467 drop:
2468   return res;
2469 }
2470
2471 static gboolean
2472 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2473     GstQuery * query)
2474 {
2475   GstQTDemux *demux = GST_QTDEMUX (parent);
2476   gboolean res = FALSE;
2477
2478   switch (GST_QUERY_TYPE (query)) {
2479     case GST_QUERY_BITRATE:
2480     {
2481       GstClockTime duration;
2482
2483       /* populate demux->upstream_size if not done yet */
2484       gst_qtdemux_check_seekability (demux);
2485
2486       if (demux->upstream_size != -1
2487           && gst_qtdemux_get_duration (demux, &duration)) {
2488         guint bitrate =
2489             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2490             duration);
2491
2492         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2493             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2494             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2495
2496         /* TODO: better results based on ranges/index tables */
2497         gst_query_set_bitrate (query, bitrate);
2498         res = TRUE;
2499       }
2500       break;
2501     }
2502     default:
2503       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2504       break;
2505   }
2506
2507   return res;
2508 }
2509
2510
2511 #if 0
2512 static void
2513 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2514 {
2515   GstQTDemux *demux = GST_QTDEMUX (element);
2516
2517   GST_OBJECT_LOCK (demux);
2518   if (demux->element_index)
2519     gst_object_unref (demux->element_index);
2520   if (index) {
2521     demux->element_index = gst_object_ref (index);
2522   } else {
2523     demux->element_index = NULL;
2524   }
2525   GST_OBJECT_UNLOCK (demux);
2526   /* object lock might be taken again */
2527   if (index)
2528     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2529   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2530       demux->element_index, demux->index_id);
2531 }
2532
2533 static GstIndex *
2534 gst_qtdemux_get_index (GstElement * element)
2535 {
2536   GstIndex *result = NULL;
2537   GstQTDemux *demux = GST_QTDEMUX (element);
2538
2539   GST_OBJECT_LOCK (demux);
2540   if (demux->element_index)
2541     result = gst_object_ref (demux->element_index);
2542   GST_OBJECT_UNLOCK (demux);
2543
2544   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2545
2546   return result;
2547 }
2548 #endif
2549
2550 static void
2551 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2552 {
2553   g_free ((gpointer) stream->stco.data);
2554   stream->stco.data = NULL;
2555   g_free ((gpointer) stream->stsz.data);
2556   stream->stsz.data = NULL;
2557   g_free ((gpointer) stream->stsc.data);
2558   stream->stsc.data = NULL;
2559   g_free ((gpointer) stream->stts.data);
2560   stream->stts.data = NULL;
2561   g_free ((gpointer) stream->stss.data);
2562   stream->stss.data = NULL;
2563   g_free ((gpointer) stream->stps.data);
2564   stream->stps.data = NULL;
2565   g_free ((gpointer) stream->ctts.data);
2566   stream->ctts.data = NULL;
2567 }
2568
2569 static void
2570 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2571 {
2572   g_free (stream->segments);
2573   stream->segments = NULL;
2574   stream->segment_index = -1;
2575   stream->accumulated_base = 0;
2576 }
2577
2578 static void
2579 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2580 {
2581   g_free (stream->samples);
2582   stream->samples = NULL;
2583   gst_qtdemux_stbl_free (stream);
2584
2585   /* fragments */
2586   g_free (stream->ra_entries);
2587   stream->ra_entries = NULL;
2588   stream->n_ra_entries = 0;
2589
2590   stream->sample_index = -1;
2591   stream->stbl_index = -1;
2592   stream->n_samples = 0;
2593   stream->time_position = 0;
2594
2595   stream->n_samples_moof = 0;
2596   stream->duration_moof = 0;
2597   stream->duration_last_moof = 0;
2598 }
2599
2600 static void
2601 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2602 {
2603   gint i;
2604   if (stream->allocator)
2605     gst_object_unref (stream->allocator);
2606   while (stream->buffers) {
2607     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2608     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2609   }
2610   for (i = 0; i < stream->stsd_entries_length; i++) {
2611     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2612     if (entry->rgb8_palette) {
2613       gst_memory_unref (entry->rgb8_palette);
2614       entry->rgb8_palette = NULL;
2615     }
2616     entry->sparse = FALSE;
2617   }
2618
2619   if (stream->stream_tags)
2620     gst_tag_list_unref (stream->stream_tags);
2621
2622   stream->stream_tags = gst_tag_list_new_empty ();
2623   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2624   g_free (stream->redirect_uri);
2625   stream->redirect_uri = NULL;
2626   stream->sent_eos = FALSE;
2627   stream->protected = FALSE;
2628   if (stream->protection_scheme_info) {
2629     if (stream->protection_scheme_type == FOURCC_cenc
2630         || stream->protection_scheme_type == FOURCC_cbcs) {
2631       QtDemuxCencSampleSetInfo *info =
2632           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2633       if (info->default_properties)
2634         gst_structure_free (info->default_properties);
2635       if (info->crypto_info)
2636         g_ptr_array_free (info->crypto_info, TRUE);
2637     }
2638     if (stream->protection_scheme_type == FOURCC_aavd) {
2639       QtDemuxAavdEncryptionInfo *info =
2640           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2641       if (info->default_properties)
2642         gst_structure_free (info->default_properties);
2643     }
2644     g_free (stream->protection_scheme_info);
2645     stream->protection_scheme_info = NULL;
2646   }
2647   stream->protection_scheme_type = 0;
2648   stream->protection_scheme_version = 0;
2649   g_queue_foreach (&stream->protection_scheme_event_queue,
2650       (GFunc) gst_event_unref, NULL);
2651   g_queue_clear (&stream->protection_scheme_event_queue);
2652   gst_qtdemux_stream_flush_segments_data (stream);
2653   gst_qtdemux_stream_flush_samples_data (stream);
2654 }
2655
2656 static void
2657 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2658 {
2659   gint i;
2660   gst_qtdemux_stream_clear (stream);
2661   for (i = 0; i < stream->stsd_entries_length; i++) {
2662     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2663     if (entry->caps) {
2664       gst_caps_unref (entry->caps);
2665       entry->caps = NULL;
2666     }
2667   }
2668   g_free (stream->stsd_entries);
2669   stream->stsd_entries = NULL;
2670   stream->stsd_entries_length = 0;
2671 }
2672
2673 static QtDemuxStream *
2674 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2675 {
2676   g_atomic_int_add (&stream->ref_count, 1);
2677
2678   return stream;
2679 }
2680
2681 static void
2682 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2683 {
2684   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2685     gst_qtdemux_stream_reset (stream);
2686     gst_tag_list_unref (stream->stream_tags);
2687     if (stream->pad) {
2688       GstQTDemux *demux = stream->demux;
2689       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2690       GST_OBJECT_LOCK (demux);
2691       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2692       GST_OBJECT_UNLOCK (demux);
2693     }
2694     g_free (stream->stream_id);
2695     g_free (stream);
2696   }
2697 }
2698
2699 static GstStateChangeReturn
2700 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2701 {
2702   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2703   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2704
2705   switch (transition) {
2706     case GST_STATE_CHANGE_READY_TO_PAUSED:
2707       gst_qtdemux_reset (qtdemux, TRUE);
2708       break;
2709     default:
2710       break;
2711   }
2712
2713   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2714
2715   switch (transition) {
2716     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2717       gst_qtdemux_reset (qtdemux, TRUE);
2718       break;
2719     }
2720     default:
2721       break;
2722   }
2723
2724   return result;
2725 }
2726
2727 static void
2728 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2729 {
2730   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2731
2732   g_return_if_fail (GST_IS_CONTEXT (context));
2733
2734   if (gst_context_has_context_type (context,
2735           "drm-preferred-decryption-system-id")) {
2736     const GstStructure *s;
2737
2738     s = gst_context_get_structure (context);
2739     g_free (qtdemux->preferred_protection_system_id);
2740     qtdemux->preferred_protection_system_id =
2741         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2742     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2743         qtdemux->preferred_protection_system_id);
2744   }
2745
2746   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2747 }
2748
2749 static void
2750 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2751 {
2752   /* counts as header data */
2753   qtdemux->header_size += length;
2754
2755   /* only consider at least a sufficiently complete ftyp atom */
2756   if (length >= 20) {
2757     GstBuffer *buf;
2758
2759     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2760     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2761         GST_FOURCC_ARGS (qtdemux->major_brand));
2762     if (qtdemux->comp_brands)
2763       gst_buffer_unref (qtdemux->comp_brands);
2764     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2765     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2766   }
2767 }
2768
2769 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
2770 static void
2771 _get_int_value_from_xml_string (GstQTDemux * qtdemux,
2772     const char *xml_str, const char *param_name, int *value)
2773 {
2774   char *value_start, *value_end, *endptr;
2775   const short value_length_max = 12;
2776   char init_view_ret[12];
2777   int value_length = 0;
2778   int i = 0;
2779
2780   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2781
2782   if (!value_start) {
2783     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2784         param_name);
2785     return;
2786   }
2787
2788   value_start += strlen (param_name);
2789   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2790     value_start++;
2791
2792   value_end = strchr (value_start, '<');
2793   if (!value_end) {
2794     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2795     return;
2796   }
2797
2798   value_length = value_end - value_start;
2799   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2800           || (value_start[value_length - 1] == '\t')))
2801     value_length--;
2802
2803   if (value_start[i] == '+' || value_start[i] == '-')
2804     i++;
2805   while (i < value_length) {
2806     if (value_start[i] < '0' || value_start[i] > '9') {
2807       GST_ERROR_OBJECT (qtdemux,
2808           "error: incorrect value, integer was expected\n");
2809       return;
2810     }
2811     i++;
2812   }
2813
2814   if (value_length >= value_length_max || value_length < 1) {
2815     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2816     return;
2817   }
2818
2819   strncpy (init_view_ret, value_start, value_length_max);
2820   init_view_ret[value_length] = '\0';
2821
2822   *value = strtol (init_view_ret, &endptr, 10);
2823   if (endptr == init_view_ret) {
2824     GST_ERROR_OBJECT (qtdemux, "error: no digits were found\n");
2825     return;
2826   }
2827
2828   return;
2829 }
2830
2831 static void
2832 _get_string_value_from_xml_string (GstQTDemux * qtdemux,
2833     const char *xml_str, const char *param_name, char **value)
2834 {
2835   char *value_start, *value_end;
2836   const short value_length_max = 256;
2837   int value_length = 0;
2838
2839   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2840
2841   if (!value_start) {
2842     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2843         param_name);
2844     return;
2845   }
2846
2847   value_start += strlen (param_name);
2848   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2849     value_start++;
2850
2851   value_end = strchr (value_start, '<');
2852   if (!value_end) {
2853     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2854     return;
2855   }
2856
2857   value_length = value_end - value_start;
2858   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2859           || (value_start[value_length - 1] == '\t')))
2860     value_length--;
2861
2862   if (value_length >= value_length_max || value_length < 1) {
2863     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2864     return;
2865   }
2866
2867   *value = strndup(value_start, value_length);
2868
2869   return;
2870 }
2871
2872 static void
2873 _get_bool_value_from_xml_string (GstQTDemux * qtdemux,
2874     const char *xml_str, const char *param_name, gboolean * value)
2875 {
2876   char *value_start, *value_end;
2877   int value_length = 0;
2878
2879   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2880
2881   if (!value_start) {
2882     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2883         param_name);
2884     return;
2885   }
2886
2887   value_start += strlen (param_name);
2888   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2889     value_start++;
2890
2891   value_end = strchr (value_start, '<');
2892   if (!value_end) {
2893     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2894     return;
2895   }
2896
2897   value_length = value_end - value_start;
2898   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2899           || (value_start[value_length - 1] == '\t')))
2900     value_length--;
2901
2902   if (value_length < 1) {
2903     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2904     return;
2905   }
2906
2907   *value = g_strstr_len(value_start, value_length, "true") ? TRUE : FALSE;
2908
2909   return;
2910 }
2911
2912 static void
2913 _parse_spatial_video_metadata_from_xml_string (GstQTDemux * qtdemux, const char *xmlStr)
2914 {
2915   const char is_spherical_str[] = "<GSpherical:Spherical>";
2916   const char is_stitched_str[] = "<GSpherical:Stitched>";
2917   const char stitching_software_str[] = "<GSpherical:StitchingSoftware>";
2918   const char projection_type_str[] = "<GSpherical:ProjectionType>";
2919   const char stereo_mode_str[] = "<GSpherical:StereoMode>";
2920   const char source_count_str[] = "<GSpherical:SourceCount>";
2921   const char init_view_heading_str[] = "<GSpherical:InitialViewHeadingDegrees>";
2922   const char init_view_pitch_str[] = "<GSpherical:InitialViewPitchDegrees>";
2923   const char init_view_roll_str[] = "<GSpherical:InitialViewRollDegrees>";
2924   const char timestamp_str[] = "<GSpherical:Timestamp>";
2925   const char full_pano_width_str[] = "<GSpherical:FullPanoWidthPixels>";
2926   const char full_pano_height_str[] = "<GSpherical:FullPanoHeightPixels>";
2927   const char cropped_area_image_width_str[] =
2928       "<GSpherical:CroppedAreaImageWidthPixels>";
2929   const char cropped_area_image_height_str[] =
2930       "<GSpherical:CroppedAreaImageHeightPixels>";
2931   const char cropped_area_left_str[] = "<GSpherical:CroppedAreaLeftPixels>";
2932   const char cropped_area_top_str[] = "<GSpherical:CroppedAreaTopPixels>";
2933
2934   QtDemuxSphericalMetadata * spherical_metadata = qtdemux->spherical_metadata;
2935
2936   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_spherical_str,
2937       (gboolean *) & spherical_metadata->is_spherical);
2938   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_stitched_str,
2939       (gboolean *) & spherical_metadata->is_stitched);
2940
2941   if (spherical_metadata->is_spherical && spherical_metadata->is_stitched) {
2942     _get_string_value_from_xml_string (qtdemux, xmlStr,
2943         stitching_software_str, &spherical_metadata->stitching_software);
2944     _get_string_value_from_xml_string (qtdemux, xmlStr,
2945         projection_type_str, &spherical_metadata->projection_type);
2946     _get_string_value_from_xml_string (qtdemux, xmlStr, stereo_mode_str,
2947         &spherical_metadata->stereo_mode);
2948     _get_int_value_from_xml_string (qtdemux, xmlStr, source_count_str,
2949         &spherical_metadata->source_count);
2950     _get_int_value_from_xml_string (qtdemux, xmlStr,
2951         init_view_heading_str, &spherical_metadata->init_view_heading);
2952     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_pitch_str,
2953         &spherical_metadata->init_view_pitch);
2954     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_roll_str,
2955         &spherical_metadata->init_view_roll);
2956     _get_int_value_from_xml_string (qtdemux, xmlStr, timestamp_str,
2957         &spherical_metadata->timestamp);
2958     _get_int_value_from_xml_string (qtdemux, xmlStr, full_pano_width_str,
2959         &spherical_metadata->full_pano_width_pixels);
2960     _get_int_value_from_xml_string (qtdemux, xmlStr,
2961         full_pano_height_str, &spherical_metadata->full_pano_height_pixels);
2962     _get_int_value_from_xml_string (qtdemux, xmlStr,
2963         cropped_area_image_width_str,
2964         &spherical_metadata->cropped_area_image_width);
2965     _get_int_value_from_xml_string (qtdemux, xmlStr,
2966         cropped_area_image_height_str,
2967         &spherical_metadata->cropped_area_image_height);
2968     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_left_str,
2969         &spherical_metadata->cropped_area_left);
2970     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_top_str,
2971         &spherical_metadata->cropped_area_top);
2972   }
2973
2974   return;
2975 }
2976
2977 static void
2978 gst_tag_register_spherical_tags (void) {
2979   gst_tag_register ("is_spherical", GST_TAG_FLAG_META,
2980       G_TYPE_INT,
2981       _("tag-spherical"),
2982       _("Flag indicating if the video is a spherical video"),
2983       NULL);
2984   gst_tag_register ("is_stitched", GST_TAG_FLAG_META,
2985       G_TYPE_INT,
2986       _("tag-stitched"),
2987       _("Flag indicating if the video is stitched"),
2988       NULL);
2989   gst_tag_register ("stitching_software", GST_TAG_FLAG_META,
2990       G_TYPE_STRING,
2991       _("tag-stitching-software"),
2992       _("Software used to stitch the spherical video"),
2993       NULL);
2994   gst_tag_register ("projection_type", GST_TAG_FLAG_META,
2995       G_TYPE_STRING,
2996       _("tag-projection-type"),
2997       _("Projection type used in the video frames"),
2998       NULL);
2999   gst_tag_register ("stereo_mode", GST_TAG_FLAG_META,
3000       G_TYPE_STRING,
3001       _("tag-stereo-mode"),
3002       _("Description of stereoscopic 3D layout"),
3003       NULL);
3004   gst_tag_register ("source_count", GST_TAG_FLAG_META,
3005       G_TYPE_INT,
3006       _("tag-source-count"),
3007       _("Number of cameras used to create the spherical video"),
3008       NULL);
3009   gst_tag_register ("init_view_heading", GST_TAG_FLAG_META,
3010       G_TYPE_INT,
3011       _("tag-init-view-heading"),
3012       _("The heading angle of the initial view in degrees"),
3013       NULL);
3014   gst_tag_register ("init_view_pitch", GST_TAG_FLAG_META,
3015       G_TYPE_INT,
3016       _("tag-init-view-pitch"),
3017       _("The pitch angle of the initial view in degrees"),
3018       NULL);
3019   gst_tag_register ("init_view_roll", GST_TAG_FLAG_META,
3020       G_TYPE_INT,
3021       _("tag-init-view-roll"),
3022       _("The roll angle of the initial view in degrees"),
3023       NULL);
3024   gst_tag_register ("timestamp", GST_TAG_FLAG_META,
3025       G_TYPE_INT,
3026       _("tag-timestamp"),
3027       _("Epoch timestamp of when the first frame in the video was recorded"),
3028       NULL);
3029   gst_tag_register ("full_pano_width_pixels", GST_TAG_FLAG_META,
3030       G_TYPE_INT,
3031       _("tag-full-pano-width"),
3032       _("Width of the encoded video frame in pixels"),
3033       NULL);
3034   gst_tag_register ("full_pano_height_pixels", GST_TAG_FLAG_META,
3035       G_TYPE_INT,
3036       _("tag-full-pano-height"),
3037       _("Height of the encoded video frame in pixels"),
3038       NULL);
3039   gst_tag_register ("cropped_area_image_width", GST_TAG_FLAG_META,
3040       G_TYPE_INT,
3041       _("tag-cropped-area-image-width"),
3042       _("Width of the video frame to display (e.g. cropping)"),
3043       NULL);
3044   gst_tag_register ("cropped_area_image_height", GST_TAG_FLAG_META,
3045       G_TYPE_INT,
3046       _("tag-cropped-area-image-height"),
3047       _("Height of the video frame to display (e.g. cropping)"),
3048       NULL);
3049   gst_tag_register ("cropped_area_left", GST_TAG_FLAG_META,
3050       G_TYPE_INT,
3051       _("tag-cropped-area-left"),
3052       _("Column where the left edge of the image was cropped from the"
3053           " full sized panorama"),
3054       NULL);
3055   gst_tag_register ("cropped_area_top", GST_TAG_FLAG_META,
3056       G_TYPE_INT,
3057       _("tag-cropped-area-top"),
3058       _("Row where the top edge of the image was cropped from the"
3059           " full sized panorama"),
3060       NULL);
3061   gst_tag_register ("ambisonic_type", GST_TAG_FLAG_META,
3062       G_TYPE_INT,
3063       _("tag-ambisonic-type"),
3064       _("Specifies the type of ambisonic audio represented"),
3065       NULL);
3066   gst_tag_register ("ambisonic_format", GST_TAG_FLAG_META,
3067       G_TYPE_INT,
3068       _("tag-ambisonic-format"),
3069       _("Specifies the ambisonic audio format"),
3070       NULL);
3071   gst_tag_register ("ambisonic_order", GST_TAG_FLAG_META,
3072       G_TYPE_INT,
3073       _("tag-ambisonic-order"),
3074       _("Specifies the ambisonic audio channel order"),
3075       NULL);
3076
3077   return;
3078 }
3079
3080 static void
3081 _send_spherical_metadata_msg_to_bus (GstQTDemux * qtdemux)
3082 {
3083   GstTagList *taglist;
3084   QtDemuxSphericalMetadata *spherical_metadata = qtdemux->spherical_metadata;
3085
3086   GST_DEBUG_OBJECT (qtdemux, "is_spherical = %d",
3087       spherical_metadata->is_spherical);
3088   GST_DEBUG_OBJECT (qtdemux, "is_stitched = %d",
3089       spherical_metadata->is_stitched);
3090   GST_DEBUG_OBJECT (qtdemux, "stitching_software = %s",
3091       spherical_metadata->stitching_software);
3092   GST_DEBUG_OBJECT (qtdemux, "projection_type = %s",
3093       spherical_metadata->projection_type);
3094   GST_DEBUG_OBJECT (qtdemux, "stereo_mode = %s",
3095       spherical_metadata->stereo_mode);
3096   GST_DEBUG_OBJECT (qtdemux, "source_count %d",
3097       spherical_metadata->source_count);
3098   GST_DEBUG_OBJECT (qtdemux, "init_view_heading = %d",
3099       spherical_metadata->init_view_heading);
3100   GST_DEBUG_OBJECT (qtdemux, "init_view_pitch = %d",
3101       spherical_metadata->init_view_pitch);
3102   GST_DEBUG_OBJECT (qtdemux, "init_view_roll = %d",
3103       spherical_metadata->init_view_roll);
3104   GST_DEBUG_OBJECT (qtdemux, "timestamp = %d", spherical_metadata->timestamp);
3105   GST_DEBUG_OBJECT (qtdemux, "full_pano_width_pixels = %d",
3106       spherical_metadata->full_pano_width_pixels);
3107   GST_DEBUG_OBJECT (qtdemux, "full_pano_height_pixels = %d",
3108       spherical_metadata->full_pano_height_pixels);
3109   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_width = %d",
3110       spherical_metadata->cropped_area_image_width);
3111   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_height = %d",
3112       spherical_metadata->cropped_area_image_height);
3113   GST_DEBUG_OBJECT (qtdemux, "cropped_area_left = %d",
3114       spherical_metadata->cropped_area_left);
3115   GST_DEBUG_OBJECT (qtdemux, "cropped_area_top = %d",
3116       spherical_metadata->cropped_area_top);
3117   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type = %d",
3118       spherical_metadata->ambisonic_type);
3119   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order = %d",
3120       spherical_metadata->ambisonic_order);
3121   GST_DEBUG_OBJECT (qtdemux, "ambisonic_format = %d",
3122       spherical_metadata->ambisonic_format);
3123
3124   taglist = gst_tag_list_new_empty ();
3125   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3126       "is_spherical", spherical_metadata->is_spherical,
3127       "is_stitched", spherical_metadata->is_stitched,
3128       "source_count", spherical_metadata->source_count,
3129       "init_view_heading", spherical_metadata->init_view_heading,
3130       "init_view_pitch", spherical_metadata->init_view_pitch,
3131       "init_view_roll", spherical_metadata->init_view_roll,
3132       "timestamp", spherical_metadata->timestamp,
3133       "full_pano_width_pixels", spherical_metadata->full_pano_width_pixels,
3134       "full_pano_height_pixels", spherical_metadata->full_pano_height_pixels,
3135       "cropped_area_image_width", spherical_metadata->cropped_area_image_width,
3136       "cropped_area_image_height", spherical_metadata->cropped_area_image_height,
3137       "cropped_area_left", spherical_metadata->cropped_area_left,
3138       "cropped_area_top", spherical_metadata->cropped_area_top,
3139       "ambisonic_type", spherical_metadata->ambisonic_type,
3140       "ambisonic_format", spherical_metadata->ambisonic_format,
3141       "ambisonic_order", spherical_metadata->ambisonic_order,
3142       NULL);
3143
3144   if (spherical_metadata->stitching_software)
3145     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3146         "stitching_software", spherical_metadata->stitching_software,
3147         NULL);
3148   if (spherical_metadata->projection_type)
3149     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3150         "projection_type", spherical_metadata->projection_type,
3151         NULL);
3152   if (spherical_metadata->stereo_mode)
3153     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3154         "stereo_mode", spherical_metadata->stereo_mode,
3155         NULL);
3156
3157   gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
3158           gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
3159                   gst_tag_list_copy (taglist)));
3160
3161   gst_tag_list_unref(taglist);
3162
3163   return;
3164 }
3165
3166 static void
3167 qtdemux_parse_SA3D (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3168 {
3169   guint offset = 0;
3170
3171   guint8 version = 0;
3172   guint8 ambisonic_type  = 0;
3173   guint32 ambisonic_order = 0;
3174   guint8 ambisonic_channel_ordering = 0;
3175   guint8 ambisonic_normalization = 0;
3176   guint32 num_channels = 0;
3177   guint32 channel_map[49] = { 0 };      /* Up to 6th order */
3178
3179   int i;
3180
3181   GST_DEBUG_OBJECT (qtdemux, "qtdemux_parse_SA3D");
3182
3183   qtdemux->header_size += length;
3184   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3185
3186   if (length <= offset + 16) {
3187     GST_DEBUG_OBJECT (qtdemux, "SA3D atom is too short, skipping");
3188     return;
3189   }
3190
3191   version = QT_UINT8 (buffer + offset);
3192   ambisonic_type = QT_UINT8 (buffer + offset + 1);
3193   ambisonic_order = QT_UINT32 (buffer + offset + 2);
3194   ambisonic_channel_ordering = QT_UINT8 (buffer + offset + 6);
3195   ambisonic_normalization = QT_UINT8 (buffer + offset + 7);
3196   num_channels = QT_UINT32 (buffer + offset + 8);
3197   for (i = 0; i < num_channels; ++i)
3198     channel_map[i] = QT_UINT32 (buffer + offset + 12 + i * 4);
3199
3200   GST_DEBUG_OBJECT (qtdemux, "version: %d", version);
3201   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type: %d", ambisonic_type);
3202   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order: %d", ambisonic_order);
3203   GST_DEBUG_OBJECT (qtdemux, "ambisonic_channel_ordering: %d",
3204       ambisonic_channel_ordering);
3205   GST_DEBUG_OBJECT (qtdemux, "ambisonic_normalization: %d",
3206       ambisonic_normalization);
3207   GST_DEBUG_OBJECT (qtdemux, "num_channels: %d", num_channels);
3208   for (i = 0; i < num_channels; ++i)
3209     GST_DEBUG_OBJECT (qtdemux, "channel_map: %d", channel_map[i]);
3210
3211   if (version == RFC_AMBISONIC_SA3DBOX_VERSION_SUPPORTED) {
3212     if (ambisonic_type == RFC_AMBISONIC_TYPE_PERIPHONIC)
3213       qtdemux->spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_PERIPHONIC;
3214
3215     if (ambisonic_order == RFC_AMBISONIC_ORDER_FOA) {
3216       if (num_channels == 4) {
3217         qtdemux->spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_FOA;
3218
3219         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN)
3220             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D)
3221             && (channel_map[0] == 0) && (channel_map[1] == 1)
3222             && (channel_map[2] == 2) && (channel_map[3] == 3))
3223           qtdemux->spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMBIX;
3224
3225         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA)
3226             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA)
3227             && (channel_map[0] == 0) && (channel_map[1] == 3)
3228             && (channel_map[2] == 1) && (channel_map[3] == 2))
3229           qtdemux->spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMB;
3230       }
3231     }
3232   }
3233
3234   return;
3235 }
3236 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3237
3238 static void
3239 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
3240     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
3241     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
3242     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
3243     const guint8 * constant_iv)
3244 {
3245   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
3246   gst_buffer_fill (kid_buf, 0, kid, 16);
3247   if (info->default_properties)
3248     gst_structure_free (info->default_properties);
3249   info->default_properties =
3250       gst_structure_new ("application/x-cenc",
3251       "iv_size", G_TYPE_UINT, iv_size,
3252       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
3253       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
3254   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
3255       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
3256   gst_buffer_unref (kid_buf);
3257   if (protection_scheme_type == FOURCC_cbcs) {
3258     if (crypt_byte_block != 0 || skip_byte_block != 0) {
3259       gst_structure_set (info->default_properties, "crypt_byte_block",
3260           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
3261           skip_byte_block, NULL);
3262     }
3263     if (constant_iv != NULL) {
3264       GstBuffer *constant_iv_buf =
3265           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
3266       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
3267       gst_structure_set (info->default_properties, "constant_iv_size",
3268           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
3269           NULL);
3270       gst_buffer_unref (constant_iv_buf);
3271     }
3272     gst_structure_set (info->default_properties, "cipher-mode",
3273         G_TYPE_STRING, "cbcs", NULL);
3274   } else {
3275     gst_structure_set (info->default_properties, "cipher-mode",
3276         G_TYPE_STRING, "cenc", NULL);
3277   }
3278 }
3279
3280 static gboolean
3281 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
3282     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
3283 {
3284   guint32 algorithm_id = 0;
3285   const guint8 *kid;
3286   gboolean is_encrypted = TRUE;
3287   guint8 iv_size = 8;
3288
3289   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
3290     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
3291     return FALSE;
3292   }
3293
3294   algorithm_id >>= 8;
3295   if (algorithm_id == 0) {
3296     is_encrypted = FALSE;
3297   } else if (algorithm_id == 1) {
3298     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
3299   } else if (algorithm_id == 2) {
3300     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
3301   }
3302
3303   if (!gst_byte_reader_get_uint8 (br, &iv_size))
3304     return FALSE;
3305
3306   if (!gst_byte_reader_get_data (br, 16, &kid))
3307     return FALSE;
3308
3309   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
3310       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
3311   gst_structure_set (info->default_properties, "piff_algorithm_id",
3312       G_TYPE_UINT, algorithm_id, NULL);
3313   return TRUE;
3314 }
3315
3316
3317 static void
3318 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
3319     guint offset)
3320 {
3321   GstByteReader br;
3322   guint8 version;
3323   guint32 flags = 0;
3324   guint i;
3325   guint iv_size = 8;
3326   QtDemuxStream *stream;
3327   GstStructure *structure;
3328   QtDemuxCencSampleSetInfo *ss_info = NULL;
3329   const gchar *system_id;
3330   gboolean uses_sub_sample_encryption = FALSE;
3331   guint32 sample_count;
3332
3333   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
3334     return;
3335
3336   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
3337
3338   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
3339   if (!gst_structure_has_name (structure, "application/x-cenc")) {
3340     GST_WARNING_OBJECT (qtdemux,
3341         "Attempting PIFF box parsing on an unencrypted stream.");
3342     return;
3343   }
3344
3345   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
3346       G_TYPE_STRING, &system_id, NULL);
3347   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
3348
3349   stream->protected = TRUE;
3350   stream->protection_scheme_type = FOURCC_cenc;
3351
3352   if (!stream->protection_scheme_info)
3353     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
3354
3355   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3356   if (!ss_info->default_properties) {
3357     ss_info->default_properties =
3358         gst_structure_new ("application/x-cenc",
3359         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
3360         NULL);
3361
3362   }
3363
3364   if (ss_info->crypto_info) {
3365     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3366     g_ptr_array_free (ss_info->crypto_info, TRUE);
3367     ss_info->crypto_info = NULL;
3368   }
3369
3370   /* skip UUID */
3371   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
3372
3373   if (!gst_byte_reader_get_uint8 (&br, &version)) {
3374     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
3375     return;
3376   }
3377
3378   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
3379     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
3380     return;
3381   }
3382
3383   if ((flags & 0x000001)) {
3384     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
3385             &br))
3386       return;
3387   } else if ((flags & 0x000002)) {
3388     uses_sub_sample_encryption = TRUE;
3389   }
3390
3391   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
3392           &iv_size)) {
3393     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
3394     return;
3395   }
3396
3397   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
3398     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
3399     return;
3400   }
3401
3402   ss_info->crypto_info =
3403       g_ptr_array_new_full (sample_count,
3404       (GDestroyNotify) qtdemux_gst_structure_free);
3405
3406   for (i = 0; i < sample_count; ++i) {
3407     GstStructure *properties;
3408     guint8 *data;
3409     GstBuffer *buf;
3410
3411     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3412     if (properties == NULL) {
3413       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3414       qtdemux->cenc_aux_sample_count = i;
3415       return;
3416     }
3417
3418     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
3419       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
3420       gst_structure_free (properties);
3421       qtdemux->cenc_aux_sample_count = i;
3422       return;
3423     }
3424     buf = gst_buffer_new_wrapped (data, iv_size);
3425     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3426     gst_buffer_unref (buf);
3427
3428     if (uses_sub_sample_encryption) {
3429       guint16 n_subsamples;
3430       const GValue *kid_buf_value;
3431
3432       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
3433           || n_subsamples == 0) {
3434         GST_ERROR_OBJECT (qtdemux,
3435             "failed to get subsample count for sample %u", i);
3436         gst_structure_free (properties);
3437         qtdemux->cenc_aux_sample_count = i;
3438         return;
3439       }
3440       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3441       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
3442         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3443             i);
3444         gst_structure_free (properties);
3445         qtdemux->cenc_aux_sample_count = i;
3446         return;
3447       }
3448       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3449
3450       kid_buf_value =
3451           gst_structure_get_value (ss_info->default_properties, "kid");
3452
3453       gst_structure_set (properties,
3454           "subsample_count", G_TYPE_UINT, n_subsamples,
3455           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3456       gst_structure_set_value (properties, "kid", kid_buf_value);
3457       gst_buffer_unref (buf);
3458     } else {
3459       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3460     }
3461
3462     g_ptr_array_add (ss_info->crypto_info, properties);
3463   }
3464
3465   qtdemux->cenc_aux_sample_count = sample_count;
3466 }
3467
3468 static void
3469 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3470 {
3471   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
3472     0x97, 0xA9, 0x42, 0xE8,
3473     0x9C, 0x71, 0x99, 0x94,
3474     0x91, 0xE3, 0xAF, 0xAC
3475   };
3476   static const guint8 playready_uuid[] = {
3477     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
3478     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
3479   };
3480
3481   static const guint8 piff_sample_encryption_uuid[] = {
3482     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3483     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3484   };
3485
3486 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
3487   static const guint8 spherical_uuid[] = {
3488     0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
3489     0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd
3490   };
3491 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3492
3493   guint offset;
3494
3495   /* counts as header data */
3496   qtdemux->header_size += length;
3497
3498   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3499
3500   if (length <= offset + 16) {
3501     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3502     return;
3503   }
3504
3505 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
3506   if (memcmp (buffer + offset, spherical_uuid, 16) == 0) {
3507     const char *contents;
3508
3509     GST_DEBUG_OBJECT (qtdemux, "spherical uuid was found");
3510     contents = (char *) (buffer + offset + 16);
3511     GST_DEBUG_OBJECT (qtdemux, "contents: %s\n", contents);
3512
3513     if (qtdemux->spherical_metadata)
3514       _parse_spatial_video_metadata_from_xml_string (qtdemux, contents);
3515
3516     return;
3517   }
3518 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3519
3520   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3521     GstBuffer *buf;
3522     GstTagList *taglist;
3523
3524     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3525         length - offset - 16, NULL);
3526     taglist = gst_tag_list_from_xmp_buffer (buf);
3527     gst_buffer_unref (buf);
3528
3529     /* make sure we have a usable taglist */
3530     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3531
3532     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3533
3534   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3535     int len;
3536     const gunichar2 *s_utf16;
3537     char *contents;
3538
3539     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3540     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3541     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3542     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3543
3544     g_free (contents);
3545
3546     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3547         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3548         (NULL));
3549   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3550     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3551   } else {
3552     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3553         GST_READ_UINT32_LE (buffer + offset),
3554         GST_READ_UINT32_LE (buffer + offset + 4),
3555         GST_READ_UINT32_LE (buffer + offset + 8),
3556         GST_READ_UINT32_LE (buffer + offset + 12));
3557   }
3558 }
3559
3560 static void
3561 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3562 {
3563   GstSidxParser sidx_parser;
3564   GstIsoffParserResult res;
3565   guint consumed;
3566
3567   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3568
3569   res =
3570       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3571       &consumed);
3572   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3573   if (res == GST_ISOFF_QT_PARSER_DONE) {
3574     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3575   }
3576   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3577 }
3578
3579 /* caller verifies at least 8 bytes in buf */
3580 static void
3581 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3582     guint64 * plength, guint32 * pfourcc)
3583 {
3584   guint64 length;
3585   guint32 fourcc;
3586
3587   length = QT_UINT32 (data);
3588   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3589   fourcc = QT_FOURCC (data + 4);
3590   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3591
3592   if (length == 0) {
3593     length = G_MAXUINT64;
3594   } else if (length == 1 && size >= 16) {
3595     /* this means we have an extended size, which is the 64 bit value of
3596      * the next 8 bytes */
3597     length = QT_UINT64 (data + 8);
3598     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3599   }
3600
3601   if (plength)
3602     *plength = length;
3603   if (pfourcc)
3604     *pfourcc = fourcc;
3605 }
3606
3607 static gboolean
3608 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3609 {
3610   guint32 version = 0;
3611   GstClockTime duration = 0;
3612
3613   if (!gst_byte_reader_get_uint32_be (br, &version))
3614     goto failed;
3615
3616   version >>= 24;
3617   if (version == 1) {
3618     if (!gst_byte_reader_get_uint64_be (br, &duration))
3619       goto failed;
3620   } else {
3621     guint32 dur = 0;
3622
3623     if (!gst_byte_reader_get_uint32_be (br, &dur))
3624       goto failed;
3625     duration = dur;
3626   }
3627
3628   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3629   qtdemux->duration = duration;
3630
3631   return TRUE;
3632
3633 failed:
3634   {
3635     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3636     return FALSE;
3637   }
3638 }
3639
3640 static gboolean
3641 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3642     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3643 {
3644   if (!stream->parsed_trex && qtdemux->moov_node) {
3645     GNode *mvex, *trex;
3646     GstByteReader trex_data;
3647
3648     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3649     if (mvex) {
3650       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3651           &trex_data);
3652       while (trex) {
3653         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3654
3655         /* skip version/flags */
3656         if (!gst_byte_reader_skip (&trex_data, 4))
3657           goto next;
3658         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3659           goto next;
3660         if (id != stream->track_id)
3661           goto next;
3662         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3663           goto next;
3664         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3665           goto next;
3666         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3667           goto next;
3668         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3669           goto next;
3670
3671         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3672             "duration %d,  size %d, flags 0x%x", stream->track_id,
3673             dur, size, flags);
3674
3675         stream->parsed_trex = TRUE;
3676         stream->def_sample_description_index = sdi;
3677         stream->def_sample_duration = dur;
3678         stream->def_sample_size = size;
3679         stream->def_sample_flags = flags;
3680
3681       next:
3682         /* iterate all siblings */
3683         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3684             &trex_data);
3685       }
3686     }
3687   }
3688
3689   *ds_duration = stream->def_sample_duration;
3690   *ds_size = stream->def_sample_size;
3691   *ds_flags = stream->def_sample_flags;
3692
3693   /* even then, above values are better than random ... */
3694   if (G_UNLIKELY (!stream->parsed_trex)) {
3695     GST_WARNING_OBJECT (qtdemux,
3696         "failed to find fragment defaults for stream %d", stream->track_id);
3697     return FALSE;
3698   }
3699
3700   return TRUE;
3701 }
3702
3703 /* This method should be called whenever a more accurate duration might
3704  * have been found. It will update all relevant variables if/where needed
3705  */
3706 static void
3707 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3708 {
3709   guint i;
3710   guint64 movdur;
3711   GstClockTime prevdur;
3712
3713   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3714
3715   if (movdur > qtdemux->duration) {
3716     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3717     GST_DEBUG_OBJECT (qtdemux,
3718         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3719         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3720     qtdemux->duration = movdur;
3721     GST_DEBUG_OBJECT (qtdemux,
3722         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3723         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3724         GST_TIME_ARGS (qtdemux->segment.stop));
3725     if (qtdemux->segment.duration == prevdur) {
3726       /* If the current segment has duration/stop identical to previous duration
3727        * update them also (because they were set at that point in time with
3728        * the wrong duration */
3729       /* We convert the value *from* the timescale version to avoid rounding errors */
3730       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3731       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3732       qtdemux->segment.duration = fixeddur;
3733       qtdemux->segment.stop = fixeddur;
3734     }
3735   }
3736
3737   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3738     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3739
3740     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3741     if (movdur > stream->duration) {
3742       GST_DEBUG_OBJECT (qtdemux,
3743           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3744           GST_TIME_ARGS (duration));
3745       stream->duration = movdur;
3746       /* internal duration tracking state has been updated above, so */
3747       /* preserve an open-ended dummy segment rather than repeatedly updating
3748        * it and spamming downstream accordingly with segment events */
3749       /* also mangle the edit list end time when fragmented with a single edit
3750        * list that may only cover any non-fragmented data */
3751       if ((stream->dummy_segment ||
3752               (qtdemux->fragmented && stream->n_segments == 1)) &&
3753           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3754         /* Update all dummy values to new duration */
3755         stream->segments[0].stop_time = duration;
3756         stream->segments[0].duration = duration;
3757         stream->segments[0].media_stop = duration;
3758
3759         /* let downstream know we possibly have a new stop time */
3760         if (stream->segment_index != -1) {
3761           GstClockTime pos;
3762
3763           if (qtdemux->segment.rate >= 0) {
3764             pos = stream->segment.start;
3765           } else {
3766             pos = stream->segment.stop;
3767           }
3768
3769           gst_qtdemux_stream_update_segment (qtdemux, stream,
3770               stream->segment_index, pos, NULL, NULL);
3771         }
3772       }
3773     }
3774   }
3775 }
3776
3777 static gboolean
3778 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3779     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3780     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3781     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3782     gboolean has_tfdt)
3783 {
3784   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3785   guint64 timestamp;
3786   gint32 data_offset = 0;
3787   guint8 version;
3788   guint32 flags = 0, first_flags = 0, samples_count = 0;
3789   gint i;
3790   guint8 *data;
3791   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3792   QtDemuxSample *sample;
3793   gboolean ismv = FALSE;
3794   gint64 initial_offset;
3795   gint32 min_ct = 0;
3796
3797   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3798       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3799       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3800       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3801
3802   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3803     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3804     return TRUE;
3805   }
3806
3807   /* presence of stss or not can't really tell us much,
3808    * and flags and so on tend to be marginally reliable in these files */
3809   if (stream->subtype == FOURCC_soun) {
3810     GST_DEBUG_OBJECT (qtdemux,
3811         "sound track in fragmented file; marking all keyframes");
3812     stream->all_keyframe = TRUE;
3813   }
3814
3815   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3816       !gst_byte_reader_get_uint24_be (trun, &flags))
3817     goto fail;
3818
3819   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3820     goto fail;
3821
3822   if (flags & TR_DATA_OFFSET) {
3823     /* note this is really signed */
3824     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3825       goto fail;
3826     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3827     /* default base offset = first byte of moof */
3828     if (*base_offset == -1) {
3829       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3830       *base_offset = moof_offset;
3831     }
3832     *running_offset = *base_offset + data_offset;
3833   } else {
3834     /* if no offset at all, that would mean data starts at moof start,
3835      * which is a bit wrong and is ismv crappy way, so compensate
3836      * assuming data is in mdat following moof */
3837     if (*base_offset == -1) {
3838       *base_offset = moof_offset + moof_length + 8;
3839       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3840       ismv = TRUE;
3841     }
3842     if (*running_offset == -1)
3843       *running_offset = *base_offset;
3844   }
3845
3846   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3847       *running_offset);
3848   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3849       data_offset, flags, samples_count);
3850
3851   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3852     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3853       GST_DEBUG_OBJECT (qtdemux,
3854           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3855       flags ^= TR_FIRST_SAMPLE_FLAGS;
3856     } else {
3857       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3858         goto fail;
3859       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3860     }
3861   }
3862
3863   /* FIXME ? spec says other bits should also be checked to determine
3864    * entry size (and prefix size for that matter) */
3865   entry_size = 0;
3866   dur_offset = size_offset = 0;
3867   if (flags & TR_SAMPLE_DURATION) {
3868     GST_LOG_OBJECT (qtdemux, "entry duration present");
3869     dur_offset = entry_size;
3870     entry_size += 4;
3871   }
3872   if (flags & TR_SAMPLE_SIZE) {
3873     GST_LOG_OBJECT (qtdemux, "entry size present");
3874     size_offset = entry_size;
3875     entry_size += 4;
3876   }
3877   if (flags & TR_SAMPLE_FLAGS) {
3878     GST_LOG_OBJECT (qtdemux, "entry flags present");
3879     flags_offset = entry_size;
3880     entry_size += 4;
3881   }
3882   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3883     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3884     ct_offset = entry_size;
3885     entry_size += 4;
3886   }
3887
3888   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3889     goto fail;
3890   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3891
3892   if (stream->n_samples + samples_count >=
3893       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3894     goto index_too_big;
3895
3896   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3897       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3898       (stream->n_samples + samples_count) *
3899       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3900
3901   /* create a new array of samples if it's the first sample parsed */
3902   if (stream->n_samples == 0) {
3903     g_assert (stream->samples == NULL);
3904     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3905     /* or try to reallocate it with space enough to insert the new samples */
3906   } else
3907     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3908         stream->n_samples + samples_count);
3909   if (stream->samples == NULL)
3910     goto out_of_memory;
3911
3912   if (qtdemux->fragment_start != -1) {
3913     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3914     qtdemux->fragment_start = -1;
3915   } else {
3916     if (stream->n_samples == 0) {
3917       if (decode_ts > 0) {
3918         timestamp = decode_ts;
3919       } else if (stream->pending_seek != NULL) {
3920         /* if we don't have a timestamp from a tfdt box, we'll use the one
3921          * from the mfra seek table */
3922         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3923             GST_TIME_ARGS (stream->pending_seek->ts));
3924
3925         /* FIXME: this is not fully correct, the timestamp refers to the random
3926          * access sample refered to in the tfra entry, which may not necessarily
3927          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3928         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3929       } else {
3930         timestamp = 0;
3931       }
3932
3933       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3934       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3935           GST_TIME_ARGS (gst_ts));
3936     } else {
3937       /* subsequent fragments extend stream */
3938       timestamp =
3939           stream->samples[stream->n_samples - 1].timestamp +
3940           stream->samples[stream->n_samples - 1].duration;
3941
3942       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3943        * difference (1 sec.) between decode_ts and timestamp, prefer the
3944        * former */
3945       if (has_tfdt && !qtdemux->upstream_format_is_time
3946           && ABSDIFF (decode_ts, timestamp) >
3947           MAX (stream->duration_last_moof / 2,
3948               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3949         GST_INFO_OBJECT (qtdemux,
3950             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3951             ") are significantly different (more than %" GST_TIME_FORMAT
3952             "), using decode_ts",
3953             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3954             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3955             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3956                     MAX (stream->duration_last_moof / 2,
3957                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3958         timestamp = decode_ts;
3959       }
3960
3961       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3962       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3963           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3964     }
3965   }
3966
3967   initial_offset = *running_offset;
3968
3969   sample = stream->samples + stream->n_samples;
3970   for (i = 0; i < samples_count; i++) {
3971     guint32 dur, size, sflags;
3972     gint32 ct;
3973
3974     /* first read sample data */
3975     if (flags & TR_SAMPLE_DURATION) {
3976       dur = QT_UINT32 (data + dur_offset);
3977     } else {
3978       dur = d_sample_duration;
3979     }
3980     if (flags & TR_SAMPLE_SIZE) {
3981       size = QT_UINT32 (data + size_offset);
3982     } else {
3983       size = d_sample_size;
3984     }
3985     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3986       if (i == 0) {
3987         sflags = first_flags;
3988       } else {
3989         sflags = d_sample_flags;
3990       }
3991     } else if (flags & TR_SAMPLE_FLAGS) {
3992       sflags = QT_UINT32 (data + flags_offset);
3993     } else {
3994       sflags = d_sample_flags;
3995     }
3996
3997     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3998       /* Read offsets as signed numbers regardless of trun version as very
3999        * high offsets are unlikely and there are files out there that use
4000        * version=0 truns with negative offsets */
4001       ct = QT_UINT32 (data + ct_offset);
4002
4003       /* FIXME: Set offset to 0 for "no decode samples". This needs
4004        * to be handled in a codec specific manner ideally. */
4005       if (ct == G_MININT32)
4006         ct = 0;
4007     } else {
4008       ct = 0;
4009     }
4010     data += entry_size;
4011
4012     /* fill the sample information */
4013     sample->offset = *running_offset;
4014     sample->pts_offset = ct;
4015     sample->size = size;
4016     sample->timestamp = timestamp;
4017     sample->duration = dur;
4018     /* sample-is-difference-sample */
4019     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
4020      * now idea how it relates to bitfield other than massive LE/BE confusion */
4021     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
4022     *running_offset += size;
4023     timestamp += dur;
4024     stream->duration_moof += dur;
4025     sample++;
4026
4027     if (ct < min_ct)
4028       min_ct = ct;
4029   }
4030
4031   /* Shift PTS/DTS to allow for negative composition offsets while keeping
4032    * A/V sync in place. This is similar to the code handling ctts/cslg in the
4033    * non-fragmented case.
4034    */
4035   if (min_ct < 0)
4036     stream->cslg_shift = -min_ct;
4037   else
4038     stream->cslg_shift = 0;
4039
4040   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
4041       stream->cslg_shift);
4042
4043   /* Update total duration if needed */
4044   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
4045
4046   /* Pre-emptively figure out size of mdat based on trun information.
4047    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
4048    * size, else we will still be able to use this when dealing with gap'ed
4049    * input */
4050   qtdemux->mdatleft = *running_offset - initial_offset;
4051   qtdemux->mdatoffset = initial_offset;
4052   qtdemux->mdatsize = qtdemux->mdatleft;
4053
4054   stream->n_samples += samples_count;
4055   stream->n_samples_moof += samples_count;
4056
4057   if (stream->pending_seek != NULL)
4058     stream->pending_seek = NULL;
4059
4060   return TRUE;
4061
4062 fail:
4063   {
4064     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
4065     return FALSE;
4066   }
4067 out_of_memory:
4068   {
4069     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
4070         stream->n_samples);
4071     return FALSE;
4072   }
4073 index_too_big:
4074   {
4075     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
4076         "be larger than %uMB (broken file?)", stream->n_samples,
4077         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
4078     return FALSE;
4079   }
4080 }
4081
4082 /* find stream with @id */
4083 static inline QtDemuxStream *
4084 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
4085 {
4086   QtDemuxStream *stream;
4087   gint i;
4088
4089   /* check */
4090   if (G_UNLIKELY (!id)) {
4091     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
4092     return NULL;
4093   }
4094
4095   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4096     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4097     if (stream->track_id == id)
4098       return stream;
4099   }
4100   if (qtdemux->mss_mode) {
4101     /* mss should have only 1 stream anyway */
4102     return QTDEMUX_NTH_STREAM (qtdemux, 0);
4103   }
4104
4105   return NULL;
4106 }
4107
4108 static gboolean
4109 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
4110     guint32 * fragment_number)
4111 {
4112   if (!gst_byte_reader_skip (mfhd, 4))
4113     goto fail;
4114   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
4115     goto fail;
4116   return TRUE;
4117 fail:
4118   {
4119     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
4120     return FALSE;
4121   }
4122 }
4123
4124 static gboolean
4125 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
4126     QtDemuxStream ** stream, guint32 * default_sample_duration,
4127     guint32 * default_sample_size, guint32 * default_sample_flags,
4128     gint64 * base_offset)
4129 {
4130   guint32 flags = 0;
4131   guint32 track_id = 0;
4132
4133   if (!gst_byte_reader_skip (tfhd, 1) ||
4134       !gst_byte_reader_get_uint24_be (tfhd, &flags))
4135     goto invalid_track;
4136
4137   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
4138     goto invalid_track;
4139
4140   *stream = qtdemux_find_stream (qtdemux, track_id);
4141   if (G_UNLIKELY (!*stream))
4142     goto unknown_stream;
4143
4144   if (flags & TF_DEFAULT_BASE_IS_MOOF)
4145     *base_offset = qtdemux->moof_offset;
4146
4147   if (flags & TF_BASE_DATA_OFFSET)
4148     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
4149       goto invalid_track;
4150
4151   /* obtain stream defaults */
4152   qtdemux_parse_trex (qtdemux, *stream,
4153       default_sample_duration, default_sample_size, default_sample_flags);
4154
4155   (*stream)->stsd_sample_description_id =
4156       (*stream)->def_sample_description_index - 1;
4157
4158   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
4159     guint32 sample_description_index;
4160     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
4161       goto invalid_track;
4162     (*stream)->stsd_sample_description_id = sample_description_index - 1;
4163   }
4164
4165   if (qtdemux->mss_mode) {
4166     /* mss has no stsd entry */
4167     (*stream)->stsd_sample_description_id = 0;
4168   }
4169
4170   if (flags & TF_DEFAULT_SAMPLE_DURATION)
4171     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
4172       goto invalid_track;
4173
4174   if (flags & TF_DEFAULT_SAMPLE_SIZE)
4175     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
4176       goto invalid_track;
4177
4178   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
4179     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
4180       goto invalid_track;
4181
4182   return TRUE;
4183
4184 invalid_track:
4185   {
4186     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
4187     return FALSE;
4188   }
4189 unknown_stream:
4190   {
4191     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
4192     return TRUE;
4193   }
4194 }
4195
4196 static gboolean
4197 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
4198     guint64 * decode_time)
4199 {
4200   guint32 version = 0;
4201
4202   if (!gst_byte_reader_get_uint32_be (br, &version))
4203     return FALSE;
4204
4205   version >>= 24;
4206   if (version == 1) {
4207     if (!gst_byte_reader_get_uint64_be (br, decode_time))
4208       goto failed;
4209   } else {
4210     guint32 dec_time = 0;
4211     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
4212       goto failed;
4213     *decode_time = dec_time;
4214   }
4215
4216   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
4217       *decode_time);
4218
4219   return TRUE;
4220
4221 failed:
4222   {
4223     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
4224     return FALSE;
4225   }
4226 }
4227
4228 /* Returns a pointer to a GstStructure containing the properties of
4229  * the stream sample identified by @sample_index. The caller must unref
4230  * the returned object after use. Returns NULL if unsuccessful. */
4231 static GstStructure *
4232 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
4233     QtDemuxStream * stream, guint sample_index)
4234 {
4235   QtDemuxCencSampleSetInfo *info = NULL;
4236
4237   g_return_val_if_fail (stream != NULL, NULL);
4238   g_return_val_if_fail (stream->protected, NULL);
4239   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
4240
4241   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4242
4243   /* Currently, cenc properties for groups of samples are not supported, so
4244    * simply return a copy of the default sample properties */
4245   return gst_structure_copy (info->default_properties);
4246 }
4247
4248 /* Parses the sizes of sample auxiliary information contained within a stream,
4249  * as given in a saiz box. Returns array of sample_count guint8 size values,
4250  * or NULL on failure */
4251 static guint8 *
4252 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
4253     GstByteReader * br, guint32 * sample_count)
4254 {
4255   guint32 flags = 0;
4256   guint8 *info_sizes;
4257   guint8 default_info_size;
4258
4259   g_return_val_if_fail (qtdemux != NULL, NULL);
4260   g_return_val_if_fail (stream != NULL, NULL);
4261   g_return_val_if_fail (br != NULL, NULL);
4262   g_return_val_if_fail (sample_count != NULL, NULL);
4263
4264   if (!gst_byte_reader_get_uint32_be (br, &flags))
4265     return NULL;
4266
4267   if (flags & 0x1) {
4268     /* aux_info_type and aux_info_type_parameter are ignored */
4269     if (!gst_byte_reader_skip (br, 8))
4270       return NULL;
4271   }
4272
4273   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
4274     return NULL;
4275   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
4276
4277   if (!gst_byte_reader_get_uint32_be (br, sample_count))
4278     return NULL;
4279   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
4280
4281
4282   if (default_info_size == 0) {
4283     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
4284       return NULL;
4285     }
4286   } else {
4287     info_sizes = g_new (guint8, *sample_count);
4288     memset (info_sizes, default_info_size, *sample_count);
4289   }
4290
4291   return info_sizes;
4292 }
4293
4294 /* Parses the offset of sample auxiliary information contained within a stream,
4295  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
4296 static gboolean
4297 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
4298     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
4299     guint64 * offset)
4300 {
4301   guint8 version = 0;
4302   guint32 flags = 0;
4303   guint32 aux_info_type = 0;
4304   guint32 aux_info_type_parameter = 0;
4305   guint32 entry_count;
4306   guint32 off_32;
4307   guint64 off_64;
4308   const guint8 *aux_info_type_data = NULL;
4309
4310   g_return_val_if_fail (qtdemux != NULL, FALSE);
4311   g_return_val_if_fail (stream != NULL, FALSE);
4312   g_return_val_if_fail (br != NULL, FALSE);
4313   g_return_val_if_fail (offset != NULL, FALSE);
4314
4315   if (!gst_byte_reader_get_uint8 (br, &version))
4316     return FALSE;
4317
4318   if (!gst_byte_reader_get_uint24_be (br, &flags))
4319     return FALSE;
4320
4321   if (flags & 0x1) {
4322
4323     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
4324       return FALSE;
4325     aux_info_type = QT_FOURCC (aux_info_type_data);
4326
4327     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
4328       return FALSE;
4329   } else if (stream->protected) {
4330     aux_info_type = stream->protection_scheme_type;
4331   } else {
4332     aux_info_type = CUR_STREAM (stream)->fourcc;
4333   }
4334
4335   if (info_type)
4336     *info_type = aux_info_type;
4337   if (info_type_parameter)
4338     *info_type_parameter = aux_info_type_parameter;
4339
4340   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
4341       "aux_info_type_parameter:  %#06x",
4342       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
4343
4344   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
4345     return FALSE;
4346
4347   if (entry_count != 1) {
4348     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
4349     return FALSE;
4350   }
4351
4352   if (version == 0) {
4353     if (!gst_byte_reader_get_uint32_be (br, &off_32))
4354       return FALSE;
4355     *offset = (guint64) off_32;
4356   } else {
4357     if (!gst_byte_reader_get_uint64_be (br, &off_64))
4358       return FALSE;
4359     *offset = off_64;
4360   }
4361
4362   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
4363   return TRUE;
4364 }
4365
4366 static void
4367 qtdemux_gst_structure_free (GstStructure * gststructure)
4368 {
4369   if (gststructure) {
4370     gst_structure_free (gststructure);
4371   }
4372 }
4373
4374 /* Parses auxiliary information relating to samples protected using
4375  * Common Encryption (cenc); the format of this information
4376  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
4377  * otherwise. */
4378 static gboolean
4379 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
4380     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
4381 {
4382   QtDemuxCencSampleSetInfo *ss_info = NULL;
4383   guint8 size;
4384   gint i;
4385   GPtrArray *old_crypto_info = NULL;
4386   guint old_entries = 0;
4387
4388   g_return_val_if_fail (qtdemux != NULL, FALSE);
4389   g_return_val_if_fail (stream != NULL, FALSE);
4390   g_return_val_if_fail (br != NULL, FALSE);
4391   g_return_val_if_fail (stream->protected, FALSE);
4392   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
4393
4394   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4395
4396   if (ss_info->crypto_info) {
4397     old_crypto_info = ss_info->crypto_info;
4398     /* Count number of non-null entries remaining at the tail end */
4399     for (i = old_crypto_info->len - 1; i >= 0; i--) {
4400       if (g_ptr_array_index (old_crypto_info, i) == NULL)
4401         break;
4402       old_entries++;
4403     }
4404   }
4405
4406   ss_info->crypto_info =
4407       g_ptr_array_new_full (sample_count + old_entries,
4408       (GDestroyNotify) qtdemux_gst_structure_free);
4409
4410   /* We preserve old entries because we parse the next moof in advance
4411    * of consuming all samples from the previous moof, and otherwise
4412    * we'd discard the corresponding crypto info for the samples
4413    * from the previous fragment. */
4414   if (old_entries) {
4415     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
4416         old_entries);
4417     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
4418       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
4419               i));
4420       g_ptr_array_index (old_crypto_info, i) = NULL;
4421     }
4422   }
4423
4424   if (old_crypto_info) {
4425     /* Everything now belongs to the new array */
4426     g_ptr_array_free (old_crypto_info, TRUE);
4427   }
4428
4429   for (i = 0; i < sample_count; ++i) {
4430     GstStructure *properties;
4431     guint16 n_subsamples = 0;
4432     guint8 *data;
4433     guint iv_size;
4434     GstBuffer *buf;
4435     gboolean could_read_iv;
4436
4437     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
4438     if (properties == NULL) {
4439       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
4440       return FALSE;
4441     }
4442     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
4443       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
4444       gst_structure_free (properties);
4445       return FALSE;
4446     }
4447     could_read_iv =
4448         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
4449     if (could_read_iv) {
4450       buf = gst_buffer_new_wrapped (data, iv_size);
4451       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
4452       gst_buffer_unref (buf);
4453     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
4454       const GValue *constant_iv_size_value =
4455           gst_structure_get_value (properties, "constant_iv_size");
4456       const GValue *constant_iv_value =
4457           gst_structure_get_value (properties, "iv");
4458       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
4459         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
4460         gst_structure_free (properties);
4461         return FALSE;
4462       }
4463       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
4464       gst_structure_remove_field (properties, "constant_iv_size");
4465     } else if (stream->protection_scheme_type == FOURCC_cenc) {
4466       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
4467       gst_structure_free (properties);
4468       return FALSE;
4469     }
4470     size = info_sizes[i];
4471     if (size > iv_size) {
4472       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4473           || !(n_subsamples > 0)) {
4474         gst_structure_free (properties);
4475         GST_ERROR_OBJECT (qtdemux,
4476             "failed to get subsample count for sample %u", i);
4477         return FALSE;
4478       }
4479       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4480       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4481         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4482             i);
4483         gst_structure_free (properties);
4484         return FALSE;
4485       }
4486       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4487       if (!buf) {
4488         gst_structure_free (properties);
4489         return FALSE;
4490       }
4491       gst_structure_set (properties,
4492           "subsample_count", G_TYPE_UINT, n_subsamples,
4493           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4494       gst_buffer_unref (buf);
4495     } else {
4496       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4497     }
4498     g_ptr_array_add (ss_info->crypto_info, properties);
4499   }
4500   return TRUE;
4501 }
4502
4503 /* Converts a UUID in raw byte form to a string representation, as defined in
4504  * RFC 4122. The caller takes ownership of the returned string and is
4505  * responsible for freeing it after use. */
4506 static gchar *
4507 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4508 {
4509   const guint8 *uuid = (const guint8 *) uuid_bytes;
4510
4511   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4512       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4513       uuid[0], uuid[1], uuid[2], uuid[3],
4514       uuid[4], uuid[5], uuid[6], uuid[7],
4515       uuid[8], uuid[9], uuid[10], uuid[11],
4516       uuid[12], uuid[13], uuid[14], uuid[15]);
4517 }
4518
4519 /* Parses a Protection System Specific Header box (pssh), as defined in the
4520  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4521  * information needed by a specific content protection system in order to
4522  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4523  * otherwise. */
4524 static gboolean
4525 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4526 {
4527   gchar *sysid_string;
4528   guint32 pssh_size = QT_UINT32 (node->data);
4529   GstBuffer *pssh = NULL;
4530   GstEvent *event = NULL;
4531   guint32 parent_box_type;
4532   gint i;
4533
4534   if (G_UNLIKELY (pssh_size < 32U)) {
4535     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4536     return FALSE;
4537   }
4538
4539   sysid_string =
4540       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4541
4542   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4543
4544   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4545   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4546       gst_buffer_get_size (pssh));
4547
4548   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4549
4550   /* Push an event containing the pssh box onto the queues of all streams. */
4551   event = gst_event_new_protection (sysid_string, pssh,
4552       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4553   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4554     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4555     GST_TRACE_OBJECT (qtdemux,
4556         "adding protection event for stream %s and system %s",
4557         stream->stream_id, sysid_string);
4558     g_queue_push_tail (&stream->protection_scheme_event_queue,
4559         gst_event_ref (event));
4560   }
4561   g_free (sysid_string);
4562   gst_event_unref (event);
4563   gst_buffer_unref (pssh);
4564   return TRUE;
4565 }
4566
4567 static gboolean
4568 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4569     guint64 moof_offset, QtDemuxStream * stream)
4570 {
4571   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4572   GNode *uuid_node;
4573   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4574   GNode *saiz_node, *saio_node, *pssh_node;
4575   GstByteReader saiz_data, saio_data;
4576   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4577   gint64 base_offset, running_offset;
4578   guint32 frag_num;
4579   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4580
4581   /* NOTE @stream ignored */
4582
4583   moof_node = g_node_new ((guint8 *) buffer);
4584   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4585   qtdemux_node_dump (qtdemux, moof_node);
4586
4587   /* Get fragment number from mfhd and check it's valid */
4588   mfhd_node =
4589       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4590   if (mfhd_node == NULL)
4591     goto missing_mfhd;
4592   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4593     goto fail;
4594   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4595
4596   /* unknown base_offset to start with */
4597   base_offset = running_offset = -1;
4598   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4599   while (traf_node) {
4600     guint64 decode_time = 0;
4601
4602     /* Fragment Header node */
4603     tfhd_node =
4604         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4605         &tfhd_data);
4606     if (!tfhd_node)
4607       goto missing_tfhd;
4608     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4609             &ds_size, &ds_flags, &base_offset))
4610       goto missing_tfhd;
4611
4612     /* The following code assumes at most a single set of sample auxiliary
4613      * data in the fragment (consisting of a saiz box and a corresponding saio
4614      * box); in theory, however, there could be multiple sets of sample
4615      * auxiliary data in a fragment. */
4616     saiz_node =
4617         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4618         &saiz_data);
4619     if (saiz_node) {
4620       guint32 info_type = 0;
4621       guint64 offset = 0;
4622       guint32 info_type_parameter = 0;
4623
4624       g_free (qtdemux->cenc_aux_info_sizes);
4625
4626       qtdemux->cenc_aux_info_sizes =
4627           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4628           &qtdemux->cenc_aux_sample_count);
4629       if (qtdemux->cenc_aux_info_sizes == NULL) {
4630         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4631         goto fail;
4632       }
4633       saio_node =
4634           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4635           &saio_data);
4636       if (!saio_node) {
4637         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4638         g_free (qtdemux->cenc_aux_info_sizes);
4639         qtdemux->cenc_aux_info_sizes = NULL;
4640         goto fail;
4641       }
4642
4643       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4644                   &info_type, &info_type_parameter, &offset))) {
4645         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4646         g_free (qtdemux->cenc_aux_info_sizes);
4647         qtdemux->cenc_aux_info_sizes = NULL;
4648         goto fail;
4649       }
4650       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4651         offset += (guint64) (base_offset - qtdemux->moof_offset);
4652       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4653           && info_type_parameter == 0U) {
4654         GstByteReader br;
4655         if (offset > length) {
4656           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4657           qtdemux->cenc_aux_info_offset = offset;
4658         } else {
4659           gst_byte_reader_init (&br, buffer + offset, length - offset);
4660           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4661                   qtdemux->cenc_aux_info_sizes,
4662                   qtdemux->cenc_aux_sample_count)) {
4663             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4664             g_free (qtdemux->cenc_aux_info_sizes);
4665             qtdemux->cenc_aux_info_sizes = NULL;
4666             goto fail;
4667           }
4668         }
4669       }
4670     }
4671
4672     tfdt_node =
4673         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4674         &tfdt_data);
4675     if (tfdt_node) {
4676       /* We'll use decode_time to interpolate timestamps
4677        * in case the input timestamps are missing */
4678       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4679
4680       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4681           " (%" GST_TIME_FORMAT ")", decode_time,
4682           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4683                   decode_time) : GST_CLOCK_TIME_NONE));
4684
4685       /* Discard the fragment buffer timestamp info to avoid using it.
4686        * Rely on tfdt instead as it is more accurate than the timestamp
4687        * that is fetched from a manifest/playlist and is usually
4688        * less accurate. */
4689       qtdemux->fragment_start = -1;
4690     }
4691
4692     if (G_UNLIKELY (!stream)) {
4693       /* we lost track of offset, we'll need to regain it,
4694        * but can delay complaining until later or avoid doing so altogether */
4695       base_offset = -2;
4696       goto next;
4697     }
4698     if (G_UNLIKELY (base_offset < -1))
4699       goto lost_offset;
4700
4701     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4702
4703     if (!qtdemux->pullbased) {
4704       /* Sample tables can grow enough to be problematic if the system memory
4705        * is very low (e.g. embedded devices) and the videos very long
4706        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4707        * Fortunately, we can easily discard them for each new fragment when
4708        * we know qtdemux will not receive seeks outside of the current fragment.
4709        * adaptivedemux honors this assumption.
4710        * This optimization is also useful for applications that use qtdemux as
4711        * a push-based simple demuxer, like Media Source Extensions. */
4712       gst_qtdemux_stream_flush_samples_data (stream);
4713     }
4714
4715     /* initialise moof sample data */
4716     stream->n_samples_moof = 0;
4717     stream->duration_last_moof = stream->duration_moof;
4718     stream->duration_moof = 0;
4719
4720     /* Track Run node */
4721     trun_node =
4722         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4723         &trun_data);
4724     while (trun_node) {
4725       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4726           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4727           &running_offset, decode_time, (tfdt_node != NULL));
4728       /* iterate all siblings */
4729       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4730           &trun_data);
4731     }
4732
4733     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4734     if (uuid_node) {
4735       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4736       guint32 box_length = QT_UINT32 (uuid_buffer);
4737
4738       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4739     }
4740
4741     /* if no new base_offset provided for next traf,
4742      * base is end of current traf */
4743     base_offset = running_offset;
4744     running_offset = -1;
4745
4746     if (stream->n_samples_moof && stream->duration_moof)
4747       stream->new_caps = TRUE;
4748
4749   next:
4750     /* iterate all siblings */
4751     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4752   }
4753
4754   /* parse any protection system info */
4755   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4756   while (pssh_node) {
4757     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4758     qtdemux_parse_pssh (qtdemux, pssh_node);
4759     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4760   }
4761
4762   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4763       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4764       && min_dts != 0) {
4765     /* Unless the user has explicitly requested another seek, perform an
4766      * internal seek to the time specified in the tfdt.
4767      *
4768      * This way if the user opens a file where the first tfdt is 1 hour
4769      * into the presentation, they will not have to wait 1 hour for run
4770      * time to catch up and actual playback to start. */
4771     gint i;
4772
4773     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4774         "performing an internal seek to %" GST_TIME_FORMAT,
4775         GST_TIME_ARGS (min_dts));
4776
4777     qtdemux->segment.start = min_dts;
4778     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4779
4780     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4781       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4782       stream->time_position = min_dts;
4783     }
4784
4785     /* Before this code was run a segment was already sent when the moov was
4786      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4787      * be emitted after a moov, and we can emit a second segment anyway for
4788      * special cases like this. */
4789     qtdemux->need_segment = TRUE;
4790   }
4791
4792   qtdemux->first_moof_already_parsed = TRUE;
4793
4794   g_node_destroy (moof_node);
4795   return TRUE;
4796
4797 missing_tfhd:
4798   {
4799     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4800     goto fail;
4801   }
4802 missing_mfhd:
4803   {
4804     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4805     goto fail;
4806   }
4807 lost_offset:
4808   {
4809     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4810     goto fail;
4811   }
4812 fail:
4813   {
4814     g_node_destroy (moof_node);
4815     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4816         (_("This file is corrupt and cannot be played.")), (NULL));
4817     return FALSE;
4818   }
4819 }
4820
4821 #if 0
4822 /* might be used if some day we actually use mfra & co
4823  * for random access to fragments,
4824  * but that will require quite some modifications and much less relying
4825  * on a sample array */
4826 #endif
4827
4828 static gboolean
4829 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4830 {
4831   QtDemuxStream *stream;
4832   guint32 ver_flags, track_id, len, num_entries, i;
4833   guint value_size, traf_size, trun_size, sample_size;
4834   guint64 time = 0, moof_offset = 0;
4835 #if 0
4836   GstBuffer *buf = NULL;
4837   GstFlowReturn ret;
4838 #endif
4839   GstByteReader tfra;
4840
4841   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4842
4843   if (!gst_byte_reader_skip (&tfra, 8))
4844     return FALSE;
4845
4846   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4847     return FALSE;
4848
4849   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4850       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4851       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4852     return FALSE;
4853
4854   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4855
4856   stream = qtdemux_find_stream (qtdemux, track_id);
4857   if (stream == NULL)
4858     goto unknown_trackid;
4859
4860   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4861   sample_size = (len & 3) + 1;
4862   trun_size = ((len & 12) >> 2) + 1;
4863   traf_size = ((len & 48) >> 4) + 1;
4864
4865   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4866       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4867
4868   if (num_entries == 0)
4869     goto no_samples;
4870
4871   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4872           value_size + value_size + traf_size + trun_size + sample_size))
4873     goto corrupt_file;
4874
4875   g_free (stream->ra_entries);
4876   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4877   stream->n_ra_entries = num_entries;
4878
4879   for (i = 0; i < num_entries; i++) {
4880     qt_atom_parser_get_offset (&tfra, value_size, &time);
4881     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4882     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4883     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4884     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4885
4886     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4887
4888     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4889         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4890
4891     stream->ra_entries[i].ts = time;
4892     stream->ra_entries[i].moof_offset = moof_offset;
4893
4894     /* don't want to go through the entire file and read all moofs at startup */
4895 #if 0
4896     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4897     if (ret != GST_FLOW_OK)
4898       goto corrupt_file;
4899     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4900         moof_offset, stream);
4901     gst_buffer_unref (buf);
4902 #endif
4903   }
4904
4905   check_update_duration (qtdemux, time);
4906
4907   return TRUE;
4908
4909 /* ERRORS */
4910 unknown_trackid:
4911   {
4912     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4913     return FALSE;
4914   }
4915 corrupt_file:
4916   {
4917     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4918     return FALSE;
4919   }
4920 no_samples:
4921   {
4922     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4923     return FALSE;
4924   }
4925 }
4926
4927 static gboolean
4928 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4929 {
4930   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4931   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4932   GstBuffer *mfro = NULL, *mfra = NULL;
4933   GstFlowReturn flow;
4934   gboolean ret = FALSE;
4935   GNode *mfra_node, *tfra_node;
4936   guint64 mfra_offset = 0;
4937   guint32 fourcc, mfra_size;
4938   gint64 len;
4939
4940   /* query upstream size in bytes */
4941   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4942     goto size_query_failed;
4943
4944   /* mfro box should be at the very end of the file */
4945   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4946   if (flow != GST_FLOW_OK)
4947     goto exit;
4948
4949   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4950
4951   fourcc = QT_FOURCC (mfro_map.data + 4);
4952   if (fourcc != FOURCC_mfro)
4953     goto exit;
4954
4955   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4956   if (mfro_map.size < 16)
4957     goto invalid_mfro_size;
4958
4959   mfra_size = QT_UINT32 (mfro_map.data + 12);
4960   if (mfra_size >= len)
4961     goto invalid_mfra_size;
4962
4963   mfra_offset = len - mfra_size;
4964
4965   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4966       mfra_offset, mfra_size);
4967
4968   /* now get and parse mfra box */
4969   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4970   if (flow != GST_FLOW_OK)
4971     goto broken_file;
4972
4973   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4974
4975   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4976   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4977
4978   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4979
4980   while (tfra_node) {
4981     qtdemux_parse_tfra (qtdemux, tfra_node);
4982     /* iterate all siblings */
4983     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4984   }
4985   g_node_destroy (mfra_node);
4986
4987   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4988   ret = TRUE;
4989
4990 exit:
4991
4992   if (mfro) {
4993     if (mfro_map.memory != NULL)
4994       gst_buffer_unmap (mfro, &mfro_map);
4995     gst_buffer_unref (mfro);
4996   }
4997   if (mfra) {
4998     if (mfra_map.memory != NULL)
4999       gst_buffer_unmap (mfra, &mfra_map);
5000     gst_buffer_unref (mfra);
5001   }
5002   return ret;
5003
5004 /* ERRORS */
5005 size_query_failed:
5006   {
5007     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
5008     goto exit;
5009   }
5010 invalid_mfro_size:
5011   {
5012     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
5013     goto exit;
5014   }
5015 invalid_mfra_size:
5016   {
5017     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
5018     goto exit;
5019   }
5020 broken_file:
5021   {
5022     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
5023     goto exit;
5024   }
5025 }
5026
5027 static guint64
5028 add_offset (guint64 offset, guint64 advance)
5029 {
5030   /* Avoid 64-bit overflow by clamping */
5031   if (offset > G_MAXUINT64 - advance)
5032     return G_MAXUINT64;
5033   return offset + advance;
5034 }
5035
5036 static GstFlowReturn
5037 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
5038 {
5039   guint64 length = 0;
5040   guint32 fourcc = 0;
5041   GstBuffer *buf = NULL;
5042   GstFlowReturn ret = GST_FLOW_OK;
5043   guint64 cur_offset = qtdemux->offset;
5044   GstMapInfo map;
5045
5046   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
5047   if (G_UNLIKELY (ret != GST_FLOW_OK))
5048     goto beach;
5049   gst_buffer_map (buf, &map, GST_MAP_READ);
5050   if (G_LIKELY (map.size >= 8))
5051     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
5052   gst_buffer_unmap (buf, &map);
5053   gst_buffer_unref (buf);
5054
5055   /* maybe we already got most we needed, so only consider this eof */
5056   if (G_UNLIKELY (length == 0)) {
5057     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
5058         (_("Invalid atom size.")),
5059         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
5060             GST_FOURCC_ARGS (fourcc)));
5061     ret = GST_FLOW_EOS;
5062     goto beach;
5063   }
5064
5065   switch (fourcc) {
5066     case FOURCC_moof:
5067       /* record for later parsing when needed */
5068       if (!qtdemux->moof_offset) {
5069         qtdemux->moof_offset = qtdemux->offset;
5070       }
5071       if (qtdemux_pull_mfro_mfra (qtdemux)) {
5072         /* FIXME */
5073       } else {
5074         qtdemux->offset += length;      /* skip moof and keep going */
5075       }
5076       if (qtdemux->got_moov) {
5077         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
5078         ret = GST_FLOW_EOS;
5079         goto beach;
5080       }
5081       break;
5082     case FOURCC_mdat:
5083     case FOURCC_free:
5084     case FOURCC_skip:
5085     case FOURCC_wide:
5086     case FOURCC_PICT:
5087     case FOURCC_pnot:
5088     {
5089       GST_LOG_OBJECT (qtdemux,
5090           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
5091           GST_FOURCC_ARGS (fourcc), cur_offset);
5092       qtdemux->offset = add_offset (qtdemux->offset, length);
5093       break;
5094     }
5095     case FOURCC_moov:
5096     {
5097       GstBuffer *moov = NULL;
5098
5099       if (qtdemux->got_moov) {
5100         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
5101         qtdemux->offset = add_offset (qtdemux->offset, length);
5102         goto beach;
5103       }
5104
5105       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
5106       if (ret != GST_FLOW_OK)
5107         goto beach;
5108       gst_buffer_map (moov, &map, GST_MAP_READ);
5109
5110       if (length != map.size) {
5111         /* Some files have a 'moov' atom at the end of the file which contains
5112          * a terminal 'free' atom where the body of the atom is missing.
5113          * Check for, and permit, this special case.
5114          */
5115         if (map.size >= 8) {
5116           guint8 *final_data = map.data + (map.size - 8);
5117           guint32 final_length = QT_UINT32 (final_data);
5118           guint32 final_fourcc = QT_FOURCC (final_data + 4);
5119
5120           if (final_fourcc == FOURCC_free
5121               && map.size + final_length - 8 == length) {
5122             /* Ok, we've found that special case. Allocate a new buffer with
5123              * that free atom actually present. */
5124             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
5125             gst_buffer_fill (newmoov, 0, map.data, map.size);
5126             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
5127             gst_buffer_unmap (moov, &map);
5128             gst_buffer_unref (moov);
5129             moov = newmoov;
5130             gst_buffer_map (moov, &map, GST_MAP_READ);
5131           }
5132         }
5133       }
5134
5135       if (length != map.size) {
5136         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
5137             (_("This file is incomplete and cannot be played.")),
5138             ("We got less than expected (received %" G_GSIZE_FORMAT
5139                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
5140                 (guint) length, cur_offset));
5141         gst_buffer_unmap (moov, &map);
5142         gst_buffer_unref (moov);
5143         ret = GST_FLOW_ERROR;
5144         goto beach;
5145       }
5146       qtdemux->offset += length;
5147
5148       qtdemux_parse_moov (qtdemux, map.data, length);
5149       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
5150
5151       qtdemux_parse_tree (qtdemux);
5152       if (qtdemux->moov_node_compressed) {
5153         g_node_destroy (qtdemux->moov_node_compressed);
5154         g_free (qtdemux->moov_node->data);
5155       }
5156       qtdemux->moov_node_compressed = NULL;
5157       g_node_destroy (qtdemux->moov_node);
5158       qtdemux->moov_node = NULL;
5159       gst_buffer_unmap (moov, &map);
5160       gst_buffer_unref (moov);
5161       qtdemux->got_moov = TRUE;
5162
5163       break;
5164     }
5165     case FOURCC_ftyp:
5166     {
5167       GstBuffer *ftyp = NULL;
5168
5169       /* extract major brand; might come in handy for ISO vs QT issues */
5170       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
5171       if (ret != GST_FLOW_OK)
5172         goto beach;
5173       qtdemux->offset += length;
5174       gst_buffer_map (ftyp, &map, GST_MAP_READ);
5175       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
5176       gst_buffer_unmap (ftyp, &map);
5177       gst_buffer_unref (ftyp);
5178       break;
5179     }
5180     case FOURCC_uuid:
5181     {
5182       GstBuffer *uuid = NULL;
5183
5184       /* uuid are extension atoms */
5185       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
5186       if (ret != GST_FLOW_OK)
5187         goto beach;
5188       qtdemux->offset += length;
5189       gst_buffer_map (uuid, &map, GST_MAP_READ);
5190       qtdemux_parse_uuid (qtdemux, map.data, map.size);
5191       gst_buffer_unmap (uuid, &map);
5192       gst_buffer_unref (uuid);
5193       break;
5194     }
5195     case FOURCC_sidx:
5196     {
5197       GstBuffer *sidx = NULL;
5198       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
5199       if (ret != GST_FLOW_OK)
5200         goto beach;
5201       qtdemux->offset += length;
5202       gst_buffer_map (sidx, &map, GST_MAP_READ);
5203       qtdemux_parse_sidx (qtdemux, map.data, map.size);
5204       gst_buffer_unmap (sidx, &map);
5205       gst_buffer_unref (sidx);
5206       break;
5207     }
5208     default:
5209     {
5210       GstBuffer *unknown = NULL;
5211
5212       GST_LOG_OBJECT (qtdemux,
5213           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
5214           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
5215           cur_offset);
5216       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
5217       if (ret != GST_FLOW_OK)
5218         goto beach;
5219       gst_buffer_map (unknown, &map, GST_MAP_READ);
5220       GST_MEMDUMP ("Unknown tag", map.data, map.size);
5221       gst_buffer_unmap (unknown, &map);
5222       gst_buffer_unref (unknown);
5223       qtdemux->offset += length;
5224       break;
5225     }
5226   }
5227
5228 beach:
5229   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
5230     /* digested all data, show what we have */
5231 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
5232     if (qtdemux->spherical_metadata)
5233       _send_spherical_metadata_msg_to_bus (qtdemux);
5234 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
5235     qtdemux_prepare_streams (qtdemux);
5236     QTDEMUX_EXPOSE_LOCK (qtdemux);
5237     ret = qtdemux_expose_streams (qtdemux);
5238     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
5239
5240     qtdemux->state = QTDEMUX_STATE_MOVIE;
5241     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
5242         qtdemux->state);
5243     return ret;
5244   }
5245   return ret;
5246 }
5247
5248 /* Seeks to the previous keyframe of the indexed stream and
5249  * aligns other streams with respect to the keyframe timestamp
5250  * of indexed stream. Only called in case of Reverse Playback
5251  */
5252 static GstFlowReturn
5253 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
5254 {
5255   guint32 seg_idx = 0, k_index = 0;
5256   guint32 ref_seg_idx, ref_k_index;
5257   GstClockTime k_pos = 0, last_stop = 0;
5258   QtDemuxSegment *seg = NULL;
5259   QtDemuxStream *ref_str = NULL;
5260   guint64 seg_media_start_mov;  /* segment media start time in mov format */
5261   guint64 target_ts;
5262   gint i;
5263
5264   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
5265    * and finally align all the other streams on that timestamp with their
5266    * respective keyframes */
5267   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
5268     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
5269
5270     /* No candidate yet, take the first stream */
5271     if (!ref_str) {
5272       ref_str = str;
5273       continue;
5274     }
5275
5276     /* So that stream has a segment, we prefer video streams */
5277     if (str->subtype == FOURCC_vide) {
5278       ref_str = str;
5279       break;
5280     }
5281   }
5282
5283   if (G_UNLIKELY (!ref_str)) {
5284     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
5285     goto eos;
5286   }
5287
5288   if (G_UNLIKELY (!ref_str->from_sample)) {
5289     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
5290     goto eos;
5291   }
5292
5293   /* So that stream has been playing from from_sample to to_sample. We will
5294    * get the timestamp of the previous sample and search for a keyframe before
5295    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
5296   if (ref_str->subtype == FOURCC_vide) {
5297     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
5298         ref_str->from_sample - 1, FALSE);
5299   } else {
5300     if (ref_str->from_sample >= 10)
5301       k_index = ref_str->from_sample - 10;
5302     else
5303       k_index = 0;
5304   }
5305
5306   target_ts =
5307       ref_str->samples[k_index].timestamp +
5308       ref_str->samples[k_index].pts_offset;
5309
5310   /* get current segment for that stream */
5311   seg = &ref_str->segments[ref_str->segment_index];
5312   /* Use segment start in original timescale for comparisons */
5313   seg_media_start_mov = seg->trak_media_start;
5314
5315   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
5316       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
5317       k_index, target_ts, seg_media_start_mov,
5318       GST_TIME_ARGS (seg->media_start));
5319
5320   /* Crawl back through segments to find the one containing this I frame */
5321   while (target_ts < seg_media_start_mov) {
5322     GST_DEBUG_OBJECT (qtdemux,
5323         "keyframe position (sample %u) is out of segment %u " " target %"
5324         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
5325         ref_str->segment_index, target_ts, seg_media_start_mov);
5326
5327     if (G_UNLIKELY (!ref_str->segment_index)) {
5328       /* Reached first segment, let's consider it's EOS */
5329       goto eos;
5330     }
5331     ref_str->segment_index--;
5332     seg = &ref_str->segments[ref_str->segment_index];
5333     /* Use segment start in original timescale for comparisons */
5334     seg_media_start_mov = seg->trak_media_start;
5335   }
5336   /* Calculate time position of the keyframe and where we should stop */
5337   k_pos =
5338       QTSTREAMTIME_TO_GSTTIME (ref_str,
5339       target_ts - seg->trak_media_start) + seg->time;
5340   last_stop =
5341       QTSTREAMTIME_TO_GSTTIME (ref_str,
5342       ref_str->samples[ref_str->from_sample].timestamp -
5343       seg->trak_media_start) + seg->time;
5344
5345   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
5346       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
5347       k_index, GST_TIME_ARGS (k_pos));
5348
5349   /* Set last_stop with the keyframe timestamp we pushed of that stream */
5350   qtdemux->segment.position = last_stop;
5351   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
5352       GST_TIME_ARGS (last_stop));
5353
5354   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
5355     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
5356     goto eos;
5357   }
5358
5359   ref_seg_idx = ref_str->segment_index;
5360   ref_k_index = k_index;
5361
5362   /* Align them all on this */
5363   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
5364     guint32 index = 0;
5365     GstClockTime seg_time = 0;
5366     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
5367
5368     /* aligning reference stream again might lead to backing up to yet another
5369      * keyframe (due to timestamp rounding issues),
5370      * potentially putting more load on downstream; so let's try to avoid */
5371     if (str == ref_str) {
5372       seg_idx = ref_seg_idx;
5373       seg = &str->segments[seg_idx];
5374       k_index = ref_k_index;
5375       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
5376           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
5377     } else {
5378       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
5379       GST_DEBUG_OBJECT (qtdemux,
5380           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
5381           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
5382
5383       /* get segment and time in the segment */
5384       seg = &str->segments[seg_idx];
5385       seg_time = k_pos - seg->time;
5386
5387       /* get the media time in the segment.
5388        * No adjustment for empty "filler" segments */
5389       if (seg->media_start != GST_CLOCK_TIME_NONE)
5390         seg_time += seg->media_start;
5391
5392       /* get the index of the sample with media time */
5393       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
5394       GST_DEBUG_OBJECT (qtdemux,
5395           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
5396           GST_TIME_ARGS (seg_time), index);
5397
5398       /* find previous keyframe */
5399       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
5400     }
5401
5402     /* Remember until where we want to go */
5403     str->to_sample = str->from_sample - 1;
5404     /* Define our time position */
5405     target_ts =
5406         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
5407     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
5408     if (seg->media_start != GST_CLOCK_TIME_NONE)
5409       str->time_position -= seg->media_start;
5410
5411     /* Now seek back in time */
5412     gst_qtdemux_move_stream (qtdemux, str, k_index);
5413     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
5414         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
5415         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
5416   }
5417
5418   return GST_FLOW_OK;
5419
5420 eos:
5421   return GST_FLOW_EOS;
5422 }
5423
5424 /*
5425  * Gets the current qt segment start, stop and position for the
5426  * given time offset. This is used in update_segment()
5427  */
5428 static void
5429 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5430     QtDemuxStream * stream, GstClockTime offset,
5431     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5432 {
5433   GstClockTime seg_time;
5434   GstClockTime start, stop, time;
5435   QtDemuxSegment *segment;
5436
5437   segment = &stream->segments[stream->segment_index];
5438
5439   /* get time in this segment */
5440   seg_time = (offset - segment->time) * segment->rate;
5441
5442   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5443       GST_TIME_ARGS (seg_time));
5444
5445   if (G_UNLIKELY (seg_time > segment->duration)) {
5446     GST_LOG_OBJECT (stream->pad,
5447         "seg_time > segment->duration %" GST_TIME_FORMAT,
5448         GST_TIME_ARGS (segment->duration));
5449     seg_time = segment->duration;
5450   }
5451
5452   /* qtdemux->segment.stop is in outside-time-realm, whereas
5453    * segment->media_stop is in track-time-realm.
5454    *
5455    * In order to compare the two, we need to bring segment.stop
5456    * into the track-time-realm
5457    *
5458    * FIXME - does this comment still hold? Don't see any conversion here */
5459
5460   stop = qtdemux->segment.stop;
5461   if (stop == GST_CLOCK_TIME_NONE)
5462     stop = qtdemux->segment.duration;
5463   if (stop == GST_CLOCK_TIME_NONE)
5464     stop = segment->media_stop;
5465   else
5466     stop =
5467         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5468
5469   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5470     start = segment->time + seg_time;
5471     time = offset;
5472     stop = start - seg_time + segment->duration;
5473   } else if (qtdemux->segment.rate >= 0) {
5474     start = MIN (segment->media_start + seg_time, stop);
5475     time = offset;
5476   } else {
5477     if (segment->media_start >= qtdemux->segment.start) {
5478       time = segment->time;
5479     } else {
5480       time = segment->time + (qtdemux->segment.start - segment->media_start);
5481     }
5482
5483     start = MAX (segment->media_start, qtdemux->segment.start);
5484     stop = MIN (segment->media_start + seg_time, stop);
5485   }
5486
5487   *_start = start;
5488   *_stop = stop;
5489   *_time = time;
5490 }
5491
5492 /*
5493  * Updates the qt segment used for the stream and pushes a new segment event
5494  * downstream on this stream's pad.
5495  */
5496 static gboolean
5497 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5498     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5499     GstClockTime * _stop)
5500 {
5501   QtDemuxSegment *segment;
5502   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5503   gdouble rate;
5504   GstEvent *event;
5505
5506   /* update the current segment */
5507   stream->segment_index = seg_idx;
5508
5509   /* get the segment */
5510   segment = &stream->segments[seg_idx];
5511
5512   if (G_UNLIKELY (offset < segment->time)) {
5513     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5514         GST_TIME_ARGS (segment->time));
5515     return FALSE;
5516   }
5517
5518   /* segment lies beyond total indicated duration */
5519   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5520           segment->time > qtdemux->segment.duration)) {
5521     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5522         " < segment->time %" GST_TIME_FORMAT,
5523         GST_TIME_ARGS (qtdemux->segment.duration),
5524         GST_TIME_ARGS (segment->time));
5525     return FALSE;
5526   }
5527
5528   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5529       &start, &stop, &time);
5530
5531   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5532       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5533       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5534
5535   /* combine global rate with that of the segment */
5536   rate = segment->rate * qtdemux->segment.rate;
5537
5538   /* Copy flags from main segment */
5539   stream->segment.flags = qtdemux->segment.flags;
5540
5541   /* update the segment values used for clipping */
5542   stream->segment.offset = qtdemux->segment.offset;
5543   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5544   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5545   stream->segment.rate = rate;
5546   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5547       stream->cslg_shift);
5548   if (stop != -1)
5549     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5550         stream->cslg_shift);
5551   else
5552     stream->segment.stop = stop;
5553   stream->segment.time = time;
5554   stream->segment.position = stream->segment.start;
5555
5556   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5557       &stream->segment);
5558
5559   /* now prepare and send the segment */
5560   if (stream->pad) {
5561     event = gst_event_new_segment (&stream->segment);
5562     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5563       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5564     }
5565     gst_pad_push_event (stream->pad, event);
5566     /* assume we can send more data now */
5567     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5568     /* clear to send tags on this pad now */
5569     gst_qtdemux_push_tags (qtdemux, stream);
5570   }
5571
5572   if (_start)
5573     *_start = start;
5574   if (_stop)
5575     *_stop = stop;
5576
5577   return TRUE;
5578 }
5579
5580 /* activate the given segment number @seg_idx of @stream at time @offset.
5581  * @offset is an absolute global position over all the segments.
5582  *
5583  * This will push out a NEWSEGMENT event with the right values and
5584  * position the stream index to the first decodable sample before
5585  * @offset.
5586  */
5587 static gboolean
5588 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5589     guint32 seg_idx, GstClockTime offset)
5590 {
5591   QtDemuxSegment *segment;
5592   guint32 index, kf_index;
5593   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5594
5595   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5596       seg_idx, GST_TIME_ARGS (offset));
5597
5598   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5599           &start, &stop))
5600     return FALSE;
5601
5602   segment = &stream->segments[stream->segment_index];
5603
5604   /* in the fragmented case, we pick a fragment that starts before our
5605    * desired position and rely on downstream to wait for a keyframe
5606    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5607    * tfra entries tells us which trun/sample the key unit is in, but we don't
5608    * make use of this additional information at the moment) */
5609   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5610     stream->to_sample = G_MAXUINT32;
5611     return TRUE;
5612   } else {
5613     /* well, it will be taken care of below */
5614     qtdemux->fragmented_seek_pending = FALSE;
5615     /* FIXME ideally the do_fragmented_seek can be done right here,
5616      * rather than at loop level
5617      * (which might even allow handling edit lists in a fragmented file) */
5618   }
5619
5620   /* We don't need to look for a sample in push-based */
5621   if (!qtdemux->pullbased)
5622     return TRUE;
5623
5624   /* and move to the keyframe before the indicated media time of the
5625    * segment */
5626   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5627     if (qtdemux->segment.rate >= 0) {
5628       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5629       stream->to_sample = G_MAXUINT32;
5630       GST_DEBUG_OBJECT (stream->pad,
5631           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5632           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5633           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5634     } else {
5635       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5636       stream->to_sample = index;
5637       GST_DEBUG_OBJECT (stream->pad,
5638           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5639           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5640           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5641     }
5642   } else {
5643     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5644         "this is an empty segment");
5645     return TRUE;
5646   }
5647
5648   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5649    * encountered an error and printed a message so we return appropriately */
5650   if (index == -1)
5651     return FALSE;
5652
5653   /* we're at the right spot */
5654   if (index == stream->sample_index) {
5655     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5656     return TRUE;
5657   }
5658
5659   /* find keyframe of the target index */
5660   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5661
5662   /* go back two frames to provide lead-in for non-raw audio decoders */
5663   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5664     guint32 lead_in = 2;
5665     guint32 old_index = kf_index;
5666     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5667
5668     if (gst_structure_has_name (s, "audio/mpeg")) {
5669       gint mpegversion;
5670       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5671           && mpegversion == 1) {
5672         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5673         lead_in = 30;
5674       }
5675     }
5676
5677     kf_index = MAX (kf_index, lead_in) - lead_in;
5678     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5679       GST_DEBUG_OBJECT (stream->pad,
5680           "Moving backwards %u frames to ensure sufficient sound lead-in",
5681           old_index - kf_index);
5682     } else {
5683       kf_index = old_index;
5684     }
5685   }
5686
5687   /* if we move forwards, we don't have to go back to the previous
5688    * keyframe since we already sent that. We can also just jump to
5689    * the keyframe right before the target index if there is one. */
5690   if (index > stream->sample_index) {
5691     /* moving forwards check if we move past a keyframe */
5692     if (kf_index > stream->sample_index) {
5693       GST_DEBUG_OBJECT (stream->pad,
5694           "moving forwards to keyframe at %u "
5695           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5696           kf_index,
5697           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5698           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5699       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5700     } else {
5701       GST_DEBUG_OBJECT (stream->pad,
5702           "moving forwards, keyframe at %u "
5703           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5704           kf_index,
5705           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5706           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5707     }
5708   } else {
5709     GST_DEBUG_OBJECT (stream->pad,
5710         "moving backwards to %sframe at %u "
5711         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5712         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5713         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5714         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5715     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5716   }
5717
5718   return TRUE;
5719 }
5720
5721 /* prepare to get the current sample of @stream, getting essential values.
5722  *
5723  * This function will also prepare and send the segment when needed.
5724  *
5725  * Return FALSE if the stream is EOS.
5726  *
5727  * PULL-BASED
5728  */
5729 static gboolean
5730 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5731     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5732     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5733     gboolean * keyframe)
5734 {
5735   QtDemuxSample *sample;
5736   GstClockTime time_position;
5737   guint32 seg_idx;
5738
5739   g_return_val_if_fail (stream != NULL, FALSE);
5740
5741   time_position = stream->time_position;
5742   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5743     goto eos;
5744
5745   seg_idx = stream->segment_index;
5746   if (G_UNLIKELY (seg_idx == -1)) {
5747     /* find segment corresponding to time_position if we are looking
5748      * for a segment. */
5749     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5750   }
5751
5752   /* different segment, activate it, sample_index will be set. */
5753   if (G_UNLIKELY (stream->segment_index != seg_idx))
5754     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5755
5756   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5757               segments[stream->segment_index]))) {
5758     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5759
5760     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5761         " prepare empty sample");
5762
5763     *empty = TRUE;
5764     *pts = *dts = time_position;
5765     *duration = seg->duration - (time_position - seg->time);
5766
5767     return TRUE;
5768   }
5769
5770   *empty = FALSE;
5771
5772   if (stream->sample_index == -1)
5773     stream->sample_index = 0;
5774
5775   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5776       stream->sample_index, stream->n_samples);
5777
5778   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5779     if (!qtdemux->fragmented)
5780       goto eos;
5781
5782     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5783     do {
5784       GstFlowReturn flow;
5785
5786       GST_OBJECT_LOCK (qtdemux);
5787       flow = qtdemux_add_fragmented_samples (qtdemux);
5788       GST_OBJECT_UNLOCK (qtdemux);
5789
5790       if (flow != GST_FLOW_OK)
5791         goto eos;
5792     }
5793     while (stream->sample_index >= stream->n_samples);
5794   }
5795
5796   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5797     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5798         stream->sample_index);
5799     return FALSE;
5800   }
5801
5802   /* now get the info for the sample we're at */
5803   sample = &stream->samples[stream->sample_index];
5804
5805   *dts = QTSAMPLE_DTS (stream, sample);
5806   *pts = QTSAMPLE_PTS (stream, sample);
5807   *offset = sample->offset;
5808   *size = sample->size;
5809   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5810   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5811
5812   return TRUE;
5813
5814   /* special cases */
5815 eos:
5816   {
5817     stream->time_position = GST_CLOCK_TIME_NONE;
5818     return FALSE;
5819   }
5820 }
5821
5822 /* move to the next sample in @stream.
5823  *
5824  * Moves to the next segment when needed.
5825  */
5826 static void
5827 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5828 {
5829   QtDemuxSample *sample;
5830   QtDemuxSegment *segment;
5831
5832   /* get current segment */
5833   segment = &stream->segments[stream->segment_index];
5834
5835   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5836     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5837     goto next_segment;
5838   }
5839
5840   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5841     /* Mark the stream as EOS */
5842     GST_DEBUG_OBJECT (qtdemux,
5843         "reached max allowed sample %u, mark EOS", stream->to_sample);
5844     stream->time_position = GST_CLOCK_TIME_NONE;
5845     return;
5846   }
5847
5848   /* move to next sample */
5849   stream->sample_index++;
5850   stream->offset_in_sample = 0;
5851
5852   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5853       stream->n_samples);
5854
5855   /* reached the last sample, we need the next segment */
5856   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5857     goto next_segment;
5858
5859   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5860     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5861         stream->sample_index);
5862     return;
5863   }
5864
5865   /* get next sample */
5866   sample = &stream->samples[stream->sample_index];
5867
5868   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5869       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5870       GST_TIME_ARGS (segment->media_stop));
5871
5872   /* see if we are past the segment */
5873   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5874     goto next_segment;
5875
5876   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5877     /* inside the segment, update time_position, looks very familiar to
5878      * GStreamer segments, doesn't it? */
5879     stream->time_position =
5880         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5881   } else {
5882     /* not yet in segment, time does not yet increment. This means
5883      * that we are still prerolling keyframes to the decoder so it can
5884      * decode the first sample of the segment. */
5885     stream->time_position = segment->time;
5886   }
5887   return;
5888
5889   /* move to the next segment */
5890 next_segment:
5891   {
5892     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5893
5894     if (stream->segment_index == stream->n_segments - 1) {
5895       /* are we at the end of the last segment, we're EOS */
5896       stream->time_position = GST_CLOCK_TIME_NONE;
5897     } else {
5898       /* else we're only at the end of the current segment */
5899       stream->time_position = segment->stop_time;
5900     }
5901     /* make sure we select a new segment */
5902
5903     /* accumulate previous segments */
5904     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5905       stream->accumulated_base +=
5906           (stream->segment.stop -
5907           stream->segment.start) / ABS (stream->segment.rate);
5908
5909     stream->segment_index = -1;
5910   }
5911 }
5912
5913 static void
5914 gst_qtdemux_sync_streams (GstQTDemux * demux)
5915 {
5916   gint i;
5917
5918   if (QTDEMUX_N_STREAMS (demux) <= 1)
5919     return;
5920
5921   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5922     QtDemuxStream *stream;
5923     GstClockTime end_time;
5924
5925     stream = QTDEMUX_NTH_STREAM (demux, i);
5926
5927     if (!stream->pad)
5928       continue;
5929
5930     /* TODO advance time on subtitle streams here, if any some day */
5931
5932     /* some clips/trailers may have unbalanced streams at the end,
5933      * so send EOS on shorter stream to prevent stalling others */
5934
5935     /* do not mess with EOS if SEGMENT seeking */
5936     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5937       continue;
5938
5939     if (demux->pullbased) {
5940       /* loop mode is sample time based */
5941       if (!STREAM_IS_EOS (stream))
5942         continue;
5943     } else {
5944       /* push mode is byte position based */
5945       if (stream->n_samples &&
5946           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5947         continue;
5948     }
5949
5950     if (stream->sent_eos)
5951       continue;
5952
5953     /* only act if some gap */
5954     end_time = stream->segments[stream->n_segments - 1].stop_time;
5955     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5956         ", stream end: %" GST_TIME_FORMAT,
5957         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5958     if (GST_CLOCK_TIME_IS_VALID (end_time)
5959         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5960       GstEvent *event;
5961
5962       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5963           GST_PAD_NAME (stream->pad));
5964       stream->sent_eos = TRUE;
5965       event = gst_event_new_eos ();
5966       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5967         gst_event_set_seqnum (event, demux->segment_seqnum);
5968       gst_pad_push_event (stream->pad, event);
5969     }
5970   }
5971 }
5972
5973 /* EOS and NOT_LINKED need to be combined. This means that we return:
5974  *
5975  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5976  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5977  */
5978 static GstFlowReturn
5979 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5980     GstFlowReturn ret)
5981 {
5982   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5983
5984   if (stream->pad)
5985     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5986         ret);
5987   else
5988     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5989
5990   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5991   return ret;
5992 }
5993
5994 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5995  * completely clipped
5996  *
5997  * Should be used only with raw buffers */
5998 static GstBuffer *
5999 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6000     GstBuffer * buf)
6001 {
6002   guint64 start, stop, cstart, cstop, diff;
6003   GstClockTime pts, duration;
6004   gsize size, osize;
6005   gint num_rate, denom_rate;
6006   gint frame_size;
6007   gboolean clip_data;
6008   guint offset;
6009
6010   osize = size = gst_buffer_get_size (buf);
6011   offset = 0;
6012
6013   /* depending on the type, setup the clip parameters */
6014   if (stream->subtype == FOURCC_soun) {
6015     frame_size = CUR_STREAM (stream)->bytes_per_frame;
6016     num_rate = GST_SECOND;
6017     denom_rate = (gint) CUR_STREAM (stream)->rate;
6018     clip_data = TRUE;
6019   } else if (stream->subtype == FOURCC_vide) {
6020     frame_size = size;
6021     num_rate = CUR_STREAM (stream)->fps_n;
6022     denom_rate = CUR_STREAM (stream)->fps_d;
6023     clip_data = FALSE;
6024   } else
6025     goto wrong_type;
6026
6027   if (frame_size <= 0)
6028     goto bad_frame_size;
6029
6030   /* we can only clip if we have a valid pts */
6031   pts = GST_BUFFER_PTS (buf);
6032   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
6033     goto no_pts;
6034
6035   duration = GST_BUFFER_DURATION (buf);
6036
6037   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
6038     duration =
6039         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
6040   }
6041
6042   start = pts;
6043   stop = start + duration;
6044
6045   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
6046               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
6047     goto clipped;
6048
6049   /* see if some clipping happened */
6050   diff = cstart - start;
6051   if (diff > 0) {
6052     pts += diff;
6053     duration -= diff;
6054
6055     if (clip_data) {
6056       /* bring clipped time to samples and to bytes */
6057       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
6058       diff *= frame_size;
6059
6060       GST_DEBUG_OBJECT (qtdemux,
6061           "clipping start to %" GST_TIME_FORMAT " %"
6062           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
6063
6064       offset = diff;
6065       size -= diff;
6066     }
6067   }
6068   diff = stop - cstop;
6069   if (diff > 0) {
6070     duration -= diff;
6071
6072     if (clip_data) {
6073       /* bring clipped time to samples and then to bytes */
6074       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
6075       diff *= frame_size;
6076       GST_DEBUG_OBJECT (qtdemux,
6077           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
6078           " bytes", GST_TIME_ARGS (cstop), diff);
6079       size -= diff;
6080     }
6081   }
6082
6083   if (offset != 0 || size != osize)
6084     gst_buffer_resize (buf, offset, size);
6085
6086   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
6087   GST_BUFFER_PTS (buf) = pts;
6088   GST_BUFFER_DURATION (buf) = duration;
6089
6090   return buf;
6091
6092   /* dropped buffer */
6093 wrong_type:
6094   {
6095     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
6096     return buf;
6097   }
6098 bad_frame_size:
6099   {
6100     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
6101     return buf;
6102   }
6103 no_pts:
6104   {
6105     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
6106     return buf;
6107   }
6108 clipped:
6109   {
6110     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
6111     gst_buffer_unref (buf);
6112     return NULL;
6113   }
6114 }
6115
6116 static GstBuffer *
6117 gst_qtdemux_align_buffer (GstQTDemux * demux,
6118     GstBuffer * buffer, gsize alignment)
6119 {
6120   GstMapInfo map;
6121
6122   gst_buffer_map (buffer, &map, GST_MAP_READ);
6123
6124   if (map.size < sizeof (guintptr)) {
6125     gst_buffer_unmap (buffer, &map);
6126     return buffer;
6127   }
6128
6129   if (((guintptr) map.data) & (alignment - 1)) {
6130     GstBuffer *new_buffer;
6131     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
6132
6133     new_buffer = gst_buffer_new_allocate (NULL,
6134         gst_buffer_get_size (buffer), &params);
6135
6136     /* Copy data "by hand", so ensure alignment is kept: */
6137     gst_buffer_fill (new_buffer, 0, map.data, map.size);
6138
6139     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
6140     GST_DEBUG_OBJECT (demux,
6141         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
6142         alignment);
6143
6144     gst_buffer_unmap (buffer, &map);
6145     gst_buffer_unref (buffer);
6146
6147     return new_buffer;
6148   }
6149
6150   gst_buffer_unmap (buffer, &map);
6151   return buffer;
6152 }
6153
6154 static guint8 *
6155 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
6156     gsize * res)
6157 {
6158   guint8 *storage;
6159   gsize i;
6160
6161   /* We are converting from pairs to triplets */
6162   *res = ccpair_size / 2 * 3;
6163   storage = g_malloc (*res);
6164   for (i = 0; i * 2 < ccpair_size; i += 1) {
6165     /* FIXME: Use line offset 0 as we simply can't know here */
6166     if (field == 1)
6167       storage[i * 3] = 0x80 | 0x00;
6168     else
6169       storage[i * 3] = 0x00 | 0x00;
6170     storage[i * 3 + 1] = ccpair[i * 2];
6171     storage[i * 3 + 2] = ccpair[i * 2 + 1];
6172   }
6173
6174   return storage;
6175 }
6176
6177 static guint8 *
6178 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
6179     gsize * cclen)
6180 {
6181   guint8 *res = NULL;
6182   guint32 atom_length, fourcc;
6183   QtDemuxStreamStsdEntry *stsd_entry;
6184
6185   GST_MEMDUMP ("caption atom", data, size);
6186
6187   /* There might be multiple atoms */
6188
6189   *cclen = 0;
6190   if (size < 8)
6191     goto invalid_cdat;
6192   atom_length = QT_UINT32 (data);
6193   fourcc = QT_FOURCC (data + 4);
6194   if (G_UNLIKELY (atom_length > size || atom_length == 8))
6195     goto invalid_cdat;
6196
6197   GST_DEBUG_OBJECT (stream->pad, "here");
6198
6199   /* Check if we have something compatible */
6200   stsd_entry = CUR_STREAM (stream);
6201   switch (stsd_entry->fourcc) {
6202     case FOURCC_c608:{
6203       guint8 *cdat = NULL, *cdt2 = NULL;
6204       gsize cdat_size = 0, cdt2_size = 0;
6205       /* Should be cdat or cdt2 */
6206       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
6207         GST_WARNING_OBJECT (stream->pad,
6208             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
6209             GST_FOURCC_ARGS (fourcc));
6210         goto invalid_cdat;
6211       }
6212
6213       /* Convert to S334-1 Annex A byte triplet */
6214       if (fourcc == FOURCC_cdat)
6215         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
6216       else
6217         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
6218       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
6219           size, atom_length);
6220
6221       /* Check for another atom ? */
6222       if (size > atom_length + 8) {
6223         guint32 new_atom_length = QT_UINT32 (data + atom_length);
6224         if (size >= atom_length + new_atom_length) {
6225           fourcc = QT_FOURCC (data + atom_length + 4);
6226           if (fourcc == FOURCC_cdat) {
6227             if (cdat == NULL)
6228               cdat =
6229                   convert_to_s334_1a (data + atom_length + 8,
6230                   new_atom_length - 8, 1, &cdat_size);
6231             else
6232               GST_WARNING_OBJECT (stream->pad,
6233                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
6234           } else {
6235             if (cdt2 == NULL)
6236               cdt2 =
6237                   convert_to_s334_1a (data + atom_length + 8,
6238                   new_atom_length - 8, 2, &cdt2_size);
6239             else
6240               GST_WARNING_OBJECT (stream->pad,
6241                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
6242           }
6243         }
6244       }
6245
6246       *cclen = cdat_size + cdt2_size;
6247       res = g_malloc (*cclen);
6248       if (cdat_size)
6249         memcpy (res, cdat, cdat_size);
6250       if (cdt2_size)
6251         memcpy (res + cdat_size, cdt2, cdt2_size);
6252       g_free (cdat);
6253       g_free (cdt2);
6254     }
6255       break;
6256     case FOURCC_c708:
6257       if (fourcc != FOURCC_ccdp) {
6258         GST_WARNING_OBJECT (stream->pad,
6259             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
6260             GST_FOURCC_ARGS (fourcc));
6261         goto invalid_cdat;
6262       }
6263       *cclen = atom_length - 8;
6264       res = g_memdup2 (data + 8, *cclen);
6265       break;
6266     default:
6267       /* Keep this here in case other closed caption formats are added */
6268       g_assert_not_reached ();
6269       break;
6270   }
6271
6272   GST_MEMDUMP ("Output", res, *cclen);
6273   return res;
6274
6275   /* Errors */
6276 invalid_cdat:
6277   GST_WARNING ("[cdat] atom is too small or invalid");
6278   return NULL;
6279 }
6280
6281 /* Handle Closed Caption sample buffers.
6282  * The input buffer metadata must be writable,
6283  * but time/duration etc not yet set and need not be preserved */
6284 static GstBuffer *
6285 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
6286     GstBuffer * buf)
6287 {
6288   GstBuffer *outbuf = NULL;
6289   GstMapInfo map;
6290   guint8 *cc;
6291   gsize cclen = 0;
6292
6293   gst_buffer_map (buf, &map, GST_MAP_READ);
6294
6295   /* empty buffer is sent to terminate previous subtitle */
6296   if (map.size <= 2) {
6297     gst_buffer_unmap (buf, &map);
6298     gst_buffer_unref (buf);
6299     return NULL;
6300   }
6301
6302   /* For closed caption, we need to extract the information from the
6303    * [cdat],[cdt2] or [ccdp] atom */
6304   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
6305   gst_buffer_unmap (buf, &map);
6306   if (cc) {
6307     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
6308     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6309   } else {
6310     /* Conversion failed or there's nothing */
6311   }
6312   gst_buffer_unref (buf);
6313
6314   return outbuf;
6315 }
6316
6317 /* DVD subpicture specific sample handling.
6318  * the input buffer metadata must be writable,
6319  * but time/duration etc not yet set and need not be preserved */
6320 static GstBuffer *
6321 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
6322     GstBuffer * buf)
6323 {
6324   /* send a one time dvd clut event */
6325   if (stream->pending_event && stream->pad)
6326     gst_pad_push_event (stream->pad, stream->pending_event);
6327   stream->pending_event = NULL;
6328
6329   /* empty buffer is sent to terminate previous subtitle */
6330   if (gst_buffer_get_size (buf) <= 2) {
6331     gst_buffer_unref (buf);
6332     return NULL;
6333   }
6334
6335   /* That's all the processing needed for subpictures */
6336   return buf;
6337 }
6338
6339 /* Timed text formats
6340  * the input buffer metadata must be writable,
6341  * but time/duration etc not yet set and need not be preserved */
6342 static GstBuffer *
6343 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
6344     GstBuffer * buf)
6345 {
6346   GstBuffer *outbuf = NULL;
6347   GstMapInfo map;
6348   guint nsize = 0;
6349   gchar *str;
6350
6351   /* not many cases for now */
6352   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
6353           stream->subtype != FOURCC_sbtl)) {
6354     return buf;
6355   }
6356
6357   gst_buffer_map (buf, &map, GST_MAP_READ);
6358
6359   /* empty buffer is sent to terminate previous subtitle */
6360   if (map.size <= 2) {
6361     gst_buffer_unmap (buf, &map);
6362     gst_buffer_unref (buf);
6363     return NULL;
6364   }
6365
6366   nsize = GST_READ_UINT16_BE (map.data);
6367   nsize = MIN (nsize, map.size - 2);
6368
6369   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
6370       nsize, map.size);
6371
6372   /* takes care of UTF-8 validation or UTF-16 recognition,
6373    * no other encoding expected */
6374   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
6375   gst_buffer_unmap (buf, &map);
6376
6377   if (str) {
6378     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
6379     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6380   } else {
6381     /* this should not really happen unless the subtitle is corrupted */
6382   }
6383   gst_buffer_unref (buf);
6384
6385   /* FIXME ? convert optional subsequent style info to markup */
6386
6387   return outbuf;
6388 }
6389
6390 /* WebVTT sample handling according to 14496-30 */
6391 static GstBuffer *
6392 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
6393     GstBuffer * buf)
6394 {
6395   GstBuffer *outbuf = NULL;
6396   GstMapInfo map;
6397
6398   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
6399     g_assert_not_reached ();    /* The buffer must be mappable */
6400   }
6401
6402   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
6403     GstEvent *gap = NULL;
6404     /* Push a gap event */
6405     stream->segment.position = GST_BUFFER_PTS (buf);
6406     gap =
6407         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
6408     gst_pad_push_event (stream->pad, gap);
6409
6410     if (GST_BUFFER_DURATION_IS_VALID (buf))
6411       stream->segment.position += GST_BUFFER_DURATION (buf);
6412   } else {
6413     outbuf =
6414         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
6415         GST_BUFFER_DURATION (buf), map.data, map.size);
6416     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
6417   }
6418
6419   gst_buffer_unmap (buf, &map);
6420   gst_buffer_unref (buf);
6421
6422   return outbuf;
6423 }
6424
6425 static GstFlowReturn
6426 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6427     GstBuffer * buf)
6428 {
6429   GstFlowReturn ret = GST_FLOW_OK;
6430   GstClockTime pts, duration;
6431
6432   if (stream->need_clip)
6433     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6434
6435   if (G_UNLIKELY (buf == NULL))
6436     goto exit;
6437
6438   if (G_UNLIKELY (stream->discont)) {
6439     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6440     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6441     stream->discont = FALSE;
6442   } else {
6443     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6444   }
6445
6446   GST_LOG_OBJECT (qtdemux,
6447       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6448       ", duration %" GST_TIME_FORMAT " on pad %s",
6449       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6450       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6451       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6452
6453   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6454     GstStructure *crypto_info;
6455     QtDemuxAavdEncryptionInfo *info =
6456         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6457
6458     crypto_info = gst_structure_copy (info->default_properties);
6459     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6460       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6461   }
6462
6463   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6464           || stream->protection_scheme_type == FOURCC_cbcs)) {
6465     GstStructure *crypto_info;
6466     QtDemuxCencSampleSetInfo *info =
6467         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6468     gint index;
6469     GstEvent *event;
6470
6471     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6472       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6473           GST_PTR_FORMAT, event);
6474       gst_pad_push_event (stream->pad, event);
6475     }
6476
6477     if (info->crypto_info == NULL) {
6478       if (stream->protection_scheme_type == FOURCC_cbcs) {
6479         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6480         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6481           GST_ERROR_OBJECT (qtdemux,
6482               "failed to attach cbcs metadata to buffer");
6483           qtdemux_gst_structure_free (crypto_info);
6484         } else {
6485           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6486         }
6487       } else {
6488         GST_DEBUG_OBJECT (qtdemux,
6489             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6490       }
6491     } else {
6492       /* The end of the crypto_info array matches our n_samples position,
6493        * so count backward from there */
6494       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6495       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6496         /* steal structure from array */
6497         crypto_info = g_ptr_array_index (info->crypto_info, index);
6498         g_ptr_array_index (info->crypto_info, index) = NULL;
6499         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6500             info->crypto_info->len);
6501         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6502           GST_ERROR_OBJECT (qtdemux,
6503               "failed to attach cenc metadata to buffer");
6504       } else {
6505         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6506             index, stream->sample_index);
6507       }
6508     }
6509   }
6510
6511   if (stream->alignment > 1)
6512     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6513
6514   pts = GST_BUFFER_PTS (buf);
6515   duration = GST_BUFFER_DURATION (buf);
6516
6517   ret = gst_pad_push (stream->pad, buf);
6518
6519   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6520     /* mark position in stream, we'll need this to know when to send GAP event */
6521     stream->segment.position = pts + duration;
6522   }
6523
6524 exit:
6525
6526   return ret;
6527 }
6528
6529 static GstFlowReturn
6530 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6531     GstBuffer * buf)
6532 {
6533   GstFlowReturn ret = GST_FLOW_OK;
6534
6535   if (stream->subtype == FOURCC_clcp
6536       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6537     GstMapInfo map;
6538     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6539     guint n_triplets, i;
6540     guint field1_off = 0, field2_off = 0;
6541
6542     /* We have to split CEA608 buffers so that each outgoing buffer contains
6543      * one byte pair per field according to the framerate of the video track.
6544      *
6545      * If there is only a single byte pair per field we don't have to do
6546      * anything
6547      */
6548
6549     gst_buffer_map (buf, &map, GST_MAP_READ);
6550
6551     n_triplets = map.size / 3;
6552     for (i = 0; i < n_triplets; i++) {
6553       if (map.data[3 * i] & 0x80)
6554         n_field1++;
6555       else
6556         n_field2++;
6557     }
6558
6559     g_assert (n_field1 || n_field2);
6560
6561     /* If there's more than 1 frame we have to split, otherwise we can just
6562      * pass through */
6563     if (n_field1 > 1 || n_field2 > 1) {
6564       n_output_buffers =
6565           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6566           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6567
6568       for (i = 0; i < n_output_buffers; i++) {
6569         GstBuffer *outbuf =
6570             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6571         GstMapInfo outmap;
6572         guint8 *outptr;
6573
6574         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6575         outptr = outmap.data;
6576
6577         if (n_field1) {
6578           gboolean found = FALSE;
6579
6580           while (map.data + field1_off < map.data + map.size) {
6581             if (map.data[field1_off] & 0x80) {
6582               memcpy (outptr, &map.data[field1_off], 3);
6583               field1_off += 3;
6584               found = TRUE;
6585               break;
6586             }
6587             field1_off += 3;
6588           }
6589
6590           if (!found) {
6591             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6592
6593             memcpy (outptr, empty, 3);
6594           }
6595
6596           outptr += 3;
6597         }
6598
6599         if (n_field2) {
6600           gboolean found = FALSE;
6601
6602           while (map.data + field2_off < map.data + map.size) {
6603             if ((map.data[field2_off] & 0x80) == 0) {
6604               memcpy (outptr, &map.data[field2_off], 3);
6605               field2_off += 3;
6606               found = TRUE;
6607               break;
6608             }
6609             field2_off += 3;
6610           }
6611
6612           if (!found) {
6613             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6614
6615             memcpy (outptr, empty, 3);
6616           }
6617
6618           outptr += 3;
6619         }
6620
6621         gst_buffer_unmap (outbuf, &outmap);
6622
6623         GST_BUFFER_PTS (outbuf) =
6624             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6625             GST_SECOND * CUR_STREAM (stream)->fps_d,
6626             CUR_STREAM (stream)->fps_n);
6627         GST_BUFFER_DURATION (outbuf) =
6628             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6629             CUR_STREAM (stream)->fps_n);
6630         GST_BUFFER_OFFSET (outbuf) = -1;
6631         GST_BUFFER_OFFSET_END (outbuf) = -1;
6632
6633         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6634
6635         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6636           break;
6637       }
6638       gst_buffer_unmap (buf, &map);
6639       gst_buffer_unref (buf);
6640     } else {
6641       gst_buffer_unmap (buf, &map);
6642       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6643     }
6644   } else {
6645     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6646   }
6647
6648   return ret;
6649 }
6650
6651 /* Sets a buffer's attributes properly and pushes it downstream.
6652  * Also checks for additional actions and custom processing that may
6653  * need to be done first.
6654  */
6655 static GstFlowReturn
6656 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6657     QtDemuxStream * stream, GstBuffer * buf,
6658     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6659     gboolean keyframe, GstClockTime position, guint64 byte_position)
6660 {
6661   GstFlowReturn ret = GST_FLOW_OK;
6662
6663   /* offset the timestamps according to the edit list */
6664
6665   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6666     gchar *url;
6667     GstMapInfo map;
6668
6669     gst_buffer_map (buf, &map, GST_MAP_READ);
6670     url = g_strndup ((gchar *) map.data, map.size);
6671     gst_buffer_unmap (buf, &map);
6672     if (url != NULL && strlen (url) != 0) {
6673       /* we have RTSP redirect now */
6674       g_free (qtdemux->redirect_location);
6675       qtdemux->redirect_location = g_strdup (url);
6676       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6677           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6678               gst_structure_new ("redirect",
6679                   "new-location", G_TYPE_STRING, url, NULL)));
6680     } else {
6681       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6682           "posting");
6683     }
6684     g_free (url);
6685   }
6686
6687   /* position reporting */
6688   if (qtdemux->segment.rate >= 0) {
6689     qtdemux->segment.position = position;
6690     gst_qtdemux_sync_streams (qtdemux);
6691   }
6692
6693   if (G_UNLIKELY (!stream->pad)) {
6694     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6695     gst_buffer_unref (buf);
6696     goto exit;
6697   }
6698
6699   /* send out pending buffers */
6700   while (stream->buffers) {
6701     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6702
6703     if (G_UNLIKELY (stream->discont)) {
6704       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6705       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6706       stream->discont = FALSE;
6707     } else {
6708       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6709     }
6710
6711     if (stream->alignment > 1)
6712       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6713     gst_pad_push (stream->pad, buffer);
6714
6715     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6716   }
6717
6718   /* we're going to modify the metadata */
6719   buf = gst_buffer_make_writable (buf);
6720
6721   GST_BUFFER_DTS (buf) = dts;
6722   GST_BUFFER_PTS (buf) = pts;
6723   GST_BUFFER_DURATION (buf) = duration;
6724   GST_BUFFER_OFFSET (buf) = -1;
6725   GST_BUFFER_OFFSET_END (buf) = -1;
6726
6727   if (G_UNLIKELY (stream->process_func))
6728     buf = stream->process_func (qtdemux, stream, buf);
6729
6730   if (!buf) {
6731     goto exit;
6732   }
6733
6734   if (!keyframe) {
6735     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6736     stream->on_keyframe = FALSE;
6737   } else {
6738     stream->on_keyframe = TRUE;
6739   }
6740
6741   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6742     gst_buffer_append_memory (buf,
6743         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6744
6745   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6746     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6747   }
6748 #if 0
6749   if (G_UNLIKELY (qtdemux->element_index)) {
6750     GstClockTime stream_time;
6751
6752     stream_time =
6753         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6754         timestamp);
6755     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6756       GST_LOG_OBJECT (qtdemux,
6757           "adding association %" GST_TIME_FORMAT "-> %"
6758           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6759       gst_index_add_association (qtdemux->element_index,
6760           qtdemux->index_id,
6761           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6762           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6763           GST_FORMAT_BYTES, byte_position, NULL);
6764     }
6765   }
6766 #endif
6767
6768   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6769
6770 exit:
6771   return ret;
6772 }
6773
6774 static const QtDemuxRandomAccessEntry *
6775 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6776     GstClockTime pos, gboolean after)
6777 {
6778   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6779   guint n_entries = stream->n_ra_entries;
6780   guint i;
6781
6782   /* we assume the table is sorted */
6783   for (i = 0; i < n_entries; ++i) {
6784     if (entries[i].ts > pos)
6785       break;
6786   }
6787
6788   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6789    * probably okay to assume that the index lists the very first fragment */
6790   if (i == 0)
6791     return &entries[0];
6792
6793   if (after)
6794     return &entries[i];
6795   else
6796     return &entries[i - 1];
6797 }
6798
6799 static gboolean
6800 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6801 {
6802   const QtDemuxRandomAccessEntry *best_entry = NULL;
6803   gint i;
6804
6805   GST_OBJECT_LOCK (qtdemux);
6806
6807   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6808
6809   /* first see if we can determine where to go to using mfra,
6810    * before we start clearing things */
6811   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6812     const QtDemuxRandomAccessEntry *entry;
6813     QtDemuxStream *stream;
6814     gboolean is_audio_or_video;
6815
6816     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6817
6818     if (stream->ra_entries == NULL)
6819       continue;
6820
6821     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6822       is_audio_or_video = TRUE;
6823     else
6824       is_audio_or_video = FALSE;
6825
6826     entry =
6827         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6828         stream->time_position, !is_audio_or_video);
6829
6830     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6831         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6832
6833     stream->pending_seek = entry;
6834
6835     /* decide position to jump to just based on audio/video tracks, not subs */
6836     if (!is_audio_or_video)
6837       continue;
6838
6839     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6840       best_entry = entry;
6841   }
6842
6843   /* no luck, will handle seek otherwise */
6844   if (best_entry == NULL) {
6845     GST_OBJECT_UNLOCK (qtdemux);
6846     return FALSE;
6847   }
6848
6849   /* ok, now we can prepare for processing as of located moof */
6850   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6851     QtDemuxStream *stream;
6852
6853     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6854
6855     g_free (stream->samples);
6856     stream->samples = NULL;
6857     stream->n_samples = 0;
6858     stream->stbl_index = -1;    /* no samples have yet been parsed */
6859     stream->sample_index = -1;
6860
6861     if (stream->protection_scheme_info) {
6862       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6863       if (stream->protection_scheme_type == FOURCC_cenc
6864           || stream->protection_scheme_type == FOURCC_cbcs) {
6865         QtDemuxCencSampleSetInfo *info =
6866             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6867         if (info->crypto_info) {
6868           g_ptr_array_free (info->crypto_info, TRUE);
6869           info->crypto_info = NULL;
6870         }
6871       }
6872     }
6873   }
6874
6875   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6876       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6877       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6878       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6879
6880   qtdemux->moof_offset = best_entry->moof_offset;
6881
6882   qtdemux_add_fragmented_samples (qtdemux);
6883
6884   GST_OBJECT_UNLOCK (qtdemux);
6885   return TRUE;
6886 }
6887
6888 static GstFlowReturn
6889 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6890 {
6891   GstFlowReturn ret = GST_FLOW_OK;
6892   GstBuffer *buf = NULL;
6893   QtDemuxStream *stream, *target_stream = NULL;
6894   GstClockTime min_time;
6895   guint64 offset = 0;
6896   GstClockTime dts = GST_CLOCK_TIME_NONE;
6897   GstClockTime pts = GST_CLOCK_TIME_NONE;
6898   GstClockTime duration = 0;
6899   gboolean keyframe = FALSE;
6900   guint sample_size = 0;
6901   guint num_samples = 1;
6902   gboolean empty = 0;
6903   guint size;
6904   gint i;
6905
6906   if (qtdemux->fragmented_seek_pending) {
6907     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6908     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6909       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6910       qtdemux->fragmented_seek_pending = FALSE;
6911     } else {
6912       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6913     }
6914   }
6915
6916   /* Figure out the next stream sample to output, min_time is expressed in
6917    * global time and runs over the edit list segments. */
6918   min_time = G_MAXUINT64;
6919   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6920     GstClockTime position;
6921
6922     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6923     position = stream->time_position;
6924
6925     if (!GST_CLOCK_TIME_IS_VALID (position))
6926       continue;
6927
6928     if (stream->segment_index != -1) {
6929       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6930       position += segment->media_start;
6931     }
6932
6933     /* position of -1 is EOS */
6934     if (position < min_time) {
6935       min_time = position;
6936       target_stream = stream;
6937     }
6938   }
6939   /* all are EOS */
6940   if (G_UNLIKELY (target_stream == NULL)) {
6941     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6942     goto eos;
6943   }
6944
6945   /* check for segment end */
6946   if (G_UNLIKELY (qtdemux->segment.stop != -1
6947           && qtdemux->segment.rate >= 0
6948           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6949     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6950     target_stream->time_position = GST_CLOCK_TIME_NONE;
6951     goto eos_stream;
6952   }
6953
6954   /* gap events for subtitle streams */
6955   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6956     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6957     if (stream->pad) {
6958       GstClockTime gap_threshold;
6959
6960       /* Only send gap events on non-subtitle streams if lagging way behind. */
6961       if (stream->subtype == FOURCC_subp
6962           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6963           stream->subtype == FOURCC_wvtt)
6964         gap_threshold = 1 * GST_SECOND;
6965       else
6966         gap_threshold = 3 * GST_SECOND;
6967
6968       /* send gap events until the stream catches up */
6969       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6970       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6971           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6972           stream->segment.position + gap_threshold < min_time) {
6973         GstEvent *gap =
6974             gst_event_new_gap (stream->segment.position, gap_threshold);
6975         gst_pad_push_event (stream->pad, gap);
6976         stream->segment.position += gap_threshold;
6977       }
6978     }
6979   }
6980
6981   stream = target_stream;
6982   /* fetch info for the current sample of this stream */
6983   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6984               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6985     goto eos_stream;
6986
6987   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6988   if (stream->new_caps) {
6989     gst_qtdemux_configure_stream (qtdemux, stream);
6990     qtdemux_do_allocation (stream, qtdemux);
6991   }
6992
6993   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6994   if (G_UNLIKELY (qtdemux->segment.
6995           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6996     if (stream->subtype == FOURCC_vide) {
6997       if (!keyframe) {
6998         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6999             stream->track_id);
7000         goto next;
7001       } else if (qtdemux->trickmode_interval > 0) {
7002         GstClockTimeDiff interval;
7003
7004         if (qtdemux->segment.rate > 0)
7005           interval = stream->time_position - stream->last_keyframe_dts;
7006         else
7007           interval = stream->last_keyframe_dts - stream->time_position;
7008
7009         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
7010             && interval < qtdemux->trickmode_interval) {
7011           GST_LOG_OBJECT (qtdemux,
7012               "Skipping keyframe within interval on track-id %u",
7013               stream->track_id);
7014           goto next;
7015         } else {
7016           stream->last_keyframe_dts = stream->time_position;
7017         }
7018       }
7019     }
7020   }
7021
7022   GST_DEBUG_OBJECT (qtdemux,
7023       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
7024       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
7025       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
7026       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
7027       GST_TIME_ARGS (duration));
7028
7029   if (G_UNLIKELY (empty)) {
7030     /* empty segment, push a gap if there's a second or more
7031      * difference and move to the next one */
7032     if ((pts + duration - stream->segment.position) >= GST_SECOND)
7033       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
7034     stream->segment.position = pts + duration;
7035     goto next;
7036   }
7037
7038   /* hmm, empty sample, skip and move to next sample */
7039   if (G_UNLIKELY (sample_size <= 0))
7040     goto next;
7041
7042   /* last pushed sample was out of boundary, goto next sample */
7043   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
7044     goto next;
7045
7046   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
7047     GST_DEBUG_OBJECT (qtdemux,
7048         "size %d larger than stream max_buffer_size %d, trimming",
7049         sample_size, stream->max_buffer_size);
7050     size =
7051         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
7052   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
7053       && sample_size < stream->min_buffer_size) {
7054     guint start_sample_index = stream->sample_index;
7055     guint accumulated_size = sample_size;
7056     guint64 expected_next_offset = offset + sample_size;
7057
7058     GST_DEBUG_OBJECT (qtdemux,
7059         "size %d smaller than stream min_buffer_size %d, combining with the next",
7060         sample_size, stream->min_buffer_size);
7061
7062     while (stream->sample_index < stream->to_sample
7063         && stream->sample_index + 1 < stream->n_samples) {
7064       const QtDemuxSample *next_sample;
7065
7066       /* Increment temporarily */
7067       stream->sample_index++;
7068
7069       /* Failed to parse sample so let's go back to the previous one that was
7070        * still successful */
7071       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
7072         stream->sample_index--;
7073         break;
7074       }
7075
7076       next_sample = &stream->samples[stream->sample_index];
7077
7078       /* Not contiguous with the previous sample so let's go back to the
7079        * previous one that was still successful */
7080       if (next_sample->offset != expected_next_offset) {
7081         stream->sample_index--;
7082         break;
7083       }
7084
7085       accumulated_size += next_sample->size;
7086       expected_next_offset += next_sample->size;
7087       if (accumulated_size >= stream->min_buffer_size)
7088         break;
7089     }
7090
7091     num_samples = stream->sample_index + 1 - start_sample_index;
7092     stream->sample_index = start_sample_index;
7093     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
7094         num_samples, accumulated_size);
7095     size = accumulated_size;
7096   } else {
7097     size = sample_size;
7098   }
7099
7100   if (qtdemux->cenc_aux_info_offset > 0) {
7101     GstMapInfo map;
7102     GstByteReader br;
7103     GstBuffer *aux_info = NULL;
7104
7105     /* pull the data stored before the sample */
7106     ret =
7107         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
7108         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
7109     if (G_UNLIKELY (ret != GST_FLOW_OK))
7110       goto beach;
7111     gst_buffer_map (aux_info, &map, GST_MAP_READ);
7112     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
7113     gst_byte_reader_init (&br, map.data + 8, map.size);
7114     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
7115             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
7116       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
7117       gst_buffer_unmap (aux_info, &map);
7118       gst_buffer_unref (aux_info);
7119       ret = GST_FLOW_ERROR;
7120       goto beach;
7121     }
7122     gst_buffer_unmap (aux_info, &map);
7123     gst_buffer_unref (aux_info);
7124   }
7125
7126   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
7127       offset);
7128
7129   if (stream->use_allocator) {
7130     /* if we have a per-stream allocator, use it */
7131     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
7132   }
7133
7134   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
7135       size, &buf);
7136   if (G_UNLIKELY (ret != GST_FLOW_OK))
7137     goto beach;
7138
7139   /* Update for both splitting and combining of samples */
7140   if (size != sample_size) {
7141     pts += gst_util_uint64_scale_int (GST_SECOND,
7142         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
7143         stream->timescale);
7144     dts +=
7145         gst_util_uint64_scale_int (GST_SECOND,
7146         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
7147         stream->timescale);
7148     duration =
7149         gst_util_uint64_scale_int (GST_SECOND,
7150         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
7151   }
7152
7153   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
7154       dts, pts, duration, keyframe, min_time, offset);
7155
7156   if (size < sample_size) {
7157     QtDemuxSample *sample = &stream->samples[stream->sample_index];
7158     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
7159
7160     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
7161         sample->timestamp +
7162         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
7163     if (time_position >= segment->media_start) {
7164       /* inside the segment, update time_position, looks very familiar to
7165        * GStreamer segments, doesn't it? */
7166       stream->time_position = (time_position - segment->media_start) +
7167           segment->time;
7168     } else {
7169       /* not yet in segment, time does not yet increment. This means
7170        * that we are still prerolling keyframes to the decoder so it can
7171        * decode the first sample of the segment. */
7172       stream->time_position = segment->time;
7173     }
7174   } else if (size > sample_size) {
7175     /* Increase to the last sample we already pulled so that advancing
7176      * below brings us to the next sample we need to pull */
7177     stream->sample_index += num_samples - 1;
7178   }
7179
7180   /* combine flows */
7181   GST_OBJECT_LOCK (qtdemux);
7182   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
7183   GST_OBJECT_UNLOCK (qtdemux);
7184   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
7185    * we have no more data for the pad to push */
7186   if (ret == GST_FLOW_EOS)
7187     ret = GST_FLOW_OK;
7188
7189   stream->offset_in_sample += size;
7190   if (stream->offset_in_sample >= sample_size) {
7191     gst_qtdemux_advance_sample (qtdemux, stream);
7192   }
7193   goto beach;
7194
7195 next:
7196   gst_qtdemux_advance_sample (qtdemux, stream);
7197
7198 beach:
7199   return ret;
7200
7201   /* special cases */
7202 eos:
7203   {
7204     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
7205     ret = GST_FLOW_EOS;
7206     goto beach;
7207   }
7208 eos_stream:
7209   {
7210     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
7211     /* EOS will be raised if all are EOS */
7212     ret = GST_FLOW_OK;
7213     goto beach;
7214   }
7215 }
7216
7217 static void
7218 gst_qtdemux_loop (GstPad * pad)
7219 {
7220   GstQTDemux *qtdemux;
7221   guint64 cur_offset;
7222   GstFlowReturn ret;
7223
7224   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
7225
7226   cur_offset = qtdemux->offset;
7227   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
7228       cur_offset, qt_demux_state_string (qtdemux->state));
7229
7230   switch (qtdemux->state) {
7231     case QTDEMUX_STATE_INITIAL:
7232     case QTDEMUX_STATE_HEADER:
7233       ret = gst_qtdemux_loop_state_header (qtdemux);
7234       break;
7235     case QTDEMUX_STATE_MOVIE:
7236       ret = gst_qtdemux_loop_state_movie (qtdemux);
7237       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
7238         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
7239       }
7240       break;
7241     default:
7242       /* ouch */
7243       goto invalid_state;
7244   }
7245
7246   /* if something went wrong, pause */
7247   if (ret != GST_FLOW_OK)
7248     goto pause;
7249
7250 done:
7251   gst_object_unref (qtdemux);
7252   return;
7253
7254   /* ERRORS */
7255 invalid_state:
7256   {
7257     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
7258         (NULL), ("streaming stopped, invalid state"));
7259     gst_pad_pause_task (pad);
7260     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
7261     goto done;
7262   }
7263 pause:
7264   {
7265     const gchar *reason = gst_flow_get_name (ret);
7266
7267     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
7268
7269     gst_pad_pause_task (pad);
7270
7271     /* fatal errors need special actions */
7272     /* check EOS */
7273     if (ret == GST_FLOW_EOS) {
7274       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
7275         /* we have no streams, post an error */
7276         gst_qtdemux_post_no_playable_stream_error (qtdemux);
7277       }
7278       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
7279         gint64 stop;
7280
7281         if ((stop = qtdemux->segment.stop) == -1)
7282           stop = qtdemux->segment.duration;
7283
7284         if (qtdemux->segment.rate >= 0) {
7285           GstMessage *message;
7286           GstEvent *event;
7287
7288           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
7289           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
7290               GST_FORMAT_TIME, stop);
7291           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
7292           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
7293             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
7294             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
7295           }
7296           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
7297           gst_qtdemux_push_event (qtdemux, event);
7298         } else {
7299           GstMessage *message;
7300           GstEvent *event;
7301
7302           /*  For Reverse Playback */
7303           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
7304           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
7305               GST_FORMAT_TIME, qtdemux->segment.start);
7306           event = gst_event_new_segment_done (GST_FORMAT_TIME,
7307               qtdemux->segment.start);
7308           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
7309             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
7310             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
7311           }
7312           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
7313           gst_qtdemux_push_event (qtdemux, event);
7314         }
7315       } else {
7316         GstEvent *event;
7317
7318         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
7319         event = gst_event_new_eos ();
7320         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
7321           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
7322         gst_qtdemux_push_event (qtdemux, event);
7323       }
7324     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
7325       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
7326       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
7327     }
7328     goto done;
7329   }
7330 }
7331
7332 /*
7333  * has_next_entry
7334  *
7335  * Returns if there are samples to be played.
7336  */
7337 static gboolean
7338 has_next_entry (GstQTDemux * demux)
7339 {
7340   QtDemuxStream *stream;
7341   gint i;
7342
7343   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
7344
7345   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7346     stream = QTDEMUX_NTH_STREAM (demux, i);
7347
7348     if (stream->sample_index == -1) {
7349       stream->sample_index = 0;
7350       stream->offset_in_sample = 0;
7351     }
7352
7353     if (stream->sample_index >= stream->n_samples) {
7354       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7355       continue;
7356     }
7357     GST_DEBUG_OBJECT (demux, "Found a sample");
7358     return TRUE;
7359   }
7360
7361   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
7362   return FALSE;
7363 }
7364
7365 /*
7366  * next_entry_size
7367  *
7368  * Returns the size of the first entry at the current offset.
7369  * If -1, there are none (which means EOS or empty file).
7370  */
7371 static guint64
7372 next_entry_size (GstQTDemux * demux)
7373 {
7374   QtDemuxStream *stream, *target_stream = NULL;
7375   guint64 smalloffs = (guint64) - 1;
7376   QtDemuxSample *sample;
7377   gint i;
7378
7379   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
7380       demux->offset);
7381
7382   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7383     stream = QTDEMUX_NTH_STREAM (demux, i);
7384
7385     if (stream->sample_index == -1) {
7386       stream->sample_index = 0;
7387       stream->offset_in_sample = 0;
7388     }
7389
7390     if (stream->sample_index >= stream->n_samples) {
7391       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
7392       continue;
7393     }
7394
7395     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7396       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7397           stream->sample_index);
7398       return -1;
7399     }
7400
7401     sample = &stream->samples[stream->sample_index];
7402
7403     GST_LOG_OBJECT (demux,
7404         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7405         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7406         stream->sample_index, sample->offset, sample->size);
7407
7408     if (((smalloffs == -1)
7409             || (sample->offset < smalloffs)) && (sample->size)) {
7410       smalloffs = sample->offset;
7411       target_stream = stream;
7412     }
7413   }
7414
7415   if (!target_stream)
7416     return -1;
7417
7418   GST_LOG_OBJECT (demux,
7419       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7420       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7421
7422   stream = target_stream;
7423   sample = &stream->samples[stream->sample_index];
7424
7425   if (sample->offset >= demux->offset) {
7426     demux->todrop = sample->offset - demux->offset;
7427     return sample->size + demux->todrop;
7428   }
7429
7430   GST_DEBUG_OBJECT (demux,
7431       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7432   return -1;
7433 }
7434
7435 static void
7436 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7437 {
7438   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7439
7440   gst_element_post_message (GST_ELEMENT_CAST (demux),
7441       gst_message_new_element (GST_OBJECT_CAST (demux),
7442           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7443 }
7444
7445 static gboolean
7446 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7447 {
7448   GstEvent *event;
7449   gboolean res = 0;
7450
7451   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7452
7453   event =
7454       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7455       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7456       GST_SEEK_TYPE_NONE, -1);
7457
7458   /* store seqnum to drop flush events, they don't need to reach downstream */
7459   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7460   res = gst_pad_push_event (demux->sinkpad, event);
7461   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7462
7463   return res;
7464 }
7465
7466 /* check for seekable upstream, above and beyond a mere query */
7467 static void
7468 gst_qtdemux_check_seekability (GstQTDemux * demux)
7469 {
7470   GstQuery *query;
7471   gboolean seekable = FALSE;
7472   gint64 start = -1, stop = -1;
7473
7474   if (demux->upstream_size)
7475     return;
7476
7477   if (demux->upstream_format_is_time)
7478     return;
7479
7480   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7481   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7482     GST_DEBUG_OBJECT (demux, "seeking query failed");
7483     goto done;
7484   }
7485
7486   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7487
7488   /* try harder to query upstream size if we didn't get it the first time */
7489   if (seekable && stop == -1) {
7490     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7491     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7492   }
7493
7494   /* if upstream doesn't know the size, it's likely that it's not seekable in
7495    * practice even if it technically may be seekable */
7496   if (seekable && (start != 0 || stop <= start)) {
7497     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7498     seekable = FALSE;
7499   }
7500
7501 done:
7502   gst_query_unref (query);
7503
7504   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7505       G_GUINT64_FORMAT ")", seekable, start, stop);
7506   demux->upstream_seekable = seekable;
7507   demux->upstream_size = seekable ? stop : -1;
7508 }
7509
7510 static void
7511 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7512 {
7513   g_return_if_fail (bytes <= demux->todrop);
7514
7515   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7516   gst_adapter_flush (demux->adapter, bytes);
7517   demux->neededbytes -= bytes;
7518   demux->offset += bytes;
7519   demux->todrop -= bytes;
7520 }
7521
7522 /* PUSH-MODE only: Send a segment, if not done already. */
7523 static void
7524 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7525 {
7526   if (G_UNLIKELY (demux->need_segment)) {
7527     gint i;
7528
7529     if (!demux->upstream_format_is_time) {
7530       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7531     } else {
7532       GstEvent *segment_event;
7533       segment_event = gst_event_new_segment (&demux->segment);
7534       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7535         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7536       gst_qtdemux_push_event (demux, segment_event);
7537     }
7538
7539     demux->need_segment = FALSE;
7540
7541     /* clear to send tags on all streams */
7542     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7543       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7544       gst_qtdemux_push_tags (demux, stream);
7545       if (CUR_STREAM (stream)->sparse) {
7546         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7547         gst_pad_push_event (stream->pad,
7548             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7549       }
7550     }
7551   }
7552 }
7553
7554 /* Used for push mode only. */
7555 static void
7556 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7557     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7558 {
7559   GstClockTime ts, dur;
7560
7561   ts = pos;
7562   dur =
7563       stream->segments[segment_index].duration - (pos -
7564       stream->segments[segment_index].time);
7565   stream->time_position += dur;
7566
7567   /* Only gaps with a duration of at least one second are propagated.
7568    * Same workaround as in pull mode.
7569    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7570   if (dur >= GST_SECOND) {
7571     GstEvent *gap;
7572     gap = gst_event_new_gap (ts, dur);
7573
7574     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7575         "segment: %" GST_PTR_FORMAT, gap);
7576     gst_pad_push_event (stream->pad, gap);
7577   }
7578 }
7579
7580 static GstFlowReturn
7581 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7582 {
7583   GstQTDemux *demux;
7584
7585   demux = GST_QTDEMUX (parent);
7586
7587   GST_DEBUG_OBJECT (demux,
7588       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7589       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7590       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7591       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7592       gst_buffer_get_size (inbuf), demux->offset);
7593
7594   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7595     gboolean is_gap_input = FALSE;
7596     gint i;
7597
7598     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7599
7600     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7601       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7602     }
7603
7604     /* Check if we can land back on our feet in the case where upstream is
7605      * handling the seeking/pushing of samples with gaps in between (like
7606      * in the case of trick-mode DASH for example) */
7607     if (demux->upstream_format_is_time
7608         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7609       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7610         guint32 res;
7611         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7612         GST_LOG_OBJECT (demux,
7613             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7614             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7615         res =
7616             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7617             stream, GST_BUFFER_OFFSET (inbuf));
7618         if (res != -1) {
7619           QtDemuxSample *sample = &stream->samples[res];
7620           GST_LOG_OBJECT (demux,
7621               "Checking if sample %d from track-id %u is valid (offset:%"
7622               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7623               stream->track_id, sample->offset, sample->size);
7624           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7625             GST_LOG_OBJECT (demux,
7626                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7627                 res);
7628             is_gap_input = TRUE;
7629             /* We can go back to standard playback mode */
7630             demux->state = QTDEMUX_STATE_MOVIE;
7631             /* Remember which sample this stream is at */
7632             stream->sample_index = res;
7633             /* Finally update all push-based values to the expected values */
7634             demux->neededbytes = stream->samples[res].size;
7635             demux->offset = GST_BUFFER_OFFSET (inbuf);
7636             demux->mdatleft =
7637                 demux->mdatsize - demux->offset + demux->mdatoffset;
7638             demux->todrop = 0;
7639           }
7640         }
7641       }
7642       if (!is_gap_input) {
7643         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7644         /* Reset state if it's a real discont */
7645         demux->neededbytes = 16;
7646         demux->state = QTDEMUX_STATE_INITIAL;
7647         demux->offset = GST_BUFFER_OFFSET (inbuf);
7648         gst_adapter_clear (demux->adapter);
7649       }
7650     }
7651     /* Reverse fragmented playback, need to flush all we have before
7652      * consuming a new fragment.
7653      * The samples array have the timestamps calculated by accumulating the
7654      * durations but this won't work for reverse playback of fragments as
7655      * the timestamps of a subsequent fragment should be smaller than the
7656      * previously received one. */
7657     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7658       gst_qtdemux_process_adapter (demux, TRUE);
7659       g_ptr_array_foreach (demux->active_streams,
7660           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7661     }
7662   }
7663
7664   gst_adapter_push (demux->adapter, inbuf);
7665
7666   GST_DEBUG_OBJECT (demux,
7667       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7668       demux->neededbytes, gst_adapter_available (demux->adapter));
7669
7670   return gst_qtdemux_process_adapter (demux, FALSE);
7671 }
7672
7673 static GstFlowReturn
7674 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7675 {
7676   GstFlowReturn ret = GST_FLOW_OK;
7677
7678   /* we never really mean to buffer that much */
7679   if (demux->neededbytes == -1) {
7680     goto eos;
7681   }
7682
7683   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7684       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7685
7686 #ifndef GST_DISABLE_GST_DEBUG
7687     {
7688       guint64 discont_offset, distance_from_discont;
7689
7690       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7691       distance_from_discont =
7692           gst_adapter_distance_from_discont (demux->adapter);
7693
7694       GST_DEBUG_OBJECT (demux,
7695           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7696           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7697           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7698           demux->offset, discont_offset, distance_from_discont);
7699     }
7700 #endif
7701
7702     switch (demux->state) {
7703       case QTDEMUX_STATE_INITIAL:{
7704         const guint8 *data;
7705         guint32 fourcc;
7706         guint64 size;
7707
7708         gst_qtdemux_check_seekability (demux);
7709
7710         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7711
7712         /* get fourcc/length, set neededbytes */
7713         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7714             &size, &fourcc);
7715         gst_adapter_unmap (demux->adapter);
7716         data = NULL;
7717         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7718             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7719         if (size == 0) {
7720           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7721               (_("This file is invalid and cannot be played.")),
7722               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7723                   GST_FOURCC_ARGS (fourcc)));
7724           ret = GST_FLOW_ERROR;
7725           break;
7726         }
7727         if (fourcc == FOURCC_mdat) {
7728           gint next_entry = next_entry_size (demux);
7729           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7730                   || !demux->fragmented)) {
7731             /* we have the headers, start playback */
7732             demux->state = QTDEMUX_STATE_MOVIE;
7733             demux->neededbytes = next_entry;
7734             demux->mdatleft = size;
7735             demux->mdatsize = demux->mdatleft;
7736           } else {
7737             /* no headers yet, try to get them */
7738             guint bs;
7739             gboolean res;
7740             guint64 old, target;
7741
7742           buffer_data:
7743             old = demux->offset;
7744             target = old + size;
7745
7746             /* try to jump over the atom with a seek */
7747             /* only bother if it seems worth doing so,
7748              * and avoids possible upstream/server problems */
7749             if (demux->upstream_seekable &&
7750                 demux->upstream_size > 4 * (1 << 20)) {
7751               res = qtdemux_seek_offset (demux, target);
7752             } else {
7753               GST_DEBUG_OBJECT (demux, "skipping seek");
7754               res = FALSE;
7755             }
7756
7757             if (res) {
7758               GST_DEBUG_OBJECT (demux, "seek success");
7759               /* remember the offset fo the first mdat so we can seek back to it
7760                * after we have the headers */
7761               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7762                 demux->first_mdat = old;
7763                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7764                     demux->first_mdat);
7765               }
7766               /* seek worked, continue reading */
7767               demux->offset = target;
7768               demux->neededbytes = 16;
7769               demux->state = QTDEMUX_STATE_INITIAL;
7770             } else {
7771               /* seek failed, need to buffer */
7772               demux->offset = old;
7773               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7774               /* there may be multiple mdat (or alike) buffers */
7775               /* sanity check */
7776               if (demux->mdatbuffer)
7777                 bs = gst_buffer_get_size (demux->mdatbuffer);
7778               else
7779                 bs = 0;
7780               if (size + bs > 10 * (1 << 20))
7781                 goto no_moov;
7782               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7783               demux->neededbytes = size;
7784               if (!demux->mdatbuffer)
7785                 demux->mdatoffset = demux->offset;
7786             }
7787           }
7788         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7789           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7790               (_("This file is invalid and cannot be played.")),
7791               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7792                   GST_FOURCC_ARGS (fourcc), size));
7793           ret = GST_FLOW_ERROR;
7794           break;
7795         } else {
7796           /* this means we already started buffering and still no moov header,
7797            * let's continue buffering everything till we get moov */
7798           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7799                   || fourcc == FOURCC_moof))
7800             goto buffer_data;
7801           demux->neededbytes = size;
7802           demux->state = QTDEMUX_STATE_HEADER;
7803         }
7804         break;
7805       }
7806       case QTDEMUX_STATE_HEADER:{
7807         const guint8 *data;
7808         guint32 fourcc;
7809
7810         GST_DEBUG_OBJECT (demux, "In header");
7811
7812         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7813
7814         /* parse the header */
7815         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7816             &fourcc);
7817         if (fourcc == FOURCC_moov) {
7818           /* in usual fragmented setup we could try to scan for more
7819            * and end up at the the moov (after mdat) again */
7820           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7821               (!demux->fragmented
7822                   || demux->last_moov_offset == demux->offset)) {
7823             GST_DEBUG_OBJECT (demux,
7824                 "Skipping moov atom as we have (this) one already");
7825           } else {
7826             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7827
7828             if (demux->got_moov && demux->fragmented) {
7829               GST_DEBUG_OBJECT (demux,
7830                   "Got a second moov, clean up data from old one");
7831               if (demux->moov_node_compressed) {
7832                 g_node_destroy (demux->moov_node_compressed);
7833                 if (demux->moov_node)
7834                   g_free (demux->moov_node->data);
7835               }
7836               demux->moov_node_compressed = NULL;
7837               if (demux->moov_node)
7838                 g_node_destroy (demux->moov_node);
7839               demux->moov_node = NULL;
7840             }
7841
7842             demux->last_moov_offset = demux->offset;
7843
7844             /* Update streams with new moov */
7845             gst_qtdemux_stream_concat (demux,
7846                 demux->old_streams, demux->active_streams);
7847
7848             qtdemux_parse_moov (demux, data, demux->neededbytes);
7849             qtdemux_node_dump (demux, demux->moov_node);
7850             qtdemux_parse_tree (demux);
7851             qtdemux_prepare_streams (demux);
7852             QTDEMUX_EXPOSE_LOCK (demux);
7853             qtdemux_expose_streams (demux);
7854             QTDEMUX_EXPOSE_UNLOCK (demux);
7855
7856             demux->got_moov = TRUE;
7857
7858             gst_qtdemux_check_send_pending_segment (demux);
7859
7860             if (demux->moov_node_compressed) {
7861               g_node_destroy (demux->moov_node_compressed);
7862               g_free (demux->moov_node->data);
7863             }
7864             demux->moov_node_compressed = NULL;
7865             g_node_destroy (demux->moov_node);
7866             demux->moov_node = NULL;
7867             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7868           }
7869         } else if (fourcc == FOURCC_moof) {
7870           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7871             guint64 dist = 0;
7872             GstClockTime prev_pts;
7873             guint64 prev_offset;
7874             guint64 adapter_discont_offset, adapter_discont_dist;
7875
7876             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7877
7878             /*
7879              * The timestamp of the moof buffer is relevant as some scenarios
7880              * won't have the initial timestamp in the atoms. Whenever a new
7881              * buffer has started, we get that buffer's PTS and use it as a base
7882              * timestamp for the trun entries.
7883              *
7884              * To keep track of the current buffer timestamp and starting point
7885              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7886              * from the beginning of the buffer, with the distance and demux->offset
7887              * we know if it is still the same buffer or not.
7888              */
7889             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7890             prev_offset = demux->offset - dist;
7891             if (demux->fragment_start_offset == -1
7892                 || prev_offset > demux->fragment_start_offset) {
7893               demux->fragment_start_offset = prev_offset;
7894               demux->fragment_start = prev_pts;
7895               GST_DEBUG_OBJECT (demux,
7896                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7897                   GST_TIME_FORMAT, demux->fragment_start_offset,
7898                   GST_TIME_ARGS (demux->fragment_start));
7899             }
7900
7901             /* We can't use prev_offset() here because this would require
7902              * upstream to set consistent and correct offsets on all buffers
7903              * since the discont. Nothing ever did that in the past and we
7904              * would break backwards compatibility here then.
7905              * Instead take the offset we had at the last discont and count
7906              * the bytes from there. This works with old code as there would
7907              * be no discont between moov and moof, and also works with
7908              * adaptivedemux which correctly sets offset and will set the
7909              * DISCONT flag accordingly when needed.
7910              *
7911              * We also only do this for upstream TIME segments as otherwise
7912              * there are potential backwards compatibility problems with
7913              * seeking in PUSH mode and upstream providing inconsistent
7914              * timestamps. */
7915             adapter_discont_offset =
7916                 gst_adapter_offset_at_discont (demux->adapter);
7917             adapter_discont_dist =
7918                 gst_adapter_distance_from_discont (demux->adapter);
7919
7920             GST_DEBUG_OBJECT (demux,
7921                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7922                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7923                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7924
7925             if (demux->upstream_format_is_time) {
7926               demux->moof_offset = adapter_discont_offset;
7927               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7928                 demux->moof_offset += adapter_discont_dist;
7929               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7930                 demux->moof_offset = demux->offset;
7931             } else {
7932               demux->moof_offset = demux->offset;
7933             }
7934
7935             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7936                     demux->moof_offset, NULL)) {
7937               gst_adapter_unmap (demux->adapter);
7938               ret = GST_FLOW_ERROR;
7939               goto done;
7940             }
7941
7942             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7943             if (demux->mss_mode && !demux->exposed) {
7944               QTDEMUX_EXPOSE_LOCK (demux);
7945               qtdemux_expose_streams (demux);
7946               QTDEMUX_EXPOSE_UNLOCK (demux);
7947             }
7948
7949             gst_qtdemux_check_send_pending_segment (demux);
7950           } else {
7951             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7952           }
7953         } else if (fourcc == FOURCC_ftyp) {
7954           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7955           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7956         } else if (fourcc == FOURCC_uuid) {
7957           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7958           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7959         } else if (fourcc == FOURCC_sidx) {
7960           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7961           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7962         } else {
7963           switch (fourcc) {
7964             case FOURCC_styp:
7965               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7966                * FALLTHROUGH */
7967             case FOURCC_skip:
7968             case FOURCC_free:
7969               /* [free] and [skip] are padding atoms */
7970               GST_DEBUG_OBJECT (demux,
7971                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7972                   GST_FOURCC_ARGS (fourcc));
7973               break;
7974             default:
7975               GST_WARNING_OBJECT (demux,
7976                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7977                   GST_FOURCC_ARGS (fourcc));
7978               /* Let's jump that one and go back to initial state */
7979               break;
7980           }
7981         }
7982         gst_adapter_unmap (demux->adapter);
7983         data = NULL;
7984
7985         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7986           gsize remaining_data_size = 0;
7987
7988           /* the mdat was before the header */
7989           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7990               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7991           /* restore our adapter/offset view of things with upstream;
7992            * put preceding buffered data ahead of current moov data.
7993            * This should also handle evil mdat, moov, mdat cases and alike */
7994           gst_adapter_flush (demux->adapter, demux->neededbytes);
7995
7996           /* Store any remaining data after the mdat for later usage */
7997           remaining_data_size = gst_adapter_available (demux->adapter);
7998           if (remaining_data_size > 0) {
7999             g_assert (demux->restoredata_buffer == NULL);
8000             demux->restoredata_buffer =
8001                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
8002             demux->restoredata_offset = demux->offset + demux->neededbytes;
8003             GST_DEBUG_OBJECT (demux,
8004                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
8005                 G_GUINT64_FORMAT, remaining_data_size,
8006                 demux->restoredata_offset);
8007           }
8008
8009           gst_adapter_push (demux->adapter, demux->mdatbuffer);
8010           demux->mdatbuffer = NULL;
8011           demux->offset = demux->mdatoffset;
8012           demux->neededbytes = next_entry_size (demux);
8013           demux->state = QTDEMUX_STATE_MOVIE;
8014           demux->mdatleft = gst_adapter_available (demux->adapter);
8015           demux->mdatsize = demux->mdatleft;
8016         } else {
8017           GST_DEBUG_OBJECT (demux, "Carrying on normally");
8018           gst_adapter_flush (demux->adapter, demux->neededbytes);
8019
8020           /* only go back to the mdat if there are samples to play */
8021           if (demux->got_moov && demux->first_mdat != -1
8022               && has_next_entry (demux)) {
8023             gboolean res;
8024
8025             /* we need to seek back */
8026             res = qtdemux_seek_offset (demux, demux->first_mdat);
8027             if (res) {
8028               demux->offset = demux->first_mdat;
8029             } else {
8030               GST_DEBUG_OBJECT (demux, "Seek back failed");
8031             }
8032           } else {
8033             demux->offset += demux->neededbytes;
8034           }
8035           demux->neededbytes = 16;
8036           demux->state = QTDEMUX_STATE_INITIAL;
8037         }
8038
8039         break;
8040       }
8041       case QTDEMUX_STATE_BUFFER_MDAT:{
8042         GstBuffer *buf;
8043         guint8 fourcc[4];
8044
8045         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
8046             demux->offset);
8047         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
8048         gst_buffer_extract (buf, 0, fourcc, 4);
8049         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
8050             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
8051         if (demux->mdatbuffer)
8052           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
8053         else
8054           demux->mdatbuffer = buf;
8055         demux->offset += demux->neededbytes;
8056         demux->neededbytes = 16;
8057         demux->state = QTDEMUX_STATE_INITIAL;
8058         gst_qtdemux_post_progress (demux, 1, 1);
8059
8060         break;
8061       }
8062       case QTDEMUX_STATE_MOVIE:{
8063         QtDemuxStream *stream = NULL;
8064         QtDemuxSample *sample;
8065         GstClockTime dts, pts, duration;
8066         gboolean keyframe;
8067         gint i;
8068
8069         GST_DEBUG_OBJECT (demux,
8070             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
8071
8072         if (demux->fragmented) {
8073           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
8074               demux->mdatleft);
8075           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
8076             /* if needed data starts within this atom,
8077              * then it should not exceed this atom */
8078             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
8079               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8080                   (_("This file is invalid and cannot be played.")),
8081                   ("sample data crosses atom boundary"));
8082               ret = GST_FLOW_ERROR;
8083               break;
8084             }
8085             demux->mdatleft -= demux->neededbytes;
8086           } else {
8087             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
8088             /* so we are dropping more than left in this atom */
8089             gst_qtdemux_drop_data (demux, demux->mdatleft);
8090             demux->mdatleft = 0;
8091
8092             /* need to resume atom parsing so we do not miss any other pieces */
8093             demux->state = QTDEMUX_STATE_INITIAL;
8094             demux->neededbytes = 16;
8095
8096             /* check if there was any stored post mdat data from previous buffers */
8097             if (demux->restoredata_buffer) {
8098               g_assert (gst_adapter_available (demux->adapter) == 0);
8099
8100               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
8101               demux->restoredata_buffer = NULL;
8102               demux->offset = demux->restoredata_offset;
8103             }
8104
8105             break;
8106           }
8107         }
8108
8109         if (demux->todrop) {
8110           if (demux->cenc_aux_info_offset > 0) {
8111             GstByteReader br;
8112             const guint8 *data;
8113
8114             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
8115             data = gst_adapter_map (demux->adapter, demux->todrop);
8116             gst_byte_reader_init (&br, data + 8, demux->todrop);
8117             if (!qtdemux_parse_cenc_aux_info (demux,
8118                     QTDEMUX_NTH_STREAM (demux, 0), &br,
8119                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
8120               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
8121               ret = GST_FLOW_ERROR;
8122               gst_adapter_unmap (demux->adapter);
8123               g_free (demux->cenc_aux_info_sizes);
8124               demux->cenc_aux_info_sizes = NULL;
8125               goto done;
8126             }
8127             demux->cenc_aux_info_offset = 0;
8128             g_free (demux->cenc_aux_info_sizes);
8129             demux->cenc_aux_info_sizes = NULL;
8130             gst_adapter_unmap (demux->adapter);
8131           }
8132           gst_qtdemux_drop_data (demux, demux->todrop);
8133         }
8134
8135         /* first buffer? */
8136         /* initial newsegment sent here after having added pads,
8137          * possible others in sink_event */
8138         gst_qtdemux_check_send_pending_segment (demux);
8139
8140         /* Figure out which stream this packet belongs to */
8141         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
8142           stream = QTDEMUX_NTH_STREAM (demux, i);
8143           if (stream->sample_index >= stream->n_samples) {
8144             /* reset to be checked below G_UNLIKELY (stream == NULL) */
8145             stream = NULL;
8146             continue;
8147           }
8148           GST_LOG_OBJECT (demux,
8149               "Checking track-id %u (sample_index:%d / offset:%"
8150               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
8151               stream->sample_index,
8152               stream->samples[stream->sample_index].offset,
8153               stream->samples[stream->sample_index].size);
8154
8155           if (stream->samples[stream->sample_index].offset == demux->offset)
8156             break;
8157         }
8158
8159         if (G_UNLIKELY (stream == NULL))
8160           goto unknown_stream;
8161
8162         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
8163
8164         if (stream->new_caps) {
8165           gst_qtdemux_configure_stream (demux, stream);
8166         }
8167
8168         /* Put data in a buffer, set timestamps, caps, ... */
8169         sample = &stream->samples[stream->sample_index];
8170
8171         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
8172           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
8173               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
8174
8175           dts = QTSAMPLE_DTS (stream, sample);
8176           pts = QTSAMPLE_PTS (stream, sample);
8177           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
8178           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
8179
8180           /* check for segment end */
8181           if (G_UNLIKELY (demux->segment.stop != -1
8182                   && demux->segment.stop <= pts && stream->on_keyframe)
8183               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
8184             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
8185             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
8186
8187             /* skip this data, stream is EOS */
8188             gst_adapter_flush (demux->adapter, demux->neededbytes);
8189             demux->offset += demux->neededbytes;
8190
8191             /* check if all streams are eos */
8192             ret = GST_FLOW_EOS;
8193             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
8194               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
8195                 ret = GST_FLOW_OK;
8196                 break;
8197               }
8198             }
8199           } else {
8200             GstBuffer *outbuf;
8201
8202             outbuf =
8203                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
8204
8205             /* FIXME: should either be an assert or a plain check */
8206             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
8207
8208             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
8209                 dts, pts, duration, keyframe, dts, demux->offset);
8210           }
8211
8212           /* combine flows */
8213           GST_OBJECT_LOCK (demux);
8214           ret = gst_qtdemux_combine_flows (demux, stream, ret);
8215           GST_OBJECT_UNLOCK (demux);
8216         } else {
8217           /* skip this data, stream is EOS */
8218           gst_adapter_flush (demux->adapter, demux->neededbytes);
8219         }
8220
8221         stream->sample_index++;
8222         stream->offset_in_sample = 0;
8223
8224         /* update current offset and figure out size of next buffer */
8225         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
8226             demux->offset, demux->neededbytes);
8227         demux->offset += demux->neededbytes;
8228         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
8229             demux->offset);
8230
8231
8232         if (ret == GST_FLOW_EOS) {
8233           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
8234           demux->neededbytes = -1;
8235           goto eos;
8236         }
8237
8238         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
8239           if (demux->fragmented) {
8240             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
8241             /* there may be more to follow, only finish this atom */
8242             demux->todrop = demux->mdatleft;
8243             demux->neededbytes = demux->todrop;
8244             break;
8245           }
8246           goto eos;
8247         }
8248         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
8249           goto non_ok_unlinked_flow;
8250         }
8251         break;
8252       }
8253       default:
8254         goto invalid_state;
8255     }
8256   }
8257
8258   /* when buffering movie data, at least show user something is happening */
8259   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
8260       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
8261     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
8262         demux->neededbytes);
8263   }
8264 done:
8265
8266   return ret;
8267
8268   /* ERRORS */
8269 non_ok_unlinked_flow:
8270   {
8271     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
8272         gst_flow_get_name (ret));
8273     return ret;
8274   }
8275 unknown_stream:
8276   {
8277     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
8278     ret = GST_FLOW_ERROR;
8279     goto done;
8280   }
8281 eos:
8282   {
8283     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
8284     ret = GST_FLOW_EOS;
8285     goto done;
8286   }
8287 invalid_state:
8288   {
8289     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
8290         (NULL), ("qtdemuxer invalid state %d", demux->state));
8291     ret = GST_FLOW_ERROR;
8292     goto done;
8293   }
8294 no_moov:
8295   {
8296     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
8297         (NULL), ("no 'moov' atom within the first 10 MB"));
8298     ret = GST_FLOW_ERROR;
8299     goto done;
8300   }
8301 }
8302
8303 static gboolean
8304 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
8305 {
8306   GstQuery *query;
8307   gboolean pull_mode;
8308
8309   query = gst_query_new_scheduling ();
8310
8311   if (!gst_pad_peer_query (sinkpad, query)) {
8312     gst_query_unref (query);
8313     goto activate_push;
8314   }
8315
8316   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
8317       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
8318   gst_query_unref (query);
8319
8320   if (!pull_mode)
8321     goto activate_push;
8322
8323   GST_DEBUG_OBJECT (sinkpad, "activating pull");
8324   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
8325
8326 activate_push:
8327   {
8328     GST_DEBUG_OBJECT (sinkpad, "activating push");
8329     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
8330   }
8331 }
8332
8333 static gboolean
8334 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
8335     GstPadMode mode, gboolean active)
8336 {
8337   gboolean res;
8338   GstQTDemux *demux = GST_QTDEMUX (parent);
8339
8340   switch (mode) {
8341     case GST_PAD_MODE_PUSH:
8342       demux->pullbased = FALSE;
8343       res = TRUE;
8344       break;
8345     case GST_PAD_MODE_PULL:
8346       if (active) {
8347         demux->pullbased = TRUE;
8348         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
8349             sinkpad, NULL);
8350       } else {
8351         res = gst_pad_stop_task (sinkpad);
8352       }
8353       break;
8354     default:
8355       res = FALSE;
8356       break;
8357   }
8358   return res;
8359 }
8360
8361 #ifdef HAVE_ZLIB
8362 static void *
8363 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
8364 {
8365   guint8 *buffer;
8366   z_stream z;
8367   int ret;
8368
8369   memset (&z, 0, sizeof (z));
8370   z.zalloc = NULL;
8371   z.zfree = NULL;
8372   z.opaque = NULL;
8373
8374   if ((ret = inflateInit (&z)) != Z_OK) {
8375     GST_ERROR ("inflateInit() returned %d", ret);
8376     return NULL;
8377   }
8378
8379   z.next_in = z_buffer;
8380   z.avail_in = z_length;
8381
8382   buffer = (guint8 *) g_malloc (*length);
8383   z.avail_out = *length;
8384   z.next_out = (Bytef *) buffer;
8385   do {
8386     ret = inflate (&z, Z_NO_FLUSH);
8387     if (ret == Z_STREAM_END) {
8388       break;
8389     } else if (ret != Z_OK) {
8390       GST_WARNING ("inflate() returned %d", ret);
8391       break;
8392     }
8393
8394     *length += 4096;
8395     buffer = (guint8 *) g_realloc (buffer, *length);
8396     z.next_out = (Bytef *) (buffer + z.total_out);
8397     z.avail_out += 4096;
8398   } while (z.avail_in > 0);
8399
8400   if (ret != Z_STREAM_END) {
8401     g_free (buffer);
8402     buffer = NULL;
8403     *length = 0;
8404   } else {
8405     *length = z.total_out;
8406   }
8407
8408   inflateEnd (&z);
8409
8410   return buffer;
8411 }
8412 #endif /* HAVE_ZLIB */
8413
8414 static gboolean
8415 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8416 {
8417   GNode *cmov;
8418
8419   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8420
8421   /* counts as header data */
8422   qtdemux->header_size += length;
8423
8424   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8425   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8426
8427   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8428   if (cmov) {
8429     guint32 method;
8430     GNode *dcom;
8431     GNode *cmvd;
8432     guint32 dcom_len;
8433
8434     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8435     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8436     if (dcom == NULL || cmvd == NULL)
8437       goto invalid_compression;
8438
8439     dcom_len = QT_UINT32 (dcom->data);
8440     if (dcom_len < 12)
8441       goto invalid_compression;
8442
8443     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8444     switch (method) {
8445 #ifdef HAVE_ZLIB
8446       case FOURCC_zlib:{
8447         guint uncompressed_length;
8448         guint compressed_length;
8449         guint8 *buf;
8450         guint32 cmvd_len;
8451
8452         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8453         if (cmvd_len < 12)
8454           goto invalid_compression;
8455
8456         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8457         compressed_length = cmvd_len - 12;
8458         GST_LOG ("length = %u", uncompressed_length);
8459
8460         buf =
8461             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8462             compressed_length, &uncompressed_length);
8463
8464         if (buf) {
8465           qtdemux->moov_node_compressed = qtdemux->moov_node;
8466           qtdemux->moov_node = g_node_new (buf);
8467
8468           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8469               uncompressed_length);
8470         }
8471         break;
8472       }
8473 #endif /* HAVE_ZLIB */
8474       default:
8475         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8476             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8477         break;
8478     }
8479   }
8480   return TRUE;
8481
8482   /* ERRORS */
8483 invalid_compression:
8484   {
8485     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8486     return FALSE;
8487   }
8488 }
8489
8490 static gboolean
8491 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8492     const guint8 * end)
8493 {
8494   while (G_UNLIKELY (buf < end)) {
8495     GNode *child;
8496     guint32 len;
8497
8498     if (G_UNLIKELY (buf + 4 > end)) {
8499       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8500       break;
8501     }
8502     len = QT_UINT32 (buf);
8503     if (G_UNLIKELY (len == 0)) {
8504       GST_LOG_OBJECT (qtdemux, "empty container");
8505       break;
8506     }
8507     if (G_UNLIKELY (len < 8)) {
8508       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8509       break;
8510     }
8511     if (G_UNLIKELY (len > (end - buf))) {
8512       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8513           (gint) (end - buf));
8514       break;
8515     }
8516
8517     child = g_node_new ((guint8 *) buf);
8518     g_node_append (node, child);
8519     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8520     qtdemux_parse_node (qtdemux, child, buf, len);
8521
8522     buf += len;
8523   }
8524   return TRUE;
8525 }
8526
8527 static gboolean
8528 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8529     GNode * xdxt)
8530 {
8531   int len = QT_UINT32 (xdxt->data);
8532   guint8 *buf = xdxt->data;
8533   guint8 *end = buf + len;
8534   GstBuffer *buffer;
8535
8536   /* skip size and type */
8537   buf += 8;
8538   end -= 8;
8539
8540   while (buf < end) {
8541     gint size;
8542     guint32 type;
8543
8544     size = QT_UINT32 (buf);
8545     type = QT_FOURCC (buf + 4);
8546
8547     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8548
8549     if (buf + size > end || size <= 0)
8550       break;
8551
8552     buf += 8;
8553     size -= 8;
8554
8555     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8556         GST_FOURCC_ARGS (type));
8557
8558     switch (type) {
8559       case FOURCC_tCtH:
8560         buffer = gst_buffer_new_and_alloc (size);
8561         gst_buffer_fill (buffer, 0, buf, size);
8562         stream->buffers = g_slist_append (stream->buffers, buffer);
8563         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8564         break;
8565       case FOURCC_tCt_:
8566         buffer = gst_buffer_new_and_alloc (size);
8567         gst_buffer_fill (buffer, 0, buf, size);
8568         stream->buffers = g_slist_append (stream->buffers, buffer);
8569         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8570         break;
8571       case FOURCC_tCtC:
8572         buffer = gst_buffer_new_and_alloc (size);
8573         gst_buffer_fill (buffer, 0, buf, size);
8574         stream->buffers = g_slist_append (stream->buffers, buffer);
8575         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8576         break;
8577       default:
8578         GST_WARNING_OBJECT (qtdemux,
8579             "unknown theora cookie %" GST_FOURCC_FORMAT,
8580             GST_FOURCC_ARGS (type));
8581         break;
8582     }
8583     buf += size;
8584   }
8585   return TRUE;
8586 }
8587
8588 static gboolean
8589 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8590     guint length)
8591 {
8592   guint32 fourcc = 0;
8593   guint32 node_length = 0;
8594   const QtNodeType *type;
8595   const guint8 *end;
8596
8597   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8598
8599   if (G_UNLIKELY (length < 8))
8600     goto not_enough_data;
8601
8602   node_length = QT_UINT32 (buffer);
8603   fourcc = QT_FOURCC (buffer + 4);
8604
8605   /* ignore empty nodes */
8606   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8607     return TRUE;
8608
8609   type = qtdemux_type_get (fourcc);
8610
8611   end = buffer + length;
8612
8613   GST_LOG_OBJECT (qtdemux,
8614       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8615       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8616
8617   if (node_length > length)
8618     goto broken_atom_size;
8619
8620   if (type->flags & QT_FLAG_CONTAINER) {
8621     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8622   } else {
8623     switch (fourcc) {
8624       case FOURCC_stsd:
8625       {
8626         if (node_length < 20) {
8627           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8628           break;
8629         }
8630         GST_DEBUG_OBJECT (qtdemux,
8631             "parsing stsd (sample table, sample description) atom");
8632         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8633         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8634         break;
8635       }
8636       case FOURCC_mp4a:
8637       case FOURCC_alac:
8638       case FOURCC_fLaC:
8639       case FOURCC_aavd:
8640       {
8641         guint32 version;
8642         guint32 offset;
8643         guint min_size;
8644
8645         /* also read alac (or whatever) in stead of mp4a in the following,
8646          * since a similar layout is used in other cases as well */
8647         if (fourcc == FOURCC_mp4a)
8648           min_size = 20;
8649         else if (fourcc == FOURCC_fLaC)
8650           min_size = 86;
8651         else
8652           min_size = 40;
8653
8654         /* There are two things we might encounter here: a true mp4a atom, and
8655            an mp4a entry in an stsd atom. The latter is what we're interested
8656            in, and it looks like an atom, but isn't really one. The true mp4a
8657            atom is short, so we detect it based on length here. */
8658         if (length < min_size) {
8659           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8660               GST_FOURCC_ARGS (fourcc));
8661           break;
8662         }
8663
8664         /* 'version' here is the sound sample description version. Types 0 and
8665            1 are documented in the QTFF reference, but type 2 is not: it's
8666            described in Apple header files instead (struct SoundDescriptionV2
8667            in Movies.h) */
8668         version = QT_UINT16 (buffer + 16);
8669
8670         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8671             GST_FOURCC_ARGS (fourcc), version);
8672
8673         /* parse any esds descriptors */
8674         switch (version) {
8675           case 0:
8676             offset = 0x24;
8677             break;
8678           case 1:
8679             offset = 0x34;
8680             break;
8681           case 2:
8682             offset = 0x48;
8683             break;
8684           default:
8685             GST_WARNING_OBJECT (qtdemux,
8686                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8687                 GST_FOURCC_ARGS (fourcc), version);
8688             offset = 0;
8689             break;
8690         }
8691         if (offset)
8692           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8693         break;
8694       }
8695       case FOURCC_mp4v:
8696       case FOURCC_MP4V:
8697       case FOURCC_fmp4:
8698       case FOURCC_FMP4:
8699       case FOURCC_apcs:
8700       case FOURCC_apch:
8701       case FOURCC_apcn:
8702       case FOURCC_apco:
8703       case FOURCC_ap4h:
8704       case FOURCC_xvid:
8705       case FOURCC_XVID:
8706       case FOURCC_H264:
8707       case FOURCC_avc1:
8708       case FOURCC_avc3:
8709       case FOURCC_H265:
8710       case FOURCC_hvc1:
8711       case FOURCC_hev1:
8712       case FOURCC_dvh1:
8713       case FOURCC_dvhe:
8714       case FOURCC_mjp2:
8715       case FOURCC_encv:
8716       {
8717         guint32 version;
8718         guint32 str_len;
8719
8720         /* codec_data is contained inside these atoms, which all have
8721          * the same format. */
8722         /* video sample description size is 86 bytes without extension.
8723          * node_length have to be bigger than 86 bytes because video sample
8724          * description can include extensions such as esds, fiel, glbl, etc. */
8725         if (node_length < 86) {
8726           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8727               " sample description length too short (%u < 86)",
8728               GST_FOURCC_ARGS (fourcc), node_length);
8729           break;
8730         }
8731
8732         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8733             GST_FOURCC_ARGS (fourcc));
8734
8735         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8736          *              its data format.
8737          * revision level (2 bytes) : must be set to 0. */
8738         version = QT_UINT32 (buffer + 16);
8739         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8740
8741         /* compressor name : PASCAL string and informative purposes
8742          * first byte : the number of bytes to be displayed.
8743          *              it has to be less than 32 because it is reserved
8744          *              space of 32 bytes total including itself. */
8745         str_len = QT_UINT8 (buffer + 50);
8746         if (str_len < 32)
8747           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8748               (char *) buffer + 51);
8749         else
8750           GST_WARNING_OBJECT (qtdemux,
8751               "compressorname length too big (%u > 31)", str_len);
8752
8753         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8754             end - buffer);
8755         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8756         break;
8757       }
8758       case FOURCC_meta:
8759       {
8760         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8761
8762         /* You are reading this correctly. QTFF specifies that the
8763          * metadata atom is a short atom, whereas ISO BMFF specifies
8764          * it's a full atom. But since so many people are doing things
8765          * differently, we actually peek into the atom to see which
8766          * variant it is */
8767         if (length < 16) {
8768           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8769               GST_FOURCC_ARGS (fourcc));
8770           break;
8771         }
8772         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8773           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8774            * starts with a 'hdlr' atom */
8775           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8776         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8777           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8778            * with version/flags both set to zero */
8779           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8780         } else
8781           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8782         break;
8783       }
8784       case FOURCC_mp4s:
8785       {
8786         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8787         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8788         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8789         break;
8790       }
8791       case FOURCC_XiTh:
8792       {
8793         guint32 version;
8794         guint32 offset;
8795
8796         if (length < 16) {
8797           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8798               GST_FOURCC_ARGS (fourcc));
8799           break;
8800         }
8801
8802         version = QT_UINT32 (buffer + 12);
8803         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8804
8805         switch (version) {
8806           case 0x00000001:
8807             offset = 0x62;
8808             break;
8809           default:
8810             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8811             offset = 0;
8812             break;
8813         }
8814         if (offset) {
8815           if (length < offset) {
8816             GST_WARNING_OBJECT (qtdemux,
8817                 "skipping too small %" GST_FOURCC_FORMAT " box",
8818                 GST_FOURCC_ARGS (fourcc));
8819             break;
8820           }
8821           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8822         }
8823         break;
8824       }
8825       case FOURCC_in24:
8826       {
8827         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8828         break;
8829       }
8830       case FOURCC_uuid:
8831       {
8832         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8833         break;
8834       }
8835       case FOURCC_enca:
8836       {
8837         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8838         break;
8839       }
8840 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
8841       case FOURCC_SA3D:
8842       {
8843         qtdemux_parse_SA3D (qtdemux, buffer, end - buffer);
8844         break;
8845       }
8846 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
8847       default:
8848         if (!strcmp (type->name, "unknown"))
8849           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8850         break;
8851     }
8852   }
8853   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8854       GST_FOURCC_ARGS (fourcc));
8855   return TRUE;
8856
8857 /* ERRORS */
8858 not_enough_data:
8859   {
8860     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8861         (_("This file is corrupt and cannot be played.")),
8862         ("Not enough data for an atom header, got only %u bytes", length));
8863     return FALSE;
8864   }
8865 broken_atom_size:
8866   {
8867     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8868         (_("This file is corrupt and cannot be played.")),
8869         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8870             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8871             length));
8872     return FALSE;
8873   }
8874 }
8875
8876 static void
8877 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8878 {
8879 /* FIXME: This can only reliably work if demuxers have a
8880  * separate streaming thread per srcpad. This should be
8881  * done in a demuxer base class, which integrates parts
8882  * of multiqueue
8883  *
8884  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8885  */
8886 #if 0
8887   GstQuery *query;
8888
8889   query = gst_query_new_allocation (stream->caps, FALSE);
8890
8891   if (!gst_pad_peer_query (stream->pad, query)) {
8892     /* not a problem, just debug a little */
8893     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8894   }
8895
8896   if (stream->allocator)
8897     gst_object_unref (stream->allocator);
8898
8899   if (gst_query_get_n_allocation_params (query) > 0) {
8900     /* try the allocator */
8901     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8902         &stream->params);
8903     stream->use_allocator = TRUE;
8904   } else {
8905     stream->allocator = NULL;
8906     gst_allocation_params_init (&stream->params);
8907     stream->use_allocator = FALSE;
8908   }
8909   gst_query_unref (query);
8910 #endif
8911 }
8912
8913 static gboolean
8914 pad_query (const GValue * item, GValue * value, gpointer user_data)
8915 {
8916   GstPad *pad = g_value_get_object (item);
8917   GstQuery *query = user_data;
8918   gboolean res;
8919
8920   res = gst_pad_peer_query (pad, query);
8921
8922   if (res) {
8923     g_value_set_boolean (value, TRUE);
8924     return FALSE;
8925   }
8926
8927   GST_INFO_OBJECT (pad, "pad peer query failed");
8928   return TRUE;
8929 }
8930
8931 static gboolean
8932 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8933     GstPadDirection direction)
8934 {
8935   GstIterator *it;
8936   GstIteratorFoldFunction func = pad_query;
8937   GValue res = { 0, };
8938
8939   g_value_init (&res, G_TYPE_BOOLEAN);
8940   g_value_set_boolean (&res, FALSE);
8941
8942   /* Ask neighbor */
8943   if (direction == GST_PAD_SRC)
8944     it = gst_element_iterate_src_pads (element);
8945   else
8946     it = gst_element_iterate_sink_pads (element);
8947
8948   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8949     gst_iterator_resync (it);
8950
8951   gst_iterator_free (it);
8952
8953   return g_value_get_boolean (&res);
8954 }
8955
8956 static void
8957 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8958     QtDemuxStream * stream)
8959 {
8960   GstQuery *query;
8961   GstContext *ctxt;
8962   GstElement *element = GST_ELEMENT (qtdemux);
8963   GstStructure *st;
8964   gchar **filtered_sys_ids;
8965   GValue event_list = G_VALUE_INIT;
8966   GList *walk;
8967
8968   /* 1. Check if we already have the context. */
8969   if (qtdemux->preferred_protection_system_id != NULL) {
8970     GST_LOG_OBJECT (element,
8971         "already have the protection context, no need to request it again");
8972     return;
8973   }
8974
8975   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8976   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8977       (const gchar **) qtdemux->protection_system_ids->pdata);
8978
8979   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8980       qtdemux->protection_system_ids->len - 1);
8981   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8982       "decryptors for %u of them, running context request",
8983       qtdemux->protection_system_ids->len,
8984       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8985
8986
8987   if (stream->protection_scheme_event_queue.length) {
8988     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8989         stream->protection_scheme_event_queue.length);
8990     walk = stream->protection_scheme_event_queue.tail;
8991   } else {
8992     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8993         qtdemux->protection_event_queue.length);
8994     walk = qtdemux->protection_event_queue.tail;
8995   }
8996
8997   g_value_init (&event_list, GST_TYPE_LIST);
8998   for (; walk; walk = g_list_previous (walk)) {
8999     GValue *event_value = g_new0 (GValue, 1);
9000     g_value_init (event_value, GST_TYPE_EVENT);
9001     g_value_set_boxed (event_value, walk->data);
9002     gst_value_list_append_and_take_value (&event_list, event_value);
9003   }
9004
9005   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
9006    *      check if downstream already has a context of the specific type
9007    *  2b) Query upstream as above.
9008    */
9009   query = gst_query_new_context ("drm-preferred-decryption-system-id");
9010   st = gst_query_writable_structure (query);
9011   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
9012       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
9013       NULL);
9014   gst_structure_set_value (st, "stream-encryption-events", &event_list);
9015   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
9016     gst_query_parse_context (query, &ctxt);
9017     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
9018     gst_element_set_context (element, ctxt);
9019   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
9020     gst_query_parse_context (query, &ctxt);
9021     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
9022     gst_element_set_context (element, ctxt);
9023   } else {
9024     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
9025      *    the required context type and afterwards check if a
9026      *    usable context was set now as in 1). The message could
9027      *    be handled by the parent bins of the element and the
9028      *    application.
9029      */
9030     GstMessage *msg;
9031
9032     GST_INFO_OBJECT (element, "posting need context message");
9033     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
9034         "drm-preferred-decryption-system-id");
9035     st = (GstStructure *) gst_message_get_structure (msg);
9036     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
9037         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
9038         NULL);
9039
9040     gst_structure_set_value (st, "stream-encryption-events", &event_list);
9041     gst_element_post_message (element, msg);
9042   }
9043
9044   g_strfreev (filtered_sys_ids);
9045   g_value_unset (&event_list);
9046   gst_query_unref (query);
9047 }
9048
9049 static gboolean
9050 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
9051     QtDemuxStream * stream)
9052 {
9053   GstStructure *s;
9054   const gchar *selected_system = NULL;
9055
9056   g_return_val_if_fail (qtdemux != NULL, FALSE);
9057   g_return_val_if_fail (stream != NULL, FALSE);
9058   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
9059       FALSE);
9060
9061   if (stream->protection_scheme_type == FOURCC_aavd) {
9062     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
9063     if (!gst_structure_has_name (s, "application/x-aavd")) {
9064       gst_structure_set (s,
9065           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
9066           NULL);
9067       gst_structure_set_name (s, "application/x-aavd");
9068     }
9069     return TRUE;
9070   }
9071
9072   if (stream->protection_scheme_type != FOURCC_cenc
9073       && stream->protection_scheme_type != FOURCC_cbcs) {
9074     GST_ERROR_OBJECT (qtdemux,
9075         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
9076         GST_FOURCC_ARGS (stream->protection_scheme_type));
9077     return FALSE;
9078   }
9079
9080   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
9081   if (!gst_structure_has_name (s, "application/x-cenc")) {
9082     gst_structure_set (s,
9083         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
9084     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
9085         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
9086         NULL);
9087     gst_structure_set_name (s, "application/x-cenc");
9088   }
9089
9090   if (qtdemux->protection_system_ids == NULL) {
9091     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
9092         "cenc protection system information has been found, not setting a "
9093         "protection system UUID");
9094     return TRUE;
9095   }
9096
9097   gst_qtdemux_request_protection_context (qtdemux, stream);
9098   if (qtdemux->preferred_protection_system_id != NULL) {
9099     const gchar *preferred_system_array[] =
9100         { qtdemux->preferred_protection_system_id, NULL };
9101
9102     selected_system = gst_protection_select_system (preferred_system_array);
9103
9104     if (selected_system) {
9105       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
9106           qtdemux->preferred_protection_system_id);
9107     } else {
9108       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
9109           "because there is no available decryptor",
9110           qtdemux->preferred_protection_system_id);
9111     }
9112   }
9113
9114   if (!selected_system) {
9115     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
9116     selected_system = gst_protection_select_system ((const gchar **)
9117         qtdemux->protection_system_ids->pdata);
9118     g_ptr_array_remove_index (qtdemux->protection_system_ids,
9119         qtdemux->protection_system_ids->len - 1);
9120   }
9121
9122   if (!selected_system) {
9123     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
9124         "suitable decryptor element has been found");
9125     return FALSE;
9126   }
9127
9128   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
9129       selected_system);
9130
9131   gst_structure_set (s,
9132       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
9133       NULL);
9134
9135   return TRUE;
9136 }
9137
9138 static gboolean
9139 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
9140 {
9141   /* fps is calculated base on the duration of the average framerate since
9142    * qt does not have a fixed framerate. */
9143   gboolean fps_available = TRUE;
9144   guint32 first_duration = 0;
9145
9146   if (stream->n_samples > 0)
9147     first_duration = stream->samples[0].duration;
9148
9149   if ((stream->n_samples == 1 && first_duration == 0)
9150       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
9151     /* still frame */
9152     CUR_STREAM (stream)->fps_n = 0;
9153     CUR_STREAM (stream)->fps_d = 1;
9154   } else {
9155     if (stream->duration == 0 || stream->n_samples < 2) {
9156       CUR_STREAM (stream)->fps_n = stream->timescale;
9157       CUR_STREAM (stream)->fps_d = 1;
9158       fps_available = FALSE;
9159     } else {
9160       GstClockTime avg_duration;
9161       guint64 duration;
9162       guint32 n_samples;
9163
9164       /* duration and n_samples can be updated for fragmented format
9165        * so, framerate of fragmented format is calculated using data in a moof */
9166       if (qtdemux->fragmented && stream->n_samples_moof > 0
9167           && stream->duration_moof > 0) {
9168         n_samples = stream->n_samples_moof;
9169         duration = stream->duration_moof;
9170       } else {
9171         n_samples = stream->n_samples;
9172         duration = stream->duration;
9173       }
9174
9175       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
9176       /* stream->duration is guint64, timescale, n_samples are guint32 */
9177       avg_duration =
9178           gst_util_uint64_scale_round (duration -
9179           first_duration, GST_SECOND,
9180           (guint64) (stream->timescale) * (n_samples - 1));
9181
9182       GST_LOG_OBJECT (qtdemux,
9183           "Calculating avg sample duration based on stream (or moof) duration %"
9184           G_GUINT64_FORMAT
9185           " minus first sample %u, leaving %d samples gives %"
9186           GST_TIME_FORMAT, duration, first_duration,
9187           n_samples - 1, GST_TIME_ARGS (avg_duration));
9188
9189 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
9190       gst_video_guess_framerate (avg_duration,
9191         &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
9192       if (CUR_STREAM (stream)->fps_d == 0)
9193         fps_available = FALSE;
9194 #else
9195       fps_available =
9196           gst_video_guess_framerate (avg_duration,
9197           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
9198 #endif
9199
9200       GST_DEBUG_OBJECT (qtdemux,
9201           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
9202           stream->timescale, CUR_STREAM (stream)->fps_n,
9203           CUR_STREAM (stream)->fps_d);
9204     }
9205   }
9206
9207   return fps_available;
9208 }
9209
9210 static gboolean
9211 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
9212 {
9213   if (stream->subtype == FOURCC_vide) {
9214     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
9215
9216     if (CUR_STREAM (stream)->caps) {
9217       CUR_STREAM (stream)->caps =
9218           gst_caps_make_writable (CUR_STREAM (stream)->caps);
9219
9220       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
9221         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9222             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
9223             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
9224
9225       /* set framerate if calculated framerate is reliable */
9226       if (fps_available) {
9227         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9228             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
9229             CUR_STREAM (stream)->fps_d, NULL);
9230       }
9231
9232       /* calculate pixel-aspect-ratio using display width and height */
9233       GST_DEBUG_OBJECT (qtdemux,
9234           "video size %dx%d, target display size %dx%d",
9235           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
9236           stream->display_width, stream->display_height);
9237       /* qt file might have pasp atom */
9238       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
9239         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
9240             CUR_STREAM (stream)->par_h);
9241         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
9242             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
9243             CUR_STREAM (stream)->par_h, NULL);
9244       } else if (stream->display_width > 0 && stream->display_height > 0
9245           && CUR_STREAM (stream)->width > 0
9246           && CUR_STREAM (stream)->height > 0) {
9247         gint n, d;
9248
9249         /* calculate the pixel aspect ratio using the display and pixel w/h */
9250         n = stream->display_width * CUR_STREAM (stream)->height;
9251         d = stream->display_height * CUR_STREAM (stream)->width;
9252         if (n == d)
9253           n = d = 1;
9254         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
9255         CUR_STREAM (stream)->par_w = n;
9256         CUR_STREAM (stream)->par_h = d;
9257         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
9258             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
9259             CUR_STREAM (stream)->par_h, NULL);
9260       }
9261
9262       if (CUR_STREAM (stream)->interlace_mode > 0) {
9263         if (CUR_STREAM (stream)->interlace_mode == 1) {
9264           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
9265               G_TYPE_STRING, "progressive", NULL);
9266         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
9267           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
9268               G_TYPE_STRING, "interleaved", NULL);
9269           if (CUR_STREAM (stream)->field_order == 9) {
9270             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
9271                 G_TYPE_STRING, "top-field-first", NULL);
9272           } else if (CUR_STREAM (stream)->field_order == 14) {
9273             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
9274                 G_TYPE_STRING, "bottom-field-first", NULL);
9275           }
9276         }
9277       }
9278
9279       /* Create incomplete colorimetry here if needed */
9280       if (CUR_STREAM (stream)->colorimetry.range ||
9281           CUR_STREAM (stream)->colorimetry.matrix ||
9282           CUR_STREAM (stream)->colorimetry.transfer
9283           || CUR_STREAM (stream)->colorimetry.primaries) {
9284         gchar *colorimetry =
9285             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
9286         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
9287             G_TYPE_STRING, colorimetry, NULL);
9288         g_free (colorimetry);
9289       }
9290
9291       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
9292         guint par_w = 1, par_h = 1;
9293
9294         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
9295           par_w = CUR_STREAM (stream)->par_w;
9296           par_h = CUR_STREAM (stream)->par_h;
9297         }
9298
9299         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
9300                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
9301                 par_h)) {
9302           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
9303         }
9304
9305         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9306             "multiview-mode", G_TYPE_STRING,
9307             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
9308             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
9309             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
9310       }
9311     }
9312   }
9313
9314   else if (stream->subtype == FOURCC_soun) {
9315     if (CUR_STREAM (stream)->caps) {
9316       CUR_STREAM (stream)->caps =
9317           gst_caps_make_writable (CUR_STREAM (stream)->caps);
9318       if (CUR_STREAM (stream)->rate > 0)
9319         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9320             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
9321       if (CUR_STREAM (stream)->n_channels > 0)
9322         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9323             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
9324       if (CUR_STREAM (stream)->n_channels > 2) {
9325         /* FIXME: Need to parse the 'chan' atom to get channel layouts
9326          * correctly; this is just the minimum we can do - assume
9327          * we don't actually have any channel positions. */
9328         gst_caps_set_simple (CUR_STREAM (stream)->caps,
9329             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
9330       }
9331     }
9332   }
9333
9334   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
9335     const GstStructure *s;
9336     QtDemuxStream *fps_stream = NULL;
9337     gboolean fps_available = FALSE;
9338
9339     /* CEA608 closed caption tracks are a bit special in that each sample
9340      * can contain CCs for multiple frames, and CCs can be omitted and have to
9341      * be inferred from the duration of the sample then.
9342      *
9343      * As such we take the framerate from the (first) video track here for
9344      * CEA608 as there must be one CC byte pair for every video frame
9345      * according to the spec.
9346      *
9347      * For CEA708 all is fine and there is one sample per frame.
9348      */
9349
9350     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
9351     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
9352       gint i;
9353
9354       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
9355         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
9356
9357         if (tmp->subtype == FOURCC_vide) {
9358           fps_stream = tmp;
9359           break;
9360         }
9361       }
9362
9363       if (fps_stream) {
9364         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
9365         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
9366         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
9367       }
9368     } else {
9369       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
9370       fps_stream = stream;
9371     }
9372
9373     CUR_STREAM (stream)->caps =
9374         gst_caps_make_writable (CUR_STREAM (stream)->caps);
9375
9376     /* set framerate if calculated framerate is reliable */
9377     if (fps_available) {
9378       gst_caps_set_simple (CUR_STREAM (stream)->caps,
9379           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
9380           CUR_STREAM (stream)->fps_d, NULL);
9381     }
9382   }
9383
9384   if (stream->pad) {
9385     GstCaps *prev_caps = NULL;
9386
9387     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9388     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9389     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9390     gst_pad_set_active (stream->pad, TRUE);
9391
9392     gst_pad_use_fixed_caps (stream->pad);
9393
9394     if (stream->protected) {
9395       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9396         GST_ERROR_OBJECT (qtdemux,
9397             "Failed to configure protected stream caps.");
9398         return FALSE;
9399       }
9400     }
9401
9402     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9403         CUR_STREAM (stream)->caps);
9404     if (stream->new_stream) {
9405       GstEvent *event;
9406       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9407
9408       event =
9409           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9410           0);
9411       if (event) {
9412         gst_event_parse_stream_flags (event, &stream_flags);
9413         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9414           qtdemux->have_group_id = TRUE;
9415         else
9416           qtdemux->have_group_id = FALSE;
9417         gst_event_unref (event);
9418       } else if (!qtdemux->have_group_id) {
9419         qtdemux->have_group_id = TRUE;
9420         qtdemux->group_id = gst_util_group_id_next ();
9421       }
9422
9423       stream->new_stream = FALSE;
9424       event = gst_event_new_stream_start (stream->stream_id);
9425       if (qtdemux->have_group_id)
9426         gst_event_set_group_id (event, qtdemux->group_id);
9427       if (stream->disabled)
9428         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9429       if (CUR_STREAM (stream)->sparse) {
9430         stream_flags |= GST_STREAM_FLAG_SPARSE;
9431       } else {
9432         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9433       }
9434       gst_event_set_stream_flags (event, stream_flags);
9435       gst_pad_push_event (stream->pad, event);
9436     }
9437
9438     prev_caps = gst_pad_get_current_caps (stream->pad);
9439
9440     if (CUR_STREAM (stream)->caps) {
9441       if (!prev_caps
9442           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9443         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9444             CUR_STREAM (stream)->caps);
9445         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9446       } else {
9447         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9448       }
9449     } else {
9450       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9451     }
9452
9453     if (prev_caps)
9454       gst_caps_unref (prev_caps);
9455     stream->new_caps = FALSE;
9456   }
9457   return TRUE;
9458 }
9459
9460 static void
9461 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9462     QtDemuxStream * stream)
9463 {
9464   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9465     return;
9466
9467   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9468       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9469   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9470           stream->stsd_entries_length)) {
9471     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9472         (_("This file is invalid and cannot be played.")),
9473         ("New sample description id is out of bounds (%d >= %d)",
9474             stream->stsd_sample_description_id, stream->stsd_entries_length));
9475   } else {
9476     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9477     stream->new_caps = TRUE;
9478   }
9479 }
9480
9481 static gboolean
9482 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9483     QtDemuxStream * stream, GstTagList * list)
9484 {
9485   gboolean ret = TRUE;
9486
9487   if (stream->subtype == FOURCC_vide) {
9488     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9489
9490     stream->pad =
9491         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9492     g_free (name);
9493
9494     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9495       gst_object_unref (stream->pad);
9496       stream->pad = NULL;
9497       ret = FALSE;
9498       goto done;
9499     }
9500
9501     qtdemux->n_video_streams++;
9502   } else if (stream->subtype == FOURCC_soun) {
9503     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9504
9505     stream->pad =
9506         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9507     g_free (name);
9508     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9509       gst_object_unref (stream->pad);
9510       stream->pad = NULL;
9511       ret = FALSE;
9512       goto done;
9513     }
9514     qtdemux->n_audio_streams++;
9515   } else if (stream->subtype == FOURCC_strm) {
9516     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9517   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9518       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9519       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9520     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9521
9522     stream->pad =
9523         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9524     g_free (name);
9525     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9526       gst_object_unref (stream->pad);
9527       stream->pad = NULL;
9528       ret = FALSE;
9529       goto done;
9530     }
9531     qtdemux->n_sub_streams++;
9532   } else if (CUR_STREAM (stream)->caps) {
9533     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9534
9535     stream->pad =
9536         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9537     g_free (name);
9538     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9539       gst_object_unref (stream->pad);
9540       stream->pad = NULL;
9541       ret = FALSE;
9542       goto done;
9543     }
9544     qtdemux->n_video_streams++;
9545   } else {
9546     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9547     goto done;
9548   }
9549
9550   if (stream->pad) {
9551     GList *l;
9552
9553     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9554         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9555     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9556     GST_OBJECT_LOCK (qtdemux);
9557     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9558     GST_OBJECT_UNLOCK (qtdemux);
9559
9560     if (stream->stream_tags)
9561       gst_tag_list_unref (stream->stream_tags);
9562     stream->stream_tags = list;
9563     list = NULL;
9564     /* global tags go on each pad anyway */
9565     stream->send_global_tags = TRUE;
9566     /* send upstream GST_EVENT_PROTECTION events that were received before
9567        this source pad was created */
9568     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9569       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9570   }
9571 done:
9572   if (list)
9573     gst_tag_list_unref (list);
9574   return ret;
9575 }
9576
9577 /* find next atom with @fourcc starting at @offset */
9578 static GstFlowReturn
9579 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9580     guint64 * length, guint32 fourcc)
9581 {
9582   GstFlowReturn ret;
9583   guint32 lfourcc;
9584   GstBuffer *buf;
9585
9586   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9587       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9588
9589   while (TRUE) {
9590     GstMapInfo map;
9591
9592     buf = NULL;
9593     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9594     if (G_UNLIKELY (ret != GST_FLOW_OK))
9595       goto locate_failed;
9596     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9597       /* likely EOF */
9598       ret = GST_FLOW_EOS;
9599       gst_buffer_unref (buf);
9600       goto locate_failed;
9601     }
9602     gst_buffer_map (buf, &map, GST_MAP_READ);
9603     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9604     gst_buffer_unmap (buf, &map);
9605     gst_buffer_unref (buf);
9606
9607     if (G_UNLIKELY (*length == 0)) {
9608       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9609       ret = GST_FLOW_ERROR;
9610       goto locate_failed;
9611     }
9612
9613     if (lfourcc == fourcc) {
9614       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9615           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9616       break;
9617     } else {
9618       GST_LOG_OBJECT (qtdemux,
9619           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9620           GST_FOURCC_ARGS (lfourcc), *offset);
9621       if (*offset == G_MAXUINT64)
9622         goto locate_failed;
9623       *offset += *length;
9624     }
9625   }
9626
9627   return GST_FLOW_OK;
9628
9629 locate_failed:
9630   {
9631     /* might simply have had last one */
9632     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9633     return ret;
9634   }
9635 }
9636
9637 /* should only do something in pull mode */
9638 /* call with OBJECT lock */
9639 static GstFlowReturn
9640 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9641 {
9642   guint64 length, offset;
9643   GstBuffer *buf = NULL;
9644   GstFlowReturn ret = GST_FLOW_OK;
9645   GstFlowReturn res = GST_FLOW_OK;
9646   GstMapInfo map;
9647
9648   offset = qtdemux->moof_offset;
9649   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9650
9651   if (!offset) {
9652     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9653     return GST_FLOW_EOS;
9654   }
9655
9656   /* best not do pull etc with lock held */
9657   GST_OBJECT_UNLOCK (qtdemux);
9658
9659   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9660   if (ret != GST_FLOW_OK)
9661     goto flow_failed;
9662
9663   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9664   if (G_UNLIKELY (ret != GST_FLOW_OK))
9665     goto flow_failed;
9666   gst_buffer_map (buf, &map, GST_MAP_READ);
9667   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9668     gst_buffer_unmap (buf, &map);
9669     gst_buffer_unref (buf);
9670     buf = NULL;
9671     goto parse_failed;
9672   }
9673
9674   gst_buffer_unmap (buf, &map);
9675   gst_buffer_unref (buf);
9676   buf = NULL;
9677
9678   offset += length;
9679   /* look for next moof */
9680   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9681   if (G_UNLIKELY (ret != GST_FLOW_OK))
9682     goto flow_failed;
9683
9684 exit:
9685   GST_OBJECT_LOCK (qtdemux);
9686
9687   qtdemux->moof_offset = offset;
9688
9689   return res;
9690
9691 parse_failed:
9692   {
9693     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9694     offset = 0;
9695     res = GST_FLOW_ERROR;
9696     goto exit;
9697   }
9698 flow_failed:
9699   {
9700     /* maybe upstream temporarily flushing */
9701     if (ret != GST_FLOW_FLUSHING) {
9702       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9703       offset = 0;
9704     } else {
9705       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9706       /* resume at current position next time */
9707     }
9708     res = ret;
9709     goto exit;
9710   }
9711 }
9712
9713 static void
9714 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9715 {
9716   guint i;
9717   guint32 num_chunks;
9718   gint32 stts_duration;
9719   GstByteWriter stsc, stts, stsz;
9720
9721   /* Each sample has a different size, which we don't support for merging */
9722   if (stream->sample_size == 0) {
9723     GST_DEBUG_OBJECT (qtdemux,
9724         "Not all samples have the same size, not merging");
9725     return;
9726   }
9727
9728   /* The stream has a ctts table, we don't support that */
9729   if (stream->ctts_present) {
9730     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9731     return;
9732   }
9733
9734   /* If there's a sync sample table also ignore this stream */
9735   if (stream->stps_present || stream->stss_present) {
9736     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9737     return;
9738   }
9739
9740   /* If chunks are considered samples already ignore this stream */
9741   if (stream->chunks_are_samples) {
9742     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9743     return;
9744   }
9745
9746   /* Require that all samples have the same duration */
9747   if (stream->n_sample_times > 1) {
9748     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9749     return;
9750   }
9751
9752   /* Parse the stts to get the sample duration and number of samples */
9753   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9754   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9755
9756   /* Parse the number of chunks from the stco manually because the
9757    * reader is already behind that */
9758   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9759
9760   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9761       num_chunks);
9762
9763   /* Now parse stsc, convert chunks into single samples and generate a
9764    * new stsc, stts and stsz from this information */
9765   gst_byte_writer_init (&stsc);
9766   gst_byte_writer_init (&stts);
9767   gst_byte_writer_init (&stsz);
9768
9769   /* Note: we skip fourccs, size, version, flags and other fields of the new
9770    * atoms as the byte readers with them are already behind that position
9771    * anyway and only update the values of those inside the stream directly.
9772    */
9773   stream->n_sample_times = 0;
9774   stream->n_samples = 0;
9775   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9776     guint j;
9777     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9778
9779     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9780     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9781     sample_description_id =
9782         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9783
9784     if (i == stream->n_samples_per_chunk - 1) {
9785       /* +1 because first_chunk is 1-based */
9786       last_chunk = num_chunks + 1;
9787     } else {
9788       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9789     }
9790
9791     GST_DEBUG_OBJECT (qtdemux,
9792         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9793         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9794
9795     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9796     /* One sample in this chunk */
9797     gst_byte_writer_put_uint32_be (&stsc, 1);
9798     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9799
9800     /* For each chunk write a stts and stsz entry now */
9801     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9802     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9803     for (j = first_chunk; j < last_chunk; j++) {
9804       gst_byte_writer_put_uint32_be (&stsz,
9805           stream->sample_size * samples_per_chunk);
9806     }
9807
9808     stream->n_sample_times += 1;
9809     stream->n_samples += last_chunk - first_chunk;
9810   }
9811
9812   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9813
9814   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9815       stream->n_samples, stream->n_sample_times);
9816
9817   /* We don't have a fixed sample size anymore */
9818   stream->sample_size = 0;
9819
9820   /* Free old data for the atoms */
9821   g_free ((gpointer) stream->stsz.data);
9822   stream->stsz.data = NULL;
9823   g_free ((gpointer) stream->stsc.data);
9824   stream->stsc.data = NULL;
9825   g_free ((gpointer) stream->stts.data);
9826   stream->stts.data = NULL;
9827
9828   /* Store new data and replace byte readers */
9829   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9830   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9831   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9832   stream->stts.size = gst_byte_writer_get_size (&stts);
9833   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9834   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9835   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9836   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9837   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9838 }
9839
9840 /* initialise bytereaders for stbl sub-atoms */
9841 static gboolean
9842 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9843 {
9844   stream->stbl_index = -1;      /* no samples have yet been parsed */
9845   stream->sample_index = -1;
9846
9847   /* time-to-sample atom */
9848   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9849     goto corrupt_file;
9850
9851   /* copy atom data into a new buffer for later use */
9852   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9853
9854   /* skip version + flags */
9855   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9856       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9857     goto corrupt_file;
9858   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9859
9860   /* make sure there's enough data */
9861   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9862     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9863     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9864         stream->n_sample_times);
9865     if (!stream->n_sample_times)
9866       goto corrupt_file;
9867   }
9868
9869   /* sync sample atom */
9870   stream->stps_present = FALSE;
9871   if ((stream->stss_present =
9872           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9873               &stream->stss) ? TRUE : FALSE) == TRUE) {
9874     /* copy atom data into a new buffer for later use */
9875     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9876
9877     /* skip version + flags */
9878     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9879         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9880       goto corrupt_file;
9881
9882     if (stream->n_sample_syncs) {
9883       /* make sure there's enough data */
9884       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9885         goto corrupt_file;
9886     }
9887
9888     /* partial sync sample atom */
9889     if ((stream->stps_present =
9890             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9891                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9892       /* copy atom data into a new buffer for later use */
9893       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9894
9895       /* skip version + flags */
9896       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9897           !gst_byte_reader_get_uint32_be (&stream->stps,
9898               &stream->n_sample_partial_syncs))
9899         goto corrupt_file;
9900
9901       /* if there are no entries, the stss table contains the real
9902        * sync samples */
9903       if (stream->n_sample_partial_syncs) {
9904         /* make sure there's enough data */
9905         if (!qt_atom_parser_has_chunks (&stream->stps,
9906                 stream->n_sample_partial_syncs, 4))
9907           goto corrupt_file;
9908       }
9909     }
9910   }
9911
9912   /* sample size */
9913   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9914     goto no_samples;
9915
9916   /* copy atom data into a new buffer for later use */
9917   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9918
9919   /* skip version + flags */
9920   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9921       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9922     goto corrupt_file;
9923
9924   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9925     goto corrupt_file;
9926
9927   if (!stream->n_samples)
9928     goto no_samples;
9929
9930   /* sample-to-chunk atom */
9931   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9932     goto corrupt_file;
9933
9934   /* copy atom data into a new buffer for later use */
9935   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9936
9937   /* skip version + flags */
9938   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9939       !gst_byte_reader_get_uint32_be (&stream->stsc,
9940           &stream->n_samples_per_chunk))
9941     goto corrupt_file;
9942
9943   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9944       stream->n_samples_per_chunk);
9945
9946   /* make sure there's enough data */
9947   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9948           12))
9949     goto corrupt_file;
9950
9951
9952   /* chunk offset */
9953   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9954     stream->co_size = sizeof (guint32);
9955   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9956           &stream->stco))
9957     stream->co_size = sizeof (guint64);
9958   else
9959     goto corrupt_file;
9960
9961   /* copy atom data into a new buffer for later use */
9962   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9963
9964   /* skip version + flags */
9965   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9966     goto corrupt_file;
9967
9968   /* chunks_are_samples == TRUE means treat chunks as samples */
9969   stream->chunks_are_samples = stream->sample_size
9970       && !CUR_STREAM (stream)->sampled;
9971   if (stream->chunks_are_samples) {
9972     /* treat chunks as samples */
9973     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9974       goto corrupt_file;
9975   } else {
9976     /* skip number of entries */
9977     if (!gst_byte_reader_skip (&stream->stco, 4))
9978       goto corrupt_file;
9979
9980     /* make sure there are enough data in the stsz atom */
9981     if (!stream->sample_size) {
9982       /* different sizes for each sample */
9983       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9984         goto corrupt_file;
9985     }
9986   }
9987
9988   /* composition time-to-sample */
9989   if ((stream->ctts_present =
9990           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9991               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9992     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9993     guint8 ctts_version;
9994     gboolean checked_ctts = FALSE;
9995
9996     /* copy atom data into a new buffer for later use */
9997     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9998
9999     /* version 1 has signed offsets */
10000     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
10001       goto corrupt_file;
10002
10003     /* flags */
10004     if (!gst_byte_reader_skip (&stream->ctts, 3)
10005         || !gst_byte_reader_get_uint32_be (&stream->ctts,
10006             &stream->n_composition_times))
10007       goto corrupt_file;
10008
10009     /* make sure there's enough data */
10010     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
10011             4 + 4))
10012       goto corrupt_file;
10013
10014     /* This is optional, if missing we iterate the ctts */
10015     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
10016       guint8 cslg_version;
10017
10018       /* cslg version 1 has 64 bit fields */
10019       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
10020         goto corrupt_file;
10021
10022       /* skip flags */
10023       if (!gst_byte_reader_skip (&cslg, 3))
10024         goto corrupt_file;
10025
10026       if (cslg_version == 0) {
10027         gint32 composition_to_dts_shift;
10028
10029         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
10030           goto corrupt_file;
10031
10032         stream->cslg_shift = MAX (0, composition_to_dts_shift);
10033       } else {
10034         gint64 composition_to_dts_shift;
10035
10036         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
10037           goto corrupt_file;
10038
10039         stream->cslg_shift = MAX (0, composition_to_dts_shift);
10040       }
10041     } else {
10042       gint32 cslg_least = 0;
10043       guint num_entries, pos;
10044       gint i;
10045
10046       pos = gst_byte_reader_get_pos (&stream->ctts);
10047       num_entries = stream->n_composition_times;
10048
10049       checked_ctts = TRUE;
10050
10051       stream->cslg_shift = 0;
10052
10053       for (i = 0; i < num_entries; i++) {
10054         gint32 offset;
10055
10056         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
10057         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10058         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
10059          * slightly inaccurate PTS could be more usable than corrupted one */
10060         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
10061                 && ABS (offset) / 2 > stream->duration)) {
10062           GST_WARNING_OBJECT (qtdemux,
10063               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
10064               " larger than duration %" G_GUINT64_FORMAT, offset,
10065               stream->duration);
10066
10067           stream->cslg_shift = 0;
10068           stream->ctts_present = FALSE;
10069           goto done;
10070         }
10071
10072         /* Don't consider "no decode samples" with offset G_MININT32
10073          * for the DTS/PTS shift */
10074         if (offset != G_MININT32 && offset < cslg_least)
10075           cslg_least = offset;
10076       }
10077
10078       if (cslg_least < 0)
10079         stream->cslg_shift = -cslg_least;
10080       else
10081         stream->cslg_shift = 0;
10082
10083       /* reset the reader so we can generate sample table */
10084       gst_byte_reader_set_pos (&stream->ctts, pos);
10085     }
10086
10087     /* Check if ctts values are looking reasonable if that didn't happen above */
10088     if (!checked_ctts) {
10089       guint num_entries, pos;
10090       gint i;
10091
10092       pos = gst_byte_reader_get_pos (&stream->ctts);
10093       num_entries = stream->n_composition_times;
10094
10095       for (i = 0; i < num_entries; i++) {
10096         gint32 offset;
10097
10098         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
10099         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10100         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
10101          * slightly inaccurate PTS could be more usable than corrupted one */
10102         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
10103                 && ABS (offset) / 2 > stream->duration)) {
10104           GST_WARNING_OBJECT (qtdemux,
10105               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
10106               " larger than duration %" G_GUINT64_FORMAT, offset,
10107               stream->duration);
10108
10109           stream->cslg_shift = 0;
10110           stream->ctts_present = FALSE;
10111           goto done;
10112         }
10113       }
10114
10115       /* reset the reader so we can generate sample table */
10116       gst_byte_reader_set_pos (&stream->ctts, pos);
10117     }
10118   } else {
10119     /* Ensure the cslg_shift value is consistent so we can use it
10120      * unconditionally to produce TS and Segment */
10121     stream->cslg_shift = 0;
10122   }
10123
10124   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
10125       stream->cslg_shift);
10126
10127   /* For raw audio streams especially we might want to merge the samples
10128    * to not output one audio sample per buffer. We're doing this here
10129    * before allocating the sample tables so that from this point onwards
10130    * the number of container samples are static */
10131   if (stream->min_buffer_size > 0) {
10132     qtdemux_merge_sample_table (qtdemux, stream);
10133   }
10134
10135 done:
10136   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
10137       stream->n_samples, (guint) sizeof (QtDemuxSample),
10138       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
10139
10140   if (stream->n_samples >=
10141       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
10142     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
10143         "be larger than %uMB (broken file?)", stream->n_samples,
10144         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
10145     return FALSE;
10146   }
10147
10148   g_assert (stream->samples == NULL);
10149   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
10150   if (!stream->samples) {
10151     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
10152         stream->n_samples);
10153     return FALSE;
10154   }
10155
10156   return TRUE;
10157
10158 corrupt_file:
10159   {
10160     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10161         (_("This file is corrupt and cannot be played.")), (NULL));
10162     return FALSE;
10163   }
10164 no_samples:
10165   {
10166     gst_qtdemux_stbl_free (stream);
10167     if (!qtdemux->fragmented) {
10168       /* not quite good */
10169       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
10170       return FALSE;
10171     } else {
10172       /* may pick up samples elsewhere */
10173       return TRUE;
10174     }
10175   }
10176 }
10177
10178 /* collect samples from the next sample to be parsed up to sample @n for @stream
10179  * by reading the info from @stbl
10180  *
10181  * This code can be executed from both the streaming thread and the seeking
10182  * thread so it takes the object lock to protect itself
10183  */
10184 static gboolean
10185 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
10186 {
10187   gint i, j, k;
10188   QtDemuxSample *samples, *first, *cur, *last;
10189   guint32 n_samples_per_chunk;
10190   guint32 n_samples;
10191
10192   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
10193       GST_FOURCC_FORMAT ", pad %s",
10194       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
10195       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
10196
10197   n_samples = stream->n_samples;
10198
10199   if (n >= n_samples)
10200     goto out_of_samples;
10201
10202   GST_OBJECT_LOCK (qtdemux);
10203   if (n <= stream->stbl_index)
10204     goto already_parsed;
10205
10206   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
10207
10208   if (!stream->stsz.data) {
10209     /* so we already parsed and passed all the moov samples;
10210      * onto fragmented ones */
10211     g_assert (qtdemux->fragmented);
10212     goto done;
10213   }
10214
10215   /* pointer to the sample table */
10216   samples = stream->samples;
10217
10218   /* starts from -1, moves to the next sample index to parse */
10219   stream->stbl_index++;
10220
10221   /* keep track of the first and last sample to fill */
10222   first = &samples[stream->stbl_index];
10223   last = &samples[n];
10224
10225   if (!stream->chunks_are_samples) {
10226     /* set the sample sizes */
10227     if (stream->sample_size == 0) {
10228       /* different sizes for each sample */
10229       for (cur = first; cur <= last; cur++) {
10230         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
10231         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
10232             (guint) (cur - samples), cur->size);
10233       }
10234     } else {
10235       /* samples have the same size */
10236       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
10237       for (cur = first; cur <= last; cur++)
10238         cur->size = stream->sample_size;
10239     }
10240   }
10241
10242   n_samples_per_chunk = stream->n_samples_per_chunk;
10243   cur = first;
10244
10245   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
10246     guint32 last_chunk;
10247
10248     if (stream->stsc_chunk_index >= stream->last_chunk
10249         || stream->stsc_chunk_index < stream->first_chunk) {
10250       stream->first_chunk =
10251           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10252       stream->samples_per_chunk =
10253           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
10254       /* starts from 1 */
10255       stream->stsd_sample_description_id =
10256           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
10257
10258       /* chunk numbers are counted from 1 it seems */
10259       if (G_UNLIKELY (stream->first_chunk == 0))
10260         goto corrupt_file;
10261
10262       --stream->first_chunk;
10263
10264       /* the last chunk of each entry is calculated by taking the first chunk
10265        * of the next entry; except if there is no next, where we fake it with
10266        * INT_MAX */
10267       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
10268         stream->last_chunk = G_MAXUINT32;
10269       } else {
10270         stream->last_chunk =
10271             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
10272         if (G_UNLIKELY (stream->last_chunk == 0))
10273           goto corrupt_file;
10274
10275         --stream->last_chunk;
10276       }
10277
10278       GST_LOG_OBJECT (qtdemux,
10279           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
10280           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
10281           stream->samples_per_chunk, stream->stsd_sample_description_id);
10282
10283       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
10284         goto corrupt_file;
10285
10286       if (stream->last_chunk != G_MAXUINT32) {
10287         if (!qt_atom_parser_peek_sub (&stream->stco,
10288                 stream->first_chunk * stream->co_size,
10289                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
10290                 &stream->co_chunk))
10291           goto corrupt_file;
10292
10293       } else {
10294         stream->co_chunk = stream->stco;
10295         if (!gst_byte_reader_skip (&stream->co_chunk,
10296                 stream->first_chunk * stream->co_size))
10297           goto corrupt_file;
10298       }
10299
10300       stream->stsc_chunk_index = stream->first_chunk;
10301     }
10302
10303     last_chunk = stream->last_chunk;
10304
10305     if (stream->chunks_are_samples) {
10306       cur = &samples[stream->stsc_chunk_index];
10307
10308       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
10309         if (j > n) {
10310           /* save state */
10311           stream->stsc_chunk_index = j;
10312           goto done;
10313         }
10314
10315         cur->offset =
10316             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
10317             stream->co_size);
10318
10319         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
10320             "%" G_GUINT64_FORMAT, j, cur->offset);
10321
10322         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
10323             CUR_STREAM (stream)->bytes_per_frame > 0) {
10324           cur->size =
10325               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
10326               CUR_STREAM (stream)->samples_per_frame *
10327               CUR_STREAM (stream)->bytes_per_frame;
10328         } else {
10329           cur->size = stream->samples_per_chunk;
10330         }
10331
10332         GST_DEBUG_OBJECT (qtdemux,
10333             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
10334             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
10335                     stream->stco_sample_index)), cur->size);
10336
10337         cur->timestamp = stream->stco_sample_index;
10338         cur->duration = stream->samples_per_chunk;
10339         cur->keyframe = TRUE;
10340         cur++;
10341
10342         stream->stco_sample_index += stream->samples_per_chunk;
10343       }
10344       stream->stsc_chunk_index = j;
10345     } else {
10346       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
10347         guint32 samples_per_chunk;
10348         guint64 chunk_offset;
10349
10350         if (!stream->stsc_sample_index
10351             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
10352                 &stream->chunk_offset))
10353           goto corrupt_file;
10354
10355         samples_per_chunk = stream->samples_per_chunk;
10356         chunk_offset = stream->chunk_offset;
10357
10358         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
10359           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
10360               G_GUINT64_FORMAT " and size %d",
10361               (guint) (cur - samples), chunk_offset, cur->size);
10362
10363           cur->offset = chunk_offset;
10364           chunk_offset += cur->size;
10365           cur++;
10366
10367           if (G_UNLIKELY (cur > last)) {
10368             /* save state */
10369             stream->stsc_sample_index = k + 1;
10370             stream->chunk_offset = chunk_offset;
10371             stream->stsc_chunk_index = j;
10372             goto done2;
10373           }
10374         }
10375         stream->stsc_sample_index = 0;
10376       }
10377       stream->stsc_chunk_index = j;
10378     }
10379     stream->stsc_index++;
10380   }
10381
10382   if (stream->chunks_are_samples)
10383     goto ctts;
10384 done2:
10385   {
10386     guint32 n_sample_times;
10387
10388     n_sample_times = stream->n_sample_times;
10389     cur = first;
10390
10391     for (i = stream->stts_index; i < n_sample_times; i++) {
10392       guint32 stts_samples;
10393       gint32 stts_duration;
10394       gint64 stts_time;
10395
10396       if (stream->stts_sample_index >= stream->stts_samples
10397           || !stream->stts_sample_index) {
10398
10399         stream->stts_samples =
10400             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10401         stream->stts_duration =
10402             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10403
10404         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10405             i, stream->stts_samples, stream->stts_duration);
10406
10407         stream->stts_sample_index = 0;
10408       }
10409
10410       stts_samples = stream->stts_samples;
10411       stts_duration = stream->stts_duration;
10412       stts_time = stream->stts_time;
10413
10414       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10415         GST_DEBUG_OBJECT (qtdemux,
10416             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10417             (guint) (cur - samples), j,
10418             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10419
10420         cur->timestamp = stts_time;
10421         cur->duration = stts_duration;
10422
10423         /* avoid 32-bit wrap-around,
10424          * but still mind possible 'negative' duration */
10425         stts_time += (gint64) stts_duration;
10426         cur++;
10427
10428         if (G_UNLIKELY (cur > last)) {
10429           /* save values */
10430           stream->stts_time = stts_time;
10431           stream->stts_sample_index = j + 1;
10432           if (stream->stts_sample_index >= stream->stts_samples)
10433             stream->stts_index++;
10434           goto done3;
10435         }
10436       }
10437       stream->stts_sample_index = 0;
10438       stream->stts_time = stts_time;
10439       stream->stts_index++;
10440     }
10441     /* fill up empty timestamps with the last timestamp, this can happen when
10442      * the last samples do not decode and so we don't have timestamps for them.
10443      * We however look at the last timestamp to estimate the track length so we
10444      * need something in here. */
10445     for (; cur < last; cur++) {
10446       GST_DEBUG_OBJECT (qtdemux,
10447           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10448           (guint) (cur - samples),
10449           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10450       cur->timestamp = stream->stts_time;
10451       cur->duration = -1;
10452     }
10453   }
10454 done3:
10455   {
10456     /* sample sync, can be NULL */
10457     if (stream->stss_present == TRUE) {
10458       guint32 n_sample_syncs;
10459
10460       n_sample_syncs = stream->n_sample_syncs;
10461
10462       if (!n_sample_syncs) {
10463         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10464         stream->all_keyframe = TRUE;
10465       } else {
10466         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10467           /* note that the first sample is index 1, not 0 */
10468           guint32 index;
10469
10470           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10471
10472           if (G_LIKELY (index > 0 && index <= n_samples)) {
10473             index -= 1;
10474             samples[index].keyframe = TRUE;
10475             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10476             /* and exit if we have enough samples */
10477             if (G_UNLIKELY (index >= n)) {
10478               i++;
10479               break;
10480             }
10481           }
10482         }
10483         /* save state */
10484         stream->stss_index = i;
10485       }
10486
10487       /* stps marks partial sync frames like open GOP I-Frames */
10488       if (stream->stps_present == TRUE) {
10489         guint32 n_sample_partial_syncs;
10490
10491         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10492
10493         /* if there are no entries, the stss table contains the real
10494          * sync samples */
10495         if (n_sample_partial_syncs) {
10496           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10497             /* note that the first sample is index 1, not 0 */
10498             guint32 index;
10499
10500             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10501
10502             if (G_LIKELY (index > 0 && index <= n_samples)) {
10503               index -= 1;
10504               samples[index].keyframe = TRUE;
10505               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10506               /* and exit if we have enough samples */
10507               if (G_UNLIKELY (index >= n)) {
10508                 i++;
10509                 break;
10510               }
10511             }
10512           }
10513           /* save state */
10514           stream->stps_index = i;
10515         }
10516       }
10517     } else {
10518       /* no stss, all samples are keyframes */
10519       stream->all_keyframe = TRUE;
10520       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10521     }
10522   }
10523
10524 ctts:
10525   /* composition time to sample */
10526   if (stream->ctts_present == TRUE) {
10527     guint32 n_composition_times;
10528     guint32 ctts_count;
10529     gint32 ctts_soffset;
10530
10531     /* Fill in the pts_offsets */
10532     cur = first;
10533     n_composition_times = stream->n_composition_times;
10534
10535     for (i = stream->ctts_index; i < n_composition_times; i++) {
10536       if (stream->ctts_sample_index >= stream->ctts_count
10537           || !stream->ctts_sample_index) {
10538         stream->ctts_count =
10539             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10540         stream->ctts_soffset =
10541             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10542         stream->ctts_sample_index = 0;
10543       }
10544
10545       ctts_count = stream->ctts_count;
10546       ctts_soffset = stream->ctts_soffset;
10547
10548       /* FIXME: Set offset to 0 for "no decode samples". This needs
10549        * to be handled in a codec specific manner ideally. */
10550       if (ctts_soffset == G_MININT32)
10551         ctts_soffset = 0;
10552
10553       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10554         cur->pts_offset = ctts_soffset;
10555         cur++;
10556
10557         if (G_UNLIKELY (cur > last)) {
10558           /* save state */
10559           stream->ctts_sample_index = j + 1;
10560           goto done;
10561         }
10562       }
10563       stream->ctts_sample_index = 0;
10564       stream->ctts_index++;
10565     }
10566   }
10567 done:
10568   stream->stbl_index = n;
10569   /* if index has been completely parsed, free data that is no-longer needed */
10570   if (n + 1 == stream->n_samples) {
10571     gst_qtdemux_stbl_free (stream);
10572     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10573     if (qtdemux->pullbased) {
10574       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10575       while (n + 1 == stream->n_samples)
10576         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10577           break;
10578     }
10579   }
10580   GST_OBJECT_UNLOCK (qtdemux);
10581
10582   return TRUE;
10583
10584   /* SUCCESS */
10585 already_parsed:
10586   {
10587     GST_LOG_OBJECT (qtdemux,
10588         "Tried to parse up to sample %u but this sample has already been parsed",
10589         n);
10590     /* if fragmented, there may be more */
10591     if (qtdemux->fragmented && n == stream->stbl_index)
10592       goto done;
10593     GST_OBJECT_UNLOCK (qtdemux);
10594     return TRUE;
10595   }
10596   /* ERRORS */
10597 out_of_samples:
10598   {
10599     GST_LOG_OBJECT (qtdemux,
10600         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10601         stream->n_samples);
10602     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10603         (_("This file is corrupt and cannot be played.")), (NULL));
10604     return FALSE;
10605   }
10606 corrupt_file:
10607   {
10608     GST_OBJECT_UNLOCK (qtdemux);
10609     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10610         (_("This file is corrupt and cannot be played.")), (NULL));
10611     return FALSE;
10612   }
10613 }
10614
10615 /* collect all segment info for @stream.
10616  */
10617 static gboolean
10618 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10619     GNode * trak)
10620 {
10621   GNode *edts;
10622   /* accept edts if they contain gaps at start and there is only
10623    * one media segment */
10624   gboolean allow_pushbased_edts = TRUE;
10625   gint media_segments_count = 0;
10626
10627   /* parse and prepare segment info from the edit list */
10628   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10629   stream->n_segments = 0;
10630   stream->segments = NULL;
10631   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10632     GNode *elst;
10633     gint n_segments;
10634     gint segment_number, entry_size;
10635     guint64 time;
10636     GstClockTime stime;
10637     const guint8 *buffer;
10638     guint8 version;
10639     guint32 size;
10640
10641     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10642     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10643       goto done;
10644
10645     buffer = elst->data;
10646
10647     size = QT_UINT32 (buffer);
10648     /* version, flags, n_segments */
10649     if (size < 16) {
10650       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10651       goto done;
10652     }
10653     version = QT_UINT8 (buffer + 8);
10654     entry_size = (version == 1) ? 20 : 12;
10655
10656     n_segments = QT_UINT32 (buffer + 12);
10657
10658     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10659       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10660       goto done;
10661     }
10662
10663     /* we might allocate a bit too much, at least allocate 1 segment */
10664     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10665
10666     /* segments always start from 0 */
10667     time = 0;
10668     stime = 0;
10669     buffer += 16;
10670     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10671       guint64 duration;
10672       guint64 media_time;
10673       gboolean empty_edit = FALSE;
10674       QtDemuxSegment *segment;
10675       guint32 rate_int;
10676       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10677
10678       if (version == 1) {
10679         media_time = QT_UINT64 (buffer + 8);
10680         duration = QT_UINT64 (buffer);
10681         if (media_time == G_MAXUINT64)
10682           empty_edit = TRUE;
10683       } else {
10684         media_time = QT_UINT32 (buffer + 4);
10685         duration = QT_UINT32 (buffer);
10686         if (media_time == G_MAXUINT32)
10687           empty_edit = TRUE;
10688       }
10689
10690       if (!empty_edit)
10691         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10692
10693       segment = &stream->segments[segment_number];
10694
10695       /* time and duration expressed in global timescale */
10696       segment->time = stime;
10697       if (duration != 0 || empty_edit) {
10698         /* edge case: empty edits with duration=zero are treated here.
10699          * (files should not have these anyway). */
10700
10701         /* add non scaled values so we don't cause roundoff errors */
10702         time += duration;
10703         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10704         segment->duration = stime - segment->time;
10705       } else {
10706         /* zero duration does not imply media_start == media_stop
10707          * but, only specify media_start. The edit ends with the track. */
10708         stime = segment->duration = GST_CLOCK_TIME_NONE;
10709         /* Don't allow more edits after this one. */
10710         n_segments = segment_number + 1;
10711       }
10712       segment->stop_time = stime;
10713
10714       segment->trak_media_start = media_time;
10715       /* media_time expressed in stream timescale */
10716       if (!empty_edit) {
10717         segment->media_start = media_start;
10718         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10719             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10720         media_segments_count++;
10721       } else {
10722         segment->media_start = GST_CLOCK_TIME_NONE;
10723         segment->media_stop = GST_CLOCK_TIME_NONE;
10724       }
10725       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10726
10727       if (rate_int <= 1) {
10728         /* 0 is not allowed, some programs write 1 instead of the floating point
10729          * value */
10730         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10731             rate_int);
10732         segment->rate = 1;
10733       } else {
10734         segment->rate = rate_int / 65536.0;
10735       }
10736
10737       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10738           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10739           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10740           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10741           segment_number, GST_TIME_ARGS (segment->time),
10742           GST_TIME_ARGS (segment->duration),
10743           GST_TIME_ARGS (segment->media_start), media_time,
10744           GST_TIME_ARGS (segment->media_stop),
10745           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10746           stream->timescale);
10747       if (segment->stop_time > qtdemux->segment.stop &&
10748           !qtdemux->upstream_format_is_time) {
10749         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10750             " extends to %" GST_TIME_FORMAT
10751             " past the end of the declared movie duration %" GST_TIME_FORMAT
10752             " movie segment will be extended", segment_number,
10753             GST_TIME_ARGS (segment->stop_time),
10754             GST_TIME_ARGS (qtdemux->segment.stop));
10755         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10756       }
10757
10758       buffer += entry_size;
10759     }
10760     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10761     stream->n_segments = n_segments;
10762     if (media_segments_count != 1)
10763       allow_pushbased_edts = FALSE;
10764   }
10765 done:
10766
10767   /* push based does not handle segments, so act accordingly here,
10768    * and warn if applicable */
10769   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10770     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10771     /* remove and use default one below, we stream like it anyway */
10772     g_free (stream->segments);
10773     stream->segments = NULL;
10774     stream->n_segments = 0;
10775   }
10776
10777   /* no segments, create one to play the complete trak */
10778   if (stream->n_segments == 0) {
10779     GstClockTime stream_duration =
10780         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10781
10782     if (stream->segments == NULL)
10783       stream->segments = g_new (QtDemuxSegment, 1);
10784
10785     /* represent unknown our way */
10786     if (stream_duration == 0)
10787       stream_duration = GST_CLOCK_TIME_NONE;
10788
10789     stream->segments[0].time = 0;
10790     stream->segments[0].stop_time = stream_duration;
10791     stream->segments[0].duration = stream_duration;
10792     stream->segments[0].media_start = 0;
10793     stream->segments[0].media_stop = stream_duration;
10794     stream->segments[0].rate = 1.0;
10795     stream->segments[0].trak_media_start = 0;
10796
10797     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10798         GST_TIME_ARGS (stream_duration));
10799     stream->n_segments = 1;
10800     stream->dummy_segment = TRUE;
10801   }
10802   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10803
10804   return TRUE;
10805 }
10806
10807 /*
10808  * Parses the stsd atom of a svq3 trak looking for
10809  * the SMI and gama atoms.
10810  */
10811 static void
10812 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10813     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10814 {
10815   const guint8 *_gamma = NULL;
10816   GstBuffer *_seqh = NULL;
10817   const guint8 *stsd_data = stsd_entry_data;
10818   guint32 length = QT_UINT32 (stsd_data);
10819   guint16 version;
10820
10821   if (length < 32) {
10822     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10823     goto end;
10824   }
10825
10826   stsd_data += 16;
10827   length -= 16;
10828   version = QT_UINT16 (stsd_data);
10829   if (version == 3) {
10830     if (length >= 70) {
10831       length -= 70;
10832       stsd_data += 70;
10833       while (length > 8) {
10834         guint32 fourcc, size;
10835         const guint8 *data;
10836         size = QT_UINT32 (stsd_data);
10837         fourcc = QT_FOURCC (stsd_data + 4);
10838         data = stsd_data + 8;
10839
10840         if (size == 0) {
10841           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10842               "svq3 atom parsing");
10843           goto end;
10844         }
10845
10846         switch (fourcc) {
10847           case FOURCC_gama:{
10848             if (size == 12) {
10849               _gamma = data;
10850             } else {
10851               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10852                   " for gama atom, expected 12", size);
10853             }
10854             break;
10855           }
10856           case FOURCC_SMI_:{
10857             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10858               guint32 seqh_size;
10859               if (_seqh != NULL) {
10860                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10861                     " found, ignoring");
10862               } else {
10863                 seqh_size = QT_UINT32 (data + 4);
10864                 if (seqh_size > 0) {
10865                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10866                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10867                 }
10868               }
10869             }
10870             break;
10871           }
10872           default:{
10873             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10874                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10875           }
10876         }
10877
10878         if (size <= length) {
10879           length -= size;
10880           stsd_data += size;
10881         }
10882       }
10883     } else {
10884       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10885     }
10886   } else {
10887     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10888         G_GUINT16_FORMAT, version);
10889     goto end;
10890   }
10891
10892 end:
10893   if (gamma) {
10894     *gamma = _gamma;
10895   }
10896   if (seqh) {
10897     *seqh = _seqh;
10898   } else if (_seqh) {
10899     gst_buffer_unref (_seqh);
10900   }
10901 }
10902
10903 static gchar *
10904 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10905 {
10906   GNode *dinf;
10907   GstByteReader dref;
10908   gchar *uri = NULL;
10909
10910   /*
10911    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10912    * atom that might contain a 'data' atom with the rtsp uri.
10913    * This case was reported in bug #597497, some info about
10914    * the hndl atom can be found in TN1195
10915    */
10916   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10917   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10918
10919   if (dinf) {
10920     guint32 dref_num_entries = 0;
10921     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10922         gst_byte_reader_skip (&dref, 4) &&
10923         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10924       gint i;
10925
10926       /* search dref entries for hndl atom */
10927       for (i = 0; i < dref_num_entries; i++) {
10928         guint32 size = 0, type;
10929         guint8 string_len = 0;
10930         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10931             qt_atom_parser_get_fourcc (&dref, &type)) {
10932           if (type == FOURCC_hndl) {
10933             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10934
10935             /* skip data reference handle bytes and the
10936              * following pascal string and some extra 4
10937              * bytes I have no idea what are */
10938             if (!gst_byte_reader_skip (&dref, 4) ||
10939                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10940                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10941               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10942               break;
10943             }
10944
10945             /* iterate over the atoms to find the data atom */
10946             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10947               guint32 atom_size;
10948               guint32 atom_type;
10949
10950               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10951                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10952                 if (atom_type == FOURCC_data) {
10953                   const guint8 *uri_aux = NULL;
10954
10955                   /* found the data atom that might contain the rtsp uri */
10956                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10957                       "hndl atom, interpreting it as an URI");
10958                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10959                           &uri_aux)) {
10960                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10961                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10962                     else
10963                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10964                           "didn't contain a rtsp address");
10965                   } else {
10966                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10967                         "atom contents");
10968                   }
10969                   break;
10970                 }
10971                 /* skipping to the next entry */
10972                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10973                   break;
10974               } else {
10975                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10976                     "atom header");
10977                 break;
10978               }
10979             }
10980             break;
10981           }
10982           /* skip to the next entry */
10983           if (!gst_byte_reader_skip (&dref, size - 8))
10984             break;
10985         } else {
10986           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10987         }
10988       }
10989       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10990     }
10991   }
10992   return uri;
10993 }
10994
10995 #define AMR_NB_ALL_MODES        0x81ff
10996 #define AMR_WB_ALL_MODES        0x83ff
10997 static guint
10998 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10999 {
11000   /* The 'damr' atom is of the form:
11001    *
11002    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
11003    *    32 b       8 b          16 b           8 b                 8 b
11004    *
11005    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
11006    * represents the highest mode used in the stream (and thus the maximum
11007    * bitrate), with a couple of special cases as seen below.
11008    */
11009
11010   /* Map of frame type ID -> bitrate */
11011   static const guint nb_bitrates[] = {
11012     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
11013   };
11014   static const guint wb_bitrates[] = {
11015     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
11016   };
11017   GstMapInfo map;
11018   gsize max_mode;
11019   guint16 mode_set;
11020
11021   gst_buffer_map (buf, &map, GST_MAP_READ);
11022
11023   if (map.size != 0x11) {
11024     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
11025     goto bad_data;
11026   }
11027
11028   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
11029     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
11030         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
11031     goto bad_data;
11032   }
11033
11034   mode_set = QT_UINT16 (map.data + 13);
11035
11036   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
11037     max_mode = 7 + (wb ? 1 : 0);
11038   else
11039     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
11040     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
11041
11042   if (max_mode == -1) {
11043     GST_DEBUG ("No mode indication was found (mode set) = %x",
11044         (guint) mode_set);
11045     goto bad_data;
11046   }
11047
11048   gst_buffer_unmap (buf, &map);
11049   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
11050
11051 bad_data:
11052   gst_buffer_unmap (buf, &map);
11053   return 0;
11054 }
11055
11056 static gboolean
11057 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
11058     GstByteReader * reader, guint32 * matrix, const gchar * atom)
11059 {
11060   /*
11061    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
11062    * [0 1 2]
11063    * [3 4 5]
11064    * [6 7 8]
11065    */
11066
11067   if (gst_byte_reader_get_remaining (reader) < 36)
11068     return FALSE;
11069
11070   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
11071   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
11072   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
11073   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
11074   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
11075   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
11076   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
11077   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
11078   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
11079
11080   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
11081   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
11082       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
11083       matrix[2] & 0xFF);
11084   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
11085       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
11086       matrix[5] & 0xFF);
11087   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
11088       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
11089       matrix[8] & 0xFF);
11090
11091   return TRUE;
11092 }
11093
11094 static void
11095 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
11096     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
11097 {
11098
11099 /* [a b c]
11100  * [d e f]
11101  * [g h i]
11102  *
11103  * This macro will only compare value abdegh, it expects cfi to have already
11104  * been checked
11105  */
11106 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
11107                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
11108
11109   /* only handle the cases where the last column has standard values */
11110   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
11111     const gchar *rotation_tag = NULL;
11112
11113     /* no rotation needed */
11114     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
11115       /* NOP */
11116     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
11117       rotation_tag = "rotate-90";
11118     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
11119       rotation_tag = "rotate-180";
11120     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
11121       rotation_tag = "rotate-270";
11122     } else {
11123       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
11124     }
11125
11126     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
11127         GST_STR_NULL (rotation_tag));
11128     if (rotation_tag != NULL) {
11129       if (*taglist == NULL)
11130         *taglist = gst_tag_list_new_empty ();
11131       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
11132           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
11133     }
11134   } else {
11135     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
11136   }
11137 }
11138
11139 static gboolean
11140 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
11141     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
11142 {
11143   GNode *adrm;
11144   guint32 adrm_size;
11145   GstBuffer *adrm_buf = NULL;
11146   QtDemuxAavdEncryptionInfo *info;
11147
11148   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
11149   if (G_UNLIKELY (!adrm)) {
11150     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
11151     return FALSE;
11152   }
11153   adrm_size = QT_UINT32 (adrm->data);
11154   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
11155
11156   stream->protection_scheme_type = FOURCC_aavd;
11157
11158   if (!stream->protection_scheme_info)
11159     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
11160
11161   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
11162
11163   if (info->default_properties)
11164     gst_structure_free (info->default_properties);
11165   info->default_properties = gst_structure_new ("application/x-aavd",
11166       "encrypted", G_TYPE_BOOLEAN, TRUE,
11167       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
11168   gst_buffer_unref (adrm_buf);
11169
11170   *original_fmt = FOURCC_mp4a;
11171   return TRUE;
11172 }
11173
11174 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
11175  * protected streams (sinf, frma, schm and schi); if the protection scheme is
11176  * Common Encryption (cenc), the function will also parse the tenc box (defined
11177  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
11178  * (typically an enc[v|a|t|s] sample entry); the function will set
11179  * @original_fmt to the fourcc of the original unencrypted stream format.
11180  * Returns TRUE if successful; FALSE otherwise. */
11181 static gboolean
11182 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
11183     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
11184 {
11185   GNode *sinf;
11186   GNode *frma;
11187   GNode *schm;
11188   GNode *schi;
11189   QtDemuxCencSampleSetInfo *info;
11190   GNode *tenc;
11191   const guint8 *tenc_data;
11192
11193   g_return_val_if_fail (qtdemux != NULL, FALSE);
11194   g_return_val_if_fail (stream != NULL, FALSE);
11195   g_return_val_if_fail (container != NULL, FALSE);
11196   g_return_val_if_fail (original_fmt != NULL, FALSE);
11197
11198   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
11199   if (G_UNLIKELY (!sinf)) {
11200     if (stream->protection_scheme_type == FOURCC_cenc
11201         || stream->protection_scheme_type == FOURCC_cbcs) {
11202       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
11203           "mandatory for Common Encryption");
11204       return FALSE;
11205     }
11206     return TRUE;
11207   }
11208
11209   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
11210   if (G_UNLIKELY (!frma)) {
11211     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
11212     return FALSE;
11213   }
11214
11215   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
11216   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
11217       GST_FOURCC_ARGS (*original_fmt));
11218
11219   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
11220   if (!schm) {
11221     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
11222     return FALSE;
11223   }
11224   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
11225   stream->protection_scheme_version =
11226       QT_UINT32 ((const guint8 *) schm->data + 16);
11227
11228   GST_DEBUG_OBJECT (qtdemux,
11229       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
11230       "protection_scheme_version: %#010x",
11231       GST_FOURCC_ARGS (stream->protection_scheme_type),
11232       stream->protection_scheme_version);
11233
11234   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
11235   if (!schi) {
11236     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
11237     return FALSE;
11238   }
11239   if (stream->protection_scheme_type != FOURCC_cenc &&
11240       stream->protection_scheme_type != FOURCC_piff &&
11241       stream->protection_scheme_type != FOURCC_cbcs) {
11242     GST_ERROR_OBJECT (qtdemux,
11243         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
11244         GST_FOURCC_ARGS (stream->protection_scheme_type));
11245     return FALSE;
11246   }
11247
11248   if (G_UNLIKELY (!stream->protection_scheme_info))
11249     stream->protection_scheme_info =
11250         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
11251
11252   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
11253
11254   if (stream->protection_scheme_type == FOURCC_cenc
11255       || stream->protection_scheme_type == FOURCC_cbcs) {
11256     guint8 is_encrypted;
11257     guint8 iv_size;
11258     guint8 constant_iv_size = 0;
11259     const guint8 *default_kid;
11260     guint8 crypt_byte_block = 0;
11261     guint8 skip_byte_block = 0;
11262     const guint8 *constant_iv = NULL;
11263
11264     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
11265     if (!tenc) {
11266       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
11267           "which is mandatory for Common Encryption");
11268       return FALSE;
11269     }
11270     tenc_data = (const guint8 *) tenc->data + 12;
11271     is_encrypted = QT_UINT8 (tenc_data + 2);
11272     iv_size = QT_UINT8 (tenc_data + 3);
11273     default_kid = (tenc_data + 4);
11274     if (stream->protection_scheme_type == FOURCC_cbcs) {
11275       guint8 possible_pattern_info;
11276       if (iv_size == 0) {
11277         constant_iv_size = QT_UINT8 (tenc_data + 20);
11278         if (constant_iv_size != 8 && constant_iv_size != 16) {
11279           GST_ERROR_OBJECT (qtdemux,
11280               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
11281           return FALSE;
11282         }
11283         constant_iv = (tenc_data + 21);
11284       }
11285       possible_pattern_info = QT_UINT8 (tenc_data + 1);
11286       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
11287       skip_byte_block = possible_pattern_info & 0x0f;
11288     }
11289     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
11290         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
11291         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
11292   } else if (stream->protection_scheme_type == FOURCC_piff) {
11293     GstByteReader br;
11294     static const guint8 piff_track_encryption_uuid[] = {
11295       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
11296       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
11297     };
11298
11299     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
11300     if (!tenc) {
11301       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
11302           "which is mandatory for Common Encryption");
11303       return FALSE;
11304     }
11305
11306     tenc_data = (const guint8 *) tenc->data + 8;
11307     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
11308       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
11309       GST_ERROR_OBJECT (qtdemux,
11310           "Unsupported track encryption box with uuid: %s", box_uuid);
11311       g_free (box_uuid);
11312       return FALSE;
11313     }
11314     tenc_data = (const guint8 *) tenc->data + 16 + 12;
11315     gst_byte_reader_init (&br, tenc_data, 20);
11316     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
11317       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
11318       return FALSE;
11319     }
11320     stream->protection_scheme_type = FOURCC_cenc;
11321   }
11322
11323   return TRUE;
11324 }
11325
11326 static gint
11327 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
11328     QtDemuxStream ** stream2)
11329 {
11330   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
11331 }
11332
11333 static gboolean
11334 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
11335     GNode * stbl)
11336 {
11337   GNode *svmi;
11338
11339   /*parse svmi header if existing */
11340   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
11341   if (svmi) {
11342     guint len = QT_UINT32 ((guint8 *) svmi->data);
11343     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
11344     if (!version) {
11345       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
11346       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
11347       guint8 frame_type, frame_layout;
11348       guint32 stereo_mono_change_count;
11349
11350       if (len < 18)
11351         return FALSE;
11352
11353       /* MPEG-A stereo video */
11354       if (qtdemux->major_brand == FOURCC_ss02)
11355         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
11356
11357       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
11358       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
11359       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
11360
11361       switch (frame_type) {
11362         case 0:
11363           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
11364           break;
11365         case 1:
11366           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11367           break;
11368         case 2:
11369           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11370           break;
11371         case 3:
11372           /* mode 3 is primary/secondary view sequence, ie
11373            * left/right views in separate tracks. See section 7.2
11374            * of ISO/IEC 23000-11:2009 */
11375           /* In the future this might be supported using related
11376            * streams, like an enhancement track - if files like this
11377            * ever exist */
11378           GST_FIXME_OBJECT (qtdemux,
11379               "Implement stereo video in separate streams");
11380       }
11381
11382       if ((frame_layout & 0x1) == 0)
11383         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11384
11385       GST_LOG_OBJECT (qtdemux,
11386           "StereoVideo: composition type: %u, is_left_first: %u",
11387           frame_type, frame_layout);
11388
11389       if (stereo_mono_change_count > 1) {
11390         GST_FIXME_OBJECT (qtdemux,
11391             "Mixed-mono flags are not yet supported in qtdemux.");
11392       }
11393
11394       stream->multiview_mode = mode;
11395       stream->multiview_flags = flags;
11396     }
11397   }
11398
11399   return TRUE;
11400 }
11401
11402 /* parse the traks.
11403  * With each track we associate a new QtDemuxStream that contains all the info
11404  * about the trak.
11405  * traks that do not decode to something (like strm traks) will not have a pad.
11406  */
11407 static gboolean
11408 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11409 {
11410   GstByteReader tkhd;
11411   int offset;
11412   GNode *mdia;
11413   GNode *mdhd;
11414   GNode *hdlr;
11415   GNode *minf;
11416   GNode *stbl;
11417   GNode *stsd;
11418   GNode *mp4a;
11419   GNode *mp4v;
11420   GNode *esds;
11421   GNode *tref;
11422   GNode *udta;
11423
11424   QtDemuxStream *stream = NULL;
11425   const guint8 *stsd_data;
11426   const guint8 *stsd_entry_data;
11427   guint remaining_stsd_len;
11428   guint stsd_entry_count;
11429   guint stsd_index;
11430   guint16 lang_code;            /* quicktime lang code or packed iso code */
11431   guint32 version;
11432   guint32 tkhd_flags = 0;
11433   guint8 tkhd_version = 0;
11434   guint32 w = 0, h = 0;
11435   guint value_size, stsd_len, len;
11436   guint32 track_id;
11437   guint32 dummy;
11438
11439   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11440
11441   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11442       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11443       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11444     goto corrupt_file;
11445
11446   /* pick between 64 or 32 bits */
11447   value_size = tkhd_version == 1 ? 8 : 4;
11448   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11449       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11450     goto corrupt_file;
11451
11452   /* Check if current moov has duplicated track_id */
11453   if (qtdemux_find_stream (qtdemux, track_id))
11454     goto existing_stream;
11455
11456   stream = _create_stream (qtdemux, track_id);
11457   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11458
11459 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
11460   if (!gst_byte_reader_skip (&tkhd, 4))
11461     goto corrupt_file;
11462
11463   if (tkhd_version == 1) {
11464     if (!gst_byte_reader_get_uint64_be (&tkhd, &stream->tkhd_duration))
11465       goto corrupt_file;
11466   } else {
11467     guint32 dur = 0;
11468     if (!gst_byte_reader_get_uint32_be (&tkhd, &dur))
11469       goto corrupt_file;
11470     stream->tkhd_duration = dur;
11471   }
11472   GST_INFO_OBJECT (qtdemux, "tkhd duration: %" G_GUINT64_FORMAT,
11473       stream->tkhd_duration);
11474 #endif
11475   /* need defaults for fragments */
11476   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11477
11478   if ((tkhd_flags & 1) == 0)
11479     stream->disabled = TRUE;
11480
11481   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11482       tkhd_version, tkhd_flags, stream->track_id);
11483
11484   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11485     goto corrupt_file;
11486
11487   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11488     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11489     if (qtdemux->major_brand != FOURCC_mjp2 ||
11490         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11491       goto corrupt_file;
11492   }
11493
11494   len = QT_UINT32 ((guint8 *) mdhd->data);
11495   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11496   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11497   if (version == 0x01000000) {
11498     if (len < 42)
11499       goto corrupt_file;
11500     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11501     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11502     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11503   } else {
11504     if (len < 30)
11505       goto corrupt_file;
11506     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11507     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11508     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11509   }
11510
11511   if (lang_code < 0x400) {
11512     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11513   } else if (lang_code == 0x7fff) {
11514     stream->lang_id[0] = 0;     /* unspecified */
11515   } else {
11516     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11517     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11518     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11519     stream->lang_id[3] = 0;
11520   }
11521
11522   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11523       stream->timescale);
11524   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11525       stream->duration);
11526   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11527       lang_code, stream->lang_id);
11528
11529   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11530     goto corrupt_file;
11531
11532   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11533     /* chapters track reference */
11534     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11535     if (chap) {
11536       gsize length = GST_READ_UINT32_BE (chap->data);
11537       if (qtdemux->chapters_track_id)
11538         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11539
11540       if (length >= 12) {
11541         qtdemux->chapters_track_id =
11542             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11543       }
11544     }
11545   }
11546
11547   /* fragmented files may have bogus duration in moov */
11548   if (!qtdemux->fragmented &&
11549       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11550     guint64 tdur1, tdur2;
11551
11552     /* don't overflow */
11553     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11554     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11555
11556     /* HACK:
11557      * some of those trailers, nowadays, have prologue images that are
11558      * themselves video tracks as well. I haven't really found a way to
11559      * identify those yet, except for just looking at their duration. */
11560     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11561       GST_WARNING_OBJECT (qtdemux,
11562           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11563           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11564           "found, assuming preview image or something; skipping track",
11565           stream->duration, stream->timescale, qtdemux->duration,
11566           qtdemux->timescale);
11567       gst_qtdemux_stream_unref (stream);
11568       return TRUE;
11569     }
11570   }
11571
11572   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11573     goto corrupt_file;
11574
11575   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11576       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11577
11578   len = QT_UINT32 ((guint8 *) hdlr->data);
11579   if (len >= 20)
11580     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11581   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11582       GST_FOURCC_ARGS (stream->subtype));
11583
11584   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11585     goto corrupt_file;
11586
11587   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11588     goto corrupt_file;
11589
11590   /* Parse out svmi (and later st3d/sv3d) atoms */
11591   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11592     goto corrupt_file;
11593
11594   /* parse rest of tkhd */
11595   if (stream->subtype == FOURCC_vide) {
11596     guint32 matrix[9];
11597
11598     /* version 1 uses some 64-bit ints */
11599 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
11600     if (!gst_byte_reader_skip (&tkhd, 16))
11601 #else
11602     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11603 #endif
11604       goto corrupt_file;
11605
11606     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11607       goto corrupt_file;
11608
11609     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11610         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11611       goto corrupt_file;
11612
11613     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11614         &stream->stream_tags);
11615   }
11616
11617   /* parse stsd */
11618   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11619     goto corrupt_file;
11620   stsd_data = (const guint8 *) stsd->data;
11621
11622   /* stsd should at least have one entry */
11623   stsd_len = QT_UINT32 (stsd_data);
11624   if (stsd_len < 24) {
11625     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11626     if (stream->subtype == FOURCC_vivo) {
11627       gst_qtdemux_stream_unref (stream);
11628       return TRUE;
11629     } else {
11630       goto corrupt_file;
11631     }
11632   }
11633
11634   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11635   /* each stsd entry must contain at least 8 bytes */
11636   if (stream->stsd_entries_length == 0
11637       || stream->stsd_entries_length > stsd_len / 8) {
11638     stream->stsd_entries_length = 0;
11639     goto corrupt_file;
11640   }
11641   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11642   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11643   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11644
11645   stsd_entry_data = stsd_data + 16;
11646   remaining_stsd_len = stsd_len - 16;
11647   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11648     guint32 fourcc;
11649     gchar *codec = NULL;
11650     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11651
11652     /* and that entry should fit within stsd */
11653     len = QT_UINT32 (stsd_entry_data);
11654     if (len > remaining_stsd_len)
11655       goto corrupt_file;
11656
11657     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11658     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11659         GST_FOURCC_ARGS (entry->fourcc));
11660     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11661
11662     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11663       goto error_encrypted;
11664
11665     if (fourcc == FOURCC_aavd) {
11666       if (stream->subtype != FOURCC_soun) {
11667         GST_ERROR_OBJECT (qtdemux,
11668             "Unexpeced stsd type 'aavd' outside 'soun' track");
11669       } else {
11670         /* encrypted audio with sound sample description v0 */
11671         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11672         stream->protected = TRUE;
11673         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11674           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11675       }
11676     }
11677
11678     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11679       /* FIXME this looks wrong, there might be multiple children
11680        * with the same type */
11681       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11682       stream->protected = TRUE;
11683       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11684         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11685     }
11686
11687     if (stream->subtype == FOURCC_vide) {
11688       GNode *colr;
11689       GNode *fiel;
11690       GNode *pasp;
11691       gboolean gray;
11692       gint depth, palette_size, palette_count;
11693       guint32 *palette_data = NULL;
11694
11695       entry->sampled = TRUE;
11696
11697       stream->display_width = w >> 16;
11698       stream->display_height = h >> 16;
11699
11700       offset = 16;
11701       if (len < 86)             /* TODO verify */
11702         goto corrupt_file;
11703
11704       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11705       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11706       entry->fps_n = 0;         /* this is filled in later */
11707       entry->fps_d = 0;         /* this is filled in later */
11708       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11709       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11710
11711       /* if color_table_id is 0, ctab atom must follow; however some files
11712        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11713        * if color table is not present we'll correct the value */
11714       if (entry->color_table_id == 0 &&
11715           (len < 90
11716               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11717         entry->color_table_id = -1;
11718       }
11719
11720       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11721           entry->width, entry->height, entry->bits_per_sample,
11722           entry->color_table_id);
11723
11724       depth = entry->bits_per_sample;
11725
11726       /* more than 32 bits means grayscale */
11727       gray = (depth > 32);
11728       /* low 32 bits specify the depth  */
11729       depth &= 0x1F;
11730
11731       /* different number of palette entries is determined by depth. */
11732       palette_count = 0;
11733       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11734         palette_count = (1 << depth);
11735       palette_size = palette_count * 4;
11736
11737       if (entry->color_table_id) {
11738         switch (palette_count) {
11739           case 0:
11740             break;
11741           case 2:
11742             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11743             break;
11744           case 4:
11745             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11746             break;
11747           case 16:
11748             if (gray)
11749               palette_data =
11750                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11751             else
11752               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11753             break;
11754           case 256:
11755             if (gray)
11756               palette_data =
11757                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11758             else
11759               palette_data =
11760                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11761             break;
11762           default:
11763             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11764                 (_("The video in this file might not play correctly.")),
11765                 ("unsupported palette depth %d", depth));
11766             break;
11767         }
11768       } else {
11769         gint i, j, start, end;
11770
11771         if (len < 94)
11772           goto corrupt_file;
11773
11774         /* read table */
11775         start = QT_UINT32 (stsd_entry_data + offset + 70);
11776         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11777         end = QT_UINT16 (stsd_entry_data + offset + 76);
11778
11779         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11780             start, end, palette_count);
11781
11782         if (end > 255)
11783           end = 255;
11784         if (start > end)
11785           start = end;
11786
11787         if (len < 94 + (end - start) * 8)
11788           goto corrupt_file;
11789
11790         /* palette is always the same size */
11791         palette_data = g_malloc0 (256 * 4);
11792         palette_size = 256 * 4;
11793
11794         for (j = 0, i = start; i <= end; j++, i++) {
11795           guint32 a, r, g, b;
11796
11797           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11798           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11799           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11800           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11801
11802           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11803               (g & 0xff00) | (b >> 8);
11804         }
11805       }
11806
11807       if (entry->caps)
11808         gst_caps_unref (entry->caps);
11809
11810       entry->caps =
11811           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11812           &codec);
11813       if (G_UNLIKELY (!entry->caps)) {
11814         g_free (palette_data);
11815         goto unknown_stream;
11816       }
11817
11818       if (codec) {
11819         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11820             GST_TAG_VIDEO_CODEC, codec, NULL);
11821         g_free (codec);
11822         codec = NULL;
11823       }
11824
11825       if (palette_data) {
11826         GstStructure *s;
11827
11828         if (entry->rgb8_palette)
11829           gst_memory_unref (entry->rgb8_palette);
11830         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11831             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11832
11833         s = gst_caps_get_structure (entry->caps, 0);
11834
11835         /* non-raw video has a palette_data property. raw video has the palette as
11836          * an extra plane that we append to the output buffers before we push
11837          * them*/
11838         if (!gst_structure_has_name (s, "video/x-raw")) {
11839           GstBuffer *palette;
11840
11841           palette = gst_buffer_new ();
11842           gst_buffer_append_memory (palette, entry->rgb8_palette);
11843           entry->rgb8_palette = NULL;
11844
11845           gst_caps_set_simple (entry->caps, "palette_data",
11846               GST_TYPE_BUFFER, palette, NULL);
11847           gst_buffer_unref (palette);
11848         }
11849       } else if (palette_count != 0) {
11850         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11851             (NULL), ("Unsupported palette depth %d", depth));
11852       }
11853
11854       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11855           QT_UINT16 (stsd_entry_data + offset + 32));
11856
11857       esds = NULL;
11858       pasp = NULL;
11859       colr = NULL;
11860       fiel = NULL;
11861       /* pick 'the' stsd child */
11862       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11863       // We should skip parsing the stsd for non-protected streams if
11864       // the entry doesn't match the fourcc, since they don't change
11865       // format. However, for protected streams we can have partial
11866       // encryption, where parts of the stream are encrypted and parts
11867       // not. For both parts of such streams, we should ensure the
11868       // esds overrides are parsed for both from the stsd.
11869       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11870         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11871           mp4v = NULL;
11872         else if (!stream->protected)
11873           mp4v = NULL;
11874       }
11875
11876       if (mp4v) {
11877         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11878         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11879         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11880         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11881       }
11882
11883       if (pasp) {
11884         const guint8 *pasp_data = (const guint8 *) pasp->data;
11885         gint len = QT_UINT32 (pasp_data);
11886
11887         if (len == 16) {
11888           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11889           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11890         } else {
11891           CUR_STREAM (stream)->par_w = 0;
11892           CUR_STREAM (stream)->par_h = 0;
11893         }
11894       } else {
11895         CUR_STREAM (stream)->par_w = 0;
11896         CUR_STREAM (stream)->par_h = 0;
11897       }
11898
11899       if (fiel) {
11900         const guint8 *fiel_data = (const guint8 *) fiel->data;
11901         gint len = QT_UINT32 (fiel_data);
11902
11903         if (len == 10) {
11904           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11905           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11906         }
11907       }
11908
11909       if (colr) {
11910         const guint8 *colr_data = (const guint8 *) colr->data;
11911         gint len = QT_UINT32 (colr_data);
11912
11913         if (len == 19 || len == 18) {
11914           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11915
11916           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11917             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11918             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11919             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11920             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11921
11922             CUR_STREAM (stream)->colorimetry.primaries =
11923                 gst_video_color_primaries_from_iso (primaries);
11924             CUR_STREAM (stream)->colorimetry.transfer =
11925                 gst_video_transfer_function_from_iso (transfer_function);
11926             CUR_STREAM (stream)->colorimetry.matrix =
11927                 gst_video_color_matrix_from_iso (matrix);
11928             CUR_STREAM (stream)->colorimetry.range =
11929                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11930                 GST_VIDEO_COLOR_RANGE_16_235;
11931           } else {
11932             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11933           }
11934         } else {
11935           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11936         }
11937       }
11938
11939       if (esds) {
11940         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11941             stream->stream_tags);
11942       } else {
11943         switch (fourcc) {
11944           case FOURCC_H264:
11945           case FOURCC_avc1:
11946           case FOURCC_avc3:
11947           {
11948             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11949             const guint8 *avc_data = stsd_entry_data + 0x56;
11950
11951             /* find avcC */
11952             while (len >= 0x8) {
11953               gint size;
11954
11955               if (QT_UINT32 (avc_data) <= len)
11956                 size = QT_UINT32 (avc_data) - 0x8;
11957               else
11958                 size = len - 0x8;
11959
11960               if (size < 1)
11961                 /* No real data, so break out */
11962                 break;
11963
11964               switch (QT_FOURCC (avc_data + 0x4)) {
11965                 case FOURCC_avcC:
11966                 {
11967                   /* parse, if found */
11968                   GstBuffer *buf;
11969
11970                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11971
11972                   /* First 4 bytes are the length of the atom, the next 4 bytes
11973                    * are the fourcc, the next 1 byte is the version, and the
11974                    * subsequent bytes are profile_tier_level structure like data. */
11975                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11976                       avc_data + 8 + 1, size - 1);
11977                   buf = gst_buffer_new_and_alloc (size);
11978                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11979                   gst_caps_set_simple (entry->caps,
11980                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11981                   gst_buffer_unref (buf);
11982
11983                   break;
11984                 }
11985                 case FOURCC_strf:
11986                 {
11987                   GstBuffer *buf;
11988
11989                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11990
11991                   /* First 4 bytes are the length of the atom, the next 4 bytes
11992                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11993                    * next 1 byte is the version, and the
11994                    * subsequent bytes are sequence parameter set like data. */
11995
11996                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11997                   if (size > 1) {
11998                     gst_codec_utils_h264_caps_set_level_and_profile
11999                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
12000
12001                     buf = gst_buffer_new_and_alloc (size);
12002                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
12003                     gst_caps_set_simple (entry->caps,
12004                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12005                     gst_buffer_unref (buf);
12006                   }
12007                   break;
12008                 }
12009                 case FOURCC_btrt:
12010                 {
12011                   guint avg_bitrate, max_bitrate;
12012
12013                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
12014                   if (size < 12)
12015                     break;
12016
12017                   max_bitrate = QT_UINT32 (avc_data + 0xc);
12018                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
12019
12020                   if (!max_bitrate && !avg_bitrate)
12021                     break;
12022
12023                   /* Some muxers seem to swap the average and maximum bitrates
12024                    * (I'm looking at you, YouTube), so we swap for sanity. */
12025                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
12026                     guint temp = avg_bitrate;
12027
12028                     avg_bitrate = max_bitrate;
12029                     max_bitrate = temp;
12030                   }
12031
12032                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12033                     gst_tag_list_add (stream->stream_tags,
12034                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
12035                         max_bitrate, NULL);
12036                   }
12037                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12038                     gst_tag_list_add (stream->stream_tags,
12039                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
12040                         NULL);
12041                   }
12042
12043                   break;
12044                 }
12045
12046                 default:
12047                   break;
12048               }
12049
12050               len -= size + 8;
12051               avc_data += size + 8;
12052             }
12053
12054             break;
12055           }
12056           case FOURCC_H265:
12057           case FOURCC_hvc1:
12058           case FOURCC_hev1:
12059           case FOURCC_dvh1:
12060           case FOURCC_dvhe:
12061           {
12062             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12063             const guint8 *hevc_data = stsd_entry_data + 0x56;
12064
12065             /* find hevc */
12066             while (len >= 0x8) {
12067               gint size;
12068
12069               if (QT_UINT32 (hevc_data) <= len)
12070                 size = QT_UINT32 (hevc_data) - 0x8;
12071               else
12072                 size = len - 0x8;
12073
12074               if (size < 1)
12075                 /* No real data, so break out */
12076                 break;
12077
12078               switch (QT_FOURCC (hevc_data + 0x4)) {
12079                 case FOURCC_hvcC:
12080                 {
12081                   /* parse, if found */
12082                   GstBuffer *buf;
12083
12084                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
12085
12086                   /* First 4 bytes are the length of the atom, the next 4 bytes
12087                    * are the fourcc, the next 1 byte is the version, and the
12088                    * subsequent bytes are sequence parameter set like data. */
12089                   gst_codec_utils_h265_caps_set_level_tier_and_profile
12090                       (entry->caps, hevc_data + 8 + 1, size - 1);
12091
12092                   buf = gst_buffer_new_and_alloc (size);
12093                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
12094                   gst_caps_set_simple (entry->caps,
12095                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12096                   gst_buffer_unref (buf);
12097                   break;
12098                 }
12099                 default:
12100                   break;
12101               }
12102               len -= size + 8;
12103               hevc_data += size + 8;
12104             }
12105             break;
12106           }
12107           case FOURCC_mp4v:
12108           case FOURCC_MP4V:
12109           case FOURCC_fmp4:
12110           case FOURCC_FMP4:
12111           case FOURCC_xvid:
12112           case FOURCC_XVID:
12113           {
12114             GNode *glbl;
12115
12116             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
12117                 GST_FOURCC_ARGS (fourcc));
12118
12119             /* codec data might be in glbl extension atom */
12120             glbl = mp4v ?
12121                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
12122             if (glbl) {
12123               guint8 *data;
12124               GstBuffer *buf;
12125               gint len;
12126
12127               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
12128               data = glbl->data;
12129               len = QT_UINT32 (data);
12130               if (len > 0x8) {
12131                 len -= 0x8;
12132                 buf = gst_buffer_new_and_alloc (len);
12133                 gst_buffer_fill (buf, 0, data + 8, len);
12134                 gst_caps_set_simple (entry->caps,
12135                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12136                 gst_buffer_unref (buf);
12137               }
12138             }
12139             break;
12140           }
12141           case FOURCC_mjp2:
12142           {
12143             /* see annex I of the jpeg2000 spec */
12144             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
12145             const guint8 *data;
12146             const gchar *colorspace = NULL;
12147             gint ncomp = 0;
12148             guint32 ncomp_map = 0;
12149             gint32 *comp_map = NULL;
12150             guint32 nchan_def = 0;
12151             gint32 *chan_def = NULL;
12152
12153             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
12154             /* some required atoms */
12155             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12156             if (!mjp2)
12157               break;
12158             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
12159             if (!jp2h)
12160               break;
12161
12162             /* number of components; redundant with info in codestream, but useful
12163                to a muxer */
12164             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
12165             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
12166               break;
12167             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
12168
12169             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
12170             if (!colr)
12171               break;
12172             GST_DEBUG_OBJECT (qtdemux, "found colr");
12173             /* extract colour space info */
12174             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
12175               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
12176                 case 16:
12177                   colorspace = "sRGB";
12178                   break;
12179                 case 17:
12180                   colorspace = "GRAY";
12181                   break;
12182                 case 18:
12183                   colorspace = "sYUV";
12184                   break;
12185                 default:
12186                   colorspace = NULL;
12187                   break;
12188               }
12189             }
12190             if (!colorspace)
12191               /* colr is required, and only values 16, 17, and 18 are specified,
12192                  so error if we have no colorspace */
12193               break;
12194
12195             /* extract component mapping */
12196             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
12197             if (cmap) {
12198               guint32 cmap_len = 0;
12199               int i;
12200               cmap_len = QT_UINT32 (cmap->data);
12201               if (cmap_len >= 8) {
12202                 /* normal box, subtract off header */
12203                 cmap_len -= 8;
12204                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
12205                 if (cmap_len % 4 == 0) {
12206                   ncomp_map = (cmap_len / 4);
12207                   comp_map = g_new0 (gint32, ncomp_map);
12208                   for (i = 0; i < ncomp_map; i++) {
12209                     guint16 cmp;
12210                     guint8 mtyp, pcol;
12211                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
12212                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
12213                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
12214                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
12215                   }
12216                 }
12217               }
12218             }
12219             /* extract channel definitions */
12220             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
12221             if (cdef) {
12222               guint32 cdef_len = 0;
12223               int i;
12224               cdef_len = QT_UINT32 (cdef->data);
12225               if (cdef_len >= 10) {
12226                 /* normal box, subtract off header and len */
12227                 cdef_len -= 10;
12228                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
12229                 if (cdef_len % 6 == 0) {
12230                   nchan_def = (cdef_len / 6);
12231                   chan_def = g_new0 (gint32, nchan_def);
12232                   for (i = 0; i < nchan_def; i++)
12233                     chan_def[i] = -1;
12234                   for (i = 0; i < nchan_def; i++) {
12235                     guint16 cn, typ, asoc;
12236                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
12237                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
12238                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
12239                     if (cn < nchan_def) {
12240                       switch (typ) {
12241                         case 0:
12242                           chan_def[cn] = asoc;
12243                           break;
12244                         case 1:
12245                           chan_def[cn] = 0;     /* alpha */
12246                           break;
12247                         default:
12248                           chan_def[cn] = -typ;
12249                       }
12250                     }
12251                   }
12252                 }
12253               }
12254             }
12255
12256             gst_caps_set_simple (entry->caps,
12257                 "num-components", G_TYPE_INT, ncomp, NULL);
12258             gst_caps_set_simple (entry->caps,
12259                 "colorspace", G_TYPE_STRING, colorspace, NULL);
12260
12261             if (comp_map) {
12262               GValue arr = { 0, };
12263               GValue elt = { 0, };
12264               int i;
12265               g_value_init (&arr, GST_TYPE_ARRAY);
12266               g_value_init (&elt, G_TYPE_INT);
12267               for (i = 0; i < ncomp_map; i++) {
12268                 g_value_set_int (&elt, comp_map[i]);
12269                 gst_value_array_append_value (&arr, &elt);
12270               }
12271               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
12272                   "component-map", &arr);
12273               g_value_unset (&elt);
12274               g_value_unset (&arr);
12275               g_free (comp_map);
12276             }
12277
12278             if (chan_def) {
12279               GValue arr = { 0, };
12280               GValue elt = { 0, };
12281               int i;
12282               g_value_init (&arr, GST_TYPE_ARRAY);
12283               g_value_init (&elt, G_TYPE_INT);
12284               for (i = 0; i < nchan_def; i++) {
12285                 g_value_set_int (&elt, chan_def[i]);
12286                 gst_value_array_append_value (&arr, &elt);
12287               }
12288               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
12289                   "channel-definitions", &arr);
12290               g_value_unset (&elt);
12291               g_value_unset (&arr);
12292               g_free (chan_def);
12293             }
12294
12295             /* some optional atoms */
12296             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
12297             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
12298
12299             /* indicate possible fields in caps */
12300             if (field) {
12301               data = (guint8 *) field->data + 8;
12302               if (*data != 1)
12303                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
12304                     (gint) * data, NULL);
12305             }
12306             /* add codec_data if provided */
12307             if (prefix) {
12308               GstBuffer *buf;
12309               gint len;
12310
12311               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
12312               data = prefix->data;
12313               len = QT_UINT32 (data);
12314               if (len > 0x8) {
12315                 len -= 0x8;
12316                 buf = gst_buffer_new_and_alloc (len);
12317                 gst_buffer_fill (buf, 0, data + 8, len);
12318                 gst_caps_set_simple (entry->caps,
12319                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12320                 gst_buffer_unref (buf);
12321               }
12322             }
12323             break;
12324           }
12325           case FOURCC_SVQ3:
12326           case FOURCC_VP31:
12327           {
12328             GstBuffer *buf;
12329             GstBuffer *seqh = NULL;
12330             const guint8 *gamma_data = NULL;
12331             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
12332
12333             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
12334                 &seqh);
12335             if (gamma_data) {
12336               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
12337                   QT_FP32 (gamma_data), NULL);
12338             }
12339             if (seqh) {
12340               /* sorry for the bad name, but we don't know what this is, other
12341                * than its own fourcc */
12342               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
12343                   NULL);
12344               gst_buffer_unref (seqh);
12345             }
12346
12347             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
12348             buf = gst_buffer_new_and_alloc (len);
12349             gst_buffer_fill (buf, 0, stsd_data, len);
12350             gst_caps_set_simple (entry->caps,
12351                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12352             gst_buffer_unref (buf);
12353             break;
12354           }
12355           case FOURCC_jpeg:
12356           {
12357             /* https://developer.apple.com/standards/qtff-2001.pdf,
12358              * page 92, "Video Sample Description", under table 3.1 */
12359             GstByteReader br;
12360
12361             const gint compressor_offset =
12362                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
12363             const gint min_size = compressor_offset + 32 + 2 + 2;
12364             GNode *jpeg;
12365             guint32 len;
12366             guint16 color_table_id = 0;
12367             gboolean ok;
12368
12369             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
12370
12371             /* recover information on interlaced/progressive */
12372             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
12373             if (!jpeg)
12374               break;
12375
12376             len = QT_UINT32 (jpeg->data);
12377             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
12378                 min_size);
12379             if (len >= min_size) {
12380               gst_byte_reader_init (&br, jpeg->data, len);
12381
12382               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
12383               gst_byte_reader_get_uint16_le (&br, &color_table_id);
12384               if (color_table_id != 0) {
12385                 /* the spec says there can be concatenated chunks in the data, and we want
12386                  * to find one called field. Walk through them. */
12387                 gint offset = min_size;
12388                 while (offset + 8 < len) {
12389                   guint32 size = 0, tag;
12390                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12391                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12392                   if (!ok || size < 8) {
12393                     GST_WARNING_OBJECT (qtdemux,
12394                         "Failed to walk optional chunk list");
12395                     break;
12396                   }
12397                   GST_DEBUG_OBJECT (qtdemux,
12398                       "Found optional %4.4s chunk, size %u",
12399                       (const char *) &tag, size);
12400                   if (tag == FOURCC_fiel) {
12401                     guint8 n_fields = 0, ordering = 0;
12402                     gst_byte_reader_get_uint8 (&br, &n_fields);
12403                     gst_byte_reader_get_uint8 (&br, &ordering);
12404                     if (n_fields == 1 || n_fields == 2) {
12405                       GST_DEBUG_OBJECT (qtdemux,
12406                           "Found fiel tag with %u fields, ordering %u",
12407                           n_fields, ordering);
12408                       if (n_fields == 2)
12409                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12410                             "interlace-mode", G_TYPE_STRING, "interleaved",
12411                             NULL);
12412                     } else {
12413                       GST_WARNING_OBJECT (qtdemux,
12414                           "Found fiel tag with invalid fields (%u)", n_fields);
12415                     }
12416                   }
12417                   offset += size;
12418                 }
12419               } else {
12420                 GST_DEBUG_OBJECT (qtdemux,
12421                     "Color table ID is 0, not trying to get interlacedness");
12422               }
12423             } else {
12424               GST_WARNING_OBJECT (qtdemux,
12425                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12426             }
12427
12428             break;
12429           }
12430           case FOURCC_rle_:
12431           case FOURCC_WRLE:
12432           {
12433             gst_caps_set_simple (entry->caps,
12434                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12435                 NULL);
12436             break;
12437           }
12438           case FOURCC_XiTh:
12439           {
12440             GNode *xith, *xdxt;
12441
12442             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12443             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12444             if (!xith)
12445               break;
12446
12447             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12448             if (!xdxt)
12449               break;
12450
12451             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12452             /* collect the headers and store them in a stream list so that we can
12453              * send them out first */
12454             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12455             break;
12456           }
12457           case FOURCC_ovc1:
12458           {
12459             GNode *ovc1;
12460             guint8 *ovc1_data;
12461             guint ovc1_len;
12462             GstBuffer *buf;
12463
12464             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12465             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12466             if (!ovc1)
12467               break;
12468             ovc1_data = ovc1->data;
12469             ovc1_len = QT_UINT32 (ovc1_data);
12470             if (ovc1_len <= 198) {
12471               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12472               break;
12473             }
12474             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12475             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12476             gst_caps_set_simple (entry->caps,
12477                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12478             gst_buffer_unref (buf);
12479             break;
12480           }
12481           case FOURCC_vc_1:
12482           {
12483             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12484             const guint8 *vc1_data = stsd_entry_data + 0x56;
12485
12486             /* find dvc1 */
12487             while (len >= 8) {
12488               gint size;
12489
12490               if (QT_UINT32 (vc1_data) <= len)
12491                 size = QT_UINT32 (vc1_data) - 8;
12492               else
12493                 size = len - 8;
12494
12495               if (size < 1)
12496                 /* No real data, so break out */
12497                 break;
12498
12499               switch (QT_FOURCC (vc1_data + 0x4)) {
12500                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12501                 {
12502                   GstBuffer *buf;
12503
12504                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12505                   buf = gst_buffer_new_and_alloc (size);
12506                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12507                   gst_caps_set_simple (entry->caps,
12508                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12509                   gst_buffer_unref (buf);
12510                   break;
12511                 }
12512                 default:
12513                   break;
12514               }
12515               len -= size + 8;
12516               vc1_data += size + 8;
12517             }
12518             break;
12519           }
12520           case FOURCC_av01:
12521           {
12522             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12523             const guint8 *av1_data = stsd_entry_data + 0x56;
12524
12525             /* find av1C */
12526             while (len >= 0x8) {
12527               gint size;
12528
12529               if (QT_UINT32 (av1_data) <= len)
12530                 size = QT_UINT32 (av1_data) - 0x8;
12531               else
12532                 size = len - 0x8;
12533
12534               if (size < 1)
12535                 /* No real data, so break out */
12536                 break;
12537
12538               switch (QT_FOURCC (av1_data + 0x4)) {
12539                 case FOURCC_av1C:
12540                 {
12541                   /* parse, if found */
12542                   GstBuffer *buf;
12543                   guint8 pres_delay_field;
12544
12545                   GST_DEBUG_OBJECT (qtdemux,
12546                       "found av1C codec_data in stsd of size %d", size);
12547
12548                   /* not enough data, just ignore and hope for the best */
12549                   if (size < 5)
12550                     break;
12551
12552                   /* Content is:
12553                    * 4 bytes: atom length
12554                    * 4 bytes: fourcc
12555                    * 1 byte: version
12556                    * 3 bytes: flags
12557                    * 3 bits: reserved
12558                    * 1 bits:  initial_presentation_delay_present
12559                    * 4 bits: initial_presentation_delay (if present else reserved
12560                    * rest: OBUs.
12561                    */
12562
12563                   if (av1_data[9] != 0) {
12564                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12565                     break;
12566                   }
12567
12568                   /* We skip initial_presentation_delay* for now */
12569                   pres_delay_field = *(av1_data + 12);
12570                   if (pres_delay_field & (1 << 5)) {
12571                     gst_caps_set_simple (entry->caps,
12572                         "presentation-delay", G_TYPE_INT,
12573                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12574                   }
12575                   if (size > 5) {
12576                     buf = gst_buffer_new_and_alloc (size - 5);
12577                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12578                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12579                     gst_caps_set_simple (entry->caps,
12580                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12581                     gst_buffer_unref (buf);
12582                   }
12583                   break;
12584                 }
12585                 default:
12586                   break;
12587               }
12588
12589               len -= size + 8;
12590               av1_data += size + 8;
12591             }
12592
12593             break;
12594           }
12595
12596             /* TODO: Need to parse vpcC for VP8 codec too.
12597              * Note that VPCodecConfigurationBox (vpcC) is defined for
12598              * vp08, vp09, and vp10 fourcc. */
12599           case FOURCC_vp09:
12600           {
12601             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12602             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12603
12604             /* find vpcC */
12605             while (len >= 0x8) {
12606               gint size;
12607
12608               if (QT_UINT32 (vpcc_data) <= len)
12609                 size = QT_UINT32 (vpcc_data) - 0x8;
12610               else
12611                 size = len - 0x8;
12612
12613               if (size < 1)
12614                 /* No real data, so break out */
12615                 break;
12616
12617               switch (QT_FOURCC (vpcc_data + 0x4)) {
12618                 case FOURCC_vpcC:
12619                 {
12620                   const gchar *profile_str = NULL;
12621                   const gchar *chroma_format_str = NULL;
12622                   guint8 profile;
12623                   guint8 bitdepth;
12624                   guint8 chroma_format;
12625                   GstVideoColorimetry cinfo;
12626
12627                   /* parse, if found */
12628                   GST_DEBUG_OBJECT (qtdemux,
12629                       "found vp codec_data in stsd of size %d", size);
12630
12631                   /* the meaning of "size" is length of the atom body, excluding
12632                    * atom length and fourcc fields */
12633                   if (size < 12)
12634                     break;
12635
12636                   /* Content is:
12637                    * 4 bytes: atom length
12638                    * 4 bytes: fourcc
12639                    * 1 byte: version
12640                    * 3 bytes: flags
12641                    * 1 byte: profile
12642                    * 1 byte: level
12643                    * 4 bits: bitDepth
12644                    * 3 bits: chromaSubsampling
12645                    * 1 bit: videoFullRangeFlag
12646                    * 1 byte: colourPrimaries
12647                    * 1 byte: transferCharacteristics
12648                    * 1 byte: matrixCoefficients
12649                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12650                    * rest: codecIntializationData (not used for vp8 and vp9)
12651                    */
12652
12653                   if (vpcc_data[8] != 1) {
12654                     GST_WARNING_OBJECT (qtdemux,
12655                         "unknown vpcC version %d", vpcc_data[8]);
12656                     break;
12657                   }
12658
12659                   profile = vpcc_data[12];
12660                   switch (profile) {
12661                     case 0:
12662                       profile_str = "0";
12663                       break;
12664                     case 1:
12665                       profile_str = "1";
12666                       break;
12667                     case 2:
12668                       profile_str = "2";
12669                       break;
12670                     case 3:
12671                       profile_str = "3";
12672                       break;
12673                     default:
12674                       break;
12675                   }
12676
12677                   if (profile_str) {
12678                     gst_caps_set_simple (entry->caps,
12679                         "profile", G_TYPE_STRING, profile_str, NULL);
12680                   }
12681
12682                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12683                    * but webm spec define various ones. Add level to caps
12684                    * if we really need it then */
12685
12686                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12687                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12688                     gst_caps_set_simple (entry->caps,
12689                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12690                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12691                   }
12692
12693                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12694                   switch (chroma_format) {
12695                     case 0:
12696                     case 1:
12697                       chroma_format_str = "4:2:0";
12698                       break;
12699                     case 2:
12700                       chroma_format_str = "4:2:2";
12701                       break;
12702                     case 3:
12703                       chroma_format_str = "4:4:4";
12704                       break;
12705                     default:
12706                       break;
12707                   }
12708
12709                   if (chroma_format_str) {
12710                     gst_caps_set_simple (entry->caps,
12711                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12712                         NULL);
12713                   }
12714
12715                   if ((vpcc_data[14] & 0x1) != 0)
12716                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12717                   else
12718                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12719                   cinfo.primaries =
12720                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12721                   cinfo.transfer =
12722                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12723                   cinfo.matrix =
12724                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12725
12726                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12727                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12728                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12729                     /* set this only if all values are known, otherwise this
12730                      * might overwrite valid ones parsed from other color box */
12731                     CUR_STREAM (stream)->colorimetry = cinfo;
12732                   }
12733                   break;
12734                 }
12735                 default:
12736                   break;
12737               }
12738
12739               len -= size + 8;
12740               vpcc_data += size + 8;
12741             }
12742
12743             break;
12744           }
12745           default:
12746             break;
12747         }
12748       }
12749
12750       GST_INFO_OBJECT (qtdemux,
12751           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12752           GST_FOURCC_ARGS (fourcc), entry->caps);
12753
12754     } else if (stream->subtype == FOURCC_soun) {
12755       GNode *wave;
12756       int version, samplesize;
12757       guint16 compression_id;
12758       gboolean amrwb = FALSE;
12759
12760       offset = 16;
12761       /* sample description entry (16) + sound sample description v0 (20) */
12762       if (len < 36)
12763         goto corrupt_file;
12764
12765       version = QT_UINT32 (stsd_entry_data + offset);
12766       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12767       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12768       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12769       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12770
12771       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12772       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12773           QT_UINT32 (stsd_entry_data + offset + 4));
12774       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12775       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12776       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12777       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12778           QT_UINT16 (stsd_entry_data + offset + 14));
12779       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12780
12781       if (compression_id == 0xfffe)
12782         entry->sampled = TRUE;
12783
12784       /* first assume uncompressed audio */
12785       entry->bytes_per_sample = samplesize / 8;
12786       entry->samples_per_frame = entry->n_channels;
12787       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12788       entry->samples_per_packet = entry->samples_per_frame;
12789       entry->bytes_per_packet = entry->bytes_per_sample;
12790
12791       offset = 36;
12792
12793       if (version == 0x00010000) {
12794         /* sample description entry (16) + sound sample description v1 (20+16) */
12795         if (len < 52)
12796           goto corrupt_file;
12797
12798         /* take information from here over the normal sample description */
12799         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12800         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12801         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12802         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12803
12804         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12805         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12806             entry->samples_per_packet);
12807         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12808             entry->bytes_per_packet);
12809         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12810             entry->bytes_per_frame);
12811         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12812             entry->bytes_per_sample);
12813
12814         if (!entry->sampled && entry->bytes_per_packet) {
12815           entry->samples_per_frame = (entry->bytes_per_frame /
12816               entry->bytes_per_packet) * entry->samples_per_packet;
12817           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12818               entry->samples_per_frame);
12819         }
12820       } else if (version == 0x00020000) {
12821         /* sample description entry (16) + sound sample description v2 (56) */
12822         if (len < 72)
12823           goto corrupt_file;
12824
12825         /* take information from here over the normal sample description */
12826         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12827         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12828         entry->samples_per_frame = entry->n_channels;
12829         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12830         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12831         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12832         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12833
12834         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12835         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12836         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12837         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12838             entry->bytes_per_sample * 8);
12839         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12840             QT_UINT32 (stsd_entry_data + offset + 24));
12841         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12842             entry->bytes_per_packet);
12843         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12844             entry->samples_per_packet);
12845       } else if (version != 0x00000) {
12846         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12847             version);
12848       }
12849
12850       switch (fourcc) {
12851           /* Yes, these have to be hard-coded */
12852         case FOURCC_MAC6:
12853         {
12854           entry->samples_per_packet = 6;
12855           entry->bytes_per_packet = 1;
12856           entry->bytes_per_frame = 1 * entry->n_channels;
12857           entry->bytes_per_sample = 1;
12858           entry->samples_per_frame = 6 * entry->n_channels;
12859           break;
12860         }
12861         case FOURCC_MAC3:
12862         {
12863           entry->samples_per_packet = 3;
12864           entry->bytes_per_packet = 1;
12865           entry->bytes_per_frame = 1 * entry->n_channels;
12866           entry->bytes_per_sample = 1;
12867           entry->samples_per_frame = 3 * entry->n_channels;
12868           break;
12869         }
12870         case FOURCC_ima4:
12871         {
12872           entry->samples_per_packet = 64;
12873           entry->bytes_per_packet = 34;
12874           entry->bytes_per_frame = 34 * entry->n_channels;
12875           entry->bytes_per_sample = 2;
12876           entry->samples_per_frame = 64 * entry->n_channels;
12877           break;
12878         }
12879         case FOURCC_ulaw:
12880         case FOURCC_alaw:
12881         {
12882           entry->samples_per_packet = 1;
12883           entry->bytes_per_packet = 1;
12884           entry->bytes_per_frame = 1 * entry->n_channels;
12885           entry->bytes_per_sample = 1;
12886           entry->samples_per_frame = 1 * entry->n_channels;
12887           break;
12888         }
12889         case FOURCC_agsm:
12890         {
12891           entry->samples_per_packet = 160;
12892           entry->bytes_per_packet = 33;
12893           entry->bytes_per_frame = 33 * entry->n_channels;
12894           entry->bytes_per_sample = 2;
12895           entry->samples_per_frame = 160 * entry->n_channels;
12896           break;
12897         }
12898           /* fix up any invalid header information from above */
12899         case FOURCC_twos:
12900         case FOURCC_sowt:
12901         case FOURCC_raw_:
12902         case FOURCC_lpcm:
12903           /* Sometimes these are set to 0 in the sound sample descriptions so
12904            * let's try to infer useful values from the other information we
12905            * have available */
12906           if (entry->bytes_per_sample == 0)
12907             entry->bytes_per_sample =
12908                 entry->bytes_per_frame / entry->n_channels;
12909           if (entry->bytes_per_sample == 0)
12910             entry->bytes_per_sample = samplesize / 8;
12911
12912           if (entry->bytes_per_frame == 0)
12913             entry->bytes_per_frame =
12914                 entry->bytes_per_sample * entry->n_channels;
12915
12916           if (entry->bytes_per_packet == 0)
12917             entry->bytes_per_packet = entry->bytes_per_sample;
12918
12919           if (entry->samples_per_frame == 0)
12920             entry->samples_per_frame = entry->n_channels;
12921
12922           if (entry->samples_per_packet == 0)
12923             entry->samples_per_packet = entry->samples_per_frame;
12924
12925           break;
12926         case FOURCC_in24:
12927         case FOURCC_in32:
12928         case FOURCC_fl32:
12929         case FOURCC_fl64:
12930         case FOURCC_s16l:{
12931           switch (fourcc) {
12932             case FOURCC_in24:
12933               entry->bytes_per_sample = 3;
12934               break;
12935             case FOURCC_in32:
12936             case FOURCC_fl32:
12937               entry->bytes_per_sample = 4;
12938               break;
12939             case FOURCC_fl64:
12940               entry->bytes_per_sample = 8;
12941               break;
12942             case FOURCC_s16l:
12943               entry->bytes_per_sample = 2;
12944               break;
12945             default:
12946               g_assert_not_reached ();
12947               break;
12948           }
12949           entry->samples_per_frame = entry->n_channels;
12950           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12951           entry->samples_per_packet = entry->samples_per_frame;
12952           entry->bytes_per_packet = entry->bytes_per_sample;
12953           break;
12954         }
12955         default:
12956           break;
12957       }
12958
12959       if (entry->caps)
12960         gst_caps_unref (entry->caps);
12961
12962       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12963           stsd_entry_data + 32, len - 16, &codec);
12964
12965       switch (fourcc) {
12966         case FOURCC_in24:
12967         case FOURCC_in32:
12968         case FOURCC_fl32:
12969         case FOURCC_fl64:
12970         {
12971           GNode *enda;
12972           GNode *fmt;
12973
12974           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12975
12976           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12977           if (!enda) {
12978             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12979             if (wave)
12980               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12981           }
12982           if (enda) {
12983             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12984             const gchar *format_str;
12985
12986             switch (fourcc) {
12987               case FOURCC_in24:
12988                 format_str = (enda_value) ? "S24LE" : "S24BE";
12989                 break;
12990               case FOURCC_in32:
12991                 format_str = (enda_value) ? "S32LE" : "S32BE";
12992                 break;
12993               case FOURCC_fl32:
12994                 format_str = (enda_value) ? "F32LE" : "F32BE";
12995                 break;
12996               case FOURCC_fl64:
12997                 format_str = (enda_value) ? "F64LE" : "F64BE";
12998                 break;
12999               default:
13000                 g_assert_not_reached ();
13001                 break;
13002             }
13003             gst_caps_set_simple (entry->caps,
13004                 "format", G_TYPE_STRING, format_str, NULL);
13005           }
13006           break;
13007         }
13008         case FOURCC_owma:
13009         {
13010           const guint8 *owma_data;
13011           const gchar *codec_name = NULL;
13012           guint owma_len;
13013           GstBuffer *buf;
13014           gint version = 1;
13015           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
13016           /* FIXME this should also be gst_riff_strf_auds,
13017            * but the latter one is actually missing bits-per-sample :( */
13018           typedef struct
13019           {
13020             gint16 wFormatTag;
13021             gint16 nChannels;
13022             gint32 nSamplesPerSec;
13023             gint32 nAvgBytesPerSec;
13024             gint16 nBlockAlign;
13025             gint16 wBitsPerSample;
13026             gint16 cbSize;
13027           } WAVEFORMATEX;
13028           WAVEFORMATEX *wfex;
13029
13030           GST_DEBUG_OBJECT (qtdemux, "parse owma");
13031           owma_data = stsd_entry_data;
13032           owma_len = QT_UINT32 (owma_data);
13033           if (owma_len <= 54) {
13034             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
13035             break;
13036           }
13037           wfex = (WAVEFORMATEX *) (owma_data + 36);
13038           buf = gst_buffer_new_and_alloc (owma_len - 54);
13039           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
13040           if (wfex->wFormatTag == 0x0161) {
13041             codec_name = "Windows Media Audio";
13042             version = 2;
13043           } else if (wfex->wFormatTag == 0x0162) {
13044             codec_name = "Windows Media Audio 9 Pro";
13045             version = 3;
13046           } else if (wfex->wFormatTag == 0x0163) {
13047             codec_name = "Windows Media Audio 9 Lossless";
13048             /* is that correct? gstffmpegcodecmap.c is missing it, but
13049              * fluendo codec seems to support it */
13050             version = 4;
13051           }
13052
13053           gst_caps_set_simple (entry->caps,
13054               "codec_data", GST_TYPE_BUFFER, buf,
13055               "wmaversion", G_TYPE_INT, version,
13056               "block_align", G_TYPE_INT,
13057               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
13058               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
13059               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
13060               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
13061           gst_buffer_unref (buf);
13062
13063           if (codec_name) {
13064             g_free (codec);
13065             codec = g_strdup (codec_name);
13066           }
13067           break;
13068         }
13069         case FOURCC_wma_:
13070         {
13071           gint len = QT_UINT32 (stsd_entry_data) - offset;
13072           const guint8 *wfex_data = stsd_entry_data + offset;
13073           const gchar *codec_name = NULL;
13074           gint version = 1;
13075           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
13076           /* FIXME this should also be gst_riff_strf_auds,
13077            * but the latter one is actually missing bits-per-sample :( */
13078           typedef struct
13079           {
13080             gint16 wFormatTag;
13081             gint16 nChannels;
13082             gint32 nSamplesPerSec;
13083             gint32 nAvgBytesPerSec;
13084             gint16 nBlockAlign;
13085             gint16 wBitsPerSample;
13086             gint16 cbSize;
13087           } WAVEFORMATEX;
13088           WAVEFORMATEX wfex;
13089
13090           /* FIXME: unify with similar wavformatex parsing code above */
13091           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
13092
13093           /* find wfex */
13094           while (len >= 8) {
13095             gint size;
13096
13097             if (QT_UINT32 (wfex_data) <= len)
13098               size = QT_UINT32 (wfex_data) - 8;
13099             else
13100               size = len - 8;
13101
13102             if (size < 1)
13103               /* No real data, so break out */
13104               break;
13105
13106             switch (QT_FOURCC (wfex_data + 4)) {
13107               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
13108               {
13109                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
13110
13111                 if (size < 8 + 18)
13112                   break;
13113
13114                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
13115                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
13116                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
13117                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
13118                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
13119                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
13120                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
13121
13122                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
13123                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
13124                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
13125                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
13126                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
13127                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
13128
13129                 if (wfex.wFormatTag == 0x0161) {
13130                   codec_name = "Windows Media Audio";
13131                   version = 2;
13132                 } else if (wfex.wFormatTag == 0x0162) {
13133                   codec_name = "Windows Media Audio 9 Pro";
13134                   version = 3;
13135                 } else if (wfex.wFormatTag == 0x0163) {
13136                   codec_name = "Windows Media Audio 9 Lossless";
13137                   /* is that correct? gstffmpegcodecmap.c is missing it, but
13138                    * fluendo codec seems to support it */
13139                   version = 4;
13140                 }
13141
13142                 gst_caps_set_simple (entry->caps,
13143                     "wmaversion", G_TYPE_INT, version,
13144                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
13145                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
13146                     "width", G_TYPE_INT, wfex.wBitsPerSample,
13147                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
13148
13149                 if (size > wfex.cbSize) {
13150                   GstBuffer *buf;
13151
13152                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
13153                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
13154                       size - wfex.cbSize);
13155                   gst_caps_set_simple (entry->caps,
13156                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
13157                   gst_buffer_unref (buf);
13158                 } else {
13159                   GST_WARNING_OBJECT (qtdemux, "no codec data");
13160                 }
13161
13162                 if (codec_name) {
13163                   g_free (codec);
13164                   codec = g_strdup (codec_name);
13165                 }
13166                 break;
13167               }
13168               default:
13169                 break;
13170             }
13171             len -= size + 8;
13172             wfex_data += size + 8;
13173           }
13174           break;
13175         }
13176         case FOURCC_opus:
13177         {
13178           const guint8 *dops_data;
13179           guint8 *channel_mapping = NULL;
13180           guint32 rate;
13181           guint8 channels;
13182           guint8 channel_mapping_family;
13183           guint8 stream_count;
13184           guint8 coupled_count;
13185           guint8 i;
13186
13187           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
13188           if (version == 1)
13189             dops_data = stsd_entry_data + 51;
13190           else
13191             dops_data = stsd_entry_data + 35;
13192
13193           channels = GST_READ_UINT8 (dops_data + 10);
13194           rate = GST_READ_UINT32_LE (dops_data + 13);
13195           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
13196           stream_count = GST_READ_UINT8 (dops_data + 20);
13197           coupled_count = GST_READ_UINT8 (dops_data + 21);
13198
13199           if (channels > 0) {
13200             channel_mapping = g_malloc (channels * sizeof (guint8));
13201             for (i = 0; i < channels; i++)
13202               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
13203           }
13204
13205           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
13206               channel_mapping_family, stream_count, coupled_count,
13207               channel_mapping);
13208           break;
13209         }
13210         default:
13211           break;
13212       }
13213
13214       if (codec) {
13215         GstStructure *s;
13216         gint bitrate = 0;
13217
13218         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13219             GST_TAG_AUDIO_CODEC, codec, NULL);
13220         g_free (codec);
13221         codec = NULL;
13222
13223         /* some bitrate info may have ended up in caps */
13224         s = gst_caps_get_structure (entry->caps, 0);
13225         gst_structure_get_int (s, "bitrate", &bitrate);
13226         if (bitrate > 0)
13227           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13228               GST_TAG_BITRATE, bitrate, NULL);
13229       }
13230
13231       esds = NULL;
13232       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
13233       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
13234         if (stream->protected) {
13235           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
13236             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
13237           }
13238           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
13239             mp4a = NULL;
13240           }
13241         } else {
13242           mp4a = NULL;
13243         }
13244       }
13245
13246       wave = NULL;
13247       if (mp4a) {
13248         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
13249         if (wave)
13250           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
13251         if (!esds)
13252           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
13253       }
13254
13255
13256       /* If the fourcc's bottom 16 bits gives 'sm', then the top
13257          16 bits is a byte-swapped wave-style codec identifier,
13258          and we can find a WAVE header internally to a 'wave' atom here.
13259          This can more clearly be thought of as 'ms' as the top 16 bits, and a
13260          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
13261          is big-endian).
13262        */
13263       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
13264         if (len < offset + 20) {
13265           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
13266         } else {
13267           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
13268           const guint8 *data = stsd_entry_data + offset + 16;
13269           GNode *wavenode;
13270           GNode *waveheadernode;
13271
13272           wavenode = g_node_new ((guint8 *) data);
13273           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
13274             const guint8 *waveheader;
13275             guint32 headerlen;
13276
13277             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
13278             if (waveheadernode) {
13279               waveheader = (const guint8 *) waveheadernode->data;
13280               headerlen = QT_UINT32 (waveheader);
13281
13282               if (headerlen > 8) {
13283                 gst_riff_strf_auds *header = NULL;
13284                 GstBuffer *headerbuf;
13285                 GstBuffer *extra;
13286
13287                 waveheader += 8;
13288                 headerlen -= 8;
13289
13290                 headerbuf = gst_buffer_new_and_alloc (headerlen);
13291                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
13292
13293                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
13294                         headerbuf, &header, &extra)) {
13295                   gst_caps_unref (entry->caps);
13296                   /* FIXME: Need to do something with the channel reorder map */
13297                   entry->caps =
13298                       gst_riff_create_audio_caps (header->format, NULL, header,
13299                       extra, NULL, NULL, NULL);
13300
13301                   if (extra)
13302                     gst_buffer_unref (extra);
13303                   g_free (header);
13304                 }
13305               }
13306             } else
13307               GST_DEBUG ("Didn't find waveheadernode for this codec");
13308           }
13309           g_node_destroy (wavenode);
13310         }
13311       } else if (esds) {
13312         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13313             stream->stream_tags);
13314       } else {
13315         switch (fourcc) {
13316 #if 0
13317             /* FIXME: what is in the chunk? */
13318           case FOURCC_QDMC:
13319           {
13320             gint len = QT_UINT32 (stsd_data);
13321
13322             /* seems to be always = 116 = 0x74 */
13323             break;
13324           }
13325 #endif
13326           case FOURCC_QDM2:
13327           {
13328             gint len = QT_UINT32 (stsd_entry_data);
13329
13330             if (len > 0x3C) {
13331               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
13332
13333               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
13334               gst_caps_set_simple (entry->caps,
13335                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13336               gst_buffer_unref (buf);
13337             }
13338             gst_caps_set_simple (entry->caps,
13339                 "samplesize", G_TYPE_INT, samplesize, NULL);
13340             break;
13341           }
13342           case FOURCC_alac:
13343           {
13344             GNode *alac, *wave = NULL;
13345
13346             /* apparently, m4a has this atom appended directly in the stsd entry,
13347              * while mov has it in a wave atom */
13348             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
13349             if (alac) {
13350               /* alac now refers to stsd entry atom */
13351               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
13352               if (wave)
13353                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
13354               else
13355                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
13356             }
13357             if (alac) {
13358               const guint8 *alac_data = alac->data;
13359               gint len = QT_UINT32 (alac->data);
13360               GstBuffer *buf;
13361
13362               if (len < 36) {
13363                 GST_DEBUG_OBJECT (qtdemux,
13364                     "discarding alac atom with unexpected len %d", len);
13365               } else {
13366                 /* codec-data contains alac atom size and prefix,
13367                  * ffmpeg likes it that way, not quite gst-ish though ...*/
13368                 buf = gst_buffer_new_and_alloc (len);
13369                 gst_buffer_fill (buf, 0, alac->data, len);
13370                 gst_caps_set_simple (entry->caps,
13371                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
13372                 gst_buffer_unref (buf);
13373
13374                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
13375                 entry->n_channels = QT_UINT8 (alac_data + 21);
13376                 entry->rate = QT_UINT32 (alac_data + 32);
13377                 samplesize = QT_UINT8 (alac_data + 16 + 1);
13378               }
13379             }
13380             gst_caps_set_simple (entry->caps,
13381                 "samplesize", G_TYPE_INT, samplesize, NULL);
13382             break;
13383           }
13384           case FOURCC_fLaC:
13385           {
13386             /* The codingname of the sample entry is 'fLaC' */
13387             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13388
13389             if (flac) {
13390               /* The 'dfLa' box is added to the sample entry to convey
13391                  initializing information for the decoder. */
13392               const GNode *dfla =
13393                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13394
13395               if (dfla) {
13396                 const guint32 len = QT_UINT32 (dfla->data);
13397
13398                 /* Must contain at least dfLa box header (12),
13399                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13400                 if (len < 50) {
13401                   GST_DEBUG_OBJECT (qtdemux,
13402                       "discarding dfla atom with unexpected len %d", len);
13403                 } else {
13404                   /* skip dfLa header to get the METADATA_BLOCKs */
13405                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13406                   const guint32 metadata_blocks_len = len - 12;
13407
13408                   gchar *stream_marker = g_strdup ("fLaC");
13409                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13410                       strlen (stream_marker));
13411
13412                   guint32 index = 0;
13413                   guint32 remainder = 0;
13414                   guint32 block_size = 0;
13415                   gboolean is_last = FALSE;
13416
13417                   GValue array = G_VALUE_INIT;
13418                   GValue value = G_VALUE_INIT;
13419
13420                   g_value_init (&array, GST_TYPE_ARRAY);
13421                   g_value_init (&value, GST_TYPE_BUFFER);
13422
13423                   gst_value_set_buffer (&value, block);
13424                   gst_value_array_append_value (&array, &value);
13425                   g_value_reset (&value);
13426
13427                   gst_buffer_unref (block);
13428
13429                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13430                    * of data, and we haven't already finished parsing */
13431                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13432                     remainder = metadata_blocks_len - index;
13433
13434                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13435                     block_size = 4 +
13436                         (metadata_blocks[index + 1] << 16) +
13437                         (metadata_blocks[index + 2] << 8) +
13438                         metadata_blocks[index + 3];
13439
13440                     /* be careful not to read off end of box */
13441                     if (block_size > remainder) {
13442                       break;
13443                     }
13444
13445                     is_last = metadata_blocks[index] >> 7;
13446
13447                     block = gst_buffer_new_and_alloc (block_size);
13448
13449                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13450                         block_size);
13451
13452                     gst_value_set_buffer (&value, block);
13453                     gst_value_array_append_value (&array, &value);
13454                     g_value_reset (&value);
13455
13456                     gst_buffer_unref (block);
13457
13458                     index += block_size;
13459                   }
13460
13461                   /* only append the metadata if we successfully read all of it */
13462                   if (is_last) {
13463                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13464                             (stream)->caps, 0), "streamheader", &array);
13465                   } else {
13466                     GST_WARNING_OBJECT (qtdemux,
13467                         "discarding all METADATA_BLOCKs due to invalid "
13468                         "block_size %d at idx %d, rem %d", block_size, index,
13469                         remainder);
13470                   }
13471
13472                   g_value_unset (&value);
13473                   g_value_unset (&array);
13474
13475                   /* The sample rate obtained from the stsd may not be accurate
13476                    * since it cannot represent rates greater than 65535Hz, so
13477                    * override that value with the sample rate from the
13478                    * METADATA_BLOCK_STREAMINFO block */
13479                   CUR_STREAM (stream)->rate =
13480                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13481                 }
13482               }
13483             }
13484             break;
13485           }
13486           case FOURCC_sawb:
13487             /* Fallthrough! */
13488             amrwb = TRUE;
13489           case FOURCC_samr:
13490           {
13491             gint len = QT_UINT32 (stsd_entry_data);
13492
13493             if (len > 0x24) {
13494               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13495               guint bitrate;
13496
13497               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13498
13499               /* If we have enough data, let's try to get the 'damr' atom. See
13500                * the 3GPP container spec (26.244) for more details. */
13501               if ((len - 0x34) > 8 &&
13502                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13503                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13504                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13505               }
13506
13507               gst_caps_set_simple (entry->caps,
13508                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13509               gst_buffer_unref (buf);
13510             }
13511             break;
13512           }
13513           case FOURCC_mp4a:
13514           {
13515             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13516             gint len = QT_UINT32 (stsd_entry_data);
13517             guint16 sound_version = 0;
13518             /* FIXME: Can this be determined somehow? There doesn't seem to be
13519              * anything in mp4a atom that specifis compression */
13520             gint profile = 2;
13521             guint16 channels = entry->n_channels;
13522             guint32 time_scale = (guint32) entry->rate;
13523             gint sample_rate_index = -1;
13524
13525             if (len >= 34) {
13526               sound_version = QT_UINT16 (stsd_entry_data + 16);
13527
13528               if (sound_version == 1) {
13529                 channels = QT_UINT16 (stsd_entry_data + 24);
13530                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13531               } else {
13532                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13533                     sound_version);
13534               }
13535             } else {
13536               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13537                   len);
13538             }
13539
13540             sample_rate_index =
13541                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13542             if (sample_rate_index >= 0 && channels > 0) {
13543               guint8 codec_data[2];
13544               GstBuffer *buf;
13545
13546               /* build AAC codec data */
13547               codec_data[0] = profile << 3;
13548               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13549               codec_data[1] = (sample_rate_index & 0x01) << 7;
13550               codec_data[1] |= (channels & 0xF) << 3;
13551
13552               buf = gst_buffer_new_and_alloc (2);
13553               gst_buffer_fill (buf, 0, codec_data, 2);
13554               gst_caps_set_simple (entry->caps,
13555                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13556               gst_buffer_unref (buf);
13557             }
13558             break;
13559           }
13560           case FOURCC_lpcm:
13561           case FOURCC_in24:
13562           case FOURCC_in32:
13563           case FOURCC_fl32:
13564           case FOURCC_fl64:
13565           case FOURCC_s16l:
13566             /* Fully handled elsewhere */
13567             break;
13568           default:
13569             GST_INFO_OBJECT (qtdemux,
13570                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13571             break;
13572         }
13573       }
13574       GST_INFO_OBJECT (qtdemux,
13575           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13576           GST_FOURCC_ARGS (fourcc), entry->caps);
13577
13578     } else if (stream->subtype == FOURCC_strm) {
13579       if (fourcc == FOURCC_rtsp) {
13580         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13581       } else {
13582         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13583             GST_FOURCC_ARGS (fourcc));
13584         goto unknown_stream;
13585       }
13586       entry->sampled = TRUE;
13587     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13588         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13589         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13590
13591       entry->sampled = TRUE;
13592       entry->sparse = TRUE;
13593
13594       entry->caps =
13595           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13596           &codec);
13597       if (codec) {
13598         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13599             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13600         g_free (codec);
13601         codec = NULL;
13602       }
13603
13604       /* hunt for sort-of codec data */
13605       switch (fourcc) {
13606         case FOURCC_mp4s:
13607         {
13608           GNode *mp4s = NULL;
13609           GNode *esds = NULL;
13610
13611           /* look for palette in a stsd->mp4s->esds sub-atom */
13612           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13613           if (mp4s)
13614             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13615           if (esds == NULL) {
13616             /* Invalid STSD */
13617             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13618             break;
13619           }
13620
13621           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13622               stream->stream_tags);
13623           break;
13624         }
13625         default:
13626           GST_INFO_OBJECT (qtdemux,
13627               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13628           break;
13629       }
13630       GST_INFO_OBJECT (qtdemux,
13631           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13632           GST_FOURCC_ARGS (fourcc), entry->caps);
13633     } else {
13634       /* everything in 1 sample */
13635       entry->sampled = TRUE;
13636
13637       entry->caps =
13638           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13639           &codec);
13640
13641       if (entry->caps == NULL)
13642         goto unknown_stream;
13643
13644       if (codec) {
13645         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13646             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13647         g_free (codec);
13648         codec = NULL;
13649       }
13650     }
13651
13652     /* promote to sampled format */
13653     if (entry->fourcc == FOURCC_samr) {
13654       /* force mono 8000 Hz for AMR */
13655       entry->sampled = TRUE;
13656       entry->n_channels = 1;
13657       entry->rate = 8000;
13658     } else if (entry->fourcc == FOURCC_sawb) {
13659       /* force mono 16000 Hz for AMR-WB */
13660       entry->sampled = TRUE;
13661       entry->n_channels = 1;
13662       entry->rate = 16000;
13663     } else if (entry->fourcc == FOURCC_mp4a) {
13664       entry->sampled = TRUE;
13665     }
13666
13667
13668     stsd_entry_data += len;
13669     remaining_stsd_len -= len;
13670
13671   }
13672
13673   /* collect sample information */
13674   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13675     goto samples_failed;
13676
13677   if (qtdemux->fragmented) {
13678     guint64 offset;
13679
13680     /* need all moov samples as basis; probably not many if any at all */
13681     /* prevent moof parsing taking of at this time */
13682     offset = qtdemux->moof_offset;
13683     qtdemux->moof_offset = 0;
13684     if (stream->n_samples &&
13685         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13686       qtdemux->moof_offset = offset;
13687       goto samples_failed;
13688     }
13689     qtdemux->moof_offset = offset;
13690     /* movie duration more reliable in this case (e.g. mehd) */
13691     if (qtdemux->segment.duration &&
13692         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13693       stream->duration =
13694           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13695   }
13696
13697   /* configure segments */
13698   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13699     goto segments_failed;
13700
13701   /* add some language tag, if useful */
13702   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13703       strcmp (stream->lang_id, "und")) {
13704     const gchar *lang_code;
13705
13706     /* convert ISO 639-2 code to ISO 639-1 */
13707     lang_code = gst_tag_get_language_code (stream->lang_id);
13708     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13709         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13710   }
13711
13712   /* Check for UDTA tags */
13713   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13714     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13715   }
13716
13717   /* Insert and sort new stream in track-id order.
13718    * This will help in comparing old/new streams during stream update check */
13719   g_ptr_array_add (qtdemux->active_streams, stream);
13720   g_ptr_array_sort (qtdemux->active_streams,
13721       (GCompareFunc) qtdemux_track_id_compare_func);
13722   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13723       QTDEMUX_N_STREAMS (qtdemux));
13724
13725   return TRUE;
13726
13727 /* ERRORS */
13728 corrupt_file:
13729   {
13730     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13731         (_("This file is corrupt and cannot be played.")), (NULL));
13732     if (stream)
13733       gst_qtdemux_stream_unref (stream);
13734     return FALSE;
13735   }
13736 error_encrypted:
13737   {
13738     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13739     gst_qtdemux_stream_unref (stream);
13740     return FALSE;
13741   }
13742 samples_failed:
13743 segments_failed:
13744   {
13745     /* we posted an error already */
13746     /* free stbl sub-atoms */
13747     gst_qtdemux_stbl_free (stream);
13748     gst_qtdemux_stream_unref (stream);
13749     return FALSE;
13750   }
13751 existing_stream:
13752   {
13753     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13754         track_id);
13755     return TRUE;
13756   }
13757 unknown_stream:
13758   {
13759     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13760         GST_FOURCC_ARGS (stream->subtype));
13761     gst_qtdemux_stream_unref (stream);
13762     return TRUE;
13763   }
13764 }
13765
13766 /* If we can estimate the overall bitrate, and don't have information about the
13767  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13768  * the overall bitrate minus the sum of the bitrates of all other streams. This
13769  * should be useful for the common case where we have one audio and one video
13770  * stream and can estimate the bitrate of one, but not the other. */
13771 static void
13772 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13773 {
13774   QtDemuxStream *stream = NULL;
13775   gint64 size, sys_bitrate, sum_bitrate = 0;
13776   GstClockTime duration;
13777   guint bitrate;
13778   gint i;
13779
13780   if (qtdemux->fragmented)
13781     return;
13782
13783   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13784
13785   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13786       || size <= 0) {
13787     GST_DEBUG_OBJECT (qtdemux,
13788         "Size in bytes of the stream not known - bailing");
13789     return;
13790   }
13791
13792   /* Subtract the header size */
13793   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13794       size, qtdemux->header_size);
13795
13796   if (size < qtdemux->header_size)
13797     return;
13798
13799   size = size - qtdemux->header_size;
13800
13801   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13802     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13803     return;
13804   }
13805
13806   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13807     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13808     switch (str->subtype) {
13809       case FOURCC_soun:
13810       case FOURCC_vide:
13811         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13812             CUR_STREAM (str)->caps);
13813         /* retrieve bitrate, prefer avg then max */
13814         bitrate = 0;
13815         if (str->stream_tags) {
13816           if (gst_tag_list_get_uint (str->stream_tags,
13817                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13818             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13819           if (gst_tag_list_get_uint (str->stream_tags,
13820                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13821             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13822           if (gst_tag_list_get_uint (str->stream_tags,
13823                   GST_TAG_BITRATE, &bitrate))
13824             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13825         }
13826         if (bitrate)
13827           sum_bitrate += bitrate;
13828         else {
13829           if (stream) {
13830             GST_DEBUG_OBJECT (qtdemux,
13831                 ">1 stream with unknown bitrate - bailing");
13832             return;
13833           } else
13834             stream = str;
13835         }
13836
13837       default:
13838         /* For other subtypes, we assume no significant impact on bitrate */
13839         break;
13840     }
13841   }
13842
13843   if (!stream) {
13844     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13845     return;
13846   }
13847
13848   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13849
13850   if (sys_bitrate < sum_bitrate) {
13851     /* This can happen, since sum_bitrate might be derived from maximum
13852      * bitrates and not average bitrates */
13853     GST_DEBUG_OBJECT (qtdemux,
13854         "System bitrate less than sum bitrate - bailing");
13855     return;
13856   }
13857
13858   bitrate = sys_bitrate - sum_bitrate;
13859   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13860       ", Stream bitrate = %u", sys_bitrate, bitrate);
13861
13862   if (!stream->stream_tags)
13863     stream->stream_tags = gst_tag_list_new_empty ();
13864   else
13865     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13866
13867   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13868       GST_TAG_BITRATE, bitrate, NULL);
13869 }
13870
13871 static GstFlowReturn
13872 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13873 {
13874   GstFlowReturn ret = GST_FLOW_OK;
13875 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
13876   guint64 tkhd_max_duration = 0;
13877 #endif
13878   gint i;
13879
13880   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13881
13882   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13883     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13884     guint32 sample_num = 0;
13885
13886     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13887         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13888
13889     if (qtdemux->fragmented && qtdemux->pullbased) {
13890       /* need all moov samples first */
13891       GST_OBJECT_LOCK (qtdemux);
13892       while (stream->n_samples == 0)
13893         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13894           break;
13895       GST_OBJECT_UNLOCK (qtdemux);
13896     } else {
13897       /* discard any stray moof */
13898       qtdemux->moof_offset = 0;
13899 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
13900       if (tkhd_max_duration < stream->tkhd_duration)
13901         tkhd_max_duration = stream->tkhd_duration;
13902 #endif
13903     }
13904
13905     /* prepare braking */
13906     if (ret != GST_FLOW_ERROR)
13907       ret = GST_FLOW_OK;
13908
13909     /* in pull mode, we should have parsed some sample info by now;
13910      * and quite some code will not handle no samples.
13911      * in push mode, we'll just have to deal with it */
13912     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13913       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13914       g_ptr_array_remove_index (qtdemux->active_streams, i);
13915       i--;
13916       continue;
13917     } else if (stream->track_id == qtdemux->chapters_track_id &&
13918         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13919       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13920          so that it doesn't look like a subtitle track */
13921       g_ptr_array_remove_index (qtdemux->active_streams, i);
13922       i--;
13923       continue;
13924     }
13925
13926     /* parse the initial sample for use in setting the frame rate cap */
13927     while (sample_num == 0 && sample_num < stream->n_samples) {
13928       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13929         break;
13930       ++sample_num;
13931     }
13932   }
13933
13934 #ifdef TIZEN_FEATURE_QTDEMUX_DURATION
13935   if (!qtdemux->fragmented && (qtdemux->duration > tkhd_max_duration)) {
13936     GST_INFO_OBJECT (qtdemux,
13937         "Update duration: %" G_GUINT64_FORMAT " -> %" G_GUINT64_FORMAT,
13938         qtdemux->duration, tkhd_max_duration);
13939     qtdemux->duration = tkhd_max_duration;
13940   }
13941 #endif
13942
13943   return ret;
13944 }
13945
13946 static gboolean
13947 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13948 {
13949   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13950 }
13951
13952 static gboolean
13953 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13954 {
13955   gint i;
13956
13957   /* Different length, updated */
13958   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13959     return TRUE;
13960
13961   /* streams in list are sorted in track-id order */
13962   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13963     /* Different stream-id, updated */
13964     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13965             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13966       return TRUE;
13967   }
13968
13969   return FALSE;
13970 }
13971
13972 static gboolean
13973 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13974     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13975 {
13976   /* Connect old stream's srcpad to new stream */
13977   newstream->pad = oldstream->pad;
13978   oldstream->pad = NULL;
13979
13980   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13981    * case we need to force one through */
13982   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13983
13984   return gst_qtdemux_configure_stream (qtdemux, newstream);
13985 }
13986
13987 static gboolean
13988 qtdemux_update_streams (GstQTDemux * qtdemux)
13989 {
13990   gint i;
13991   g_assert (qtdemux->streams_aware);
13992
13993   /* At below, figure out which stream in active_streams has identical stream-id
13994    * with that of in old_streams. If there is matching stream-id,
13995    * corresponding newstream will not be exposed again,
13996    * but demux will reuse srcpad of matched old stream
13997    *
13998    * active_streams : newly created streams from the latest moov
13999    * old_streams : existing streams (belong to previous moov)
14000    */
14001
14002   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14003     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14004     QtDemuxStream *oldstream = NULL;
14005     guint target;
14006
14007     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
14008         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
14009
14010     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
14011             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
14012       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
14013
14014       /* null pad stream cannot be reused */
14015       if (oldstream->pad == NULL)
14016         oldstream = NULL;
14017     }
14018
14019     if (oldstream) {
14020       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
14021
14022       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
14023         return FALSE;
14024
14025       /* we don't need to preserve order of old streams */
14026       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
14027     } else {
14028       GstTagList *list;
14029
14030       /* now we have all info and can expose */
14031       list = stream->stream_tags;
14032       stream->stream_tags = NULL;
14033       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
14034         return FALSE;
14035     }
14036   }
14037
14038   return TRUE;
14039 }
14040
14041 /* Must be called with expose lock */
14042 static GstFlowReturn
14043 qtdemux_expose_streams (GstQTDemux * qtdemux)
14044 {
14045   gint i;
14046
14047   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
14048
14049   if (!qtdemux_is_streams_update (qtdemux)) {
14050     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
14051     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14052       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14053       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
14054       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
14055         return GST_FLOW_ERROR;
14056     }
14057
14058     g_ptr_array_set_size (qtdemux->old_streams, 0);
14059     qtdemux->need_segment = TRUE;
14060
14061     return GST_FLOW_OK;
14062   }
14063
14064   if (qtdemux->streams_aware) {
14065     if (!qtdemux_update_streams (qtdemux))
14066       return GST_FLOW_ERROR;
14067   } else {
14068     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
14069       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
14070       GstTagList *list;
14071
14072       /* now we have all info and can expose */
14073       list = stream->stream_tags;
14074       stream->stream_tags = NULL;
14075       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
14076         return GST_FLOW_ERROR;
14077
14078     }
14079   }
14080
14081   gst_qtdemux_guess_bitrate (qtdemux);
14082
14083   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
14084
14085   /* If we have still old_streams, it's no more used stream */
14086   for (i = 0; i < qtdemux->old_streams->len; i++) {
14087     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
14088
14089     if (stream->pad) {
14090       GstEvent *event;
14091
14092       event = gst_event_new_eos ();
14093       if (qtdemux->segment_seqnum)
14094         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
14095
14096       gst_pad_push_event (stream->pad, event);
14097     }
14098   }
14099
14100   g_ptr_array_set_size (qtdemux->old_streams, 0);
14101
14102   /* check if we should post a redirect in case there is a single trak
14103    * and it is a redirecting trak */
14104   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
14105       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
14106     GstMessage *m;
14107
14108     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
14109         "an external content");
14110     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
14111         gst_structure_new ("redirect",
14112             "new-location", G_TYPE_STRING,
14113             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
14114     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
14115     g_free (qtdemux->redirect_location);
14116     qtdemux->redirect_location =
14117         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
14118   }
14119
14120   g_ptr_array_foreach (qtdemux->active_streams,
14121       (GFunc) qtdemux_do_allocation, qtdemux);
14122
14123   qtdemux->need_segment = TRUE;
14124
14125   qtdemux->exposed = TRUE;
14126   return GST_FLOW_OK;
14127 }
14128
14129 typedef struct
14130 {
14131   GstStructure *structure;      /* helper for sort function */
14132   gchar *location;
14133   guint min_req_bitrate;
14134   guint min_req_qt_version;
14135 } GstQtReference;
14136
14137 static gint
14138 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
14139 {
14140   GstQtReference *ref_a = (GstQtReference *) a;
14141   GstQtReference *ref_b = (GstQtReference *) b;
14142
14143   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
14144     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
14145
14146   /* known bitrates go before unknown; higher bitrates go first */
14147   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
14148 }
14149
14150 /* sort the redirects and post a message for the application.
14151  */
14152 static void
14153 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
14154 {
14155   GstQtReference *best;
14156   GstStructure *s;
14157   GstMessage *msg;
14158   GValue list_val = { 0, };
14159   GList *l;
14160
14161   g_assert (references != NULL);
14162
14163   references = g_list_sort (references, qtdemux_redirects_sort_func);
14164
14165   best = (GstQtReference *) references->data;
14166
14167   g_value_init (&list_val, GST_TYPE_LIST);
14168
14169   for (l = references; l != NULL; l = l->next) {
14170     GstQtReference *ref = (GstQtReference *) l->data;
14171     GValue struct_val = { 0, };
14172
14173     ref->structure = gst_structure_new ("redirect",
14174         "new-location", G_TYPE_STRING, ref->location, NULL);
14175
14176     if (ref->min_req_bitrate > 0) {
14177       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
14178           ref->min_req_bitrate, NULL);
14179     }
14180
14181     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
14182     g_value_set_boxed (&struct_val, ref->structure);
14183     gst_value_list_append_value (&list_val, &struct_val);
14184     g_value_unset (&struct_val);
14185     /* don't free anything here yet, since we need best->structure below */
14186   }
14187
14188   g_assert (best != NULL);
14189   s = gst_structure_copy (best->structure);
14190
14191   if (g_list_length (references) > 1) {
14192     gst_structure_set_value (s, "locations", &list_val);
14193   }
14194
14195   g_value_unset (&list_val);
14196
14197   for (l = references; l != NULL; l = l->next) {
14198     GstQtReference *ref = (GstQtReference *) l->data;
14199
14200     gst_structure_free (ref->structure);
14201     g_free (ref->location);
14202     g_free (ref);
14203   }
14204   g_list_free (references);
14205
14206   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
14207   g_free (qtdemux->redirect_location);
14208   qtdemux->redirect_location =
14209       g_strdup (gst_structure_get_string (s, "new-location"));
14210   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
14211   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
14212 }
14213
14214 /* look for redirect nodes, collect all redirect information and
14215  * process it.
14216  */
14217 static gboolean
14218 qtdemux_parse_redirects (GstQTDemux * qtdemux)
14219 {
14220   GNode *rmra, *rmda, *rdrf;
14221
14222   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
14223   if (rmra) {
14224     GList *redirects = NULL;
14225
14226     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
14227     while (rmda) {
14228       GstQtReference ref = { NULL, NULL, 0, 0 };
14229       GNode *rmdr, *rmvc;
14230
14231       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
14232         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
14233         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
14234             ref.min_req_bitrate);
14235       }
14236
14237       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
14238         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
14239         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
14240
14241 #ifndef GST_DISABLE_GST_DEBUG
14242         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
14243 #endif
14244         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
14245
14246         GST_LOG_OBJECT (qtdemux,
14247             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
14248             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
14249             bitmask, check_type);
14250         if (package == FOURCC_qtim && check_type == 0) {
14251           ref.min_req_qt_version = version;
14252         }
14253       }
14254
14255       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
14256       if (rdrf) {
14257         guint32 ref_type;
14258         guint8 *ref_data;
14259         guint ref_len;
14260
14261         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
14262         if (ref_len > 20) {
14263           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
14264           ref_data = (guint8 *) rdrf->data + 20;
14265           if (ref_type == FOURCC_alis) {
14266             guint record_len, record_version, fn_len;
14267
14268             if (ref_len > 70) {
14269               /* MacOSX alias record, google for alias-layout.txt */
14270               record_len = QT_UINT16 (ref_data + 4);
14271               record_version = QT_UINT16 (ref_data + 4 + 2);
14272               fn_len = QT_UINT8 (ref_data + 50);
14273               if (record_len > 50 && record_version == 2 && fn_len > 0) {
14274                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
14275               }
14276             } else {
14277               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
14278                   ref_len);
14279             }
14280           } else if (ref_type == FOURCC_url_) {
14281             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
14282           } else {
14283             GST_DEBUG_OBJECT (qtdemux,
14284                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
14285                 GST_FOURCC_ARGS (ref_type));
14286           }
14287           if (ref.location != NULL) {
14288             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
14289             redirects =
14290                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
14291           } else {
14292             GST_WARNING_OBJECT (qtdemux,
14293                 "Failed to extract redirect location from rdrf atom");
14294           }
14295         } else {
14296           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
14297         }
14298       }
14299
14300       /* look for others */
14301       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
14302     }
14303
14304     if (redirects != NULL) {
14305       qtdemux_process_redirects (qtdemux, redirects);
14306     }
14307   }
14308   return TRUE;
14309 }
14310
14311 static GstTagList *
14312 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
14313 {
14314   const gchar *fmt;
14315
14316   if (tags == NULL) {
14317     tags = gst_tag_list_new_empty ();
14318     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
14319   }
14320
14321   if (qtdemux->major_brand == FOURCC_mjp2)
14322     fmt = "Motion JPEG 2000";
14323   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
14324     fmt = "3GP";
14325   else if (qtdemux->major_brand == FOURCC_qt__)
14326     fmt = "Quicktime";
14327   else if (qtdemux->fragmented)
14328     fmt = "ISO fMP4";
14329   else
14330     fmt = "ISO MP4/M4A";
14331
14332   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
14333       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
14334
14335   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
14336       fmt, NULL);
14337
14338   return tags;
14339 }
14340
14341 /* we have read the complete moov node now.
14342  * This function parses all of the relevant info, creates the traks and
14343  * prepares all data structures for playback
14344  */
14345 static gboolean
14346 qtdemux_parse_tree (GstQTDemux * qtdemux)
14347 {
14348   GNode *mvhd;
14349   GNode *trak;
14350   GNode *udta;
14351   GNode *mvex;
14352   GNode *pssh;
14353   guint64 creation_time;
14354   GstDateTime *datetime = NULL;
14355   gint version;
14356
14357   /* make sure we have a usable taglist */
14358   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14359
14360   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14361   if (mvhd == NULL) {
14362     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14363     return qtdemux_parse_redirects (qtdemux);
14364   }
14365
14366   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14367   if (version == 1) {
14368     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14369     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14370     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14371   } else if (version == 0) {
14372     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14373     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14374     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14375   } else {
14376     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14377     return FALSE;
14378   }
14379
14380   /* Moving qt creation time (secs since 1904) to unix time */
14381   if (creation_time != 0) {
14382     /* Try to use epoch first as it should be faster and more commonly found */
14383     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14384       gint64 now_s;
14385
14386       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14387       /* some data cleansing sanity */
14388       now_s = g_get_real_time () / G_USEC_PER_SEC;
14389       if (now_s + 24 * 3600 < creation_time) {
14390         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14391       } else {
14392         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14393       }
14394     } else {
14395       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14396       GDateTime *dt, *dt_local;
14397
14398       dt = g_date_time_add_seconds (base_dt, creation_time);
14399       dt_local = g_date_time_to_local (dt);
14400       datetime = gst_date_time_new_from_g_date_time (dt_local);
14401
14402       g_date_time_unref (base_dt);
14403       g_date_time_unref (dt);
14404     }
14405   }
14406   if (datetime) {
14407     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14408     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14409         datetime, NULL);
14410     gst_date_time_unref (datetime);
14411   }
14412
14413   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14414   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14415
14416   /* check for fragmented file and get some (default) data */
14417   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14418   if (mvex) {
14419     GNode *mehd;
14420     GstByteReader mehd_data;
14421
14422     /* let track parsing or anyone know weird stuff might happen ... */
14423     qtdemux->fragmented = TRUE;
14424
14425     /* compensate for total duration */
14426     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14427     if (mehd)
14428       qtdemux_parse_mehd (qtdemux, &mehd_data);
14429   }
14430
14431   /* Update the movie segment duration, unless it was directly given to us
14432    * by upstream. Otherwise let it as is, as we don't want to mangle the
14433    * duration provided by upstream that may come e.g. from a MPD file. */
14434   if (!qtdemux->upstream_format_is_time) {
14435     GstClockTime duration;
14436     /* set duration in the segment info */
14437     gst_qtdemux_get_duration (qtdemux, &duration);
14438     qtdemux->segment.duration = duration;
14439     /* also do not exceed duration; stop is set that way post seek anyway,
14440      * and segment activation falls back to duration,
14441      * whereas loop only checks stop, so let's align this here as well */
14442     qtdemux->segment.stop = duration;
14443   }
14444
14445   /* parse all traks */
14446   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14447   while (trak) {
14448     qtdemux_parse_trak (qtdemux, trak);
14449     /* iterate all siblings */
14450     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14451   }
14452
14453   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14454
14455   /* find tags */
14456   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14457   if (udta) {
14458     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14459   } else {
14460     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14461   }
14462
14463   /* maybe also some tags in meta box */
14464   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14465   if (udta) {
14466     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14467     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14468   } else {
14469     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14470   }
14471
14472   /* parse any protection system info */
14473   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14474   while (pssh) {
14475     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14476     qtdemux_parse_pssh (qtdemux, pssh);
14477     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14478   }
14479
14480   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14481
14482   return TRUE;
14483 }
14484
14485 /* taken from ffmpeg */
14486 static int
14487 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14488 {
14489   int count = 4;
14490   int len = 0;
14491
14492   while (count--) {
14493     int c;
14494
14495     if (ptr >= end)
14496       return -1;
14497
14498     c = *ptr++;
14499     len = (len << 7) | (c & 0x7f);
14500     if (!(c & 0x80))
14501       break;
14502   }
14503   *end_out = ptr;
14504   return len;
14505 }
14506
14507 static GList *
14508 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14509     gsize codec_data_size)
14510 {
14511   GList *list = NULL;
14512   guint8 *p = codec_data;
14513   gint i, offset, num_packets;
14514   guint *length, last;
14515
14516   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14517
14518   if (codec_data == NULL || codec_data_size == 0)
14519     goto error;
14520
14521   /* start of the stream and vorbis audio or theora video, need to
14522    * send the codec_priv data as first three packets */
14523   num_packets = p[0] + 1;
14524   GST_DEBUG_OBJECT (qtdemux,
14525       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14526       (guint) num_packets, codec_data_size);
14527
14528   /* Let's put some limits, Don't think there even is a xiph codec
14529    * with more than 3-4 headers */
14530   if (G_UNLIKELY (num_packets > 16)) {
14531     GST_WARNING_OBJECT (qtdemux,
14532         "Unlikely number of xiph headers, most likely not valid");
14533     goto error;
14534   }
14535
14536   length = g_alloca (num_packets * sizeof (guint));
14537   last = 0;
14538   offset = 1;
14539
14540   /* first packets, read length values */
14541   for (i = 0; i < num_packets - 1; i++) {
14542     length[i] = 0;
14543     while (offset < codec_data_size) {
14544       length[i] += p[offset];
14545       if (p[offset++] != 0xff)
14546         break;
14547     }
14548     last += length[i];
14549   }
14550   if (offset + last > codec_data_size)
14551     goto error;
14552
14553   /* last packet is the remaining size */
14554   length[i] = codec_data_size - offset - last;
14555
14556   for (i = 0; i < num_packets; i++) {
14557     GstBuffer *hdr;
14558
14559     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14560
14561     if (offset + length[i] > codec_data_size)
14562       goto error;
14563
14564     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14565     list = g_list_append (list, hdr);
14566
14567     offset += length[i];
14568   }
14569
14570   return list;
14571
14572   /* ERRORS */
14573 error:
14574   {
14575     if (list != NULL)
14576       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14577     return NULL;
14578   }
14579
14580 }
14581
14582 /* this can change the codec originally present in @list */
14583 static void
14584 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14585     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14586 {
14587   int len = QT_UINT32 (esds->data);
14588   guint8 *ptr = esds->data;
14589   guint8 *end = ptr + len;
14590   int tag;
14591   guint8 *data_ptr = NULL;
14592   int data_len = 0;
14593   guint8 object_type_id = 0;
14594   guint8 stream_type = 0;
14595   const char *codec_name = NULL;
14596   GstCaps *caps = NULL;
14597
14598   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14599   ptr += 8;
14600   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14601   ptr += 4;
14602   while (ptr + 1 < end) {
14603     tag = QT_UINT8 (ptr);
14604     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14605     ptr++;
14606     len = read_descr_size (ptr, end, &ptr);
14607     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14608
14609     /* Check the stated amount of data is available for reading */
14610     if (len < 0 || ptr + len > end)
14611       break;
14612
14613     switch (tag) {
14614       case ES_DESCRIPTOR_TAG:
14615         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14616         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14617         ptr += 3;
14618         break;
14619       case DECODER_CONFIG_DESC_TAG:{
14620         guint max_bitrate, avg_bitrate;
14621
14622         object_type_id = QT_UINT8 (ptr);
14623         stream_type = QT_UINT8 (ptr + 1) >> 2;
14624         max_bitrate = QT_UINT32 (ptr + 5);
14625         avg_bitrate = QT_UINT32 (ptr + 9);
14626         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14627         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14628         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14629         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14630         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14631         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14632           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14633               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14634         }
14635         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14636           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14637               avg_bitrate, NULL);
14638         }
14639         ptr += 13;
14640         break;
14641       }
14642       case DECODER_SPECIFIC_INFO_TAG:
14643         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14644         if (object_type_id == 0xe0 && len == 0x40) {
14645           guint8 *data;
14646           GstStructure *s;
14647           guint32 clut[16];
14648           gint i;
14649
14650           GST_DEBUG_OBJECT (qtdemux,
14651               "Have VOBSUB palette. Creating palette event");
14652           /* move to decConfigDescr data and read palette */
14653           data = ptr;
14654           for (i = 0; i < 16; i++) {
14655             clut[i] = QT_UINT32 (data);
14656             data += 4;
14657           }
14658
14659           s = gst_structure_new ("application/x-gst-dvd", "event",
14660               G_TYPE_STRING, "dvd-spu-clut-change",
14661               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14662               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14663               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14664               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14665               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14666               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14667               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14668               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14669               NULL);
14670
14671           /* store event and trigger custom processing */
14672           stream->pending_event =
14673               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14674         } else {
14675           /* Generic codec_data handler puts it on the caps */
14676           data_ptr = ptr;
14677           data_len = len;
14678         }
14679
14680         ptr += len;
14681         break;
14682       case SL_CONFIG_DESC_TAG:
14683         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14684         ptr += 1;
14685         break;
14686       default:
14687         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14688             tag);
14689         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14690         ptr += len;
14691         break;
14692     }
14693   }
14694
14695   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14696    * in use, and should also be used to override some other parameters for some
14697    * codecs. */
14698   switch (object_type_id) {
14699     case 0x20:                 /* MPEG-4 */
14700       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14701        * profile_and_level_indication */
14702       if (data_ptr != NULL && data_len >= 5 &&
14703           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14704         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14705             data_ptr + 4, data_len - 4);
14706       }
14707       break;                    /* Nothing special needed here */
14708     case 0x21:                 /* H.264 */
14709       codec_name = "H.264 / AVC";
14710       caps = gst_caps_new_simple ("video/x-h264",
14711           "stream-format", G_TYPE_STRING, "avc",
14712           "alignment", G_TYPE_STRING, "au", NULL);
14713       break;
14714     case 0x40:                 /* AAC (any) */
14715     case 0x66:                 /* AAC Main */
14716     case 0x67:                 /* AAC LC */
14717     case 0x68:                 /* AAC SSR */
14718       /* Override channels and rate based on the codec_data, as it's often
14719        * wrong. */
14720       /* Only do so for basic setup without HE-AAC extension */
14721       if (data_ptr && data_len == 2) {
14722         guint channels, rate;
14723
14724         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14725         if (channels > 0)
14726           entry->n_channels = channels;
14727
14728         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14729         if (rate > 0)
14730           entry->rate = rate;
14731       }
14732
14733       /* Set level and profile if possible */
14734       if (data_ptr != NULL && data_len >= 2) {
14735         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14736             data_ptr, data_len);
14737       } else {
14738         const gchar *profile_str = NULL;
14739         GstBuffer *buffer;
14740         GstMapInfo map;
14741         guint8 *codec_data;
14742         gint rate_idx, profile;
14743
14744         /* No codec_data, let's invent something.
14745          * FIXME: This is wrong for SBR! */
14746
14747         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14748
14749         buffer = gst_buffer_new_and_alloc (2);
14750         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14751         codec_data = map.data;
14752
14753         rate_idx =
14754             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14755             (stream)->rate);
14756
14757         switch (object_type_id) {
14758           case 0x66:
14759             profile_str = "main";
14760             profile = 0;
14761             break;
14762           case 0x67:
14763             profile_str = "lc";
14764             profile = 1;
14765             break;
14766           case 0x68:
14767             profile_str = "ssr";
14768             profile = 2;
14769             break;
14770           default:
14771             profile = 3;
14772             break;
14773         }
14774
14775         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14776         codec_data[1] =
14777             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14778
14779         gst_buffer_unmap (buffer, &map);
14780         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14781             GST_TYPE_BUFFER, buffer, NULL);
14782         gst_buffer_unref (buffer);
14783
14784         if (profile_str) {
14785           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14786               G_TYPE_STRING, profile_str, NULL);
14787         }
14788       }
14789       break;
14790     case 0x60:                 /* MPEG-2, various profiles */
14791     case 0x61:
14792     case 0x62:
14793     case 0x63:
14794     case 0x64:
14795     case 0x65:
14796       codec_name = "MPEG-2 video";
14797       caps = gst_caps_new_simple ("video/mpeg",
14798           "mpegversion", G_TYPE_INT, 2,
14799           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14800       break;
14801     case 0x69:                 /* MPEG-2 BC audio */
14802     case 0x6B:                 /* MPEG-1 audio */
14803       caps = gst_caps_new_simple ("audio/mpeg",
14804           "mpegversion", G_TYPE_INT, 1, NULL);
14805       codec_name = "MPEG-1 audio";
14806       break;
14807     case 0x6A:                 /* MPEG-1 */
14808       codec_name = "MPEG-1 video";
14809       caps = gst_caps_new_simple ("video/mpeg",
14810           "mpegversion", G_TYPE_INT, 1,
14811           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14812       break;
14813     case 0x6C:                 /* MJPEG */
14814       caps =
14815           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14816           NULL);
14817       codec_name = "Motion-JPEG";
14818       break;
14819     case 0x6D:                 /* PNG */
14820       caps =
14821           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14822           NULL);
14823       codec_name = "PNG still images";
14824       break;
14825     case 0x6E:                 /* JPEG2000 */
14826       codec_name = "JPEG-2000";
14827       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14828       break;
14829     case 0xA4:                 /* Dirac */
14830       codec_name = "Dirac";
14831       caps = gst_caps_new_empty_simple ("video/x-dirac");
14832       break;
14833     case 0xA5:                 /* AC3 */
14834       codec_name = "AC-3 audio";
14835       caps = gst_caps_new_simple ("audio/x-ac3",
14836           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14837       break;
14838     case 0xA9:                 /* AC3 */
14839       codec_name = "DTS audio";
14840       caps = gst_caps_new_simple ("audio/x-dts",
14841           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14842       break;
14843     case 0xDD:
14844       if (stream_type == 0x05 && data_ptr) {
14845         GList *headers =
14846             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14847         if (headers) {
14848           GList *tmp;
14849           GValue arr_val = G_VALUE_INIT;
14850           GValue buf_val = G_VALUE_INIT;
14851           GstStructure *s;
14852
14853           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14854           codec_name = "Vorbis";
14855           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14856           g_value_init (&arr_val, GST_TYPE_ARRAY);
14857           g_value_init (&buf_val, GST_TYPE_BUFFER);
14858           for (tmp = headers; tmp; tmp = tmp->next) {
14859             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14860             gst_value_array_append_value (&arr_val, &buf_val);
14861           }
14862           s = gst_caps_get_structure (caps, 0);
14863           gst_structure_take_value (s, "streamheader", &arr_val);
14864           g_value_unset (&buf_val);
14865           g_list_free (headers);
14866
14867           data_ptr = NULL;
14868           data_len = 0;
14869         }
14870       }
14871       break;
14872     case 0xE1:                 /* QCELP */
14873       /* QCELP, the codec_data is a riff tag (little endian) with
14874        * 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). */
14875       caps = gst_caps_new_empty_simple ("audio/qcelp");
14876       codec_name = "QCELP";
14877       break;
14878     default:
14879       break;
14880   }
14881
14882   /* If we have a replacement caps, then change our caps for this stream */
14883   if (caps) {
14884     gst_caps_unref (entry->caps);
14885     entry->caps = caps;
14886   }
14887
14888   if (codec_name && list)
14889     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14890         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14891
14892   /* Add the codec_data attribute to caps, if we have it */
14893   if (data_ptr) {
14894     GstBuffer *buffer;
14895
14896     buffer = gst_buffer_new_and_alloc (data_len);
14897     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14898
14899     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14900     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14901
14902     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14903         buffer, NULL);
14904     gst_buffer_unref (buffer);
14905   }
14906
14907 }
14908
14909 static inline GstCaps *
14910 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14911 {
14912   GstCaps *caps;
14913   guint i;
14914   char *s, fourstr[5];
14915
14916   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14917   for (i = 0; i < 4; i++) {
14918     if (!g_ascii_isalnum (fourstr[i]))
14919       fourstr[i] = '_';
14920   }
14921   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14922   caps = gst_caps_new_empty_simple (s);
14923   g_free (s);
14924   return caps;
14925 }
14926
14927 #define _codec(name) \
14928   do { \
14929     if (codec_name) { \
14930       *codec_name = g_strdup (name); \
14931     } \
14932   } while (0)
14933
14934 static GstCaps *
14935 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14936     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14937     const guint8 * stsd_entry_data, gchar ** codec_name)
14938 {
14939   GstCaps *caps = NULL;
14940   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14941
14942   switch (fourcc) {
14943     case FOURCC_png:
14944       _codec ("PNG still images");
14945       caps = gst_caps_new_empty_simple ("image/png");
14946       break;
14947     case FOURCC_jpeg:
14948       _codec ("JPEG still images");
14949       caps =
14950           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14951           NULL);
14952       break;
14953     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14954     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14955     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14956     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14957       _codec ("Motion-JPEG");
14958       caps =
14959           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14960           NULL);
14961       break;
14962     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14963       _codec ("Motion-JPEG format B");
14964       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14965       break;
14966     case FOURCC_mjp2:
14967       _codec ("JPEG-2000");
14968       /* override to what it should be according to spec, avoid palette_data */
14969       entry->bits_per_sample = 24;
14970       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14971       break;
14972     case FOURCC_SVQ3:
14973       _codec ("Sorensen video v.3");
14974       caps = gst_caps_new_simple ("video/x-svq",
14975           "svqversion", G_TYPE_INT, 3, NULL);
14976       break;
14977     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14978     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14979       _codec ("Sorensen video v.1");
14980       caps = gst_caps_new_simple ("video/x-svq",
14981           "svqversion", G_TYPE_INT, 1, NULL);
14982       break;
14983     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14984       caps = gst_caps_new_empty_simple ("video/x-raw");
14985       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14986       _codec ("Windows Raw RGB");
14987       stream->alignment = 32;
14988       break;
14989     case FOURCC_raw_:
14990     {
14991       guint16 bps;
14992
14993       bps = QT_UINT16 (stsd_entry_data + 82);
14994       switch (bps) {
14995         case 15:
14996           format = GST_VIDEO_FORMAT_RGB15;
14997           break;
14998         case 16:
14999           format = GST_VIDEO_FORMAT_RGB16;
15000           break;
15001         case 24:
15002           format = GST_VIDEO_FORMAT_RGB;
15003           break;
15004         case 32:
15005           format = GST_VIDEO_FORMAT_ARGB;
15006           break;
15007         default:
15008           /* unknown */
15009           break;
15010       }
15011       break;
15012     }
15013     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
15014       format = GST_VIDEO_FORMAT_I420;
15015       break;
15016     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
15017     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
15018       format = GST_VIDEO_FORMAT_I420;
15019       break;
15020     case FOURCC_2vuy:
15021     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
15022       format = GST_VIDEO_FORMAT_UYVY;
15023       break;
15024     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
15025       format = GST_VIDEO_FORMAT_v308;
15026       break;
15027     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
15028       format = GST_VIDEO_FORMAT_v216;
15029       break;
15030     case FOURCC_v210:
15031       format = GST_VIDEO_FORMAT_v210;
15032       break;
15033     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
15034       format = GST_VIDEO_FORMAT_r210;
15035       break;
15036       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
15037          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
15038          format = GST_VIDEO_FORMAT_v410;
15039          break;
15040        */
15041       /* Packed YUV 4:4:4:4 8 bit in 32 bits
15042        * but different order than AYUV
15043        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
15044        format = GST_VIDEO_FORMAT_v408;
15045        break;
15046        */
15047     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
15048     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
15049       _codec ("MPEG-1 video");
15050       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15051           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15052       break;
15053     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
15054     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
15055     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
15056     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
15057     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
15058     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
15059     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
15060     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
15061     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
15062     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
15063     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
15064     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
15065     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
15066     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
15067     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
15068     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
15069     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
15070     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
15071     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
15072     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
15073     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
15074     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
15075     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
15076     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
15077     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
15078     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
15079     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
15080     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
15081     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
15082     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
15083     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
15084     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
15085     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
15086     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
15087     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
15088     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
15089     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
15090     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
15091     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
15092     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
15093     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
15094     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
15095     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
15096     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
15097     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
15098     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
15099     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
15100       _codec ("MPEG-2 video");
15101       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
15102           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15103       break;
15104     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
15105       _codec ("GIF still images");
15106       caps = gst_caps_new_empty_simple ("image/gif");
15107       break;
15108     case FOURCC_h263:
15109     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
15110     case FOURCC_s263:
15111     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
15112       _codec ("H.263");
15113       /* ffmpeg uses the height/width props, don't know why */
15114       caps = gst_caps_new_simple ("video/x-h263",
15115           "variant", G_TYPE_STRING, "itu", NULL);
15116       break;
15117     case FOURCC_mp4v:
15118     case FOURCC_MP4V:
15119       _codec ("MPEG-4 video");
15120       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
15121           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15122       break;
15123     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
15124     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
15125       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
15126       caps = gst_caps_new_simple ("video/x-msmpeg",
15127           "msmpegversion", G_TYPE_INT, 43, NULL);
15128       break;
15129     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
15130       _codec ("DivX 3");
15131       caps = gst_caps_new_simple ("video/x-divx",
15132           "divxversion", G_TYPE_INT, 3, NULL);
15133       break;
15134     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
15135     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
15136       _codec ("DivX 4");
15137       caps = gst_caps_new_simple ("video/x-divx",
15138           "divxversion", G_TYPE_INT, 4, NULL);
15139       break;
15140     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
15141       _codec ("DivX 5");
15142       caps = gst_caps_new_simple ("video/x-divx",
15143           "divxversion", G_TYPE_INT, 5, NULL);
15144       break;
15145
15146     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
15147       _codec ("FFV1");
15148       caps = gst_caps_new_simple ("video/x-ffv",
15149           "ffvversion", G_TYPE_INT, 1, NULL);
15150       break;
15151
15152     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
15153     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
15154     case FOURCC_XVID:
15155     case FOURCC_xvid:
15156     case FOURCC_FMP4:
15157     case FOURCC_fmp4:
15158     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
15159       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
15160           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15161       _codec ("MPEG-4");
15162       break;
15163
15164     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
15165       _codec ("Cinepak");
15166       caps = gst_caps_new_empty_simple ("video/x-cinepak");
15167       break;
15168     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
15169       _codec ("Apple QuickDraw");
15170       caps = gst_caps_new_empty_simple ("video/x-qdrw");
15171       break;
15172     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
15173       _codec ("Apple video");
15174       caps = gst_caps_new_empty_simple ("video/x-apple-video");
15175       break;
15176     case FOURCC_H264:
15177     case FOURCC_avc1:
15178     case FOURCC_dva1:
15179       _codec ("H.264 / AVC");
15180       caps = gst_caps_new_simple ("video/x-h264",
15181           "stream-format", G_TYPE_STRING, "avc",
15182           "alignment", G_TYPE_STRING, "au", NULL);
15183       break;
15184     case FOURCC_avc3:
15185     case FOURCC_dvav:
15186       _codec ("H.264 / AVC");
15187       caps = gst_caps_new_simple ("video/x-h264",
15188           "stream-format", G_TYPE_STRING, "avc3",
15189           "alignment", G_TYPE_STRING, "au", NULL);
15190       break;
15191     case FOURCC_H265:
15192     case FOURCC_hvc1:
15193     case FOURCC_dvh1:
15194       _codec ("H.265 / HEVC");
15195       caps = gst_caps_new_simple ("video/x-h265",
15196           "stream-format", G_TYPE_STRING, "hvc1",
15197           "alignment", G_TYPE_STRING, "au", NULL);
15198       break;
15199     case FOURCC_hev1:
15200     case FOURCC_dvhe:
15201       _codec ("H.265 / HEVC");
15202       caps = gst_caps_new_simple ("video/x-h265",
15203           "stream-format", G_TYPE_STRING, "hev1",
15204           "alignment", G_TYPE_STRING, "au", NULL);
15205       break;
15206     case FOURCC_rle_:
15207       _codec ("Run-length encoding");
15208       caps = gst_caps_new_simple ("video/x-rle",
15209           "layout", G_TYPE_STRING, "quicktime", NULL);
15210       break;
15211     case FOURCC_WRLE:
15212       _codec ("Run-length encoding");
15213       caps = gst_caps_new_simple ("video/x-rle",
15214           "layout", G_TYPE_STRING, "microsoft", NULL);
15215       break;
15216     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
15217     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
15218       _codec ("Indeo Video 3");
15219       caps = gst_caps_new_simple ("video/x-indeo",
15220           "indeoversion", G_TYPE_INT, 3, NULL);
15221       break;
15222     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
15223     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
15224       _codec ("Intel Video 4");
15225       caps = gst_caps_new_simple ("video/x-indeo",
15226           "indeoversion", G_TYPE_INT, 4, NULL);
15227       break;
15228     case FOURCC_dvcp:
15229     case FOURCC_dvc_:
15230     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
15231     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
15232     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
15233     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
15234     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
15235     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
15236       _codec ("DV Video");
15237       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
15238           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15239       break;
15240     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
15241     case FOURCC_dv5p:          /* DVCPRO50 PAL */
15242       _codec ("DVCPro50 Video");
15243       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
15244           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15245       break;
15246     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
15247     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
15248       _codec ("DVCProHD Video");
15249       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
15250           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15251       break;
15252     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
15253       _codec ("Apple Graphics (SMC)");
15254       caps = gst_caps_new_empty_simple ("video/x-smc");
15255       break;
15256     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
15257       _codec ("VP3");
15258       caps = gst_caps_new_empty_simple ("video/x-vp3");
15259       break;
15260     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
15261       _codec ("VP6 Flash");
15262       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
15263       break;
15264     case FOURCC_XiTh:
15265       _codec ("Theora");
15266       caps = gst_caps_new_empty_simple ("video/x-theora");
15267       /* theora uses one byte of padding in the data stream because it does not
15268        * allow 0 sized packets while theora does */
15269       entry->padding = 1;
15270       break;
15271     case FOURCC_drac:
15272       _codec ("Dirac");
15273       caps = gst_caps_new_empty_simple ("video/x-dirac");
15274       break;
15275     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
15276       _codec ("TIFF still images");
15277       caps = gst_caps_new_empty_simple ("image/tiff");
15278       break;
15279     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
15280       _codec ("Apple Intermediate Codec");
15281       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
15282       break;
15283     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
15284       _codec ("AVID DNxHD");
15285       caps = gst_caps_from_string ("video/x-dnxhd");
15286       break;
15287     case FOURCC_VP80:
15288     case FOURCC_vp08:
15289       _codec ("On2 VP8");
15290       caps = gst_caps_from_string ("video/x-vp8");
15291       break;
15292     case FOURCC_vp09:
15293       _codec ("Google VP9");
15294       caps = gst_caps_from_string ("video/x-vp9");
15295       break;
15296     case FOURCC_apcs:
15297       _codec ("Apple ProRes LT");
15298       caps =
15299           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
15300           NULL);
15301       break;
15302     case FOURCC_apch:
15303       _codec ("Apple ProRes HQ");
15304       caps =
15305           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
15306           NULL);
15307       break;
15308     case FOURCC_apcn:
15309       _codec ("Apple ProRes");
15310       caps =
15311           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15312           "standard", NULL);
15313       break;
15314     case FOURCC_apco:
15315       _codec ("Apple ProRes Proxy");
15316       caps =
15317           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15318           "proxy", NULL);
15319       break;
15320     case FOURCC_ap4h:
15321       _codec ("Apple ProRes 4444");
15322       caps =
15323           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15324           "4444", NULL);
15325
15326       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
15327       if (entry->bits_per_sample > 0) {
15328         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
15329             NULL);
15330       }
15331       break;
15332     case FOURCC_ap4x:
15333       _codec ("Apple ProRes 4444 XQ");
15334       caps =
15335           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15336           "4444xq", NULL);
15337
15338       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
15339       if (entry->bits_per_sample > 0) {
15340         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
15341             NULL);
15342       }
15343       break;
15344     case FOURCC_cfhd:
15345       _codec ("GoPro CineForm");
15346       caps = gst_caps_from_string ("video/x-cineform");
15347       break;
15348     case FOURCC_vc_1:
15349     case FOURCC_ovc1:
15350       _codec ("VC-1");
15351       caps = gst_caps_new_simple ("video/x-wmv",
15352           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
15353       break;
15354     case FOURCC_av01:
15355       _codec ("AV1");
15356       caps = gst_caps_new_empty_simple ("video/x-av1");
15357       break;
15358     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15359     default:
15360     {
15361       caps = _get_unknown_codec_name ("video", fourcc);
15362       break;
15363     }
15364   }
15365
15366   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15367     GstVideoInfo info;
15368
15369     gst_video_info_init (&info);
15370     gst_video_info_set_format (&info, format, entry->width, entry->height);
15371
15372     caps = gst_video_info_to_caps (&info);
15373     *codec_name = gst_pb_utils_get_codec_description (caps);
15374
15375     /* enable clipping for raw video streams */
15376     stream->need_clip = TRUE;
15377     stream->alignment = 32;
15378   }
15379
15380   return caps;
15381 }
15382
15383 static guint
15384 round_up_pow2 (guint n)
15385 {
15386   n = n - 1;
15387   n = n | (n >> 1);
15388   n = n | (n >> 2);
15389   n = n | (n >> 4);
15390   n = n | (n >> 8);
15391   n = n | (n >> 16);
15392   return n + 1;
15393 }
15394
15395 static GstCaps *
15396 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15397     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15398     int len, gchar ** codec_name)
15399 {
15400   GstCaps *caps;
15401   const GstStructure *s;
15402   const gchar *name;
15403   gint endian = 0;
15404   GstAudioFormat format = 0;
15405   gint depth;
15406
15407   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15408
15409   depth = entry->bytes_per_packet * 8;
15410
15411   switch (fourcc) {
15412     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15413     case FOURCC_raw_:
15414       /* 8-bit audio is unsigned */
15415       if (depth == 8)
15416         format = GST_AUDIO_FORMAT_U8;
15417       /* otherwise it's signed and big-endian just like 'twos' */
15418     case FOURCC_twos:
15419       endian = G_BIG_ENDIAN;
15420       /* fall-through */
15421     case FOURCC_sowt:
15422     {
15423       gchar *str;
15424
15425       if (!endian)
15426         endian = G_LITTLE_ENDIAN;
15427
15428       if (!format)
15429         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15430
15431       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15432       _codec (str);
15433       g_free (str);
15434
15435       caps = gst_caps_new_simple ("audio/x-raw",
15436           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15437           "layout", G_TYPE_STRING, "interleaved", NULL);
15438       stream->alignment = GST_ROUND_UP_8 (depth);
15439       stream->alignment = round_up_pow2 (stream->alignment);
15440       break;
15441     }
15442     case FOURCC_fl64:
15443       _codec ("Raw 64-bit floating-point audio");
15444       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15445        * endian later */
15446       caps = gst_caps_new_simple ("audio/x-raw",
15447           "format", G_TYPE_STRING, "F64BE",
15448           "layout", G_TYPE_STRING, "interleaved", NULL);
15449       stream->alignment = 8;
15450       break;
15451     case FOURCC_fl32:
15452       _codec ("Raw 32-bit floating-point audio");
15453       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15454        * endian later */
15455       caps = gst_caps_new_simple ("audio/x-raw",
15456           "format", G_TYPE_STRING, "F32BE",
15457           "layout", G_TYPE_STRING, "interleaved", NULL);
15458       stream->alignment = 4;
15459       break;
15460     case FOURCC_in24:
15461       _codec ("Raw 24-bit PCM audio");
15462       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15463        * endian later */
15464       caps = gst_caps_new_simple ("audio/x-raw",
15465           "format", G_TYPE_STRING, "S24BE",
15466           "layout", G_TYPE_STRING, "interleaved", NULL);
15467       stream->alignment = 4;
15468       break;
15469     case FOURCC_in32:
15470       _codec ("Raw 32-bit PCM audio");
15471       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15472        * endian later */
15473       caps = gst_caps_new_simple ("audio/x-raw",
15474           "format", G_TYPE_STRING, "S32BE",
15475           "layout", G_TYPE_STRING, "interleaved", NULL);
15476       stream->alignment = 4;
15477       break;
15478     case FOURCC_s16l:
15479       _codec ("Raw 16-bit PCM audio");
15480       caps = gst_caps_new_simple ("audio/x-raw",
15481           "format", G_TYPE_STRING, "S16LE",
15482           "layout", G_TYPE_STRING, "interleaved", NULL);
15483       stream->alignment = 2;
15484       break;
15485     case FOURCC_ulaw:
15486       _codec ("Mu-law audio");
15487       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15488       break;
15489     case FOURCC_alaw:
15490       _codec ("A-law audio");
15491       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15492       break;
15493     case 0x0200736d:
15494     case 0x6d730002:
15495       _codec ("Microsoft ADPCM");
15496       /* Microsoft ADPCM-ACM code 2 */
15497       caps = gst_caps_new_simple ("audio/x-adpcm",
15498           "layout", G_TYPE_STRING, "microsoft", NULL);
15499       break;
15500     case 0x1100736d:
15501     case 0x6d730011:
15502       _codec ("DVI/IMA ADPCM");
15503       caps = gst_caps_new_simple ("audio/x-adpcm",
15504           "layout", G_TYPE_STRING, "dvi", NULL);
15505       break;
15506     case 0x1700736d:
15507     case 0x6d730017:
15508       _codec ("DVI/Intel IMA ADPCM");
15509       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15510       caps = gst_caps_new_simple ("audio/x-adpcm",
15511           "layout", G_TYPE_STRING, "quicktime", NULL);
15512       break;
15513     case 0x5500736d:
15514     case 0x6d730055:
15515       /* MPEG layer 3, CBR only (pre QT4.1) */
15516     case FOURCC__mp3:
15517     case FOURCC_mp3_:
15518       _codec ("MPEG-1 layer 3");
15519       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15520       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15521           "mpegversion", G_TYPE_INT, 1, NULL);
15522       break;
15523     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15524       _codec ("MPEG-1 layer 2");
15525       /* MPEG layer 2 */
15526       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15527           "mpegversion", G_TYPE_INT, 1, NULL);
15528       break;
15529     case 0x20736d:
15530     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15531       _codec ("EAC-3 audio");
15532       caps = gst_caps_new_simple ("audio/x-eac3",
15533           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15534       entry->sampled = TRUE;
15535       break;
15536     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15537     case FOURCC_ac_3:
15538       _codec ("AC-3 audio");
15539       caps = gst_caps_new_simple ("audio/x-ac3",
15540           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15541       entry->sampled = TRUE;
15542       break;
15543     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15544     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15545       _codec ("DTS audio");
15546       caps = gst_caps_new_simple ("audio/x-dts",
15547           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15548       entry->sampled = TRUE;
15549       break;
15550     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15551     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15552       _codec ("DTS-HD audio");
15553       caps = gst_caps_new_simple ("audio/x-dts",
15554           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15555       entry->sampled = TRUE;
15556       break;
15557     case FOURCC_MAC3:
15558       _codec ("MACE-3");
15559       caps = gst_caps_new_simple ("audio/x-mace",
15560           "maceversion", G_TYPE_INT, 3, NULL);
15561       break;
15562     case FOURCC_MAC6:
15563       _codec ("MACE-6");
15564       caps = gst_caps_new_simple ("audio/x-mace",
15565           "maceversion", G_TYPE_INT, 6, NULL);
15566       break;
15567     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15568       /* ogg/vorbis */
15569       caps = gst_caps_new_empty_simple ("application/ogg");
15570       break;
15571     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15572       _codec ("DV audio");
15573       caps = gst_caps_new_empty_simple ("audio/x-dv");
15574       break;
15575     case FOURCC_mp4a:
15576       _codec ("MPEG-4 AAC audio");
15577       caps = gst_caps_new_simple ("audio/mpeg",
15578           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15579           "stream-format", G_TYPE_STRING, "raw", NULL);
15580       break;
15581     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15582       _codec ("QDesign Music");
15583       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15584       break;
15585     case FOURCC_QDM2:
15586       _codec ("QDesign Music v.2");
15587       /* FIXME: QDesign music version 2 (no constant) */
15588       if (FALSE && data) {
15589         caps = gst_caps_new_simple ("audio/x-qdm2",
15590             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15591             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15592             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15593       } else {
15594         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15595       }
15596       break;
15597     case FOURCC_agsm:
15598       _codec ("GSM audio");
15599       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15600       break;
15601     case FOURCC_samr:
15602       _codec ("AMR audio");
15603       caps = gst_caps_new_empty_simple ("audio/AMR");
15604       break;
15605     case FOURCC_sawb:
15606       _codec ("AMR-WB audio");
15607       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15608       break;
15609     case FOURCC_ima4:
15610       _codec ("Quicktime IMA ADPCM");
15611       caps = gst_caps_new_simple ("audio/x-adpcm",
15612           "layout", G_TYPE_STRING, "quicktime", NULL);
15613       break;
15614     case FOURCC_alac:
15615       _codec ("Apple lossless audio");
15616       caps = gst_caps_new_empty_simple ("audio/x-alac");
15617       break;
15618     case FOURCC_fLaC:
15619       _codec ("Free Lossless Audio Codec");
15620       caps = gst_caps_new_simple ("audio/x-flac",
15621           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15622       break;
15623     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15624       _codec ("QualComm PureVoice");
15625       caps = gst_caps_from_string ("audio/qcelp");
15626       break;
15627     case FOURCC_wma_:
15628     case FOURCC_owma:
15629       _codec ("WMA");
15630       caps = gst_caps_new_empty_simple ("audio/x-wma");
15631       break;
15632     case FOURCC_opus:
15633       _codec ("Opus");
15634       caps = gst_caps_new_empty_simple ("audio/x-opus");
15635       break;
15636     case FOURCC_lpcm:
15637     {
15638       guint32 flags = 0;
15639       guint32 depth = 0;
15640       guint32 width = 0;
15641       GstAudioFormat format;
15642       enum
15643       {
15644         FLAG_IS_FLOAT = 0x1,
15645         FLAG_IS_BIG_ENDIAN = 0x2,
15646         FLAG_IS_SIGNED = 0x4,
15647         FLAG_IS_PACKED = 0x8,
15648         FLAG_IS_ALIGNED_HIGH = 0x10,
15649         FLAG_IS_NON_INTERLEAVED = 0x20
15650       };
15651       _codec ("Raw LPCM audio");
15652
15653       if (data && len >= 36) {
15654         depth = QT_UINT32 (data + 24);
15655         flags = QT_UINT32 (data + 28);
15656         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15657       }
15658       if ((flags & FLAG_IS_FLOAT) == 0) {
15659         if (depth == 0)
15660           depth = 16;
15661         if (width == 0)
15662           width = 16;
15663         if ((flags & FLAG_IS_ALIGNED_HIGH))
15664           depth = width;
15665
15666         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15667             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15668             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15669         caps = gst_caps_new_simple ("audio/x-raw",
15670             "format", G_TYPE_STRING,
15671             format !=
15672             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15673             "UNKNOWN", "layout", G_TYPE_STRING,
15674             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15675             "interleaved", NULL);
15676         stream->alignment = GST_ROUND_UP_8 (depth);
15677         stream->alignment = round_up_pow2 (stream->alignment);
15678       } else {
15679         if (width == 0)
15680           width = 32;
15681         if (width == 64) {
15682           if (flags & FLAG_IS_BIG_ENDIAN)
15683             format = GST_AUDIO_FORMAT_F64BE;
15684           else
15685             format = GST_AUDIO_FORMAT_F64LE;
15686         } else {
15687           if (flags & FLAG_IS_BIG_ENDIAN)
15688             format = GST_AUDIO_FORMAT_F32BE;
15689           else
15690             format = GST_AUDIO_FORMAT_F32LE;
15691         }
15692         caps = gst_caps_new_simple ("audio/x-raw",
15693             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15694             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15695             "non-interleaved" : "interleaved", NULL);
15696         stream->alignment = width / 8;
15697       }
15698       break;
15699     }
15700     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15701     {
15702       _codec ("AC4");
15703       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15704       break;
15705     }
15706     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15707       /* ? */
15708     default:
15709     {
15710       caps = _get_unknown_codec_name ("audio", fourcc);
15711       break;
15712     }
15713   }
15714
15715   if (caps) {
15716     GstCaps *templ_caps =
15717         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15718     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15719     gst_caps_unref (caps);
15720     gst_caps_unref (templ_caps);
15721     caps = intersection;
15722   }
15723
15724   /* enable clipping for raw audio streams */
15725   s = gst_caps_get_structure (caps, 0);
15726   name = gst_structure_get_name (s);
15727   if (g_str_has_prefix (name, "audio/x-raw")) {
15728     stream->need_clip = TRUE;
15729     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15730     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15731     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15732         stream->max_buffer_size);
15733   }
15734   return caps;
15735 }
15736
15737 static GstCaps *
15738 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15739     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15740     const guint8 * stsd_entry_data, gchar ** codec_name)
15741 {
15742   GstCaps *caps;
15743
15744   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15745
15746   switch (fourcc) {
15747     case FOURCC_mp4s:
15748       _codec ("DVD subtitle");
15749       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15750       stream->process_func = gst_qtdemux_process_buffer_dvd;
15751       break;
15752     case FOURCC_text:
15753       _codec ("Quicktime timed text");
15754       goto text;
15755     case FOURCC_tx3g:
15756       _codec ("3GPP timed text");
15757     text:
15758       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15759           "utf8", NULL);
15760       /* actual text piece needs to be extracted */
15761       stream->process_func = gst_qtdemux_process_buffer_text;
15762       break;
15763     case FOURCC_stpp:
15764       _codec ("XML subtitles");
15765       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15766       break;
15767     case FOURCC_wvtt:
15768     {
15769       GstBuffer *buffer;
15770       const gchar *buf = "WEBVTT\n\n";
15771
15772       _codec ("WebVTT subtitles");
15773       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15774       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15775
15776       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15777       buffer = gst_buffer_new_and_alloc (8);
15778       gst_buffer_fill (buffer, 0, buf, 8);
15779       stream->buffers = g_slist_append (stream->buffers, buffer);
15780
15781       break;
15782     }
15783     case FOURCC_c608:
15784       _codec ("CEA 608 Closed Caption");
15785       caps =
15786           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15787           G_TYPE_STRING, "s334-1a", NULL);
15788       stream->process_func = gst_qtdemux_process_buffer_clcp;
15789       stream->need_split = TRUE;
15790       break;
15791     case FOURCC_c708:
15792       _codec ("CEA 708 Closed Caption");
15793       caps =
15794           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15795           G_TYPE_STRING, "cdp", NULL);
15796       stream->process_func = gst_qtdemux_process_buffer_clcp;
15797       break;
15798
15799     default:
15800     {
15801       caps = _get_unknown_codec_name ("text", fourcc);
15802       break;
15803     }
15804   }
15805   return caps;
15806 }
15807
15808 static GstCaps *
15809 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15810     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15811     const guint8 * stsd_entry_data, gchar ** codec_name)
15812 {
15813   GstCaps *caps;
15814
15815   switch (fourcc) {
15816     case FOURCC_m1v:
15817       _codec ("MPEG 1 video");
15818       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15819           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15820       break;
15821     default:
15822       caps = NULL;
15823       break;
15824   }
15825   return caps;
15826 }
15827
15828 static void
15829 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15830     const gchar * system_id)
15831 {
15832   gint i;
15833
15834   if (!qtdemux->protection_system_ids)
15835     qtdemux->protection_system_ids =
15836         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15837   /* Check whether we already have an entry for this system ID. */
15838   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15839     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15840     if (g_ascii_strcasecmp (system_id, id) == 0) {
15841       return;
15842     }
15843   }
15844   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15845   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15846           -1));
15847 }