Merging gst-plugins-bad
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
97
98 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
99
100 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
101
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
104 #define QTDEMUX_NTH_STREAM(demux,idx) \
105    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
106 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
107    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
108
109 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
110
111 GST_DEBUG_CATEGORY (qtdemux_debug);
112 #define GST_CAT_DEFAULT qtdemux_debug
113
114 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
115 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
116
117 /* Macros for converting to/from timescale */
118 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
119 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
120
121 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
122 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
123
124 /* timestamp is the DTS */
125 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
126 /* timestamp + offset + cslg_shift is the outgoing PTS */
127 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
128 /* timestamp + offset is the PTS used for internal seek calculations */
129 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
130 /* timestamp + duration - dts is the duration */
131 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
132
133 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
134
135 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
136 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
137     GST_TRACE("Locking from thread %p", g_thread_self()); \
138     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
139     GST_TRACE("Locked from thread %p", g_thread_self()); \
140  } G_STMT_END
141
142 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
143     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
144     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
145  } G_STMT_END
146
147 /*
148  * Quicktime has tracks and segments. A track is a continuous piece of
149  * multimedia content. The track is not always played from start to finish but
150  * instead, pieces of the track are 'cut out' and played in sequence. This is
151  * what the segments do.
152  *
153  * Inside the track we have keyframes (K) and delta frames. The track has its
154  * own timing, which starts from 0 and extends to end. The position in the track
155  * is called the media_time.
156  *
157  * The segments now describe the pieces that should be played from this track
158  * and are basically tuples of media_time/duration/rate entries. We can have
159  * multiple segments and they are all played after one another. An example:
160  *
161  * segment 1: media_time: 1 second, duration: 1 second, rate 1
162  * segment 2: media_time: 3 second, duration: 2 second, rate 2
163  *
164  * To correctly play back this track, one must play: 1 second of media starting
165  * from media_time 1 followed by 2 seconds of media starting from media_time 3
166  * at a rate of 2.
167  *
168  * Each of the segments will be played at a specific time, the first segment at
169  * time 0, the second one after the duration of the first one, etc.. Note that
170  * the time in resulting playback is not identical to the media_time of the
171  * track anymore.
172  *
173  * Visually, assuming the track has 4 second of media_time:
174  *
175  *                (a)                   (b)          (c)              (d)
176  *         .-----------------------------------------------------------.
177  * track:  | K.....K.........K........K.......K.......K...........K... |
178  *         '-----------------------------------------------------------'
179  *         0              1              2              3              4
180  *           .------------^              ^   .----------^              ^
181  *          /              .-------------'  /       .------------------'
182  *         /              /          .-----'       /
183  *         .--------------.         .--------------.
184  *         | segment 1    |         | segment 2    |
185  *         '--------------'         '--------------'
186  *
187  * The challenge here is to cut out the right pieces of the track for each of
188  * the playback segments. This fortunately can easily be done with the SEGMENT
189  * events of GStreamer.
190  *
191  * For playback of segment 1, we need to provide the decoder with the keyframe
192  * (a), in the above figure, but we must instruct it only to output the decoded
193  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
194  * position set to the time of the segment: 0.
195  *
196  * We then proceed to push data from keyframe (a) to frame (b). The decoder
197  * decodes but clips all before media_time 1.
198  *
199  * After finishing a segment, we push out a new SEGMENT event with the clipping
200  * boundaries of the new data.
201  *
202  * This is a good usecase for the GStreamer accumulated SEGMENT events.
203  */
204
205 struct _QtDemuxSegment
206 {
207   /* global time and duration, all gst time */
208   GstClockTime time;
209   GstClockTime stop_time;
210   GstClockTime duration;
211   /* media time of trak, all gst time */
212   GstClockTime media_start;
213   GstClockTime media_stop;
214   gdouble rate;
215   /* Media start time in trak timescale units */
216   guint32 trak_media_start;
217 };
218
219 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
220
221 /* Used with fragmented MP4 files (mfra atom) */
222 struct _QtDemuxRandomAccessEntry
223 {
224   GstClockTime ts;
225   guint64 moof_offset;
226 };
227
228
229 /* Contains properties and cryptographic info for a set of samples from a
230  * track protected using Common Encryption (cenc) */
231 struct _QtDemuxCencSampleSetInfo
232 {
233   GstStructure *default_properties;
234
235   /* @crypto_info holds one GstStructure per sample */
236   GPtrArray *crypto_info;
237 };
238
239 struct _QtDemuxAavdEncryptionInfo
240 {
241   GstStructure *default_properties;
242 };
243
244 static const gchar *
245 qt_demux_state_string (enum QtDemuxState state)
246 {
247   switch (state) {
248     case QTDEMUX_STATE_INITIAL:
249       return "<INITIAL>";
250     case QTDEMUX_STATE_HEADER:
251       return "<HEADER>";
252     case QTDEMUX_STATE_MOVIE:
253       return "<MOVIE>";
254     case QTDEMUX_STATE_BUFFER_MDAT:
255       return "<BUFFER_MDAT>";
256     default:
257       return "<UNKNOWN>";
258   }
259 }
260
261 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
262
263 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
264
265 static GstStaticPadTemplate gst_qtdemux_sink_template =
266     GST_STATIC_PAD_TEMPLATE ("sink",
267     GST_PAD_SINK,
268     GST_PAD_ALWAYS,
269     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
270         "application/x-3gp")
271     );
272
273 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
274 GST_STATIC_PAD_TEMPLATE ("video_%u",
275     GST_PAD_SRC,
276     GST_PAD_SOMETIMES,
277     GST_STATIC_CAPS_ANY);
278
279 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
280 GST_STATIC_PAD_TEMPLATE ("audio_%u",
281     GST_PAD_SRC,
282     GST_PAD_SOMETIMES,
283     GST_STATIC_CAPS_ANY);
284
285 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
286 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
287     GST_PAD_SRC,
288     GST_PAD_SOMETIMES,
289     GST_STATIC_CAPS_ANY);
290
291 #define gst_qtdemux_parent_class parent_class
292 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
293 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
294     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
295
296 static void gst_qtdemux_dispose (GObject * object);
297 static void gst_qtdemux_finalize (GObject * object);
298
299 static guint32
300 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
301     GstClockTime media_time);
302 static guint32
303 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
304     QtDemuxStream * str, gint64 media_offset);
305
306 #if 0
307 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
308 static GstIndex *gst_qtdemux_get_index (GstElement * element);
309 #endif
310 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
311     GstStateChange transition);
312 static void gst_qtdemux_set_context (GstElement * element,
313     GstContext * context);
314 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
315 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
316     GstObject * parent, GstPadMode mode, gboolean active);
317
318 static void gst_qtdemux_loop (GstPad * pad);
319 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
320     GstBuffer * inbuf);
321 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
322     GstEvent * event);
323 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
324     GstQuery * query);
325 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
326 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
327     QtDemuxStream * stream);
328 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
329     QtDemuxStream * stream);
330 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
331     gboolean force);
332
333 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
334
335 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
336     const guint8 * buffer, guint length);
337 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
338     const guint8 * buffer, guint length);
339 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
340
341 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
342     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
343     GstTagList * list);
344 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
345     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
346     const guint8 * stsd_entry_data, gchar ** codec_name);
347 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
348     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
349     const guint8 * data, int len, gchar ** codec_name);
350 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
351     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
352     gchar ** codec_name);
353 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
354     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
355     const guint8 * stsd_entry_data, gchar ** codec_name);
356
357 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
358     QtDemuxStream * stream, guint32 n);
359 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
360 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
361 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
363 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
364 static void qtdemux_do_allocation (QtDemuxStream * stream,
365     GstQTDemux * qtdemux);
366 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
367     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
368 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
369     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
370     GstClockTime * _start, GstClockTime * _stop);
371 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
372     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
373
374 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
375 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
376
377 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
378
379 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
380     QtDemuxStream * stream, guint sample_index);
381 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
382     const gchar * id);
383 static void qtdemux_gst_structure_free (GstStructure * gststructure);
384 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
385
386 static void
387 gst_qtdemux_class_init (GstQTDemuxClass * klass)
388 {
389   GObjectClass *gobject_class;
390   GstElementClass *gstelement_class;
391
392   gobject_class = (GObjectClass *) klass;
393   gstelement_class = (GstElementClass *) klass;
394
395   parent_class = g_type_class_peek_parent (klass);
396
397   gobject_class->dispose = gst_qtdemux_dispose;
398   gobject_class->finalize = gst_qtdemux_finalize;
399
400   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
401 #if 0
402   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
403   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
404 #endif
405   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
406
407   gst_tag_register_musicbrainz_tags ();
408
409   gst_element_class_add_static_pad_template (gstelement_class,
410       &gst_qtdemux_sink_template);
411   gst_element_class_add_static_pad_template (gstelement_class,
412       &gst_qtdemux_videosrc_template);
413   gst_element_class_add_static_pad_template (gstelement_class,
414       &gst_qtdemux_audiosrc_template);
415   gst_element_class_add_static_pad_template (gstelement_class,
416       &gst_qtdemux_subsrc_template);
417   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
418       "Codec/Demuxer",
419       "Demultiplex a QuickTime file into audio and video streams",
420       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
421
422   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
423   gst_riff_init ();
424 }
425
426 static void
427 gst_qtdemux_init (GstQTDemux * qtdemux)
428 {
429   qtdemux->sinkpad =
430       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
431   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
432   gst_pad_set_activatemode_function (qtdemux->sinkpad,
433       qtdemux_sink_activate_mode);
434   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
435   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
436   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
437   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
438
439   qtdemux->adapter = gst_adapter_new ();
440   g_queue_init (&qtdemux->protection_event_queue);
441   qtdemux->flowcombiner = gst_flow_combiner_new ();
442   g_mutex_init (&qtdemux->expose_lock);
443
444   qtdemux->active_streams = g_ptr_array_new_with_free_func
445       ((GDestroyNotify) gst_qtdemux_stream_unref);
446   qtdemux->old_streams = g_ptr_array_new_with_free_func
447       ((GDestroyNotify) gst_qtdemux_stream_unref);
448
449   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
450
451   gst_qtdemux_reset (qtdemux, TRUE);
452 }
453
454 static void
455 gst_qtdemux_finalize (GObject * object)
456 {
457   GstQTDemux *qtdemux = GST_QTDEMUX (object);
458
459   g_free (qtdemux->redirect_location);
460
461   G_OBJECT_CLASS (parent_class)->finalize (object);
462 }
463
464 static void
465 gst_qtdemux_dispose (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   if (qtdemux->adapter) {
470     g_object_unref (G_OBJECT (qtdemux->adapter));
471     qtdemux->adapter = NULL;
472   }
473   gst_tag_list_unref (qtdemux->tag_list);
474   gst_flow_combiner_free (qtdemux->flowcombiner);
475   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
476       NULL);
477   g_queue_clear (&qtdemux->protection_event_queue);
478
479   g_free (qtdemux->cenc_aux_info_sizes);
480   qtdemux->cenc_aux_info_sizes = NULL;
481   g_mutex_clear (&qtdemux->expose_lock);
482
483   g_ptr_array_free (qtdemux->active_streams, TRUE);
484   g_ptr_array_free (qtdemux->old_streams, TRUE);
485
486   G_OBJECT_CLASS (parent_class)->dispose (object);
487 }
488
489 static void
490 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
491 {
492   if (qtdemux->redirect_location) {
493     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
494         (_("This file contains no playable streams.")),
495         ("no known streams found, a redirect message has been posted"),
496         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
497   } else {
498     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
499         (_("This file contains no playable streams.")),
500         ("no known streams found"));
501   }
502 }
503
504 static GstBuffer *
505 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
506 {
507   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
508       mem, size, 0, size, mem, free_func);
509 }
510
511 static GstFlowReturn
512 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
513     GstBuffer ** buf)
514 {
515   GstFlowReturn flow;
516   GstMapInfo map;
517   gsize bsize;
518
519   if (G_UNLIKELY (size == 0)) {
520     GstFlowReturn ret;
521     GstBuffer *tmp = NULL;
522
523     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
524     if (ret != GST_FLOW_OK)
525       return ret;
526
527     gst_buffer_map (tmp, &map, GST_MAP_READ);
528     size = QT_UINT32 (map.data);
529     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
530
531     gst_buffer_unmap (tmp, &map);
532     gst_buffer_unref (tmp);
533   }
534
535   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
536   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
537     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
538       /* we're pulling header but already got most interesting bits,
539        * so never mind the rest (e.g. tags) (that much) */
540       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
541           size);
542       return GST_FLOW_EOS;
543     } else {
544       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
545           (_("This file is invalid and cannot be played.")),
546           ("atom has bogus size %" G_GUINT64_FORMAT, size));
547       return GST_FLOW_ERROR;
548     }
549   }
550
551   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
552
553   if (G_UNLIKELY (flow != GST_FLOW_OK))
554     return flow;
555
556   bsize = gst_buffer_get_size (*buf);
557   /* Catch short reads - we don't want any partial atoms */
558   if (G_UNLIKELY (bsize < size)) {
559     GST_WARNING_OBJECT (qtdemux,
560         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
561     gst_buffer_unref (*buf);
562     *buf = NULL;
563     return GST_FLOW_EOS;
564   }
565
566   return flow;
567 }
568
569 #if 1
570 static gboolean
571 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
572     GstFormat src_format, gint64 src_value, GstFormat dest_format,
573     gint64 * dest_value)
574 {
575   gboolean res = TRUE;
576   QtDemuxStream *stream = gst_pad_get_element_private (pad);
577   gint32 index;
578
579   if (stream->subtype != FOURCC_vide) {
580     res = FALSE;
581     goto done;
582   }
583
584   switch (src_format) {
585     case GST_FORMAT_TIME:
586       switch (dest_format) {
587         case GST_FORMAT_BYTES:{
588           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
589           if (-1 == index) {
590             res = FALSE;
591             goto done;
592           }
593
594           *dest_value = stream->samples[index].offset;
595
596           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
597               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
598               GST_TIME_ARGS (src_value), *dest_value);
599           break;
600         }
601         default:
602           res = FALSE;
603           break;
604       }
605       break;
606     case GST_FORMAT_BYTES:
607       switch (dest_format) {
608         case GST_FORMAT_TIME:{
609           index =
610               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
611               stream, src_value);
612
613           if (-1 == index) {
614             res = FALSE;
615             goto done;
616           }
617
618           *dest_value =
619               QTSTREAMTIME_TO_GSTTIME (stream,
620               stream->samples[index].timestamp);
621           GST_DEBUG_OBJECT (qtdemux,
622               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
623               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
624           break;
625         }
626         default:
627           res = FALSE;
628           break;
629       }
630       break;
631     default:
632       res = FALSE;
633       break;
634   }
635
636 done:
637   return res;
638 }
639 #endif
640
641 static gboolean
642 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
643 {
644   gboolean res = FALSE;
645
646   *duration = GST_CLOCK_TIME_NONE;
647
648   if (qtdemux->duration != 0 &&
649       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
650     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
651     res = TRUE;
652   } else {
653     *duration = GST_CLOCK_TIME_NONE;
654   }
655
656   return res;
657 }
658
659 static gboolean
660 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
661     GstQuery * query)
662 {
663   gboolean res = FALSE;
664   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
665
666   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
667
668   switch (GST_QUERY_TYPE (query)) {
669     case GST_QUERY_POSITION:{
670       GstFormat fmt;
671
672       gst_query_parse_position (query, &fmt, NULL);
673       if (fmt == GST_FORMAT_TIME
674           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
675         gst_query_set_position (query, GST_FORMAT_TIME,
676             qtdemux->segment.position);
677         res = TRUE;
678       }
679     }
680       break;
681     case GST_QUERY_DURATION:{
682       GstFormat fmt;
683
684       gst_query_parse_duration (query, &fmt, NULL);
685       if (fmt == GST_FORMAT_TIME) {
686         /* First try to query upstream */
687         res = gst_pad_query_default (pad, parent, query);
688         if (!res) {
689           GstClockTime duration;
690           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
691             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
692             res = TRUE;
693           }
694         }
695       }
696       break;
697     }
698     case GST_QUERY_CONVERT:{
699       GstFormat src_fmt, dest_fmt;
700       gint64 src_value, dest_value = 0;
701
702       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
703
704       res = gst_qtdemux_src_convert (qtdemux, pad,
705           src_fmt, src_value, dest_fmt, &dest_value);
706       if (res)
707         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
708
709       break;
710     }
711     case GST_QUERY_FORMATS:
712       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
713       res = TRUE;
714       break;
715     case GST_QUERY_SEEKING:{
716       GstFormat fmt;
717       gboolean seekable;
718
719       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
720
721       if (fmt == GST_FORMAT_BYTES) {
722         /* We always refuse BYTES seeks from downstream */
723         break;
724       }
725
726       /* try upstream first */
727       res = gst_pad_query_default (pad, parent, query);
728
729       if (!res) {
730         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
731         if (fmt == GST_FORMAT_TIME) {
732           GstClockTime duration;
733
734           gst_qtdemux_get_duration (qtdemux, &duration);
735           seekable = TRUE;
736           if (!qtdemux->pullbased) {
737             GstQuery *q;
738
739             /* we might be able with help from upstream */
740             seekable = FALSE;
741             q = gst_query_new_seeking (GST_FORMAT_BYTES);
742             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
743               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
744               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
745             }
746             gst_query_unref (q);
747           }
748           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
749           res = TRUE;
750         }
751       }
752       break;
753     }
754     case GST_QUERY_SEGMENT:
755     {
756       GstFormat format;
757       gint64 start, stop;
758
759       format = qtdemux->segment.format;
760
761       start =
762           gst_segment_to_stream_time (&qtdemux->segment, format,
763           qtdemux->segment.start);
764       if ((stop = qtdemux->segment.stop) == -1)
765         stop = qtdemux->segment.duration;
766       else
767         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
768
769       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
770       res = TRUE;
771       break;
772     }
773     default:
774       res = gst_pad_query_default (pad, parent, query);
775       break;
776   }
777
778   return res;
779 }
780
781 static void
782 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
783 {
784   if (G_LIKELY (stream->pad)) {
785     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
786         GST_DEBUG_PAD_NAME (stream->pad));
787
788     if (!gst_tag_list_is_empty (stream->stream_tags)) {
789       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
790           stream->stream_tags);
791       gst_pad_push_event (stream->pad,
792           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
793     }
794
795     if (G_UNLIKELY (stream->send_global_tags)) {
796       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
797           qtdemux->tag_list);
798       gst_pad_push_event (stream->pad,
799           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
800       stream->send_global_tags = FALSE;
801     }
802   }
803 }
804
805 /* push event on all source pads; takes ownership of the event */
806 static void
807 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
808 {
809   gboolean has_valid_stream = FALSE;
810   GstEventType etype = GST_EVENT_TYPE (event);
811   guint i;
812
813   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
814       GST_EVENT_TYPE_NAME (event));
815
816   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
817     GstPad *pad;
818     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
819     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
820
821     if ((pad = stream->pad)) {
822       has_valid_stream = TRUE;
823
824       if (etype == GST_EVENT_EOS) {
825         /* let's not send twice */
826         if (stream->sent_eos)
827           continue;
828         stream->sent_eos = TRUE;
829       }
830
831       gst_pad_push_event (pad, gst_event_ref (event));
832     }
833   }
834
835   gst_event_unref (event);
836
837   /* if it is EOS and there are no pads, post an error */
838   if (!has_valid_stream && etype == GST_EVENT_EOS) {
839     gst_qtdemux_post_no_playable_stream_error (qtdemux);
840   }
841 }
842
843 typedef struct
844 {
845   guint64 media_time;
846 } FindData;
847
848 static gint
849 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
850 {
851   if ((gint64) s1->timestamp > *media_time)
852     return 1;
853   if ((gint64) s1->timestamp == *media_time)
854     return 0;
855
856   return -1;
857 }
858
859 /* find the index of the sample that includes the data for @media_time using a
860  * binary search.  Only to be called in optimized cases of linear search below.
861  *
862  * Returns the index of the sample with the corresponding *DTS*.
863  */
864 static guint32
865 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
866     guint64 media_time)
867 {
868   QtDemuxSample *result;
869   guint32 index;
870
871   /* convert media_time to mov format */
872   media_time =
873       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
874
875   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
876       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
877       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
878
879   if (G_LIKELY (result))
880     index = result - str->samples;
881   else
882     index = 0;
883
884   return index;
885 }
886
887
888
889 /* find the index of the sample that includes the data for @media_offset using a
890  * linear search
891  *
892  * Returns the index of the sample.
893  */
894 static guint32
895 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
896     QtDemuxStream * str, gint64 media_offset)
897 {
898   QtDemuxSample *result = str->samples;
899   guint32 index = 0;
900
901   if (result == NULL || str->n_samples == 0)
902     return -1;
903
904   if (media_offset == result->offset)
905     return index;
906
907   result++;
908   while (index < str->n_samples - 1) {
909     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
910       goto parse_failed;
911
912     if (media_offset < result->offset)
913       break;
914
915     index++;
916     result++;
917   }
918   return index;
919
920   /* ERRORS */
921 parse_failed:
922   {
923     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
924     return -1;
925   }
926 }
927
928 /* find the index of the sample that includes the data for @media_time using a
929  * linear search, and keeping in mind that not all samples may have been parsed
930  * yet.  If possible, it will delegate to binary search.
931  *
932  * Returns the index of the sample.
933  */
934 static guint32
935 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
936     GstClockTime media_time)
937 {
938   guint32 index = 0;
939   guint64 mov_time;
940   QtDemuxSample *sample;
941
942   /* convert media_time to mov format */
943   mov_time =
944       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
945
946   sample = str->samples;
947   if (mov_time == sample->timestamp + sample->pts_offset)
948     return index;
949
950   /* use faster search if requested time in already parsed range */
951   sample = str->samples + str->stbl_index;
952   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
953     index = gst_qtdemux_find_index (qtdemux, str, media_time);
954     sample = str->samples + index;
955   } else {
956     while (index < str->n_samples - 1) {
957       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
958         goto parse_failed;
959
960       sample = str->samples + index + 1;
961       if (mov_time < sample->timestamp) {
962         sample = str->samples + index;
963         break;
964       }
965
966       index++;
967     }
968   }
969
970   /* sample->timestamp is now <= media_time, need to find the corresponding
971    * PTS now by looking backwards */
972   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
973     index--;
974     sample = str->samples + index;
975   }
976
977   return index;
978
979   /* ERRORS */
980 parse_failed:
981   {
982     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
983     return -1;
984   }
985 }
986
987 /* find the index of the keyframe needed to decode the sample at @index
988  * of stream @str, or of a subsequent keyframe (depending on @next)
989  *
990  * Returns the index of the keyframe.
991  */
992 static guint32
993 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
994     guint32 index, gboolean next)
995 {
996   guint32 new_index = index;
997
998   if (index >= str->n_samples) {
999     new_index = str->n_samples;
1000     goto beach;
1001   }
1002
1003   /* all keyframes, return index */
1004   if (str->all_keyframe) {
1005     new_index = index;
1006     goto beach;
1007   }
1008
1009   /* else search until we have a keyframe */
1010   while (new_index < str->n_samples) {
1011     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1012       goto parse_failed;
1013
1014     if (str->samples[new_index].keyframe)
1015       break;
1016
1017     if (new_index == 0)
1018       break;
1019
1020     if (next)
1021       new_index++;
1022     else
1023       new_index--;
1024   }
1025
1026   if (new_index == str->n_samples) {
1027     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1028     new_index = -1;
1029   }
1030
1031 beach:
1032   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1033       "gave %u", next ? "after" : "before", index, new_index);
1034
1035   return new_index;
1036
1037   /* ERRORS */
1038 parse_failed:
1039   {
1040     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1041     return -1;
1042   }
1043 }
1044
1045 /* find the segment for @time_position for @stream
1046  *
1047  * Returns the index of the segment containing @time_position.
1048  * Returns the last segment and sets the @eos variable to TRUE
1049  * if the time is beyond the end. @eos may be NULL
1050  */
1051 static guint32
1052 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1053     GstClockTime time_position)
1054 {
1055   gint i;
1056   guint32 seg_idx;
1057
1058   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1059       GST_TIME_ARGS (time_position));
1060
1061   seg_idx = -1;
1062   for (i = 0; i < stream->n_segments; i++) {
1063     QtDemuxSegment *segment = &stream->segments[i];
1064
1065     GST_LOG_OBJECT (stream->pad,
1066         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1067         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1068
1069     /* For the last segment we include stop_time in the last segment */
1070     if (i < stream->n_segments - 1) {
1071       if (segment->time <= time_position && time_position < segment->stop_time) {
1072         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1073         seg_idx = i;
1074         break;
1075       }
1076     } else {
1077       /* Last segment always matches */
1078       seg_idx = i;
1079       break;
1080     }
1081   }
1082   return seg_idx;
1083 }
1084
1085 /* move the stream @str to the sample position @index.
1086  *
1087  * Updates @str->sample_index and marks discontinuity if needed.
1088  */
1089 static void
1090 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1091     guint32 index)
1092 {
1093   /* no change needed */
1094   if (index == str->sample_index)
1095     return;
1096
1097   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1098       str->n_samples);
1099
1100   /* position changed, we have a discont */
1101   str->sample_index = index;
1102   str->offset_in_sample = 0;
1103   /* Each time we move in the stream we store the position where we are
1104    * starting from */
1105   str->from_sample = index;
1106   str->discont = TRUE;
1107 }
1108
1109 static void
1110 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1111     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1112 {
1113   guint64 min_offset;
1114   gint64 min_byte_offset = -1;
1115   guint i;
1116
1117   min_offset = desired_time;
1118
1119   /* for each stream, find the index of the sample in the segment
1120    * and move back to the previous keyframe. */
1121   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1122     QtDemuxStream *str;
1123     guint32 index, kindex;
1124     guint32 seg_idx;
1125     GstClockTime media_start;
1126     GstClockTime media_time;
1127     GstClockTime seg_time;
1128     QtDemuxSegment *seg;
1129     gboolean empty_segment = FALSE;
1130
1131     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1132
1133     if (CUR_STREAM (str)->sparse && !use_sparse)
1134       continue;
1135
1136     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1137     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1138
1139     /* get segment and time in the segment */
1140     seg = &str->segments[seg_idx];
1141     seg_time = (desired_time - seg->time) * seg->rate;
1142
1143     while (QTSEGMENT_IS_EMPTY (seg)) {
1144       seg_time = 0;
1145       empty_segment = TRUE;
1146       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1147           seg_idx);
1148       seg_idx++;
1149       if (seg_idx == str->n_segments)
1150         break;
1151       seg = &str->segments[seg_idx];
1152     }
1153
1154     if (seg_idx == str->n_segments) {
1155       /* FIXME track shouldn't have the last segment as empty, but if it
1156        * happens we better handle it */
1157       continue;
1158     }
1159
1160     /* get the media time in the segment */
1161     media_start = seg->media_start + seg_time;
1162
1163     /* get the index of the sample with media time */
1164     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1165     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1166         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1167         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1168         empty_segment);
1169
1170     /* shift to next frame if we are looking for next keyframe */
1171     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1172         && index < str->stbl_index)
1173       index++;
1174
1175     if (!empty_segment) {
1176       /* find previous keyframe */
1177       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1178
1179       /* we will settle for one before if none found after */
1180       if (next && kindex == -1)
1181         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1182
1183       /* Update the requested time whenever a keyframe was found, to make it
1184        * accurate and avoid having the first buffer fall outside of the segment
1185        */
1186       if (kindex != -1) {
1187         index = kindex;
1188
1189         /* get timestamp of keyframe */
1190         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1191         GST_DEBUG_OBJECT (qtdemux,
1192             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1193             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1194             str->samples[kindex].offset);
1195
1196         /* keyframes in the segment get a chance to change the
1197          * desired_offset. keyframes out of the segment are
1198          * ignored. */
1199         if (media_time >= seg->media_start) {
1200           GstClockTime seg_time;
1201
1202           /* this keyframe is inside the segment, convert back to
1203            * segment time */
1204           seg_time = (media_time - seg->media_start) + seg->time;
1205           if ((!next && (seg_time < min_offset)) ||
1206               (next && (seg_time > min_offset)))
1207             min_offset = seg_time;
1208         }
1209       }
1210     }
1211
1212     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1213       min_byte_offset = str->samples[index].offset;
1214   }
1215
1216   if (key_time)
1217     *key_time = min_offset;
1218   if (key_offset)
1219     *key_offset = min_byte_offset;
1220 }
1221
1222 static gboolean
1223 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1224     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1225 {
1226   gboolean res;
1227
1228   g_return_val_if_fail (format != NULL, FALSE);
1229   g_return_val_if_fail (cur != NULL, FALSE);
1230   g_return_val_if_fail (stop != NULL, FALSE);
1231
1232   if (*format == GST_FORMAT_TIME)
1233     return TRUE;
1234
1235   res = TRUE;
1236   if (cur_type != GST_SEEK_TYPE_NONE)
1237     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1238   if (res && stop_type != GST_SEEK_TYPE_NONE)
1239     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1240
1241   if (res)
1242     *format = GST_FORMAT_TIME;
1243
1244   return res;
1245 }
1246
1247 /* perform seek in push based mode:
1248    find BYTE position to move to based on time and delegate to upstream
1249 */
1250 static gboolean
1251 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1252 {
1253   gdouble rate;
1254   GstFormat format;
1255   GstSeekFlags flags;
1256   GstSeekType cur_type, stop_type;
1257   gint64 cur, stop, key_cur;
1258   gboolean res;
1259   gint64 byte_cur;
1260   gint64 original_stop;
1261   guint32 seqnum;
1262
1263   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1264
1265   gst_event_parse_seek (event, &rate, &format, &flags,
1266       &cur_type, &cur, &stop_type, &stop);
1267   seqnum = gst_event_get_seqnum (event);
1268
1269   /* Directly send the instant-rate-change event here before taking the
1270    * stream-lock so that it can be applied as soon as possible */
1271   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1272     GstEvent *ev;
1273
1274     /* instant rate change only supported if direction does not change. All
1275      * other requirements are already checked before creating the seek event
1276      * but let's double-check here to be sure */
1277     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1278         (qtdemux->segment.rate < 0 && rate > 0) ||
1279         cur_type != GST_SEEK_TYPE_NONE ||
1280         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1281       GST_ERROR_OBJECT (qtdemux,
1282           "Instant rate change seeks only supported in the "
1283           "same direction, without flushing and position change");
1284       return FALSE;
1285     }
1286
1287     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1288         (GstSegmentFlags) flags);
1289     gst_event_set_seqnum (ev, seqnum);
1290     gst_qtdemux_push_event (qtdemux, ev);
1291     return TRUE;
1292   }
1293
1294   /* only forward streaming and seeking is possible */
1295   if (rate <= 0)
1296     goto unsupported_seek;
1297
1298   /* convert to TIME if needed and possible */
1299   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1300           stop_type, &stop))
1301     goto no_format;
1302
1303   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1304    * the original stop position to use when upstream pushes the new segment
1305    * for this seek */
1306   original_stop = stop;
1307   stop = -1;
1308
1309   /* find reasonable corresponding BYTE position,
1310    * also try to mind about keyframes, since we can not go back a bit for them
1311    * later on */
1312   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1313    * mostly just work, but let's not yet boldly go there  ... */
1314   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1315
1316   if (byte_cur == -1)
1317     goto abort_seek;
1318
1319   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1320       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1321       stop);
1322
1323   GST_OBJECT_LOCK (qtdemux);
1324   qtdemux->seek_offset = byte_cur;
1325   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1326     qtdemux->push_seek_start = cur;
1327   } else {
1328     qtdemux->push_seek_start = key_cur;
1329   }
1330
1331   if (stop_type == GST_SEEK_TYPE_NONE) {
1332     qtdemux->push_seek_stop = qtdemux->segment.stop;
1333   } else {
1334     qtdemux->push_seek_stop = original_stop;
1335   }
1336   GST_OBJECT_UNLOCK (qtdemux);
1337
1338   qtdemux->segment_seqnum = seqnum;
1339   /* BYTE seek event */
1340   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1341       stop_type, stop);
1342   gst_event_set_seqnum (event, seqnum);
1343   res = gst_pad_push_event (qtdemux->sinkpad, event);
1344
1345   return res;
1346
1347   /* ERRORS */
1348 abort_seek:
1349   {
1350     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1351         "seek aborted.");
1352     return FALSE;
1353   }
1354 unsupported_seek:
1355   {
1356     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1357     return FALSE;
1358   }
1359 no_format:
1360   {
1361     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1362     return FALSE;
1363   }
1364 }
1365
1366 /* perform the seek.
1367  *
1368  * We set all segment_indexes in the streams to unknown and
1369  * adjust the time_position to the desired position. this is enough
1370  * to trigger a segment switch in the streaming thread to start
1371  * streaming from the desired position.
1372  *
1373  * Keyframe seeking is a little more complicated when dealing with
1374  * segments. Ideally we want to move to the previous keyframe in
1375  * the segment but there might not be a keyframe in the segment. In
1376  * fact, none of the segments could contain a keyframe. We take a
1377  * practical approach: seek to the previous keyframe in the segment,
1378  * if there is none, seek to the beginning of the segment.
1379  *
1380  * Called with STREAM_LOCK
1381  */
1382 static gboolean
1383 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1384     guint32 seqnum, GstSeekFlags flags)
1385 {
1386   gint64 desired_offset;
1387   guint i;
1388
1389   desired_offset = segment->position;
1390
1391   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1392       GST_TIME_ARGS (desired_offset));
1393
1394   /* may not have enough fragmented info to do this adjustment,
1395    * and we can't scan (and probably should not) at this time with
1396    * possibly flushing upstream */
1397   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1398     gint64 min_offset;
1399     gboolean next, before, after;
1400
1401     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1402     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1403     next = after && !before;
1404     if (segment->rate < 0)
1405       next = !next;
1406
1407     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1408         NULL);
1409     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1410         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1411     desired_offset = min_offset;
1412   }
1413
1414   /* and set all streams to the final position */
1415   GST_OBJECT_LOCK (qtdemux);
1416   gst_flow_combiner_reset (qtdemux->flowcombiner);
1417   GST_OBJECT_UNLOCK (qtdemux);
1418   qtdemux->segment_seqnum = seqnum;
1419   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1420     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1421
1422     stream->time_position = desired_offset;
1423     stream->accumulated_base = 0;
1424     stream->sample_index = -1;
1425     stream->offset_in_sample = 0;
1426     stream->segment_index = -1;
1427     stream->sent_eos = FALSE;
1428     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1429
1430     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1431       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1432   }
1433   segment->position = desired_offset;
1434   if (segment->rate >= 0) {
1435     segment->start = desired_offset;
1436     /* We need to update time as we update start in that direction */
1437     segment->time = desired_offset;
1438
1439     /* we stop at the end */
1440     if (segment->stop == -1)
1441       segment->stop = segment->duration;
1442   } else {
1443     segment->stop = desired_offset;
1444   }
1445
1446   if (qtdemux->fragmented)
1447     qtdemux->fragmented_seek_pending = TRUE;
1448
1449   return TRUE;
1450 }
1451
1452 /* do a seek in pull based mode */
1453 static gboolean
1454 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1455 {
1456   gdouble rate = 1.0;
1457   GstFormat format;
1458   GstSeekFlags flags;
1459   GstSeekType cur_type, stop_type;
1460   gint64 cur, stop;
1461   gboolean flush, instant_rate_change;
1462   gboolean update;
1463   GstSegment seeksegment;
1464   guint32 seqnum = GST_SEQNUM_INVALID;
1465   GstEvent *flush_event;
1466   gboolean ret;
1467
1468   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1469
1470   gst_event_parse_seek (event, &rate, &format, &flags,
1471       &cur_type, &cur, &stop_type, &stop);
1472   seqnum = gst_event_get_seqnum (event);
1473
1474   /* we have to have a format as the segment format. Try to convert
1475    * if not. */
1476   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1477           stop_type, &stop))
1478     goto no_format;
1479
1480   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1481
1482   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1483   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1484
1485   /* Directly send the instant-rate-change event here before taking the
1486    * stream-lock so that it can be applied as soon as possible */
1487   if (instant_rate_change) {
1488     GstEvent *ev;
1489
1490     /* instant rate change only supported if direction does not change. All
1491      * other requirements are already checked before creating the seek event
1492      * but let's double-check here to be sure */
1493     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1494         (qtdemux->segment.rate < 0 && rate > 0) ||
1495         cur_type != GST_SEEK_TYPE_NONE ||
1496         stop_type != GST_SEEK_TYPE_NONE || flush) {
1497       GST_ERROR_OBJECT (qtdemux,
1498           "Instant rate change seeks only supported in the "
1499           "same direction, without flushing and position change");
1500       return FALSE;
1501     }
1502
1503     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1504         (GstSegmentFlags) flags);
1505     gst_event_set_seqnum (ev, seqnum);
1506     gst_qtdemux_push_event (qtdemux, ev);
1507     return TRUE;
1508   }
1509
1510   /* stop streaming, either by flushing or by pausing the task */
1511   if (flush) {
1512     flush_event = gst_event_new_flush_start ();
1513     if (seqnum != GST_SEQNUM_INVALID)
1514       gst_event_set_seqnum (flush_event, seqnum);
1515     /* unlock upstream pull_range */
1516     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1517     /* make sure out loop function exits */
1518     gst_qtdemux_push_event (qtdemux, flush_event);
1519   } else {
1520     /* non flushing seek, pause the task */
1521     gst_pad_pause_task (qtdemux->sinkpad);
1522   }
1523
1524   /* wait for streaming to finish */
1525   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1526
1527   /* copy segment, we need this because we still need the old
1528    * segment when we close the current segment. */
1529   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1530
1531   /* configure the segment with the seek variables */
1532   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1533   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1534           cur_type, cur, stop_type, stop, &update)) {
1535     ret = FALSE;
1536     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1537   } else {
1538     /* now do the seek */
1539     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1540   }
1541
1542   /* prepare for streaming again */
1543   if (flush) {
1544     flush_event = gst_event_new_flush_stop (TRUE);
1545     if (seqnum != GST_SEQNUM_INVALID)
1546       gst_event_set_seqnum (flush_event, seqnum);
1547
1548     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1549     gst_qtdemux_push_event (qtdemux, flush_event);
1550   }
1551
1552   /* commit the new segment */
1553   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1554
1555   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1556     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1557         qtdemux->segment.format, qtdemux->segment.position);
1558     if (seqnum != GST_SEQNUM_INVALID)
1559       gst_message_set_seqnum (msg, seqnum);
1560     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1561   }
1562
1563   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1564   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1565       qtdemux->sinkpad, NULL);
1566
1567   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1568
1569   return ret;
1570
1571   /* ERRORS */
1572 no_format:
1573   {
1574     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1575     return FALSE;
1576   }
1577 }
1578
1579 static gboolean
1580 qtdemux_ensure_index (GstQTDemux * qtdemux)
1581 {
1582   guint i;
1583
1584   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1585
1586   /* Build complete index */
1587   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1588     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1589
1590     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1591       GST_LOG_OBJECT (qtdemux,
1592           "Building complete index of track-id %u for seeking failed!",
1593           stream->track_id);
1594       return FALSE;
1595     }
1596   }
1597
1598   return TRUE;
1599 }
1600
1601 static gboolean
1602 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1603     GstEvent * event)
1604 {
1605   gboolean res = TRUE;
1606   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1607
1608   switch (GST_EVENT_TYPE (event)) {
1609     case GST_EVENT_RECONFIGURE:
1610       GST_OBJECT_LOCK (qtdemux);
1611       gst_flow_combiner_reset (qtdemux->flowcombiner);
1612       GST_OBJECT_UNLOCK (qtdemux);
1613       res = gst_pad_event_default (pad, parent, event);
1614       break;
1615     case GST_EVENT_SEEK:
1616     {
1617       GstSeekFlags flags = 0;
1618       GstFormat seek_format;
1619       gboolean instant_rate_change;
1620
1621 #ifndef GST_DISABLE_GST_DEBUG
1622       GstClockTime ts = gst_util_get_timestamp ();
1623 #endif
1624       guint32 seqnum = gst_event_get_seqnum (event);
1625
1626       qtdemux->received_seek = TRUE;
1627
1628       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1629           NULL);
1630       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1631
1632       if (seqnum == qtdemux->segment_seqnum) {
1633         GST_LOG_OBJECT (pad,
1634             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1635         gst_event_unref (event);
1636         return TRUE;
1637       }
1638
1639       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1640         /* seek should be handled by upstream, we might need to re-download fragments */
1641         GST_DEBUG_OBJECT (qtdemux,
1642             "let upstream handle seek for fragmented playback");
1643         goto upstream;
1644       }
1645
1646       if (seek_format == GST_FORMAT_BYTES) {
1647         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1648         gst_event_unref (event);
1649         return FALSE;
1650       }
1651
1652       gst_event_parse_seek_trickmode_interval (event,
1653           &qtdemux->trickmode_interval);
1654
1655       /* Build complete index for seeking;
1656        * if not a fragmented file at least and we're really doing a seek,
1657        * not just an instant-rate-change */
1658       if (!qtdemux->fragmented && !instant_rate_change) {
1659         if (!qtdemux_ensure_index (qtdemux))
1660           goto index_failed;
1661       }
1662 #ifndef GST_DISABLE_GST_DEBUG
1663       ts = gst_util_get_timestamp () - ts;
1664       GST_INFO_OBJECT (qtdemux,
1665           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1666 #endif
1667       if (qtdemux->pullbased) {
1668         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1669       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1670         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1671         res = TRUE;
1672       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1673           && QTDEMUX_N_STREAMS (qtdemux)
1674           && !qtdemux->fragmented) {
1675         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1676       } else {
1677         GST_DEBUG_OBJECT (qtdemux,
1678             "ignoring seek in push mode in current state");
1679         res = FALSE;
1680       }
1681       gst_event_unref (event);
1682     }
1683       break;
1684     default:
1685     upstream:
1686       res = gst_pad_event_default (pad, parent, event);
1687       break;
1688   }
1689
1690 done:
1691   return res;
1692
1693   /* ERRORS */
1694 index_failed:
1695   {
1696     GST_ERROR_OBJECT (qtdemux, "Index failed");
1697     gst_event_unref (event);
1698     res = FALSE;
1699     goto done;
1700   }
1701 }
1702
1703 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1704  *
1705  * If @fw is false, the coding order is explored backwards.
1706  *
1707  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1708  * sample is found for that track.
1709  *
1710  * The stream and sample index of the sample with the minimum offset in the direction explored
1711  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1712  *
1713  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1714  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1715  * @_stream and @_index. */
1716 static void
1717 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1718     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1719 {
1720   gint i, index;
1721   gint64 time, min_time;
1722   QtDemuxStream *stream;
1723   gint iter;
1724
1725   min_time = -1;
1726   stream = NULL;
1727   index = -1;
1728
1729   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1730     QtDemuxStream *str;
1731     gint inc;
1732     gboolean set_sample;
1733
1734     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1735     set_sample = !set;
1736
1737     if (fw) {
1738       i = 0;
1739       inc = 1;
1740     } else {
1741       i = str->n_samples - 1;
1742       inc = -1;
1743     }
1744
1745     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1746       if (str->samples[i].size == 0)
1747         continue;
1748
1749       if (fw && (str->samples[i].offset < byte_pos))
1750         continue;
1751
1752       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1753         continue;
1754
1755       /* move stream to first available sample */
1756       if (set) {
1757         gst_qtdemux_move_stream (qtdemux, str, i);
1758         set_sample = TRUE;
1759       }
1760
1761       /* avoid index from sparse streams since they might be far away */
1762       if (!CUR_STREAM (str)->sparse) {
1763         /* determine min/max time */
1764         time = QTSAMPLE_PTS (str, &str->samples[i]);
1765         if (min_time == -1 || (!fw && time > min_time) ||
1766             (fw && time < min_time)) {
1767           min_time = time;
1768         }
1769
1770         /* determine stream with leading sample, to get its position */
1771         if (!stream ||
1772             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1773             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1774           stream = str;
1775           index = i;
1776         }
1777       }
1778       break;
1779     }
1780
1781     /* no sample for this stream, mark eos */
1782     if (!set_sample)
1783       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1784   }
1785
1786   if (_time)
1787     *_time = min_time;
1788   if (_stream)
1789     *_stream = stream;
1790   if (_index)
1791     *_index = index;
1792 }
1793
1794 /* Copied from mpegtsbase code */
1795 /* FIXME: replace this function when we add new util function for stream-id creation */
1796 static gchar *
1797 _get_upstream_id (GstQTDemux * demux)
1798 {
1799   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1800
1801   if (!upstream_id) {
1802     /* Try to create one from the upstream URI, else use a randome number */
1803     GstQuery *query;
1804     gchar *uri = NULL;
1805
1806     /* Try to generate one from the URI query and
1807      * if it fails take a random number instead */
1808     query = gst_query_new_uri ();
1809     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1810       gst_query_parse_uri (query, &uri);
1811     }
1812
1813     if (uri) {
1814       GChecksum *cs;
1815
1816       /* And then generate an SHA256 sum of the URI */
1817       cs = g_checksum_new (G_CHECKSUM_SHA256);
1818       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1819       g_free (uri);
1820       upstream_id = g_strdup (g_checksum_get_string (cs));
1821       g_checksum_free (cs);
1822     } else {
1823       /* Just get some random number if the URI query fails */
1824       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1825           "implementing a deterministic way of creating a stream-id");
1826       upstream_id =
1827           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1828           g_random_int (), g_random_int ());
1829     }
1830
1831     gst_query_unref (query);
1832   }
1833   return upstream_id;
1834 }
1835
1836 static QtDemuxStream *
1837 _create_stream (GstQTDemux * demux, guint32 track_id)
1838 {
1839   QtDemuxStream *stream;
1840   gchar *upstream_id;
1841
1842   stream = g_new0 (QtDemuxStream, 1);
1843   stream->demux = demux;
1844   stream->track_id = track_id;
1845   upstream_id = _get_upstream_id (demux);
1846   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1847   g_free (upstream_id);
1848   /* new streams always need a discont */
1849   stream->discont = TRUE;
1850   /* we enable clipping for raw audio/video streams */
1851   stream->need_clip = FALSE;
1852   stream->need_process = FALSE;
1853   stream->segment_index = -1;
1854   stream->time_position = 0;
1855   stream->sample_index = -1;
1856   stream->offset_in_sample = 0;
1857   stream->new_stream = TRUE;
1858   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1859   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1860   stream->protected = FALSE;
1861   stream->protection_scheme_type = 0;
1862   stream->protection_scheme_version = 0;
1863   stream->protection_scheme_info = NULL;
1864   stream->n_samples_moof = 0;
1865   stream->duration_moof = 0;
1866   stream->duration_last_moof = 0;
1867   stream->alignment = 1;
1868   stream->stream_tags = gst_tag_list_new_empty ();
1869   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1870   g_queue_init (&stream->protection_scheme_event_queue);
1871   stream->ref_count = 1;
1872   /* consistent default for push based mode */
1873   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1874   return stream;
1875 }
1876
1877 static gboolean
1878 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1879 {
1880   GstStructure *structure;
1881   const gchar *variant;
1882   const GstCaps *mediacaps = NULL;
1883
1884   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1885
1886   structure = gst_caps_get_structure (caps, 0);
1887   variant = gst_structure_get_string (structure, "variant");
1888
1889   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1890     QtDemuxStream *stream;
1891     const GValue *value;
1892
1893     demux->fragmented = TRUE;
1894     demux->mss_mode = TRUE;
1895
1896     if (QTDEMUX_N_STREAMS (demux) > 1) {
1897       /* can't do this, we can only renegotiate for another mss format */
1898       return FALSE;
1899     }
1900
1901     value = gst_structure_get_value (structure, "media-caps");
1902     /* create stream */
1903     if (value) {
1904       const GValue *timescale_v;
1905
1906       /* TODO update when stream changes during playback */
1907
1908       if (QTDEMUX_N_STREAMS (demux) == 0) {
1909         stream = _create_stream (demux, 1);
1910         g_ptr_array_add (demux->active_streams, stream);
1911         /* mss has no stsd/stsd entry, use id 0 as default */
1912         stream->stsd_entries_length = 1;
1913         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1914         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1915       } else {
1916         stream = QTDEMUX_NTH_STREAM (demux, 0);
1917       }
1918
1919       timescale_v = gst_structure_get_value (structure, "timescale");
1920       if (timescale_v) {
1921         stream->timescale = g_value_get_uint64 (timescale_v);
1922       } else {
1923         /* default mss timescale */
1924         stream->timescale = 10000000;
1925       }
1926       demux->timescale = stream->timescale;
1927
1928       mediacaps = gst_value_get_caps (value);
1929       if (!CUR_STREAM (stream)->caps
1930           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1931         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1932             mediacaps);
1933         stream->new_caps = TRUE;
1934       }
1935       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1936       structure = gst_caps_get_structure (mediacaps, 0);
1937       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1938         stream->subtype = FOURCC_vide;
1939
1940         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1941         gst_structure_get_int (structure, "height",
1942             &CUR_STREAM (stream)->height);
1943         gst_structure_get_fraction (structure, "framerate",
1944             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1945       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1946         gint rate = 0;
1947         stream->subtype = FOURCC_soun;
1948         gst_structure_get_int (structure, "channels",
1949             &CUR_STREAM (stream)->n_channels);
1950         gst_structure_get_int (structure, "rate", &rate);
1951         CUR_STREAM (stream)->rate = rate;
1952       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1953         if (gst_structure_has_field (structure, "original-media-type")) {
1954           const gchar *media_type =
1955               gst_structure_get_string (structure, "original-media-type");
1956           if (g_str_has_prefix (media_type, "video")) {
1957             stream->subtype = FOURCC_vide;
1958           } else if (g_str_has_prefix (media_type, "audio")) {
1959             stream->subtype = FOURCC_soun;
1960           }
1961         }
1962       }
1963     }
1964     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1965   } else {
1966     demux->mss_mode = FALSE;
1967   }
1968
1969   return TRUE;
1970 }
1971
1972 static void
1973 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1974 {
1975   gint i;
1976
1977   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1978   gst_pad_stop_task (qtdemux->sinkpad);
1979
1980   if (hard || qtdemux->upstream_format_is_time) {
1981     qtdemux->state = QTDEMUX_STATE_INITIAL;
1982     qtdemux->neededbytes = 16;
1983     qtdemux->todrop = 0;
1984     qtdemux->pullbased = FALSE;
1985     g_clear_pointer (&qtdemux->redirect_location, g_free);
1986     qtdemux->first_mdat = -1;
1987     qtdemux->header_size = 0;
1988     qtdemux->mdatoffset = -1;
1989     qtdemux->restoredata_offset = -1;
1990     if (qtdemux->mdatbuffer)
1991       gst_buffer_unref (qtdemux->mdatbuffer);
1992     if (qtdemux->restoredata_buffer)
1993       gst_buffer_unref (qtdemux->restoredata_buffer);
1994     qtdemux->mdatbuffer = NULL;
1995     qtdemux->restoredata_buffer = NULL;
1996     qtdemux->mdatleft = 0;
1997     qtdemux->mdatsize = 0;
1998     if (qtdemux->comp_brands)
1999       gst_buffer_unref (qtdemux->comp_brands);
2000     qtdemux->comp_brands = NULL;
2001     qtdemux->last_moov_offset = -1;
2002     if (qtdemux->moov_node_compressed) {
2003       g_node_destroy (qtdemux->moov_node_compressed);
2004       if (qtdemux->moov_node)
2005         g_free (qtdemux->moov_node->data);
2006     }
2007     qtdemux->moov_node_compressed = NULL;
2008     if (qtdemux->moov_node)
2009       g_node_destroy (qtdemux->moov_node);
2010     qtdemux->moov_node = NULL;
2011     if (qtdemux->tag_list)
2012       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2013     qtdemux->tag_list = gst_tag_list_new_empty ();
2014     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2015 #if 0
2016     if (qtdemux->element_index)
2017       gst_object_unref (qtdemux->element_index);
2018     qtdemux->element_index = NULL;
2019 #endif
2020     qtdemux->major_brand = 0;
2021     qtdemux->upstream_format_is_time = FALSE;
2022     qtdemux->upstream_seekable = FALSE;
2023     qtdemux->upstream_size = 0;
2024
2025     qtdemux->fragment_start = -1;
2026     qtdemux->fragment_start_offset = -1;
2027     qtdemux->duration = 0;
2028     qtdemux->moof_offset = 0;
2029     qtdemux->chapters_track_id = 0;
2030     qtdemux->have_group_id = FALSE;
2031     qtdemux->group_id = G_MAXUINT;
2032
2033     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2034         NULL);
2035     g_queue_clear (&qtdemux->protection_event_queue);
2036
2037     qtdemux->received_seek = FALSE;
2038     qtdemux->first_moof_already_parsed = FALSE;
2039   }
2040   qtdemux->offset = 0;
2041   gst_adapter_clear (qtdemux->adapter);
2042   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2043   qtdemux->need_segment = TRUE;
2044
2045   if (hard) {
2046     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2047     qtdemux->trickmode_interval = 0;
2048     g_ptr_array_set_size (qtdemux->active_streams, 0);
2049     g_ptr_array_set_size (qtdemux->old_streams, 0);
2050     qtdemux->n_video_streams = 0;
2051     qtdemux->n_audio_streams = 0;
2052     qtdemux->n_sub_streams = 0;
2053     qtdemux->exposed = FALSE;
2054     qtdemux->fragmented = FALSE;
2055     qtdemux->mss_mode = FALSE;
2056     gst_caps_replace (&qtdemux->media_caps, NULL);
2057     qtdemux->timescale = 0;
2058     qtdemux->got_moov = FALSE;
2059     qtdemux->cenc_aux_info_offset = 0;
2060     qtdemux->cenc_aux_info_sizes = NULL;
2061     qtdemux->cenc_aux_sample_count = 0;
2062     if (qtdemux->protection_system_ids) {
2063       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2064       qtdemux->protection_system_ids = NULL;
2065     }
2066     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2067         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2068         GST_BIN_FLAG_STREAMS_AWARE);
2069
2070     if (qtdemux->preferred_protection_system_id) {
2071       g_free (qtdemux->preferred_protection_system_id);
2072       qtdemux->preferred_protection_system_id = NULL;
2073     }
2074   } else if (qtdemux->mss_mode) {
2075     gst_flow_combiner_reset (qtdemux->flowcombiner);
2076     g_ptr_array_foreach (qtdemux->active_streams,
2077         (GFunc) gst_qtdemux_stream_clear, NULL);
2078   } else {
2079     gst_flow_combiner_reset (qtdemux->flowcombiner);
2080     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2081       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2082       stream->sent_eos = FALSE;
2083       stream->time_position = 0;
2084       stream->accumulated_base = 0;
2085       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2086     }
2087   }
2088 }
2089
2090
2091 /* Maps the @segment to the qt edts internal segments and pushes
2092  * the corresponding segment event.
2093  *
2094  * If it ends up being at a empty segment, a gap will be pushed and the next
2095  * edts segment will be activated in sequence.
2096  *
2097  * To be used in push-mode only */
2098 static void
2099 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2100 {
2101   gint i, iter;
2102
2103   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2104     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2105
2106     stream->time_position = segment->start;
2107
2108     /* in push mode we should be guaranteed that we will have empty segments
2109      * at the beginning and then one segment after, other scenarios are not
2110      * supported and are discarded when parsing the edts */
2111     for (i = 0; i < stream->n_segments; i++) {
2112       if (stream->segments[i].stop_time > segment->start) {
2113         /* push the empty segment and move to the next one */
2114         gst_qtdemux_activate_segment (qtdemux, stream, i,
2115             stream->time_position);
2116         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2117           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2118               stream->time_position);
2119
2120           /* accumulate previous segments */
2121           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2122             stream->accumulated_base +=
2123                 (stream->segment.stop -
2124                 stream->segment.start) / ABS (stream->segment.rate);
2125           continue;
2126         }
2127
2128         g_assert (i == stream->n_segments - 1);
2129       }
2130     }
2131   }
2132 }
2133
2134 static void
2135 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2136     GPtrArray * src)
2137 {
2138   guint i;
2139   guint len;
2140
2141   len = src->len;
2142
2143   if (len == 0)
2144     return;
2145
2146   for (i = 0; i < len; i++) {
2147     QtDemuxStream *stream = g_ptr_array_index (src, i);
2148
2149 #ifndef GST_DISABLE_GST_DEBUG
2150     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2151         stream, GST_STR_NULL (stream->stream_id), dest);
2152 #endif
2153     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2154   }
2155
2156   g_ptr_array_set_size (src, 0);
2157 }
2158
2159 static gboolean
2160 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2161     GstEvent * event)
2162 {
2163   GstQTDemux *demux = GST_QTDEMUX (parent);
2164   gboolean res = TRUE;
2165
2166   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2167
2168   switch (GST_EVENT_TYPE (event)) {
2169     case GST_EVENT_SEGMENT:
2170     {
2171       gint64 offset = 0;
2172       QtDemuxStream *stream;
2173       gint idx;
2174       GstSegment segment;
2175
2176       /* some debug output */
2177       gst_event_copy_segment (event, &segment);
2178       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2179           &segment);
2180
2181       if (segment.format == GST_FORMAT_TIME) {
2182         demux->upstream_format_is_time = TRUE;
2183         demux->segment_seqnum = gst_event_get_seqnum (event);
2184       } else {
2185         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2186             "not in time format");
2187
2188         /* chain will send initial newsegment after pads have been added */
2189         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2190           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2191           goto exit;
2192         }
2193       }
2194
2195       /* check if this matches a time seek we received previously
2196        * FIXME for backwards compatibility reasons we use the
2197        * seek_offset here to compare. In the future we might want to
2198        * change this to use the seqnum as it uniquely should identify
2199        * the segment that corresponds to the seek. */
2200       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2201           ", received segment offset %" G_GINT64_FORMAT,
2202           demux->seek_offset, segment.start);
2203       if (segment.format == GST_FORMAT_BYTES
2204           && demux->seek_offset == segment.start) {
2205         GST_OBJECT_LOCK (demux);
2206         offset = segment.start;
2207
2208         segment.format = GST_FORMAT_TIME;
2209         segment.start = demux->push_seek_start;
2210         segment.stop = demux->push_seek_stop;
2211         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2212             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2213             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2214         GST_OBJECT_UNLOCK (demux);
2215       }
2216
2217       /* we only expect a BYTE segment, e.g. following a seek */
2218       if (segment.format == GST_FORMAT_BYTES) {
2219         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2220           offset = segment.start;
2221
2222           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2223               NULL, (gint64 *) & segment.start);
2224           if ((gint64) segment.start < 0)
2225             segment.start = 0;
2226         }
2227         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2228           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2229               NULL, (gint64 *) & segment.stop);
2230           /* keyframe seeking should already arrange for start >= stop,
2231            * but make sure in other rare cases */
2232           segment.stop = MAX (segment.stop, segment.start);
2233         }
2234       } else if (segment.format == GST_FORMAT_TIME) {
2235         /* push all data on the adapter before starting this
2236          * new segment */
2237         gst_qtdemux_process_adapter (demux, TRUE);
2238       } else {
2239         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2240         goto exit;
2241       }
2242
2243       /* We shouldn't modify upstream driven TIME FORMAT segment */
2244       if (!demux->upstream_format_is_time) {
2245         /* accept upstream's notion of segment and distribute along */
2246         segment.format = GST_FORMAT_TIME;
2247         segment.position = segment.time = segment.start;
2248         segment.duration = demux->segment.duration;
2249         segment.base = gst_segment_to_running_time (&demux->segment,
2250             GST_FORMAT_TIME, demux->segment.position);
2251       }
2252
2253       gst_segment_copy_into (&segment, &demux->segment);
2254       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2255
2256       /* map segment to internal qt segments and push on each stream */
2257       if (QTDEMUX_N_STREAMS (demux)) {
2258         demux->need_segment = TRUE;
2259         gst_qtdemux_check_send_pending_segment (demux);
2260       }
2261
2262       /* clear leftover in current segment, if any */
2263       gst_adapter_clear (demux->adapter);
2264
2265       /* set up streaming thread */
2266       demux->offset = offset;
2267       if (demux->upstream_format_is_time) {
2268         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2269             "set values to restart reading from a new atom");
2270         demux->neededbytes = 16;
2271         demux->todrop = 0;
2272       } else {
2273         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2274             NULL);
2275         if (stream) {
2276           demux->todrop = stream->samples[idx].offset - offset;
2277           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2278         } else {
2279           /* set up for EOS */
2280           demux->neededbytes = -1;
2281           demux->todrop = 0;
2282         }
2283       }
2284     exit:
2285       gst_event_unref (event);
2286       res = TRUE;
2287       goto drop;
2288     }
2289     case GST_EVENT_FLUSH_START:
2290     {
2291       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2292         gst_event_unref (event);
2293         goto drop;
2294       }
2295       QTDEMUX_EXPOSE_LOCK (demux);
2296       res = gst_pad_event_default (demux->sinkpad, parent, event);
2297       QTDEMUX_EXPOSE_UNLOCK (demux);
2298       goto drop;
2299     }
2300     case GST_EVENT_FLUSH_STOP:
2301     {
2302       guint64 dur;
2303
2304       dur = demux->segment.duration;
2305       gst_qtdemux_reset (demux, FALSE);
2306       demux->segment.duration = dur;
2307
2308       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2309         gst_event_unref (event);
2310         goto drop;
2311       }
2312       break;
2313     }
2314     case GST_EVENT_EOS:
2315       /* If we are in push mode, and get an EOS before we've seen any streams,
2316        * then error out - we have nowhere to send the EOS */
2317       if (!demux->pullbased) {
2318         gint i;
2319         gboolean has_valid_stream = FALSE;
2320         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2321           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2322             has_valid_stream = TRUE;
2323             break;
2324           }
2325         }
2326         if (!has_valid_stream)
2327           gst_qtdemux_post_no_playable_stream_error (demux);
2328         else {
2329           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2330               (guint) gst_adapter_available (demux->adapter));
2331           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2332             res = FALSE;
2333           }
2334         }
2335       }
2336       break;
2337     case GST_EVENT_CAPS:{
2338       GstCaps *caps = NULL;
2339
2340       gst_event_parse_caps (event, &caps);
2341       gst_qtdemux_setcaps (demux, caps);
2342       res = TRUE;
2343       gst_event_unref (event);
2344       goto drop;
2345     }
2346     case GST_EVENT_PROTECTION:
2347     {
2348       const gchar *system_id = NULL;
2349
2350       gst_event_parse_protection (event, &system_id, NULL, NULL);
2351       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2352           system_id);
2353       gst_qtdemux_append_protection_system_id (demux, system_id);
2354       /* save the event for later, for source pads that have not been created */
2355       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2356       /* send it to all pads that already exist */
2357       gst_qtdemux_push_event (demux, event);
2358       res = TRUE;
2359       goto drop;
2360     }
2361     case GST_EVENT_STREAM_START:
2362     {
2363       res = TRUE;
2364       gst_event_unref (event);
2365
2366       /* Drain all the buffers */
2367       gst_qtdemux_process_adapter (demux, TRUE);
2368       gst_qtdemux_reset (demux, FALSE);
2369       /* We expect new moov box after new stream-start event */
2370       if (demux->exposed) {
2371         gst_qtdemux_stream_concat (demux,
2372             demux->old_streams, demux->active_streams);
2373       }
2374
2375       goto drop;
2376     }
2377     default:
2378       break;
2379   }
2380
2381   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2382
2383 drop:
2384   return res;
2385 }
2386
2387 static gboolean
2388 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2389     GstQuery * query)
2390 {
2391   GstQTDemux *demux = GST_QTDEMUX (parent);
2392   gboolean res = FALSE;
2393
2394   switch (GST_QUERY_TYPE (query)) {
2395     case GST_QUERY_BITRATE:
2396     {
2397       GstClockTime duration;
2398
2399       /* populate demux->upstream_size if not done yet */
2400       gst_qtdemux_check_seekability (demux);
2401
2402       if (demux->upstream_size != -1
2403           && gst_qtdemux_get_duration (demux, &duration)) {
2404         guint bitrate =
2405             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2406             duration);
2407
2408         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2409             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2410             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2411
2412         /* TODO: better results based on ranges/index tables */
2413         gst_query_set_bitrate (query, bitrate);
2414         res = TRUE;
2415       }
2416       break;
2417     }
2418     default:
2419       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2420       break;
2421   }
2422
2423   return res;
2424 }
2425
2426
2427 #if 0
2428 static void
2429 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2430 {
2431   GstQTDemux *demux = GST_QTDEMUX (element);
2432
2433   GST_OBJECT_LOCK (demux);
2434   if (demux->element_index)
2435     gst_object_unref (demux->element_index);
2436   if (index) {
2437     demux->element_index = gst_object_ref (index);
2438   } else {
2439     demux->element_index = NULL;
2440   }
2441   GST_OBJECT_UNLOCK (demux);
2442   /* object lock might be taken again */
2443   if (index)
2444     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2445   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2446       demux->element_index, demux->index_id);
2447 }
2448
2449 static GstIndex *
2450 gst_qtdemux_get_index (GstElement * element)
2451 {
2452   GstIndex *result = NULL;
2453   GstQTDemux *demux = GST_QTDEMUX (element);
2454
2455   GST_OBJECT_LOCK (demux);
2456   if (demux->element_index)
2457     result = gst_object_ref (demux->element_index);
2458   GST_OBJECT_UNLOCK (demux);
2459
2460   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2461
2462   return result;
2463 }
2464 #endif
2465
2466 static void
2467 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2468 {
2469   g_free ((gpointer) stream->stco.data);
2470   stream->stco.data = NULL;
2471   g_free ((gpointer) stream->stsz.data);
2472   stream->stsz.data = NULL;
2473   g_free ((gpointer) stream->stsc.data);
2474   stream->stsc.data = NULL;
2475   g_free ((gpointer) stream->stts.data);
2476   stream->stts.data = NULL;
2477   g_free ((gpointer) stream->stss.data);
2478   stream->stss.data = NULL;
2479   g_free ((gpointer) stream->stps.data);
2480   stream->stps.data = NULL;
2481   g_free ((gpointer) stream->ctts.data);
2482   stream->ctts.data = NULL;
2483 }
2484
2485 static void
2486 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2487 {
2488   g_free (stream->segments);
2489   stream->segments = NULL;
2490   stream->segment_index = -1;
2491   stream->accumulated_base = 0;
2492 }
2493
2494 static void
2495 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2496 {
2497   g_free (stream->samples);
2498   stream->samples = NULL;
2499   gst_qtdemux_stbl_free (stream);
2500
2501   /* fragments */
2502   g_free (stream->ra_entries);
2503   stream->ra_entries = NULL;
2504   stream->n_ra_entries = 0;
2505
2506   stream->sample_index = -1;
2507   stream->stbl_index = -1;
2508   stream->n_samples = 0;
2509   stream->time_position = 0;
2510
2511   stream->n_samples_moof = 0;
2512   stream->duration_moof = 0;
2513   stream->duration_last_moof = 0;
2514 }
2515
2516 static void
2517 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2518 {
2519   gint i;
2520   if (stream->allocator)
2521     gst_object_unref (stream->allocator);
2522   while (stream->buffers) {
2523     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2524     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2525   }
2526   for (i = 0; i < stream->stsd_entries_length; i++) {
2527     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2528     if (entry->rgb8_palette) {
2529       gst_memory_unref (entry->rgb8_palette);
2530       entry->rgb8_palette = NULL;
2531     }
2532     entry->sparse = FALSE;
2533   }
2534
2535   if (stream->stream_tags)
2536     gst_tag_list_unref (stream->stream_tags);
2537
2538   stream->stream_tags = gst_tag_list_new_empty ();
2539   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2540   g_free (stream->redirect_uri);
2541   stream->redirect_uri = NULL;
2542   stream->sent_eos = FALSE;
2543   stream->protected = FALSE;
2544   if (stream->protection_scheme_info) {
2545     if (stream->protection_scheme_type == FOURCC_cenc
2546         || stream->protection_scheme_type == FOURCC_cbcs) {
2547       QtDemuxCencSampleSetInfo *info =
2548           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2549       if (info->default_properties)
2550         gst_structure_free (info->default_properties);
2551       if (info->crypto_info)
2552         g_ptr_array_free (info->crypto_info, TRUE);
2553     }
2554     if (stream->protection_scheme_type == FOURCC_aavd) {
2555       QtDemuxAavdEncryptionInfo *info =
2556           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2557       if (info->default_properties)
2558         gst_structure_free (info->default_properties);
2559     }
2560     g_free (stream->protection_scheme_info);
2561     stream->protection_scheme_info = NULL;
2562   }
2563   stream->protection_scheme_type = 0;
2564   stream->protection_scheme_version = 0;
2565   g_queue_foreach (&stream->protection_scheme_event_queue,
2566       (GFunc) gst_event_unref, NULL);
2567   g_queue_clear (&stream->protection_scheme_event_queue);
2568   gst_qtdemux_stream_flush_segments_data (stream);
2569   gst_qtdemux_stream_flush_samples_data (stream);
2570 }
2571
2572 static void
2573 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2574 {
2575   gint i;
2576   gst_qtdemux_stream_clear (stream);
2577   for (i = 0; i < stream->stsd_entries_length; i++) {
2578     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2579     if (entry->caps) {
2580       gst_caps_unref (entry->caps);
2581       entry->caps = NULL;
2582     }
2583   }
2584   g_free (stream->stsd_entries);
2585   stream->stsd_entries = NULL;
2586   stream->stsd_entries_length = 0;
2587 }
2588
2589 static QtDemuxStream *
2590 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2591 {
2592   g_atomic_int_add (&stream->ref_count, 1);
2593
2594   return stream;
2595 }
2596
2597 static void
2598 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2599 {
2600   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2601     gst_qtdemux_stream_reset (stream);
2602     gst_tag_list_unref (stream->stream_tags);
2603     if (stream->pad) {
2604       GstQTDemux *demux = stream->demux;
2605       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2606       GST_OBJECT_LOCK (demux);
2607       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2608       GST_OBJECT_UNLOCK (demux);
2609     }
2610     g_free (stream->stream_id);
2611     g_free (stream);
2612   }
2613 }
2614
2615 static GstStateChangeReturn
2616 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2617 {
2618   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2619   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2620
2621   switch (transition) {
2622     case GST_STATE_CHANGE_READY_TO_PAUSED:
2623       gst_qtdemux_reset (qtdemux, TRUE);
2624       break;
2625     default:
2626       break;
2627   }
2628
2629   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2630
2631   switch (transition) {
2632     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2633       gst_qtdemux_reset (qtdemux, TRUE);
2634       break;
2635     }
2636     default:
2637       break;
2638   }
2639
2640   return result;
2641 }
2642
2643 static void
2644 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2645 {
2646   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2647
2648   g_return_if_fail (GST_IS_CONTEXT (context));
2649
2650   if (gst_context_has_context_type (context,
2651           "drm-preferred-decryption-system-id")) {
2652     const GstStructure *s;
2653
2654     s = gst_context_get_structure (context);
2655     g_free (qtdemux->preferred_protection_system_id);
2656     qtdemux->preferred_protection_system_id =
2657         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2658     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2659         qtdemux->preferred_protection_system_id);
2660   }
2661
2662   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2663 }
2664
2665 static void
2666 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2667 {
2668   /* counts as header data */
2669   qtdemux->header_size += length;
2670
2671   /* only consider at least a sufficiently complete ftyp atom */
2672   if (length >= 20) {
2673     GstBuffer *buf;
2674
2675     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2676     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2677         GST_FOURCC_ARGS (qtdemux->major_brand));
2678     if (qtdemux->comp_brands)
2679       gst_buffer_unref (qtdemux->comp_brands);
2680     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2681     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2682   }
2683 }
2684
2685 static void
2686 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2687     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2688     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2689     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2690     const guint8 * constant_iv)
2691 {
2692   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2693   gst_buffer_fill (kid_buf, 0, kid, 16);
2694   if (info->default_properties)
2695     gst_structure_free (info->default_properties);
2696   info->default_properties =
2697       gst_structure_new ("application/x-cenc",
2698       "iv_size", G_TYPE_UINT, iv_size,
2699       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2700       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2701   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2702       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2703   gst_buffer_unref (kid_buf);
2704   if (protection_scheme_type == FOURCC_cbcs) {
2705     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2706       gst_structure_set (info->default_properties, "crypt_byte_block",
2707           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2708           skip_byte_block, NULL);
2709     }
2710     if (constant_iv != NULL) {
2711       GstBuffer *constant_iv_buf =
2712           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2713       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2714       gst_structure_set (info->default_properties, "constant_iv_size",
2715           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2716           NULL);
2717       gst_buffer_unref (constant_iv_buf);
2718     }
2719     gst_structure_set (info->default_properties, "cipher-mode",
2720         G_TYPE_STRING, "cbcs", NULL);
2721   } else {
2722     gst_structure_set (info->default_properties, "cipher-mode",
2723         G_TYPE_STRING, "cenc", NULL);
2724   }
2725 }
2726
2727 static gboolean
2728 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2729     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2730 {
2731   guint32 algorithm_id = 0;
2732   const guint8 *kid;
2733   gboolean is_encrypted = TRUE;
2734   guint8 iv_size = 8;
2735
2736   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2737     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2738     return FALSE;
2739   }
2740
2741   algorithm_id >>= 8;
2742   if (algorithm_id == 0) {
2743     is_encrypted = FALSE;
2744   } else if (algorithm_id == 1) {
2745     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2746   } else if (algorithm_id == 2) {
2747     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2748   }
2749
2750   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2751     return FALSE;
2752
2753   if (!gst_byte_reader_get_data (br, 16, &kid))
2754     return FALSE;
2755
2756   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2757       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2758   gst_structure_set (info->default_properties, "piff_algorithm_id",
2759       G_TYPE_UINT, algorithm_id, NULL);
2760   return TRUE;
2761 }
2762
2763
2764 static void
2765 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2766     guint offset)
2767 {
2768   GstByteReader br;
2769   guint8 version;
2770   guint32 flags = 0;
2771   guint i;
2772   guint iv_size = 8;
2773   QtDemuxStream *stream;
2774   GstStructure *structure;
2775   QtDemuxCencSampleSetInfo *ss_info = NULL;
2776   const gchar *system_id;
2777   gboolean uses_sub_sample_encryption = FALSE;
2778   guint32 sample_count;
2779
2780   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2781     return;
2782
2783   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2784
2785   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2786   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2787     GST_WARNING_OBJECT (qtdemux,
2788         "Attempting PIFF box parsing on an unencrypted stream.");
2789     return;
2790   }
2791
2792   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2793       G_TYPE_STRING, &system_id, NULL);
2794   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2795
2796   stream->protected = TRUE;
2797   stream->protection_scheme_type = FOURCC_cenc;
2798
2799   if (!stream->protection_scheme_info)
2800     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2801
2802   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2803   if (!ss_info->default_properties) {
2804     ss_info->default_properties =
2805         gst_structure_new ("application/x-cenc",
2806         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2807         NULL);
2808
2809   }
2810
2811   if (ss_info->crypto_info) {
2812     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2813     g_ptr_array_free (ss_info->crypto_info, TRUE);
2814     ss_info->crypto_info = NULL;
2815   }
2816
2817   /* skip UUID */
2818   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2819
2820   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2821     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2822     return;
2823   }
2824
2825   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2826     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2827     return;
2828   }
2829
2830   if ((flags & 0x000001)) {
2831     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2832             &br))
2833       return;
2834   } else if ((flags & 0x000002)) {
2835     uses_sub_sample_encryption = TRUE;
2836   }
2837
2838   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2839           &iv_size)) {
2840     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2841     return;
2842   }
2843
2844   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2845     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2846     return;
2847   }
2848
2849   ss_info->crypto_info =
2850       g_ptr_array_new_full (sample_count,
2851       (GDestroyNotify) qtdemux_gst_structure_free);
2852
2853   for (i = 0; i < sample_count; ++i) {
2854     GstStructure *properties;
2855     guint8 *data;
2856     GstBuffer *buf;
2857
2858     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2859     if (properties == NULL) {
2860       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2861       qtdemux->cenc_aux_sample_count = i;
2862       return;
2863     }
2864
2865     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2866       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2867       gst_structure_free (properties);
2868       qtdemux->cenc_aux_sample_count = i;
2869       return;
2870     }
2871     buf = gst_buffer_new_wrapped (data, iv_size);
2872     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2873     gst_buffer_unref (buf);
2874
2875     if (uses_sub_sample_encryption) {
2876       guint16 n_subsamples;
2877       const GValue *kid_buf_value;
2878
2879       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2880           || n_subsamples == 0) {
2881         GST_ERROR_OBJECT (qtdemux,
2882             "failed to get subsample count for sample %u", i);
2883         gst_structure_free (properties);
2884         qtdemux->cenc_aux_sample_count = i;
2885         return;
2886       }
2887       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2888       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2889         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2890             i);
2891         gst_structure_free (properties);
2892         qtdemux->cenc_aux_sample_count = i;
2893         return;
2894       }
2895       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2896
2897       kid_buf_value =
2898           gst_structure_get_value (ss_info->default_properties, "kid");
2899
2900       gst_structure_set (properties,
2901           "subsample_count", G_TYPE_UINT, n_subsamples,
2902           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2903       gst_structure_set_value (properties, "kid", kid_buf_value);
2904       gst_buffer_unref (buf);
2905     } else {
2906       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2907     }
2908
2909     g_ptr_array_add (ss_info->crypto_info, properties);
2910   }
2911
2912   qtdemux->cenc_aux_sample_count = sample_count;
2913 }
2914
2915 static void
2916 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2917 {
2918   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2919     0x97, 0xA9, 0x42, 0xE8,
2920     0x9C, 0x71, 0x99, 0x94,
2921     0x91, 0xE3, 0xAF, 0xAC
2922   };
2923   static const guint8 playready_uuid[] = {
2924     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2925     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2926   };
2927
2928   static const guint8 piff_sample_encryption_uuid[] = {
2929     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2930     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2931   };
2932
2933   guint offset;
2934
2935   /* counts as header data */
2936   qtdemux->header_size += length;
2937
2938   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2939
2940   if (length <= offset + 16) {
2941     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2942     return;
2943   }
2944
2945   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2946     GstBuffer *buf;
2947     GstTagList *taglist;
2948
2949     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2950         length - offset - 16, NULL);
2951     taglist = gst_tag_list_from_xmp_buffer (buf);
2952     gst_buffer_unref (buf);
2953
2954     /* make sure we have a usable taglist */
2955     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2956
2957     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2958
2959   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2960     int len;
2961     const gunichar2 *s_utf16;
2962     char *contents;
2963
2964     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2965     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2966     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2967     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2968
2969     g_free (contents);
2970
2971     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2972         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2973         (NULL));
2974   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2975     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2976   } else {
2977     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2978         GST_READ_UINT32_LE (buffer + offset),
2979         GST_READ_UINT32_LE (buffer + offset + 4),
2980         GST_READ_UINT32_LE (buffer + offset + 8),
2981         GST_READ_UINT32_LE (buffer + offset + 12));
2982   }
2983 }
2984
2985 static void
2986 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2987 {
2988   GstSidxParser sidx_parser;
2989   GstIsoffParserResult res;
2990   guint consumed;
2991
2992   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2993
2994   res =
2995       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2996       &consumed);
2997   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2998   if (res == GST_ISOFF_QT_PARSER_DONE) {
2999     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3000   }
3001   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3002 }
3003
3004 /* caller verifies at least 8 bytes in buf */
3005 static void
3006 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3007     guint64 * plength, guint32 * pfourcc)
3008 {
3009   guint64 length;
3010   guint32 fourcc;
3011
3012   length = QT_UINT32 (data);
3013   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3014   fourcc = QT_FOURCC (data + 4);
3015   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3016
3017   if (length == 0) {
3018     length = G_MAXUINT64;
3019   } else if (length == 1 && size >= 16) {
3020     /* this means we have an extended size, which is the 64 bit value of
3021      * the next 8 bytes */
3022     length = QT_UINT64 (data + 8);
3023     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3024   }
3025
3026   if (plength)
3027     *plength = length;
3028   if (pfourcc)
3029     *pfourcc = fourcc;
3030 }
3031
3032 static gboolean
3033 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3034 {
3035   guint32 version = 0;
3036   GstClockTime duration = 0;
3037
3038   if (!gst_byte_reader_get_uint32_be (br, &version))
3039     goto failed;
3040
3041   version >>= 24;
3042   if (version == 1) {
3043     if (!gst_byte_reader_get_uint64_be (br, &duration))
3044       goto failed;
3045   } else {
3046     guint32 dur = 0;
3047
3048     if (!gst_byte_reader_get_uint32_be (br, &dur))
3049       goto failed;
3050     duration = dur;
3051   }
3052
3053   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3054   qtdemux->duration = duration;
3055
3056   return TRUE;
3057
3058 failed:
3059   {
3060     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3061     return FALSE;
3062   }
3063 }
3064
3065 static gboolean
3066 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3067     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3068 {
3069   if (!stream->parsed_trex && qtdemux->moov_node) {
3070     GNode *mvex, *trex;
3071     GstByteReader trex_data;
3072
3073     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3074     if (mvex) {
3075       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3076           &trex_data);
3077       while (trex) {
3078         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3079
3080         /* skip version/flags */
3081         if (!gst_byte_reader_skip (&trex_data, 4))
3082           goto next;
3083         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3084           goto next;
3085         if (id != stream->track_id)
3086           goto next;
3087         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3088           goto next;
3089         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3090           goto next;
3091         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3092           goto next;
3093         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3094           goto next;
3095
3096         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3097             "duration %d,  size %d, flags 0x%x", stream->track_id,
3098             dur, size, flags);
3099
3100         stream->parsed_trex = TRUE;
3101         stream->def_sample_description_index = sdi;
3102         stream->def_sample_duration = dur;
3103         stream->def_sample_size = size;
3104         stream->def_sample_flags = flags;
3105
3106       next:
3107         /* iterate all siblings */
3108         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3109             &trex_data);
3110       }
3111     }
3112   }
3113
3114   *ds_duration = stream->def_sample_duration;
3115   *ds_size = stream->def_sample_size;
3116   *ds_flags = stream->def_sample_flags;
3117
3118   /* even then, above values are better than random ... */
3119   if (G_UNLIKELY (!stream->parsed_trex)) {
3120     GST_WARNING_OBJECT (qtdemux,
3121         "failed to find fragment defaults for stream %d", stream->track_id);
3122     return FALSE;
3123   }
3124
3125   return TRUE;
3126 }
3127
3128 /* This method should be called whenever a more accurate duration might
3129  * have been found. It will update all relevant variables if/where needed
3130  */
3131 static void
3132 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3133 {
3134   guint i;
3135   guint64 movdur;
3136   GstClockTime prevdur;
3137
3138   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3139
3140   if (movdur > qtdemux->duration) {
3141     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3142     GST_DEBUG_OBJECT (qtdemux,
3143         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3144         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3145     qtdemux->duration = movdur;
3146     GST_DEBUG_OBJECT (qtdemux,
3147         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3148         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3149         GST_TIME_ARGS (qtdemux->segment.stop));
3150     if (qtdemux->segment.duration == prevdur) {
3151       /* If the current segment has duration/stop identical to previous duration
3152        * update them also (because they were set at that point in time with
3153        * the wrong duration */
3154       /* We convert the value *from* the timescale version to avoid rounding errors */
3155       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3156       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3157       qtdemux->segment.duration = fixeddur;
3158       qtdemux->segment.stop = fixeddur;
3159     }
3160   }
3161
3162   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3163     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3164
3165     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3166     if (movdur > stream->duration) {
3167       GST_DEBUG_OBJECT (qtdemux,
3168           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3169           GST_TIME_ARGS (duration));
3170       stream->duration = movdur;
3171       /* internal duration tracking state has been updated above, so */
3172       /* preserve an open-ended dummy segment rather than repeatedly updating
3173        * it and spamming downstream accordingly with segment events */
3174       /* also mangle the edit list end time when fragmented with a single edit
3175        * list that may only cover any non-fragmented data */
3176       if ((stream->dummy_segment ||
3177               (qtdemux->fragmented && stream->n_segments == 1)) &&
3178           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3179         /* Update all dummy values to new duration */
3180         stream->segments[0].stop_time = duration;
3181         stream->segments[0].duration = duration;
3182         stream->segments[0].media_stop = duration;
3183
3184         /* let downstream know we possibly have a new stop time */
3185         if (stream->segment_index != -1) {
3186           GstClockTime pos;
3187
3188           if (qtdemux->segment.rate >= 0) {
3189             pos = stream->segment.start;
3190           } else {
3191             pos = stream->segment.stop;
3192           }
3193
3194           gst_qtdemux_stream_update_segment (qtdemux, stream,
3195               stream->segment_index, pos, NULL, NULL);
3196         }
3197       }
3198     }
3199   }
3200 }
3201
3202 static gboolean
3203 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3204     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3205     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3206     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3207     gboolean has_tfdt)
3208 {
3209   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3210   guint64 timestamp;
3211   gint32 data_offset = 0;
3212   guint32 flags = 0, first_flags = 0, samples_count = 0;
3213   gint i;
3214   guint8 *data;
3215   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3216   QtDemuxSample *sample;
3217   gboolean ismv = FALSE;
3218   gint64 initial_offset;
3219
3220   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3221       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3222       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3223       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3224
3225   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3226     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3227     return TRUE;
3228   }
3229
3230   /* presence of stss or not can't really tell us much,
3231    * and flags and so on tend to be marginally reliable in these files */
3232   if (stream->subtype == FOURCC_soun) {
3233     GST_DEBUG_OBJECT (qtdemux,
3234         "sound track in fragmented file; marking all keyframes");
3235     stream->all_keyframe = TRUE;
3236   }
3237
3238   if (!gst_byte_reader_skip (trun, 1) ||
3239       !gst_byte_reader_get_uint24_be (trun, &flags))
3240     goto fail;
3241
3242   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3243     goto fail;
3244
3245   if (flags & TR_DATA_OFFSET) {
3246     /* note this is really signed */
3247     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3248       goto fail;
3249     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3250     /* default base offset = first byte of moof */
3251     if (*base_offset == -1) {
3252       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3253       *base_offset = moof_offset;
3254     }
3255     *running_offset = *base_offset + data_offset;
3256   } else {
3257     /* if no offset at all, that would mean data starts at moof start,
3258      * which is a bit wrong and is ismv crappy way, so compensate
3259      * assuming data is in mdat following moof */
3260     if (*base_offset == -1) {
3261       *base_offset = moof_offset + moof_length + 8;
3262       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3263       ismv = TRUE;
3264     }
3265     if (*running_offset == -1)
3266       *running_offset = *base_offset;
3267   }
3268
3269   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3270       *running_offset);
3271   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3272       data_offset, flags, samples_count);
3273
3274   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3275     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3276       GST_DEBUG_OBJECT (qtdemux,
3277           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3278       flags ^= TR_FIRST_SAMPLE_FLAGS;
3279     } else {
3280       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3281         goto fail;
3282       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3283     }
3284   }
3285
3286   /* FIXME ? spec says other bits should also be checked to determine
3287    * entry size (and prefix size for that matter) */
3288   entry_size = 0;
3289   dur_offset = size_offset = 0;
3290   if (flags & TR_SAMPLE_DURATION) {
3291     GST_LOG_OBJECT (qtdemux, "entry duration present");
3292     dur_offset = entry_size;
3293     entry_size += 4;
3294   }
3295   if (flags & TR_SAMPLE_SIZE) {
3296     GST_LOG_OBJECT (qtdemux, "entry size present");
3297     size_offset = entry_size;
3298     entry_size += 4;
3299   }
3300   if (flags & TR_SAMPLE_FLAGS) {
3301     GST_LOG_OBJECT (qtdemux, "entry flags present");
3302     flags_offset = entry_size;
3303     entry_size += 4;
3304   }
3305   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3306     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3307     ct_offset = entry_size;
3308     entry_size += 4;
3309   }
3310
3311   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3312     goto fail;
3313   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3314
3315   if (stream->n_samples + samples_count >=
3316       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3317     goto index_too_big;
3318
3319   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3320       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3321       (stream->n_samples + samples_count) *
3322       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3323
3324   /* create a new array of samples if it's the first sample parsed */
3325   if (stream->n_samples == 0) {
3326     g_assert (stream->samples == NULL);
3327     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3328     /* or try to reallocate it with space enough to insert the new samples */
3329   } else
3330     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3331         stream->n_samples + samples_count);
3332   if (stream->samples == NULL)
3333     goto out_of_memory;
3334
3335   if (qtdemux->fragment_start != -1) {
3336     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3337     qtdemux->fragment_start = -1;
3338   } else {
3339     if (stream->n_samples == 0) {
3340       if (decode_ts > 0) {
3341         timestamp = decode_ts;
3342       } else if (stream->pending_seek != NULL) {
3343         /* if we don't have a timestamp from a tfdt box, we'll use the one
3344          * from the mfra seek table */
3345         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3346             GST_TIME_ARGS (stream->pending_seek->ts));
3347
3348         /* FIXME: this is not fully correct, the timestamp refers to the random
3349          * access sample refered to in the tfra entry, which may not necessarily
3350          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3351         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3352       } else {
3353         timestamp = 0;
3354       }
3355
3356       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3357       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3358           GST_TIME_ARGS (gst_ts));
3359     } else {
3360       /* subsequent fragments extend stream */
3361       timestamp =
3362           stream->samples[stream->n_samples - 1].timestamp +
3363           stream->samples[stream->n_samples - 1].duration;
3364
3365       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3366        * difference (1 sec.) between decode_ts and timestamp, prefer the
3367        * former */
3368       if (has_tfdt && !qtdemux->upstream_format_is_time
3369           && ABSDIFF (decode_ts, timestamp) >
3370           MAX (stream->duration_last_moof / 2,
3371               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3372         GST_INFO_OBJECT (qtdemux,
3373             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3374             ") are significantly different (more than %" GST_TIME_FORMAT
3375             "), using decode_ts",
3376             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3377             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3378             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3379                     MAX (stream->duration_last_moof / 2,
3380                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3381         timestamp = decode_ts;
3382       }
3383
3384       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3385       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3386           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3387     }
3388   }
3389
3390   initial_offset = *running_offset;
3391
3392   sample = stream->samples + stream->n_samples;
3393   for (i = 0; i < samples_count; i++) {
3394     guint32 dur, size, sflags, ct;
3395
3396     /* first read sample data */
3397     if (flags & TR_SAMPLE_DURATION) {
3398       dur = QT_UINT32 (data + dur_offset);
3399     } else {
3400       dur = d_sample_duration;
3401     }
3402     if (flags & TR_SAMPLE_SIZE) {
3403       size = QT_UINT32 (data + size_offset);
3404     } else {
3405       size = d_sample_size;
3406     }
3407     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3408       if (i == 0) {
3409         sflags = first_flags;
3410       } else {
3411         sflags = d_sample_flags;
3412       }
3413     } else if (flags & TR_SAMPLE_FLAGS) {
3414       sflags = QT_UINT32 (data + flags_offset);
3415     } else {
3416       sflags = d_sample_flags;
3417     }
3418     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3419       ct = QT_UINT32 (data + ct_offset);
3420     } else {
3421       ct = 0;
3422     }
3423     data += entry_size;
3424
3425     /* fill the sample information */
3426     sample->offset = *running_offset;
3427     sample->pts_offset = ct;
3428     sample->size = size;
3429     sample->timestamp = timestamp;
3430     sample->duration = dur;
3431     /* sample-is-difference-sample */
3432     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3433      * now idea how it relates to bitfield other than massive LE/BE confusion */
3434     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3435     *running_offset += size;
3436     timestamp += dur;
3437     stream->duration_moof += dur;
3438     sample++;
3439   }
3440
3441   /* Update total duration if needed */
3442   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3443
3444   /* Pre-emptively figure out size of mdat based on trun information.
3445    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3446    * size, else we will still be able to use this when dealing with gap'ed
3447    * input */
3448   qtdemux->mdatleft = *running_offset - initial_offset;
3449   qtdemux->mdatoffset = initial_offset;
3450   qtdemux->mdatsize = qtdemux->mdatleft;
3451
3452   stream->n_samples += samples_count;
3453   stream->n_samples_moof += samples_count;
3454
3455   if (stream->pending_seek != NULL)
3456     stream->pending_seek = NULL;
3457
3458   return TRUE;
3459
3460 fail:
3461   {
3462     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3463     return FALSE;
3464   }
3465 out_of_memory:
3466   {
3467     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3468         stream->n_samples);
3469     return FALSE;
3470   }
3471 index_too_big:
3472   {
3473     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3474         "be larger than %uMB (broken file?)", stream->n_samples,
3475         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3476     return FALSE;
3477   }
3478 }
3479
3480 /* find stream with @id */
3481 static inline QtDemuxStream *
3482 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3483 {
3484   QtDemuxStream *stream;
3485   gint i;
3486
3487   /* check */
3488   if (G_UNLIKELY (!id)) {
3489     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3490     return NULL;
3491   }
3492
3493   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3494     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3495     if (stream->track_id == id)
3496       return stream;
3497   }
3498   if (qtdemux->mss_mode) {
3499     /* mss should have only 1 stream anyway */
3500     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3501   }
3502
3503   return NULL;
3504 }
3505
3506 static gboolean
3507 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3508     guint32 * fragment_number)
3509 {
3510   if (!gst_byte_reader_skip (mfhd, 4))
3511     goto fail;
3512   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3513     goto fail;
3514   return TRUE;
3515 fail:
3516   {
3517     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3518     return FALSE;
3519   }
3520 }
3521
3522 static gboolean
3523 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3524     QtDemuxStream ** stream, guint32 * default_sample_duration,
3525     guint32 * default_sample_size, guint32 * default_sample_flags,
3526     gint64 * base_offset)
3527 {
3528   guint32 flags = 0;
3529   guint32 track_id = 0;
3530
3531   if (!gst_byte_reader_skip (tfhd, 1) ||
3532       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3533     goto invalid_track;
3534
3535   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3536     goto invalid_track;
3537
3538   *stream = qtdemux_find_stream (qtdemux, track_id);
3539   if (G_UNLIKELY (!*stream))
3540     goto unknown_stream;
3541
3542   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3543     *base_offset = qtdemux->moof_offset;
3544
3545   if (flags & TF_BASE_DATA_OFFSET)
3546     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3547       goto invalid_track;
3548
3549   /* obtain stream defaults */
3550   qtdemux_parse_trex (qtdemux, *stream,
3551       default_sample_duration, default_sample_size, default_sample_flags);
3552
3553   (*stream)->stsd_sample_description_id =
3554       (*stream)->def_sample_description_index - 1;
3555
3556   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3557     guint32 sample_description_index;
3558     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3559       goto invalid_track;
3560     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3561   }
3562
3563   if (qtdemux->mss_mode) {
3564     /* mss has no stsd entry */
3565     (*stream)->stsd_sample_description_id = 0;
3566   }
3567
3568   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3569     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3570       goto invalid_track;
3571
3572   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3573     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3574       goto invalid_track;
3575
3576   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3577     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3578       goto invalid_track;
3579
3580   return TRUE;
3581
3582 invalid_track:
3583   {
3584     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3585     return FALSE;
3586   }
3587 unknown_stream:
3588   {
3589     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3590     return TRUE;
3591   }
3592 }
3593
3594 static gboolean
3595 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3596     guint64 * decode_time)
3597 {
3598   guint32 version = 0;
3599
3600   if (!gst_byte_reader_get_uint32_be (br, &version))
3601     return FALSE;
3602
3603   version >>= 24;
3604   if (version == 1) {
3605     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3606       goto failed;
3607   } else {
3608     guint32 dec_time = 0;
3609     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3610       goto failed;
3611     *decode_time = dec_time;
3612   }
3613
3614   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3615       *decode_time);
3616
3617   return TRUE;
3618
3619 failed:
3620   {
3621     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3622     return FALSE;
3623   }
3624 }
3625
3626 /* Returns a pointer to a GstStructure containing the properties of
3627  * the stream sample identified by @sample_index. The caller must unref
3628  * the returned object after use. Returns NULL if unsuccessful. */
3629 static GstStructure *
3630 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3631     QtDemuxStream * stream, guint sample_index)
3632 {
3633   QtDemuxCencSampleSetInfo *info = NULL;
3634
3635   g_return_val_if_fail (stream != NULL, NULL);
3636   g_return_val_if_fail (stream->protected, NULL);
3637   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3638
3639   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3640
3641   /* Currently, cenc properties for groups of samples are not supported, so
3642    * simply return a copy of the default sample properties */
3643   return gst_structure_copy (info->default_properties);
3644 }
3645
3646 /* Parses the sizes of sample auxiliary information contained within a stream,
3647  * as given in a saiz box. Returns array of sample_count guint8 size values,
3648  * or NULL on failure */
3649 static guint8 *
3650 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3651     GstByteReader * br, guint32 * sample_count)
3652 {
3653   guint32 flags = 0;
3654   guint8 *info_sizes;
3655   guint8 default_info_size;
3656
3657   g_return_val_if_fail (qtdemux != NULL, NULL);
3658   g_return_val_if_fail (stream != NULL, NULL);
3659   g_return_val_if_fail (br != NULL, NULL);
3660   g_return_val_if_fail (sample_count != NULL, NULL);
3661
3662   if (!gst_byte_reader_get_uint32_be (br, &flags))
3663     return NULL;
3664
3665   if (flags & 0x1) {
3666     /* aux_info_type and aux_info_type_parameter are ignored */
3667     if (!gst_byte_reader_skip (br, 8))
3668       return NULL;
3669   }
3670
3671   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3672     return NULL;
3673   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3674
3675   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3676     return NULL;
3677   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3678
3679
3680   if (default_info_size == 0) {
3681     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3682       return NULL;
3683     }
3684   } else {
3685     info_sizes = g_new (guint8, *sample_count);
3686     memset (info_sizes, default_info_size, *sample_count);
3687   }
3688
3689   return info_sizes;
3690 }
3691
3692 /* Parses the offset of sample auxiliary information contained within a stream,
3693  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3694 static gboolean
3695 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3696     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3697     guint64 * offset)
3698 {
3699   guint8 version = 0;
3700   guint32 flags = 0;
3701   guint32 aux_info_type = 0;
3702   guint32 aux_info_type_parameter = 0;
3703   guint32 entry_count;
3704   guint32 off_32;
3705   guint64 off_64;
3706   const guint8 *aux_info_type_data = NULL;
3707
3708   g_return_val_if_fail (qtdemux != NULL, FALSE);
3709   g_return_val_if_fail (stream != NULL, FALSE);
3710   g_return_val_if_fail (br != NULL, FALSE);
3711   g_return_val_if_fail (offset != NULL, FALSE);
3712
3713   if (!gst_byte_reader_get_uint8 (br, &version))
3714     return FALSE;
3715
3716   if (!gst_byte_reader_get_uint24_be (br, &flags))
3717     return FALSE;
3718
3719   if (flags & 0x1) {
3720
3721     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3722       return FALSE;
3723     aux_info_type = QT_FOURCC (aux_info_type_data);
3724
3725     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3726       return FALSE;
3727   } else if (stream->protected) {
3728     aux_info_type = stream->protection_scheme_type;
3729   } else {
3730     aux_info_type = CUR_STREAM (stream)->fourcc;
3731   }
3732
3733   if (info_type)
3734     *info_type = aux_info_type;
3735   if (info_type_parameter)
3736     *info_type_parameter = aux_info_type_parameter;
3737
3738   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3739       "aux_info_type_parameter:  %#06x",
3740       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3741
3742   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3743     return FALSE;
3744
3745   if (entry_count != 1) {
3746     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3747     return FALSE;
3748   }
3749
3750   if (version == 0) {
3751     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3752       return FALSE;
3753     *offset = (guint64) off_32;
3754   } else {
3755     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3756       return FALSE;
3757     *offset = off_64;
3758   }
3759
3760   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3761   return TRUE;
3762 }
3763
3764 static void
3765 qtdemux_gst_structure_free (GstStructure * gststructure)
3766 {
3767   if (gststructure) {
3768     gst_structure_free (gststructure);
3769   }
3770 }
3771
3772 /* Parses auxiliary information relating to samples protected using
3773  * Common Encryption (cenc); the format of this information
3774  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3775  * otherwise. */
3776 static gboolean
3777 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3778     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3779 {
3780   QtDemuxCencSampleSetInfo *ss_info = NULL;
3781   guint8 size;
3782   gint i;
3783   GPtrArray *old_crypto_info = NULL;
3784   guint old_entries = 0;
3785
3786   g_return_val_if_fail (qtdemux != NULL, FALSE);
3787   g_return_val_if_fail (stream != NULL, FALSE);
3788   g_return_val_if_fail (br != NULL, FALSE);
3789   g_return_val_if_fail (stream->protected, FALSE);
3790   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3791
3792   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3793
3794   if (ss_info->crypto_info) {
3795     old_crypto_info = ss_info->crypto_info;
3796     /* Count number of non-null entries remaining at the tail end */
3797     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3798       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3799         break;
3800       old_entries++;
3801     }
3802   }
3803
3804   ss_info->crypto_info =
3805       g_ptr_array_new_full (sample_count + old_entries,
3806       (GDestroyNotify) qtdemux_gst_structure_free);
3807
3808   /* We preserve old entries because we parse the next moof in advance
3809    * of consuming all samples from the previous moof, and otherwise
3810    * we'd discard the corresponding crypto info for the samples
3811    * from the previous fragment. */
3812   if (old_entries) {
3813     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3814         old_entries);
3815     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3816       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3817               i));
3818       g_ptr_array_index (old_crypto_info, i) = NULL;
3819     }
3820   }
3821
3822   if (old_crypto_info) {
3823     /* Everything now belongs to the new array */
3824     g_ptr_array_free (old_crypto_info, TRUE);
3825   }
3826
3827   for (i = 0; i < sample_count; ++i) {
3828     GstStructure *properties;
3829     guint16 n_subsamples = 0;
3830     guint8 *data;
3831     guint iv_size;
3832     GstBuffer *buf;
3833     gboolean could_read_iv;
3834
3835     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3836     if (properties == NULL) {
3837       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3838       return FALSE;
3839     }
3840     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3841       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3842       gst_structure_free (properties);
3843       return FALSE;
3844     }
3845     could_read_iv =
3846         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3847     if (could_read_iv) {
3848       buf = gst_buffer_new_wrapped (data, iv_size);
3849       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3850       gst_buffer_unref (buf);
3851     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3852       const GValue *constant_iv_size_value =
3853           gst_structure_get_value (properties, "constant_iv_size");
3854       const GValue *constant_iv_value =
3855           gst_structure_get_value (properties, "iv");
3856       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3857         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3858         gst_structure_free (properties);
3859         return FALSE;
3860       }
3861       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3862       gst_structure_remove_field (properties, "constant_iv_size");
3863     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3864       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3865       gst_structure_free (properties);
3866       return FALSE;
3867     }
3868     size = info_sizes[i];
3869     if (size > iv_size) {
3870       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3871           || !(n_subsamples > 0)) {
3872         gst_structure_free (properties);
3873         GST_ERROR_OBJECT (qtdemux,
3874             "failed to get subsample count for sample %u", i);
3875         return FALSE;
3876       }
3877       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3878       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3879         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3880             i);
3881         gst_structure_free (properties);
3882         return FALSE;
3883       }
3884       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3885       if (!buf) {
3886         gst_structure_free (properties);
3887         return FALSE;
3888       }
3889       gst_structure_set (properties,
3890           "subsample_count", G_TYPE_UINT, n_subsamples,
3891           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3892       gst_buffer_unref (buf);
3893     } else {
3894       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3895     }
3896     g_ptr_array_add (ss_info->crypto_info, properties);
3897   }
3898   return TRUE;
3899 }
3900
3901 /* Converts a UUID in raw byte form to a string representation, as defined in
3902  * RFC 4122. The caller takes ownership of the returned string and is
3903  * responsible for freeing it after use. */
3904 static gchar *
3905 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3906 {
3907   const guint8 *uuid = (const guint8 *) uuid_bytes;
3908
3909   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3910       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3911       uuid[0], uuid[1], uuid[2], uuid[3],
3912       uuid[4], uuid[5], uuid[6], uuid[7],
3913       uuid[8], uuid[9], uuid[10], uuid[11],
3914       uuid[12], uuid[13], uuid[14], uuid[15]);
3915 }
3916
3917 /* Parses a Protection System Specific Header box (pssh), as defined in the
3918  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3919  * information needed by a specific content protection system in order to
3920  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3921  * otherwise. */
3922 static gboolean
3923 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3924 {
3925   gchar *sysid_string;
3926   guint32 pssh_size = QT_UINT32 (node->data);
3927   GstBuffer *pssh = NULL;
3928   GstEvent *event = NULL;
3929   guint32 parent_box_type;
3930   gint i;
3931
3932   if (G_UNLIKELY (pssh_size < 32U)) {
3933     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3934     return FALSE;
3935   }
3936
3937   sysid_string =
3938       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3939
3940   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3941
3942   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3943   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3944       gst_buffer_get_size (pssh));
3945
3946   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3947
3948   /* Push an event containing the pssh box onto the queues of all streams. */
3949   event = gst_event_new_protection (sysid_string, pssh,
3950       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3951   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3952     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3953     GST_TRACE_OBJECT (qtdemux,
3954         "adding protection event for stream %s and system %s",
3955         stream->stream_id, sysid_string);
3956     g_queue_push_tail (&stream->protection_scheme_event_queue,
3957         gst_event_ref (event));
3958   }
3959   g_free (sysid_string);
3960   gst_event_unref (event);
3961   gst_buffer_unref (pssh);
3962   return TRUE;
3963 }
3964
3965 static gboolean
3966 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3967     guint64 moof_offset, QtDemuxStream * stream)
3968 {
3969   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3970   GNode *uuid_node;
3971   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3972   GNode *saiz_node, *saio_node, *pssh_node;
3973   GstByteReader saiz_data, saio_data;
3974   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3975   gint64 base_offset, running_offset;
3976   guint32 frag_num;
3977   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3978
3979   /* NOTE @stream ignored */
3980
3981   moof_node = g_node_new ((guint8 *) buffer);
3982   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3983   qtdemux_node_dump (qtdemux, moof_node);
3984
3985   /* Get fragment number from mfhd and check it's valid */
3986   mfhd_node =
3987       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3988   if (mfhd_node == NULL)
3989     goto missing_mfhd;
3990   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3991     goto fail;
3992   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3993
3994   /* unknown base_offset to start with */
3995   base_offset = running_offset = -1;
3996   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3997   while (traf_node) {
3998     guint64 decode_time = 0;
3999
4000     /* Fragment Header node */
4001     tfhd_node =
4002         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4003         &tfhd_data);
4004     if (!tfhd_node)
4005       goto missing_tfhd;
4006     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4007             &ds_size, &ds_flags, &base_offset))
4008       goto missing_tfhd;
4009
4010     /* The following code assumes at most a single set of sample auxiliary
4011      * data in the fragment (consisting of a saiz box and a corresponding saio
4012      * box); in theory, however, there could be multiple sets of sample
4013      * auxiliary data in a fragment. */
4014     saiz_node =
4015         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4016         &saiz_data);
4017     if (saiz_node) {
4018       guint32 info_type = 0;
4019       guint64 offset = 0;
4020       guint32 info_type_parameter = 0;
4021
4022       g_free (qtdemux->cenc_aux_info_sizes);
4023
4024       qtdemux->cenc_aux_info_sizes =
4025           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4026           &qtdemux->cenc_aux_sample_count);
4027       if (qtdemux->cenc_aux_info_sizes == NULL) {
4028         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4029         goto fail;
4030       }
4031       saio_node =
4032           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4033           &saio_data);
4034       if (!saio_node) {
4035         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4036         g_free (qtdemux->cenc_aux_info_sizes);
4037         qtdemux->cenc_aux_info_sizes = NULL;
4038         goto fail;
4039       }
4040
4041       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4042                   &info_type, &info_type_parameter, &offset))) {
4043         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4044         g_free (qtdemux->cenc_aux_info_sizes);
4045         qtdemux->cenc_aux_info_sizes = NULL;
4046         goto fail;
4047       }
4048       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4049         offset += (guint64) (base_offset - qtdemux->moof_offset);
4050       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4051           && info_type_parameter == 0U) {
4052         GstByteReader br;
4053         if (offset > length) {
4054           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4055           qtdemux->cenc_aux_info_offset = offset;
4056         } else {
4057           gst_byte_reader_init (&br, buffer + offset, length - offset);
4058           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4059                   qtdemux->cenc_aux_info_sizes,
4060                   qtdemux->cenc_aux_sample_count)) {
4061             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4062             g_free (qtdemux->cenc_aux_info_sizes);
4063             qtdemux->cenc_aux_info_sizes = NULL;
4064             goto fail;
4065           }
4066         }
4067       }
4068     }
4069
4070     tfdt_node =
4071         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4072         &tfdt_data);
4073     if (tfdt_node) {
4074       /* We'll use decode_time to interpolate timestamps
4075        * in case the input timestamps are missing */
4076       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4077
4078       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4079           " (%" GST_TIME_FORMAT ")", decode_time,
4080           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4081                   decode_time) : GST_CLOCK_TIME_NONE));
4082
4083       /* Discard the fragment buffer timestamp info to avoid using it.
4084        * Rely on tfdt instead as it is more accurate than the timestamp
4085        * that is fetched from a manifest/playlist and is usually
4086        * less accurate. */
4087       qtdemux->fragment_start = -1;
4088     }
4089
4090     if (G_UNLIKELY (!stream)) {
4091       /* we lost track of offset, we'll need to regain it,
4092        * but can delay complaining until later or avoid doing so altogether */
4093       base_offset = -2;
4094       goto next;
4095     }
4096     if (G_UNLIKELY (base_offset < -1))
4097       goto lost_offset;
4098
4099     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4100
4101     if (!qtdemux->pullbased) {
4102       /* Sample tables can grow enough to be problematic if the system memory
4103        * is very low (e.g. embedded devices) and the videos very long
4104        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4105        * Fortunately, we can easily discard them for each new fragment when
4106        * we know qtdemux will not receive seeks outside of the current fragment.
4107        * adaptivedemux honors this assumption.
4108        * This optimization is also useful for applications that use qtdemux as
4109        * a push-based simple demuxer, like Media Source Extensions. */
4110       gst_qtdemux_stream_flush_samples_data (stream);
4111     }
4112
4113     /* initialise moof sample data */
4114     stream->n_samples_moof = 0;
4115     stream->duration_last_moof = stream->duration_moof;
4116     stream->duration_moof = 0;
4117
4118     /* Track Run node */
4119     trun_node =
4120         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4121         &trun_data);
4122     while (trun_node) {
4123       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4124           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4125           &running_offset, decode_time, (tfdt_node != NULL));
4126       /* iterate all siblings */
4127       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4128           &trun_data);
4129     }
4130
4131     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4132     if (uuid_node) {
4133       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4134       guint32 box_length = QT_UINT32 (uuid_buffer);
4135
4136       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4137     }
4138
4139     /* if no new base_offset provided for next traf,
4140      * base is end of current traf */
4141     base_offset = running_offset;
4142     running_offset = -1;
4143
4144     if (stream->n_samples_moof && stream->duration_moof)
4145       stream->new_caps = TRUE;
4146
4147   next:
4148     /* iterate all siblings */
4149     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4150   }
4151
4152   /* parse any protection system info */
4153   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4154   while (pssh_node) {
4155     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4156     qtdemux_parse_pssh (qtdemux, pssh_node);
4157     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4158   }
4159
4160   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4161       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4162       && min_dts != 0) {
4163     /* Unless the user has explicitly requested another seek, perform an
4164      * internal seek to the time specified in the tfdt.
4165      *
4166      * This way if the user opens a file where the first tfdt is 1 hour
4167      * into the presentation, they will not have to wait 1 hour for run
4168      * time to catch up and actual playback to start. */
4169     gint i;
4170
4171     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4172         "performing an internal seek to %" GST_TIME_FORMAT,
4173         GST_TIME_ARGS (min_dts));
4174
4175     qtdemux->segment.start = min_dts;
4176     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4177
4178     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4179       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4180       stream->time_position = min_dts;
4181     }
4182
4183     /* Before this code was run a segment was already sent when the moov was
4184      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4185      * be emitted after a moov, and we can emit a second segment anyway for
4186      * special cases like this. */
4187     qtdemux->need_segment = TRUE;
4188   }
4189
4190   qtdemux->first_moof_already_parsed = TRUE;
4191
4192   g_node_destroy (moof_node);
4193   return TRUE;
4194
4195 missing_tfhd:
4196   {
4197     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4198     goto fail;
4199   }
4200 missing_mfhd:
4201   {
4202     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4203     goto fail;
4204   }
4205 lost_offset:
4206   {
4207     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4208     goto fail;
4209   }
4210 fail:
4211   {
4212     g_node_destroy (moof_node);
4213     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4214         (_("This file is corrupt and cannot be played.")), (NULL));
4215     return FALSE;
4216   }
4217 }
4218
4219 #if 0
4220 /* might be used if some day we actually use mfra & co
4221  * for random access to fragments,
4222  * but that will require quite some modifications and much less relying
4223  * on a sample array */
4224 #endif
4225
4226 static gboolean
4227 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4228 {
4229   QtDemuxStream *stream;
4230   guint32 ver_flags, track_id, len, num_entries, i;
4231   guint value_size, traf_size, trun_size, sample_size;
4232   guint64 time = 0, moof_offset = 0;
4233 #if 0
4234   GstBuffer *buf = NULL;
4235   GstFlowReturn ret;
4236 #endif
4237   GstByteReader tfra;
4238
4239   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4240
4241   if (!gst_byte_reader_skip (&tfra, 8))
4242     return FALSE;
4243
4244   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4245     return FALSE;
4246
4247   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4248       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4249       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4250     return FALSE;
4251
4252   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4253
4254   stream = qtdemux_find_stream (qtdemux, track_id);
4255   if (stream == NULL)
4256     goto unknown_trackid;
4257
4258   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4259   sample_size = (len & 3) + 1;
4260   trun_size = ((len & 12) >> 2) + 1;
4261   traf_size = ((len & 48) >> 4) + 1;
4262
4263   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4264       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4265
4266   if (num_entries == 0)
4267     goto no_samples;
4268
4269   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4270           value_size + value_size + traf_size + trun_size + sample_size))
4271     goto corrupt_file;
4272
4273   g_free (stream->ra_entries);
4274   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4275   stream->n_ra_entries = num_entries;
4276
4277   for (i = 0; i < num_entries; i++) {
4278     qt_atom_parser_get_offset (&tfra, value_size, &time);
4279     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4280     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4281     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4282     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4283
4284     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4285
4286     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4287         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4288
4289     stream->ra_entries[i].ts = time;
4290     stream->ra_entries[i].moof_offset = moof_offset;
4291
4292     /* don't want to go through the entire file and read all moofs at startup */
4293 #if 0
4294     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4295     if (ret != GST_FLOW_OK)
4296       goto corrupt_file;
4297     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4298         moof_offset, stream);
4299     gst_buffer_unref (buf);
4300 #endif
4301   }
4302
4303   check_update_duration (qtdemux, time);
4304
4305   return TRUE;
4306
4307 /* ERRORS */
4308 unknown_trackid:
4309   {
4310     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4311     return FALSE;
4312   }
4313 corrupt_file:
4314   {
4315     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4316     return FALSE;
4317   }
4318 no_samples:
4319   {
4320     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4321     return FALSE;
4322   }
4323 }
4324
4325 static gboolean
4326 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4327 {
4328   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4329   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4330   GstBuffer *mfro = NULL, *mfra = NULL;
4331   GstFlowReturn flow;
4332   gboolean ret = FALSE;
4333   GNode *mfra_node, *tfra_node;
4334   guint64 mfra_offset = 0;
4335   guint32 fourcc, mfra_size;
4336   gint64 len;
4337
4338   /* query upstream size in bytes */
4339   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4340     goto size_query_failed;
4341
4342   /* mfro box should be at the very end of the file */
4343   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4344   if (flow != GST_FLOW_OK)
4345     goto exit;
4346
4347   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4348
4349   fourcc = QT_FOURCC (mfro_map.data + 4);
4350   if (fourcc != FOURCC_mfro)
4351     goto exit;
4352
4353   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4354   if (mfro_map.size < 16)
4355     goto invalid_mfro_size;
4356
4357   mfra_size = QT_UINT32 (mfro_map.data + 12);
4358   if (mfra_size >= len)
4359     goto invalid_mfra_size;
4360
4361   mfra_offset = len - mfra_size;
4362
4363   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4364       mfra_offset, mfra_size);
4365
4366   /* now get and parse mfra box */
4367   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4368   if (flow != GST_FLOW_OK)
4369     goto broken_file;
4370
4371   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4372
4373   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4374   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4375
4376   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4377
4378   while (tfra_node) {
4379     qtdemux_parse_tfra (qtdemux, tfra_node);
4380     /* iterate all siblings */
4381     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4382   }
4383   g_node_destroy (mfra_node);
4384
4385   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4386   ret = TRUE;
4387
4388 exit:
4389
4390   if (mfro) {
4391     if (mfro_map.memory != NULL)
4392       gst_buffer_unmap (mfro, &mfro_map);
4393     gst_buffer_unref (mfro);
4394   }
4395   if (mfra) {
4396     if (mfra_map.memory != NULL)
4397       gst_buffer_unmap (mfra, &mfra_map);
4398     gst_buffer_unref (mfra);
4399   }
4400   return ret;
4401
4402 /* ERRORS */
4403 size_query_failed:
4404   {
4405     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4406     goto exit;
4407   }
4408 invalid_mfro_size:
4409   {
4410     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4411     goto exit;
4412   }
4413 invalid_mfra_size:
4414   {
4415     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4416     goto exit;
4417   }
4418 broken_file:
4419   {
4420     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4421     goto exit;
4422   }
4423 }
4424
4425 static guint64
4426 add_offset (guint64 offset, guint64 advance)
4427 {
4428   /* Avoid 64-bit overflow by clamping */
4429   if (offset > G_MAXUINT64 - advance)
4430     return G_MAXUINT64;
4431   return offset + advance;
4432 }
4433
4434 static GstFlowReturn
4435 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4436 {
4437   guint64 length = 0;
4438   guint32 fourcc = 0;
4439   GstBuffer *buf = NULL;
4440   GstFlowReturn ret = GST_FLOW_OK;
4441   guint64 cur_offset = qtdemux->offset;
4442   GstMapInfo map;
4443
4444   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4445   if (G_UNLIKELY (ret != GST_FLOW_OK))
4446     goto beach;
4447   gst_buffer_map (buf, &map, GST_MAP_READ);
4448   if (G_LIKELY (map.size >= 8))
4449     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4450   gst_buffer_unmap (buf, &map);
4451   gst_buffer_unref (buf);
4452
4453   /* maybe we already got most we needed, so only consider this eof */
4454   if (G_UNLIKELY (length == 0)) {
4455     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4456         (_("Invalid atom size.")),
4457         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4458             GST_FOURCC_ARGS (fourcc)));
4459     ret = GST_FLOW_EOS;
4460     goto beach;
4461   }
4462
4463   switch (fourcc) {
4464     case FOURCC_moof:
4465       /* record for later parsing when needed */
4466       if (!qtdemux->moof_offset) {
4467         qtdemux->moof_offset = qtdemux->offset;
4468       }
4469       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4470         /* FIXME */
4471       } else {
4472         qtdemux->offset += length;      /* skip moof and keep going */
4473       }
4474       if (qtdemux->got_moov) {
4475         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4476         ret = GST_FLOW_EOS;
4477         goto beach;
4478       }
4479       break;
4480     case FOURCC_mdat:
4481     case FOURCC_free:
4482     case FOURCC_skip:
4483     case FOURCC_wide:
4484     case FOURCC_PICT:
4485     case FOURCC_pnot:
4486     {
4487       GST_LOG_OBJECT (qtdemux,
4488           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4489           GST_FOURCC_ARGS (fourcc), cur_offset);
4490       qtdemux->offset = add_offset (qtdemux->offset, length);
4491       break;
4492     }
4493     case FOURCC_moov:
4494     {
4495       GstBuffer *moov = NULL;
4496
4497       if (qtdemux->got_moov) {
4498         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4499         qtdemux->offset = add_offset (qtdemux->offset, length);
4500         goto beach;
4501       }
4502
4503       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4504       if (ret != GST_FLOW_OK)
4505         goto beach;
4506       gst_buffer_map (moov, &map, GST_MAP_READ);
4507
4508       if (length != map.size) {
4509         /* Some files have a 'moov' atom at the end of the file which contains
4510          * a terminal 'free' atom where the body of the atom is missing.
4511          * Check for, and permit, this special case.
4512          */
4513         if (map.size >= 8) {
4514           guint8 *final_data = map.data + (map.size - 8);
4515           guint32 final_length = QT_UINT32 (final_data);
4516           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4517
4518           if (final_fourcc == FOURCC_free
4519               && map.size + final_length - 8 == length) {
4520             /* Ok, we've found that special case. Allocate a new buffer with
4521              * that free atom actually present. */
4522             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4523             gst_buffer_fill (newmoov, 0, map.data, map.size);
4524             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4525             gst_buffer_unmap (moov, &map);
4526             gst_buffer_unref (moov);
4527             moov = newmoov;
4528             gst_buffer_map (moov, &map, GST_MAP_READ);
4529           }
4530         }
4531       }
4532
4533       if (length != map.size) {
4534         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4535             (_("This file is incomplete and cannot be played.")),
4536             ("We got less than expected (received %" G_GSIZE_FORMAT
4537                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4538                 (guint) length, cur_offset));
4539         gst_buffer_unmap (moov, &map);
4540         gst_buffer_unref (moov);
4541         ret = GST_FLOW_ERROR;
4542         goto beach;
4543       }
4544       qtdemux->offset += length;
4545
4546       qtdemux_parse_moov (qtdemux, map.data, length);
4547       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4548
4549       qtdemux_parse_tree (qtdemux);
4550       if (qtdemux->moov_node_compressed) {
4551         g_node_destroy (qtdemux->moov_node_compressed);
4552         g_free (qtdemux->moov_node->data);
4553       }
4554       qtdemux->moov_node_compressed = NULL;
4555       g_node_destroy (qtdemux->moov_node);
4556       qtdemux->moov_node = NULL;
4557       gst_buffer_unmap (moov, &map);
4558       gst_buffer_unref (moov);
4559       qtdemux->got_moov = TRUE;
4560
4561       break;
4562     }
4563     case FOURCC_ftyp:
4564     {
4565       GstBuffer *ftyp = NULL;
4566
4567       /* extract major brand; might come in handy for ISO vs QT issues */
4568       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4569       if (ret != GST_FLOW_OK)
4570         goto beach;
4571       qtdemux->offset += length;
4572       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4573       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4574       gst_buffer_unmap (ftyp, &map);
4575       gst_buffer_unref (ftyp);
4576       break;
4577     }
4578     case FOURCC_uuid:
4579     {
4580       GstBuffer *uuid = NULL;
4581
4582       /* uuid are extension atoms */
4583       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4584       if (ret != GST_FLOW_OK)
4585         goto beach;
4586       qtdemux->offset += length;
4587       gst_buffer_map (uuid, &map, GST_MAP_READ);
4588       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4589       gst_buffer_unmap (uuid, &map);
4590       gst_buffer_unref (uuid);
4591       break;
4592     }
4593     case FOURCC_sidx:
4594     {
4595       GstBuffer *sidx = NULL;
4596       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4597       if (ret != GST_FLOW_OK)
4598         goto beach;
4599       qtdemux->offset += length;
4600       gst_buffer_map (sidx, &map, GST_MAP_READ);
4601       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4602       gst_buffer_unmap (sidx, &map);
4603       gst_buffer_unref (sidx);
4604       break;
4605     }
4606     default:
4607     {
4608       GstBuffer *unknown = NULL;
4609
4610       GST_LOG_OBJECT (qtdemux,
4611           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4612           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4613           cur_offset);
4614       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4615       if (ret != GST_FLOW_OK)
4616         goto beach;
4617       gst_buffer_map (unknown, &map, GST_MAP_READ);
4618       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4619       gst_buffer_unmap (unknown, &map);
4620       gst_buffer_unref (unknown);
4621       qtdemux->offset += length;
4622       break;
4623     }
4624   }
4625
4626 beach:
4627   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4628     /* digested all data, show what we have */
4629     qtdemux_prepare_streams (qtdemux);
4630     QTDEMUX_EXPOSE_LOCK (qtdemux);
4631     ret = qtdemux_expose_streams (qtdemux);
4632     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4633
4634     qtdemux->state = QTDEMUX_STATE_MOVIE;
4635     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4636         qtdemux->state);
4637     return ret;
4638   }
4639   return ret;
4640 }
4641
4642 /* Seeks to the previous keyframe of the indexed stream and
4643  * aligns other streams with respect to the keyframe timestamp
4644  * of indexed stream. Only called in case of Reverse Playback
4645  */
4646 static GstFlowReturn
4647 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4648 {
4649   guint32 seg_idx = 0, k_index = 0;
4650   guint32 ref_seg_idx, ref_k_index;
4651   GstClockTime k_pos = 0, last_stop = 0;
4652   QtDemuxSegment *seg = NULL;
4653   QtDemuxStream *ref_str = NULL;
4654   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4655   guint64 target_ts;
4656   gint i;
4657
4658   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4659    * and finally align all the other streams on that timestamp with their
4660    * respective keyframes */
4661   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4662     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4663
4664     /* No candidate yet, take the first stream */
4665     if (!ref_str) {
4666       ref_str = str;
4667       continue;
4668     }
4669
4670     /* So that stream has a segment, we prefer video streams */
4671     if (str->subtype == FOURCC_vide) {
4672       ref_str = str;
4673       break;
4674     }
4675   }
4676
4677   if (G_UNLIKELY (!ref_str)) {
4678     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4679     goto eos;
4680   }
4681
4682   if (G_UNLIKELY (!ref_str->from_sample)) {
4683     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4684     goto eos;
4685   }
4686
4687   /* So that stream has been playing from from_sample to to_sample. We will
4688    * get the timestamp of the previous sample and search for a keyframe before
4689    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4690   if (ref_str->subtype == FOURCC_vide) {
4691     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4692         ref_str->from_sample - 1, FALSE);
4693   } else {
4694     if (ref_str->from_sample >= 10)
4695       k_index = ref_str->from_sample - 10;
4696     else
4697       k_index = 0;
4698   }
4699
4700   target_ts =
4701       ref_str->samples[k_index].timestamp +
4702       ref_str->samples[k_index].pts_offset;
4703
4704   /* get current segment for that stream */
4705   seg = &ref_str->segments[ref_str->segment_index];
4706   /* Use segment start in original timescale for comparisons */
4707   seg_media_start_mov = seg->trak_media_start;
4708
4709   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4710       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4711       k_index, target_ts, seg_media_start_mov,
4712       GST_TIME_ARGS (seg->media_start));
4713
4714   /* Crawl back through segments to find the one containing this I frame */
4715   while (target_ts < seg_media_start_mov) {
4716     GST_DEBUG_OBJECT (qtdemux,
4717         "keyframe position (sample %u) is out of segment %u " " target %"
4718         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4719         ref_str->segment_index, target_ts, seg_media_start_mov);
4720
4721     if (G_UNLIKELY (!ref_str->segment_index)) {
4722       /* Reached first segment, let's consider it's EOS */
4723       goto eos;
4724     }
4725     ref_str->segment_index--;
4726     seg = &ref_str->segments[ref_str->segment_index];
4727     /* Use segment start in original timescale for comparisons */
4728     seg_media_start_mov = seg->trak_media_start;
4729   }
4730   /* Calculate time position of the keyframe and where we should stop */
4731   k_pos =
4732       QTSTREAMTIME_TO_GSTTIME (ref_str,
4733       target_ts - seg->trak_media_start) + seg->time;
4734   last_stop =
4735       QTSTREAMTIME_TO_GSTTIME (ref_str,
4736       ref_str->samples[ref_str->from_sample].timestamp -
4737       seg->trak_media_start) + seg->time;
4738
4739   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4740       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4741       k_index, GST_TIME_ARGS (k_pos));
4742
4743   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4744   qtdemux->segment.position = last_stop;
4745   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4746       GST_TIME_ARGS (last_stop));
4747
4748   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4749     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4750     goto eos;
4751   }
4752
4753   ref_seg_idx = ref_str->segment_index;
4754   ref_k_index = k_index;
4755
4756   /* Align them all on this */
4757   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4758     guint32 index = 0;
4759     GstClockTime seg_time = 0;
4760     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4761
4762     /* aligning reference stream again might lead to backing up to yet another
4763      * keyframe (due to timestamp rounding issues),
4764      * potentially putting more load on downstream; so let's try to avoid */
4765     if (str == ref_str) {
4766       seg_idx = ref_seg_idx;
4767       seg = &str->segments[seg_idx];
4768       k_index = ref_k_index;
4769       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4770           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4771     } else {
4772       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4773       GST_DEBUG_OBJECT (qtdemux,
4774           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4775           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4776
4777       /* get segment and time in the segment */
4778       seg = &str->segments[seg_idx];
4779       seg_time = k_pos - seg->time;
4780
4781       /* get the media time in the segment.
4782        * No adjustment for empty "filler" segments */
4783       if (seg->media_start != GST_CLOCK_TIME_NONE)
4784         seg_time += seg->media_start;
4785
4786       /* get the index of the sample with media time */
4787       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4788       GST_DEBUG_OBJECT (qtdemux,
4789           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4790           GST_TIME_ARGS (seg_time), index);
4791
4792       /* find previous keyframe */
4793       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4794     }
4795
4796     /* Remember until where we want to go */
4797     str->to_sample = str->from_sample - 1;
4798     /* Define our time position */
4799     target_ts =
4800         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4801     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4802     if (seg->media_start != GST_CLOCK_TIME_NONE)
4803       str->time_position -= seg->media_start;
4804
4805     /* Now seek back in time */
4806     gst_qtdemux_move_stream (qtdemux, str, k_index);
4807     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4808         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4809         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4810   }
4811
4812   return GST_FLOW_OK;
4813
4814 eos:
4815   return GST_FLOW_EOS;
4816 }
4817
4818 /*
4819  * Gets the current qt segment start, stop and position for the
4820  * given time offset. This is used in update_segment()
4821  */
4822 static void
4823 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4824     QtDemuxStream * stream, GstClockTime offset,
4825     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4826 {
4827   GstClockTime seg_time;
4828   GstClockTime start, stop, time;
4829   QtDemuxSegment *segment;
4830
4831   segment = &stream->segments[stream->segment_index];
4832
4833   /* get time in this segment */
4834   seg_time = (offset - segment->time) * segment->rate;
4835
4836   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4837       GST_TIME_ARGS (seg_time));
4838
4839   if (G_UNLIKELY (seg_time > segment->duration)) {
4840     GST_LOG_OBJECT (stream->pad,
4841         "seg_time > segment->duration %" GST_TIME_FORMAT,
4842         GST_TIME_ARGS (segment->duration));
4843     seg_time = segment->duration;
4844   }
4845
4846   /* qtdemux->segment.stop is in outside-time-realm, whereas
4847    * segment->media_stop is in track-time-realm.
4848    *
4849    * In order to compare the two, we need to bring segment.stop
4850    * into the track-time-realm
4851    *
4852    * FIXME - does this comment still hold? Don't see any conversion here */
4853
4854   stop = qtdemux->segment.stop;
4855   if (stop == GST_CLOCK_TIME_NONE)
4856     stop = qtdemux->segment.duration;
4857   if (stop == GST_CLOCK_TIME_NONE)
4858     stop = segment->media_stop;
4859   else
4860     stop =
4861         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4862
4863   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4864     start = segment->time + seg_time;
4865     time = offset;
4866     stop = start - seg_time + segment->duration;
4867   } else if (qtdemux->segment.rate >= 0) {
4868     start = MIN (segment->media_start + seg_time, stop);
4869     time = offset;
4870   } else {
4871     if (segment->media_start >= qtdemux->segment.start) {
4872       time = segment->time;
4873     } else {
4874       time = segment->time + (qtdemux->segment.start - segment->media_start);
4875     }
4876
4877     start = MAX (segment->media_start, qtdemux->segment.start);
4878     stop = MIN (segment->media_start + seg_time, stop);
4879   }
4880
4881   *_start = start;
4882   *_stop = stop;
4883   *_time = time;
4884 }
4885
4886 /*
4887  * Updates the qt segment used for the stream and pushes a new segment event
4888  * downstream on this stream's pad.
4889  */
4890 static gboolean
4891 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4892     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4893     GstClockTime * _stop)
4894 {
4895   QtDemuxSegment *segment;
4896   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4897   gdouble rate;
4898   GstEvent *event;
4899
4900   /* update the current segment */
4901   stream->segment_index = seg_idx;
4902
4903   /* get the segment */
4904   segment = &stream->segments[seg_idx];
4905
4906   if (G_UNLIKELY (offset < segment->time)) {
4907     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4908         GST_TIME_ARGS (segment->time));
4909     return FALSE;
4910   }
4911
4912   /* segment lies beyond total indicated duration */
4913   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4914           segment->time > qtdemux->segment.duration)) {
4915     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4916         " < segment->time %" GST_TIME_FORMAT,
4917         GST_TIME_ARGS (qtdemux->segment.duration),
4918         GST_TIME_ARGS (segment->time));
4919     return FALSE;
4920   }
4921
4922   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4923       &start, &stop, &time);
4924
4925   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4926       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4927       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4928
4929   /* combine global rate with that of the segment */
4930   rate = segment->rate * qtdemux->segment.rate;
4931
4932   /* Copy flags from main segment */
4933   stream->segment.flags = qtdemux->segment.flags;
4934
4935   /* update the segment values used for clipping */
4936   stream->segment.offset = qtdemux->segment.offset;
4937   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4938   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4939   stream->segment.rate = rate;
4940   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4941       stream->cslg_shift);
4942   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4943       stream->cslg_shift);
4944   stream->segment.time = time;
4945   stream->segment.position = stream->segment.start;
4946
4947   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4948       &stream->segment);
4949
4950   /* now prepare and send the segment */
4951   if (stream->pad) {
4952     event = gst_event_new_segment (&stream->segment);
4953     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4954       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4955     }
4956     gst_pad_push_event (stream->pad, event);
4957     /* assume we can send more data now */
4958     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4959     /* clear to send tags on this pad now */
4960     gst_qtdemux_push_tags (qtdemux, stream);
4961   }
4962
4963   if (_start)
4964     *_start = start;
4965   if (_stop)
4966     *_stop = stop;
4967
4968   return TRUE;
4969 }
4970
4971 /* activate the given segment number @seg_idx of @stream at time @offset.
4972  * @offset is an absolute global position over all the segments.
4973  *
4974  * This will push out a NEWSEGMENT event with the right values and
4975  * position the stream index to the first decodable sample before
4976  * @offset.
4977  */
4978 static gboolean
4979 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4980     guint32 seg_idx, GstClockTime offset)
4981 {
4982   QtDemuxSegment *segment;
4983   guint32 index, kf_index;
4984   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4985
4986   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4987       seg_idx, GST_TIME_ARGS (offset));
4988
4989   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4990           &start, &stop))
4991     return FALSE;
4992
4993   segment = &stream->segments[stream->segment_index];
4994
4995   /* in the fragmented case, we pick a fragment that starts before our
4996    * desired position and rely on downstream to wait for a keyframe
4997    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4998    * tfra entries tells us which trun/sample the key unit is in, but we don't
4999    * make use of this additional information at the moment) */
5000   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5001     stream->to_sample = G_MAXUINT32;
5002     return TRUE;
5003   } else {
5004     /* well, it will be taken care of below */
5005     qtdemux->fragmented_seek_pending = FALSE;
5006     /* FIXME ideally the do_fragmented_seek can be done right here,
5007      * rather than at loop level
5008      * (which might even allow handling edit lists in a fragmented file) */
5009   }
5010
5011   /* We don't need to look for a sample in push-based */
5012   if (!qtdemux->pullbased)
5013     return TRUE;
5014
5015   /* and move to the keyframe before the indicated media time of the
5016    * segment */
5017   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5018     if (qtdemux->segment.rate >= 0) {
5019       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5020       stream->to_sample = G_MAXUINT32;
5021       GST_DEBUG_OBJECT (stream->pad,
5022           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5023           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5024           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5025     } else {
5026       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5027       stream->to_sample = index;
5028       GST_DEBUG_OBJECT (stream->pad,
5029           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5030           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5031           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5032     }
5033   } else {
5034     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5035         "this is an empty segment");
5036     return TRUE;
5037   }
5038
5039   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5040    * encountered an error and printed a message so we return appropriately */
5041   if (index == -1)
5042     return FALSE;
5043
5044   /* we're at the right spot */
5045   if (index == stream->sample_index) {
5046     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5047     return TRUE;
5048   }
5049
5050   /* find keyframe of the target index */
5051   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5052
5053   /* go back two frames to provide lead-in for non-raw audio decoders */
5054   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5055     guint32 lead_in = 2;
5056     guint32 old_index = kf_index;
5057     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5058
5059     if (gst_structure_has_name (s, "audio/mpeg")) {
5060       gint mpegversion;
5061       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5062           && mpegversion == 1) {
5063         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5064         lead_in = 30;
5065       }
5066     }
5067
5068     kf_index = MAX (kf_index, lead_in) - lead_in;
5069     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5070       GST_DEBUG_OBJECT (stream->pad,
5071           "Moving backwards %u frames to ensure sufficient sound lead-in",
5072           old_index - kf_index);
5073     } else {
5074       kf_index = old_index;
5075     }
5076   }
5077
5078   /* if we move forwards, we don't have to go back to the previous
5079    * keyframe since we already sent that. We can also just jump to
5080    * the keyframe right before the target index if there is one. */
5081   if (index > stream->sample_index) {
5082     /* moving forwards check if we move past a keyframe */
5083     if (kf_index > stream->sample_index) {
5084       GST_DEBUG_OBJECT (stream->pad,
5085           "moving forwards to keyframe at %u "
5086           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5087           kf_index,
5088           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5089           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5090       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5091     } else {
5092       GST_DEBUG_OBJECT (stream->pad,
5093           "moving forwards, keyframe at %u "
5094           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5095           kf_index,
5096           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5097           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5098     }
5099   } else {
5100     GST_DEBUG_OBJECT (stream->pad,
5101         "moving backwards to %sframe at %u "
5102         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5103         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5104         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5105         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5106     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5107   }
5108
5109   return TRUE;
5110 }
5111
5112 /* prepare to get the current sample of @stream, getting essential values.
5113  *
5114  * This function will also prepare and send the segment when needed.
5115  *
5116  * Return FALSE if the stream is EOS.
5117  *
5118  * PULL-BASED
5119  */
5120 static gboolean
5121 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5122     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5123     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5124     gboolean * keyframe)
5125 {
5126   QtDemuxSample *sample;
5127   GstClockTime time_position;
5128   guint32 seg_idx;
5129
5130   g_return_val_if_fail (stream != NULL, FALSE);
5131
5132   time_position = stream->time_position;
5133   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5134     goto eos;
5135
5136   seg_idx = stream->segment_index;
5137   if (G_UNLIKELY (seg_idx == -1)) {
5138     /* find segment corresponding to time_position if we are looking
5139      * for a segment. */
5140     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5141   }
5142
5143   /* different segment, activate it, sample_index will be set. */
5144   if (G_UNLIKELY (stream->segment_index != seg_idx))
5145     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5146
5147   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5148               segments[stream->segment_index]))) {
5149     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5150
5151     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5152         " prepare empty sample");
5153
5154     *empty = TRUE;
5155     *pts = *dts = time_position;
5156     *duration = seg->duration - (time_position - seg->time);
5157
5158     return TRUE;
5159   }
5160
5161   *empty = FALSE;
5162
5163   if (stream->sample_index == -1)
5164     stream->sample_index = 0;
5165
5166   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5167       stream->sample_index, stream->n_samples);
5168
5169   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5170     if (!qtdemux->fragmented)
5171       goto eos;
5172
5173     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5174     do {
5175       GstFlowReturn flow;
5176
5177       GST_OBJECT_LOCK (qtdemux);
5178       flow = qtdemux_add_fragmented_samples (qtdemux);
5179       GST_OBJECT_UNLOCK (qtdemux);
5180
5181       if (flow != GST_FLOW_OK)
5182         goto eos;
5183     }
5184     while (stream->sample_index >= stream->n_samples);
5185   }
5186
5187   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5188     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5189         stream->sample_index);
5190     return FALSE;
5191   }
5192
5193   /* now get the info for the sample we're at */
5194   sample = &stream->samples[stream->sample_index];
5195
5196   *dts = QTSAMPLE_DTS (stream, sample);
5197   *pts = QTSAMPLE_PTS (stream, sample);
5198   *offset = sample->offset;
5199   *size = sample->size;
5200   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5201   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5202
5203   return TRUE;
5204
5205   /* special cases */
5206 eos:
5207   {
5208     stream->time_position = GST_CLOCK_TIME_NONE;
5209     return FALSE;
5210   }
5211 }
5212
5213 /* move to the next sample in @stream.
5214  *
5215  * Moves to the next segment when needed.
5216  */
5217 static void
5218 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5219 {
5220   QtDemuxSample *sample;
5221   QtDemuxSegment *segment;
5222
5223   /* get current segment */
5224   segment = &stream->segments[stream->segment_index];
5225
5226   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5227     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5228     goto next_segment;
5229   }
5230
5231   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5232     /* Mark the stream as EOS */
5233     GST_DEBUG_OBJECT (qtdemux,
5234         "reached max allowed sample %u, mark EOS", stream->to_sample);
5235     stream->time_position = GST_CLOCK_TIME_NONE;
5236     return;
5237   }
5238
5239   /* move to next sample */
5240   stream->sample_index++;
5241   stream->offset_in_sample = 0;
5242
5243   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5244       stream->n_samples);
5245
5246   /* reached the last sample, we need the next segment */
5247   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5248     goto next_segment;
5249
5250   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5251     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5252         stream->sample_index);
5253     return;
5254   }
5255
5256   /* get next sample */
5257   sample = &stream->samples[stream->sample_index];
5258
5259   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5260       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5261       GST_TIME_ARGS (segment->media_stop));
5262
5263   /* see if we are past the segment */
5264   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5265     goto next_segment;
5266
5267   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5268     /* inside the segment, update time_position, looks very familiar to
5269      * GStreamer segments, doesn't it? */
5270     stream->time_position =
5271         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5272   } else {
5273     /* not yet in segment, time does not yet increment. This means
5274      * that we are still prerolling keyframes to the decoder so it can
5275      * decode the first sample of the segment. */
5276     stream->time_position = segment->time;
5277   }
5278   return;
5279
5280   /* move to the next segment */
5281 next_segment:
5282   {
5283     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5284
5285     if (stream->segment_index == stream->n_segments - 1) {
5286       /* are we at the end of the last segment, we're EOS */
5287       stream->time_position = GST_CLOCK_TIME_NONE;
5288     } else {
5289       /* else we're only at the end of the current segment */
5290       stream->time_position = segment->stop_time;
5291     }
5292     /* make sure we select a new segment */
5293
5294     /* accumulate previous segments */
5295     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5296       stream->accumulated_base +=
5297           (stream->segment.stop -
5298           stream->segment.start) / ABS (stream->segment.rate);
5299
5300     stream->segment_index = -1;
5301   }
5302 }
5303
5304 static void
5305 gst_qtdemux_sync_streams (GstQTDemux * demux)
5306 {
5307   gint i;
5308
5309   if (QTDEMUX_N_STREAMS (demux) <= 1)
5310     return;
5311
5312   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5313     QtDemuxStream *stream;
5314     GstClockTime end_time;
5315
5316     stream = QTDEMUX_NTH_STREAM (demux, i);
5317
5318     if (!stream->pad)
5319       continue;
5320
5321     /* TODO advance time on subtitle streams here, if any some day */
5322
5323     /* some clips/trailers may have unbalanced streams at the end,
5324      * so send EOS on shorter stream to prevent stalling others */
5325
5326     /* do not mess with EOS if SEGMENT seeking */
5327     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5328       continue;
5329
5330     if (demux->pullbased) {
5331       /* loop mode is sample time based */
5332       if (!STREAM_IS_EOS (stream))
5333         continue;
5334     } else {
5335       /* push mode is byte position based */
5336       if (stream->n_samples &&
5337           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5338         continue;
5339     }
5340
5341     if (stream->sent_eos)
5342       continue;
5343
5344     /* only act if some gap */
5345     end_time = stream->segments[stream->n_segments - 1].stop_time;
5346     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5347         ", stream end: %" GST_TIME_FORMAT,
5348         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5349     if (GST_CLOCK_TIME_IS_VALID (end_time)
5350         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5351       GstEvent *event;
5352
5353       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5354           GST_PAD_NAME (stream->pad));
5355       stream->sent_eos = TRUE;
5356       event = gst_event_new_eos ();
5357       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5358         gst_event_set_seqnum (event, demux->segment_seqnum);
5359       gst_pad_push_event (stream->pad, event);
5360     }
5361   }
5362 }
5363
5364 /* EOS and NOT_LINKED need to be combined. This means that we return:
5365  *
5366  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5367  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5368  */
5369 static GstFlowReturn
5370 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5371     GstFlowReturn ret)
5372 {
5373   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5374
5375   if (stream->pad)
5376     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5377         ret);
5378   else
5379     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5380
5381   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5382   return ret;
5383 }
5384
5385 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5386  * completely clipped
5387  *
5388  * Should be used only with raw buffers */
5389 static GstBuffer *
5390 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5391     GstBuffer * buf)
5392 {
5393   guint64 start, stop, cstart, cstop, diff;
5394   GstClockTime pts, duration;
5395   gsize size, osize;
5396   gint num_rate, denom_rate;
5397   gint frame_size;
5398   gboolean clip_data;
5399   guint offset;
5400
5401   osize = size = gst_buffer_get_size (buf);
5402   offset = 0;
5403
5404   /* depending on the type, setup the clip parameters */
5405   if (stream->subtype == FOURCC_soun) {
5406     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5407     num_rate = GST_SECOND;
5408     denom_rate = (gint) CUR_STREAM (stream)->rate;
5409     clip_data = TRUE;
5410   } else if (stream->subtype == FOURCC_vide) {
5411     frame_size = size;
5412     num_rate = CUR_STREAM (stream)->fps_n;
5413     denom_rate = CUR_STREAM (stream)->fps_d;
5414     clip_data = FALSE;
5415   } else
5416     goto wrong_type;
5417
5418   if (frame_size <= 0)
5419     goto bad_frame_size;
5420
5421   /* we can only clip if we have a valid pts */
5422   pts = GST_BUFFER_PTS (buf);
5423   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5424     goto no_pts;
5425
5426   duration = GST_BUFFER_DURATION (buf);
5427
5428   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5429     duration =
5430         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5431   }
5432
5433   start = pts;
5434   stop = start + duration;
5435
5436   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5437               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5438     goto clipped;
5439
5440   /* see if some clipping happened */
5441   diff = cstart - start;
5442   if (diff > 0) {
5443     pts += diff;
5444     duration -= diff;
5445
5446     if (clip_data) {
5447       /* bring clipped time to samples and to bytes */
5448       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5449       diff *= frame_size;
5450
5451       GST_DEBUG_OBJECT (qtdemux,
5452           "clipping start to %" GST_TIME_FORMAT " %"
5453           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5454
5455       offset = diff;
5456       size -= diff;
5457     }
5458   }
5459   diff = stop - cstop;
5460   if (diff > 0) {
5461     duration -= diff;
5462
5463     if (clip_data) {
5464       /* bring clipped time to samples and then to bytes */
5465       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5466       diff *= frame_size;
5467       GST_DEBUG_OBJECT (qtdemux,
5468           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5469           " bytes", GST_TIME_ARGS (cstop), diff);
5470       size -= diff;
5471     }
5472   }
5473
5474   if (offset != 0 || size != osize)
5475     gst_buffer_resize (buf, offset, size);
5476
5477   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5478   GST_BUFFER_PTS (buf) = pts;
5479   GST_BUFFER_DURATION (buf) = duration;
5480
5481   return buf;
5482
5483   /* dropped buffer */
5484 wrong_type:
5485   {
5486     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5487     return buf;
5488   }
5489 bad_frame_size:
5490   {
5491     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5492     return buf;
5493   }
5494 no_pts:
5495   {
5496     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5497     return buf;
5498   }
5499 clipped:
5500   {
5501     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5502     gst_buffer_unref (buf);
5503     return NULL;
5504   }
5505 }
5506
5507 static GstBuffer *
5508 gst_qtdemux_align_buffer (GstQTDemux * demux,
5509     GstBuffer * buffer, gsize alignment)
5510 {
5511   GstMapInfo map;
5512
5513   gst_buffer_map (buffer, &map, GST_MAP_READ);
5514
5515   if (map.size < sizeof (guintptr)) {
5516     gst_buffer_unmap (buffer, &map);
5517     return buffer;
5518   }
5519
5520   if (((guintptr) map.data) & (alignment - 1)) {
5521     GstBuffer *new_buffer;
5522     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5523
5524     new_buffer = gst_buffer_new_allocate (NULL,
5525         gst_buffer_get_size (buffer), &params);
5526
5527     /* Copy data "by hand", so ensure alignment is kept: */
5528     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5529
5530     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5531     GST_DEBUG_OBJECT (demux,
5532         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5533         alignment);
5534
5535     gst_buffer_unmap (buffer, &map);
5536     gst_buffer_unref (buffer);
5537
5538     return new_buffer;
5539   }
5540
5541   gst_buffer_unmap (buffer, &map);
5542   return buffer;
5543 }
5544
5545 static guint8 *
5546 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5547     gsize * res)
5548 {
5549   guint8 *storage;
5550   gsize i;
5551
5552   /* We are converting from pairs to triplets */
5553   *res = ccpair_size / 2 * 3;
5554   storage = g_malloc (*res);
5555   for (i = 0; i * 2 < ccpair_size; i += 1) {
5556     /* FIXME: Use line offset 0 as we simply can't know here */
5557     if (field == 1)
5558       storage[i * 3] = 0x80 | 0x00;
5559     else
5560       storage[i * 3] = 0x00 | 0x00;
5561     storage[i * 3 + 1] = ccpair[i * 2];
5562     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5563   }
5564
5565   return storage;
5566 }
5567
5568 static guint8 *
5569 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5570     gsize * cclen)
5571 {
5572   guint8 *res = NULL;
5573   guint32 atom_length, fourcc;
5574   QtDemuxStreamStsdEntry *stsd_entry;
5575
5576   GST_MEMDUMP ("caption atom", data, size);
5577
5578   /* There might be multiple atoms */
5579
5580   *cclen = 0;
5581   if (size < 8)
5582     goto invalid_cdat;
5583   atom_length = QT_UINT32 (data);
5584   fourcc = QT_FOURCC (data + 4);
5585   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5586     goto invalid_cdat;
5587
5588   GST_DEBUG_OBJECT (stream->pad, "here");
5589
5590   /* Check if we have something compatible */
5591   stsd_entry = CUR_STREAM (stream);
5592   switch (stsd_entry->fourcc) {
5593     case FOURCC_c608:{
5594       guint8 *cdat = NULL, *cdt2 = NULL;
5595       gsize cdat_size = 0, cdt2_size = 0;
5596       /* Should be cdat or cdt2 */
5597       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5598         GST_WARNING_OBJECT (stream->pad,
5599             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5600             GST_FOURCC_ARGS (fourcc));
5601         goto invalid_cdat;
5602       }
5603
5604       /* Convert to S334-1 Annex A byte triplet */
5605       if (fourcc == FOURCC_cdat)
5606         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5607       else
5608         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5609       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5610           size, atom_length);
5611
5612       /* Check for another atom ? */
5613       if (size > atom_length + 8) {
5614         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5615         if (size >= atom_length + new_atom_length) {
5616           fourcc = QT_FOURCC (data + atom_length + 4);
5617           if (fourcc == FOURCC_cdat) {
5618             if (cdat == NULL)
5619               cdat =
5620                   convert_to_s334_1a (data + atom_length + 8,
5621                   new_atom_length - 8, 1, &cdat_size);
5622             else
5623               GST_WARNING_OBJECT (stream->pad,
5624                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5625           } else {
5626             if (cdt2 == NULL)
5627               cdt2 =
5628                   convert_to_s334_1a (data + atom_length + 8,
5629                   new_atom_length - 8, 2, &cdt2_size);
5630             else
5631               GST_WARNING_OBJECT (stream->pad,
5632                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5633           }
5634         }
5635       }
5636
5637       *cclen = cdat_size + cdt2_size;
5638       res = g_malloc (*cclen);
5639       if (cdat_size)
5640         memcpy (res, cdat, cdat_size);
5641       if (cdt2_size)
5642         memcpy (res + cdat_size, cdt2, cdt2_size);
5643       g_free (cdat);
5644       g_free (cdt2);
5645     }
5646       break;
5647     case FOURCC_c708:
5648       if (fourcc != FOURCC_ccdp) {
5649         GST_WARNING_OBJECT (stream->pad,
5650             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5651             GST_FOURCC_ARGS (fourcc));
5652         goto invalid_cdat;
5653       }
5654       *cclen = atom_length - 8;
5655       res = g_memdup2 (data + 8, *cclen);
5656       break;
5657     default:
5658       /* Keep this here in case other closed caption formats are added */
5659       g_assert_not_reached ();
5660       break;
5661   }
5662
5663   GST_MEMDUMP ("Output", res, *cclen);
5664   return res;
5665
5666   /* Errors */
5667 invalid_cdat:
5668   GST_WARNING ("[cdat] atom is too small or invalid");
5669   return NULL;
5670 }
5671
5672 /* the input buffer metadata must be writable,
5673  * but time/duration etc not yet set and need not be preserved */
5674 static GstBuffer *
5675 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5676     GstBuffer * buf)
5677 {
5678   GstMapInfo map;
5679   guint nsize = 0;
5680   gchar *str;
5681
5682   /* not many cases for now */
5683   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5684     /* send a one time dvd clut event */
5685     if (stream->pending_event && stream->pad)
5686       gst_pad_push_event (stream->pad, stream->pending_event);
5687     stream->pending_event = NULL;
5688   }
5689
5690   if (G_UNLIKELY (stream->subtype != FOURCC_text
5691           && stream->subtype != FOURCC_sbtl &&
5692           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5693     return buf;
5694   }
5695
5696   gst_buffer_map (buf, &map, GST_MAP_READ);
5697
5698   /* empty buffer is sent to terminate previous subtitle */
5699   if (map.size <= 2) {
5700     gst_buffer_unmap (buf, &map);
5701     gst_buffer_unref (buf);
5702     return NULL;
5703   }
5704   if (stream->subtype == FOURCC_subp) {
5705     /* That's all the processing needed for subpictures */
5706     gst_buffer_unmap (buf, &map);
5707     return buf;
5708   }
5709
5710   if (stream->subtype == FOURCC_clcp) {
5711     guint8 *cc;
5712     gsize cclen = 0;
5713     /* For closed caption, we need to extract the information from the
5714      * [cdat],[cdt2] or [ccdp] atom */
5715     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5716     gst_buffer_unmap (buf, &map);
5717     gst_buffer_unref (buf);
5718     if (cc) {
5719       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5720     } else {
5721       /* Conversion failed or there's nothing */
5722       buf = NULL;
5723     }
5724     return buf;
5725   }
5726
5727   nsize = GST_READ_UINT16_BE (map.data);
5728   nsize = MIN (nsize, map.size - 2);
5729
5730   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5731       nsize, map.size);
5732
5733   /* takes care of UTF-8 validation or UTF-16 recognition,
5734    * no other encoding expected */
5735   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5736   gst_buffer_unmap (buf, &map);
5737   if (str) {
5738     gst_buffer_unref (buf);
5739     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5740   } else {
5741     /* this should not really happen unless the subtitle is corrupted */
5742     gst_buffer_unref (buf);
5743     buf = NULL;
5744   }
5745
5746   /* FIXME ? convert optional subsequent style info to markup */
5747
5748   return buf;
5749 }
5750
5751 static GstFlowReturn
5752 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5753     GstBuffer * buf)
5754 {
5755   GstFlowReturn ret = GST_FLOW_OK;
5756   GstClockTime pts, duration;
5757
5758   if (stream->need_clip)
5759     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5760
5761   if (G_UNLIKELY (buf == NULL))
5762     goto exit;
5763
5764   if (G_UNLIKELY (stream->discont)) {
5765     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5766     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5767     stream->discont = FALSE;
5768   } else {
5769     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5770   }
5771
5772   GST_LOG_OBJECT (qtdemux,
5773       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5774       ", duration %" GST_TIME_FORMAT " on pad %s",
5775       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5776       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5777       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5778
5779   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5780     GstStructure *crypto_info;
5781     QtDemuxAavdEncryptionInfo *info =
5782         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5783
5784     crypto_info = gst_structure_copy (info->default_properties);
5785     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5786       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5787   }
5788
5789   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5790           || stream->protection_scheme_type == FOURCC_cbcs)) {
5791     GstStructure *crypto_info;
5792     QtDemuxCencSampleSetInfo *info =
5793         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5794     gint index;
5795     GstEvent *event;
5796
5797     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5798       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5799           GST_PTR_FORMAT, event);
5800       gst_pad_push_event (stream->pad, event);
5801     }
5802
5803     if (info->crypto_info == NULL) {
5804       if (stream->protection_scheme_type == FOURCC_cbcs) {
5805         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5806         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5807           GST_ERROR_OBJECT (qtdemux,
5808               "failed to attach cbcs metadata to buffer");
5809           qtdemux_gst_structure_free (crypto_info);
5810         } else {
5811           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5812         }
5813       } else {
5814         GST_DEBUG_OBJECT (qtdemux,
5815             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5816       }
5817     } else {
5818       /* The end of the crypto_info array matches our n_samples position,
5819        * so count backward from there */
5820       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5821       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5822         /* steal structure from array */
5823         crypto_info = g_ptr_array_index (info->crypto_info, index);
5824         g_ptr_array_index (info->crypto_info, index) = NULL;
5825         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5826             info->crypto_info->len);
5827         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5828           GST_ERROR_OBJECT (qtdemux,
5829               "failed to attach cenc metadata to buffer");
5830       } else {
5831         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5832             index, stream->sample_index);
5833       }
5834     }
5835   }
5836
5837   if (stream->alignment > 1)
5838     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5839
5840   pts = GST_BUFFER_PTS (buf);
5841   duration = GST_BUFFER_DURATION (buf);
5842
5843   ret = gst_pad_push (stream->pad, buf);
5844
5845   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5846     /* mark position in stream, we'll need this to know when to send GAP event */
5847     stream->segment.position = pts + duration;
5848   }
5849
5850 exit:
5851
5852   return ret;
5853 }
5854
5855 static GstFlowReturn
5856 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5857     GstBuffer * buf)
5858 {
5859   GstFlowReturn ret = GST_FLOW_OK;
5860
5861   if (stream->subtype == FOURCC_clcp
5862       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5863     GstMapInfo map;
5864     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5865     guint n_triplets, i;
5866     guint field1_off = 0, field2_off = 0;
5867
5868     /* We have to split CEA608 buffers so that each outgoing buffer contains
5869      * one byte pair per field according to the framerate of the video track.
5870      *
5871      * If there is only a single byte pair per field we don't have to do
5872      * anything
5873      */
5874
5875     gst_buffer_map (buf, &map, GST_MAP_READ);
5876
5877     n_triplets = map.size / 3;
5878     for (i = 0; i < n_triplets; i++) {
5879       if (map.data[3 * i] & 0x80)
5880         n_field1++;
5881       else
5882         n_field2++;
5883     }
5884
5885     g_assert (n_field1 || n_field2);
5886
5887     /* If there's more than 1 frame we have to split, otherwise we can just
5888      * pass through */
5889     if (n_field1 > 1 || n_field2 > 1) {
5890       n_output_buffers =
5891           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5892           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5893
5894       for (i = 0; i < n_output_buffers; i++) {
5895         GstBuffer *outbuf =
5896             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5897         GstMapInfo outmap;
5898         guint8 *outptr;
5899
5900         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5901         outptr = outmap.data;
5902
5903         if (n_field1) {
5904           gboolean found = FALSE;
5905
5906           while (map.data + field1_off < map.data + map.size) {
5907             if (map.data[field1_off] & 0x80) {
5908               memcpy (outptr, &map.data[field1_off], 3);
5909               field1_off += 3;
5910               found = TRUE;
5911               break;
5912             }
5913             field1_off += 3;
5914           }
5915
5916           if (!found) {
5917             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5918
5919             memcpy (outptr, empty, 3);
5920           }
5921
5922           outptr += 3;
5923         }
5924
5925         if (n_field2) {
5926           gboolean found = FALSE;
5927
5928           while (map.data + field2_off < map.data + map.size) {
5929             if ((map.data[field2_off] & 0x80) == 0) {
5930               memcpy (outptr, &map.data[field2_off], 3);
5931               field2_off += 3;
5932               found = TRUE;
5933               break;
5934             }
5935             field2_off += 3;
5936           }
5937
5938           if (!found) {
5939             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5940
5941             memcpy (outptr, empty, 3);
5942           }
5943
5944           outptr += 3;
5945         }
5946
5947         gst_buffer_unmap (outbuf, &outmap);
5948
5949         GST_BUFFER_PTS (outbuf) =
5950             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5951             GST_SECOND * CUR_STREAM (stream)->fps_d,
5952             CUR_STREAM (stream)->fps_n);
5953         GST_BUFFER_DURATION (outbuf) =
5954             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5955             CUR_STREAM (stream)->fps_n);
5956         GST_BUFFER_OFFSET (outbuf) = -1;
5957         GST_BUFFER_OFFSET_END (outbuf) = -1;
5958
5959         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
5960
5961         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
5962           break;
5963       }
5964       gst_buffer_unmap (buf, &map);
5965       gst_buffer_unref (buf);
5966     } else {
5967       gst_buffer_unmap (buf, &map);
5968       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5969     }
5970   } else {
5971     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5972   }
5973
5974   return ret;
5975 }
5976
5977 /* Sets a buffer's attributes properly and pushes it downstream.
5978  * Also checks for additional actions and custom processing that may
5979  * need to be done first.
5980  */
5981 static GstFlowReturn
5982 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5983     QtDemuxStream * stream, GstBuffer * buf,
5984     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5985     gboolean keyframe, GstClockTime position, guint64 byte_position)
5986 {
5987   GstFlowReturn ret = GST_FLOW_OK;
5988
5989   /* offset the timestamps according to the edit list */
5990
5991   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5992     gchar *url;
5993     GstMapInfo map;
5994
5995     gst_buffer_map (buf, &map, GST_MAP_READ);
5996     url = g_strndup ((gchar *) map.data, map.size);
5997     gst_buffer_unmap (buf, &map);
5998     if (url != NULL && strlen (url) != 0) {
5999       /* we have RTSP redirect now */
6000       g_free (qtdemux->redirect_location);
6001       qtdemux->redirect_location = g_strdup (url);
6002       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6003           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6004               gst_structure_new ("redirect",
6005                   "new-location", G_TYPE_STRING, url, NULL)));
6006     } else {
6007       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6008           "posting");
6009     }
6010     g_free (url);
6011   }
6012
6013   /* position reporting */
6014   if (qtdemux->segment.rate >= 0) {
6015     qtdemux->segment.position = position;
6016     gst_qtdemux_sync_streams (qtdemux);
6017   }
6018
6019   if (G_UNLIKELY (!stream->pad)) {
6020     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6021     gst_buffer_unref (buf);
6022     goto exit;
6023   }
6024
6025   /* send out pending buffers */
6026   while (stream->buffers) {
6027     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6028
6029     if (G_UNLIKELY (stream->discont)) {
6030       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6031       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6032       stream->discont = FALSE;
6033     } else {
6034       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6035     }
6036
6037     if (stream->alignment > 1)
6038       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6039     gst_pad_push (stream->pad, buffer);
6040
6041     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6042   }
6043
6044   /* we're going to modify the metadata */
6045   buf = gst_buffer_make_writable (buf);
6046
6047   if (G_UNLIKELY (stream->need_process))
6048     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
6049
6050   if (!buf) {
6051     goto exit;
6052   }
6053
6054   GST_BUFFER_DTS (buf) = dts;
6055   GST_BUFFER_PTS (buf) = pts;
6056   GST_BUFFER_DURATION (buf) = duration;
6057   GST_BUFFER_OFFSET (buf) = -1;
6058   GST_BUFFER_OFFSET_END (buf) = -1;
6059
6060   if (!keyframe) {
6061     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6062     stream->on_keyframe = FALSE;
6063   } else {
6064     stream->on_keyframe = TRUE;
6065   }
6066
6067   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6068     gst_buffer_append_memory (buf,
6069         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6070
6071   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6072     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6073   }
6074 #if 0
6075   if (G_UNLIKELY (qtdemux->element_index)) {
6076     GstClockTime stream_time;
6077
6078     stream_time =
6079         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6080         timestamp);
6081     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6082       GST_LOG_OBJECT (qtdemux,
6083           "adding association %" GST_TIME_FORMAT "-> %"
6084           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6085       gst_index_add_association (qtdemux->element_index,
6086           qtdemux->index_id,
6087           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6088           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6089           GST_FORMAT_BYTES, byte_position, NULL);
6090     }
6091   }
6092 #endif
6093
6094   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6095
6096 exit:
6097   return ret;
6098 }
6099
6100 static const QtDemuxRandomAccessEntry *
6101 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6102     GstClockTime pos, gboolean after)
6103 {
6104   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6105   guint n_entries = stream->n_ra_entries;
6106   guint i;
6107
6108   /* we assume the table is sorted */
6109   for (i = 0; i < n_entries; ++i) {
6110     if (entries[i].ts > pos)
6111       break;
6112   }
6113
6114   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6115    * probably okay to assume that the index lists the very first fragment */
6116   if (i == 0)
6117     return &entries[0];
6118
6119   if (after)
6120     return &entries[i];
6121   else
6122     return &entries[i - 1];
6123 }
6124
6125 static gboolean
6126 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6127 {
6128   const QtDemuxRandomAccessEntry *best_entry = NULL;
6129   gint i;
6130
6131   GST_OBJECT_LOCK (qtdemux);
6132
6133   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6134
6135   /* first see if we can determine where to go to using mfra,
6136    * before we start clearing things */
6137   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6138     const QtDemuxRandomAccessEntry *entry;
6139     QtDemuxStream *stream;
6140     gboolean is_audio_or_video;
6141
6142     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6143
6144     if (stream->ra_entries == NULL)
6145       continue;
6146
6147     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6148       is_audio_or_video = TRUE;
6149     else
6150       is_audio_or_video = FALSE;
6151
6152     entry =
6153         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6154         stream->time_position, !is_audio_or_video);
6155
6156     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6157         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6158
6159     stream->pending_seek = entry;
6160
6161     /* decide position to jump to just based on audio/video tracks, not subs */
6162     if (!is_audio_or_video)
6163       continue;
6164
6165     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6166       best_entry = entry;
6167   }
6168
6169   /* no luck, will handle seek otherwise */
6170   if (best_entry == NULL) {
6171     GST_OBJECT_UNLOCK (qtdemux);
6172     return FALSE;
6173   }
6174
6175   /* ok, now we can prepare for processing as of located moof */
6176   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6177     QtDemuxStream *stream;
6178
6179     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6180
6181     g_free (stream->samples);
6182     stream->samples = NULL;
6183     stream->n_samples = 0;
6184     stream->stbl_index = -1;    /* no samples have yet been parsed */
6185     stream->sample_index = -1;
6186
6187     if (stream->protection_scheme_info) {
6188       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6189       if (stream->protection_scheme_type == FOURCC_cenc
6190           || stream->protection_scheme_type == FOURCC_cbcs) {
6191         QtDemuxCencSampleSetInfo *info =
6192             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6193         if (info->crypto_info) {
6194           g_ptr_array_free (info->crypto_info, TRUE);
6195           info->crypto_info = NULL;
6196         }
6197       }
6198     }
6199   }
6200
6201   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6202       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6203       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6204       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6205
6206   qtdemux->moof_offset = best_entry->moof_offset;
6207
6208   qtdemux_add_fragmented_samples (qtdemux);
6209
6210   GST_OBJECT_UNLOCK (qtdemux);
6211   return TRUE;
6212 }
6213
6214 static GstFlowReturn
6215 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6216 {
6217   GstFlowReturn ret = GST_FLOW_OK;
6218   GstBuffer *buf = NULL;
6219   QtDemuxStream *stream, *target_stream = NULL;
6220   GstClockTime min_time;
6221   guint64 offset = 0;
6222   GstClockTime dts = GST_CLOCK_TIME_NONE;
6223   GstClockTime pts = GST_CLOCK_TIME_NONE;
6224   GstClockTime duration = 0;
6225   gboolean keyframe = FALSE;
6226   guint sample_size = 0;
6227   guint num_samples = 1;
6228   gboolean empty = 0;
6229   guint size;
6230   gint i;
6231
6232   if (qtdemux->fragmented_seek_pending) {
6233     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6234     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6235       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6236       qtdemux->fragmented_seek_pending = FALSE;
6237     } else {
6238       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6239     }
6240   }
6241
6242   /* Figure out the next stream sample to output, min_time is expressed in
6243    * global time and runs over the edit list segments. */
6244   min_time = G_MAXUINT64;
6245   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6246     GstClockTime position;
6247
6248     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6249     position = stream->time_position;
6250
6251     if (!GST_CLOCK_TIME_IS_VALID (position))
6252       continue;
6253
6254     if (stream->segment_index != -1) {
6255       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6256       position += segment->media_start;
6257     }
6258
6259     /* position of -1 is EOS */
6260     if (position < min_time) {
6261       min_time = position;
6262       target_stream = stream;
6263     }
6264   }
6265   /* all are EOS */
6266   if (G_UNLIKELY (target_stream == NULL)) {
6267     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6268     goto eos;
6269   }
6270
6271   /* check for segment end */
6272   if (G_UNLIKELY (qtdemux->segment.stop != -1
6273           && qtdemux->segment.rate >= 0
6274           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6275     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6276     target_stream->time_position = GST_CLOCK_TIME_NONE;
6277     goto eos_stream;
6278   }
6279
6280   /* gap events for subtitle streams */
6281   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6282     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6283     if (stream->pad) {
6284       GstClockTime gap_threshold;
6285
6286       /* Only send gap events on non-subtitle streams if lagging way behind. */
6287       if (stream->subtype == FOURCC_subp
6288           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)
6289         gap_threshold = 1 * GST_SECOND;
6290       else
6291         gap_threshold = 3 * GST_SECOND;
6292
6293       /* send gap events until the stream catches up */
6294       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6295       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6296           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6297           stream->segment.position + gap_threshold < min_time) {
6298         GstEvent *gap =
6299             gst_event_new_gap (stream->segment.position, gap_threshold);
6300         gst_pad_push_event (stream->pad, gap);
6301         stream->segment.position += gap_threshold;
6302       }
6303     }
6304   }
6305
6306   stream = target_stream;
6307   /* fetch info for the current sample of this stream */
6308   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6309               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6310     goto eos_stream;
6311
6312   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6313   if (stream->new_caps) {
6314     gst_qtdemux_configure_stream (qtdemux, stream);
6315     qtdemux_do_allocation (stream, qtdemux);
6316   }
6317
6318   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6319   if (G_UNLIKELY (qtdemux->segment.
6320           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6321     if (stream->subtype == FOURCC_vide) {
6322       if (!keyframe) {
6323         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6324             stream->track_id);
6325         goto next;
6326       } else if (qtdemux->trickmode_interval > 0) {
6327         GstClockTimeDiff interval;
6328
6329         if (qtdemux->segment.rate > 0)
6330           interval = stream->time_position - stream->last_keyframe_dts;
6331         else
6332           interval = stream->last_keyframe_dts - stream->time_position;
6333
6334         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6335             && interval < qtdemux->trickmode_interval) {
6336           GST_LOG_OBJECT (qtdemux,
6337               "Skipping keyframe within interval on track-id %u",
6338               stream->track_id);
6339           goto next;
6340         } else {
6341           stream->last_keyframe_dts = stream->time_position;
6342         }
6343       }
6344     }
6345   }
6346
6347   GST_DEBUG_OBJECT (qtdemux,
6348       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6349       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6350       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6351       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6352       GST_TIME_ARGS (duration));
6353
6354   if (G_UNLIKELY (empty)) {
6355     /* empty segment, push a gap if there's a second or more
6356      * difference and move to the next one */
6357     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6358       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6359     stream->segment.position = pts + duration;
6360     goto next;
6361   }
6362
6363   /* hmm, empty sample, skip and move to next sample */
6364   if (G_UNLIKELY (sample_size <= 0))
6365     goto next;
6366
6367   /* last pushed sample was out of boundary, goto next sample */
6368   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6369     goto next;
6370
6371   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6372     GST_DEBUG_OBJECT (qtdemux,
6373         "size %d larger than stream max_buffer_size %d, trimming",
6374         sample_size, stream->max_buffer_size);
6375     size =
6376         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6377   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6378       && sample_size < stream->min_buffer_size) {
6379     guint start_sample_index = stream->sample_index;
6380     guint accumulated_size = sample_size;
6381     guint64 expected_next_offset = offset + sample_size;
6382
6383     GST_DEBUG_OBJECT (qtdemux,
6384         "size %d smaller than stream min_buffer_size %d, combining with the next",
6385         sample_size, stream->min_buffer_size);
6386
6387     while (stream->sample_index < stream->to_sample
6388         && stream->sample_index + 1 < stream->n_samples) {
6389       const QtDemuxSample *next_sample;
6390
6391       /* Increment temporarily */
6392       stream->sample_index++;
6393
6394       /* Failed to parse sample so let's go back to the previous one that was
6395        * still successful */
6396       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6397         stream->sample_index--;
6398         break;
6399       }
6400
6401       next_sample = &stream->samples[stream->sample_index];
6402
6403       /* Not contiguous with the previous sample so let's go back to the
6404        * previous one that was still successful */
6405       if (next_sample->offset != expected_next_offset) {
6406         stream->sample_index--;
6407         break;
6408       }
6409
6410       accumulated_size += next_sample->size;
6411       expected_next_offset += next_sample->size;
6412       if (accumulated_size >= stream->min_buffer_size)
6413         break;
6414     }
6415
6416     num_samples = stream->sample_index + 1 - start_sample_index;
6417     stream->sample_index = start_sample_index;
6418     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6419         num_samples, accumulated_size);
6420     size = accumulated_size;
6421   } else {
6422     size = sample_size;
6423   }
6424
6425   if (qtdemux->cenc_aux_info_offset > 0) {
6426     GstMapInfo map;
6427     GstByteReader br;
6428     GstBuffer *aux_info = NULL;
6429
6430     /* pull the data stored before the sample */
6431     ret =
6432         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6433         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6434     if (G_UNLIKELY (ret != GST_FLOW_OK))
6435       goto beach;
6436     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6437     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6438     gst_byte_reader_init (&br, map.data + 8, map.size);
6439     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6440             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6441       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6442       gst_buffer_unmap (aux_info, &map);
6443       gst_buffer_unref (aux_info);
6444       ret = GST_FLOW_ERROR;
6445       goto beach;
6446     }
6447     gst_buffer_unmap (aux_info, &map);
6448     gst_buffer_unref (aux_info);
6449   }
6450
6451   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6452       offset);
6453
6454   if (stream->use_allocator) {
6455     /* if we have a per-stream allocator, use it */
6456     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6457   }
6458
6459   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6460       size, &buf);
6461   if (G_UNLIKELY (ret != GST_FLOW_OK))
6462     goto beach;
6463
6464   /* Update for both splitting and combining of samples */
6465   if (size != sample_size) {
6466     pts += gst_util_uint64_scale_int (GST_SECOND,
6467         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6468         stream->timescale);
6469     dts +=
6470         gst_util_uint64_scale_int (GST_SECOND,
6471         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6472         stream->timescale);
6473     duration =
6474         gst_util_uint64_scale_int (GST_SECOND,
6475         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6476   }
6477
6478   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6479       dts, pts, duration, keyframe, min_time, offset);
6480
6481   if (size < sample_size) {
6482     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6483     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6484
6485     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6486         sample->timestamp +
6487         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6488     if (time_position >= segment->media_start) {
6489       /* inside the segment, update time_position, looks very familiar to
6490        * GStreamer segments, doesn't it? */
6491       stream->time_position = (time_position - segment->media_start) +
6492           segment->time;
6493     } else {
6494       /* not yet in segment, time does not yet increment. This means
6495        * that we are still prerolling keyframes to the decoder so it can
6496        * decode the first sample of the segment. */
6497       stream->time_position = segment->time;
6498     }
6499   } else if (size > sample_size) {
6500     /* Increase to the last sample we already pulled so that advancing
6501      * below brings us to the next sample we need to pull */
6502     stream->sample_index += num_samples - 1;
6503   }
6504
6505   /* combine flows */
6506   GST_OBJECT_LOCK (qtdemux);
6507   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6508   GST_OBJECT_UNLOCK (qtdemux);
6509   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6510    * we have no more data for the pad to push */
6511   if (ret == GST_FLOW_EOS)
6512     ret = GST_FLOW_OK;
6513
6514   stream->offset_in_sample += size;
6515   if (stream->offset_in_sample >= sample_size) {
6516     gst_qtdemux_advance_sample (qtdemux, stream);
6517   }
6518   goto beach;
6519
6520 next:
6521   gst_qtdemux_advance_sample (qtdemux, stream);
6522
6523 beach:
6524   return ret;
6525
6526   /* special cases */
6527 eos:
6528   {
6529     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6530     ret = GST_FLOW_EOS;
6531     goto beach;
6532   }
6533 eos_stream:
6534   {
6535     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6536     /* EOS will be raised if all are EOS */
6537     ret = GST_FLOW_OK;
6538     goto beach;
6539   }
6540 }
6541
6542 static void
6543 gst_qtdemux_loop (GstPad * pad)
6544 {
6545   GstQTDemux *qtdemux;
6546   guint64 cur_offset;
6547   GstFlowReturn ret;
6548
6549   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6550
6551   cur_offset = qtdemux->offset;
6552   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6553       cur_offset, qt_demux_state_string (qtdemux->state));
6554
6555   switch (qtdemux->state) {
6556     case QTDEMUX_STATE_INITIAL:
6557     case QTDEMUX_STATE_HEADER:
6558       ret = gst_qtdemux_loop_state_header (qtdemux);
6559       break;
6560     case QTDEMUX_STATE_MOVIE:
6561       ret = gst_qtdemux_loop_state_movie (qtdemux);
6562       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6563         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6564       }
6565       break;
6566     default:
6567       /* ouch */
6568       goto invalid_state;
6569   }
6570
6571   /* if something went wrong, pause */
6572   if (ret != GST_FLOW_OK)
6573     goto pause;
6574
6575 done:
6576   gst_object_unref (qtdemux);
6577   return;
6578
6579   /* ERRORS */
6580 invalid_state:
6581   {
6582     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6583         (NULL), ("streaming stopped, invalid state"));
6584     gst_pad_pause_task (pad);
6585     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6586     goto done;
6587   }
6588 pause:
6589   {
6590     const gchar *reason = gst_flow_get_name (ret);
6591
6592     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6593
6594     gst_pad_pause_task (pad);
6595
6596     /* fatal errors need special actions */
6597     /* check EOS */
6598     if (ret == GST_FLOW_EOS) {
6599       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6600         /* we have no streams, post an error */
6601         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6602       }
6603       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6604         gint64 stop;
6605
6606         if ((stop = qtdemux->segment.stop) == -1)
6607           stop = qtdemux->segment.duration;
6608
6609         if (qtdemux->segment.rate >= 0) {
6610           GstMessage *message;
6611           GstEvent *event;
6612
6613           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6614           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6615               GST_FORMAT_TIME, stop);
6616           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6617           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6618             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6619             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6620           }
6621           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6622           gst_qtdemux_push_event (qtdemux, event);
6623         } else {
6624           GstMessage *message;
6625           GstEvent *event;
6626
6627           /*  For Reverse Playback */
6628           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6629           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6630               GST_FORMAT_TIME, qtdemux->segment.start);
6631           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6632               qtdemux->segment.start);
6633           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6634             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6635             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6636           }
6637           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6638           gst_qtdemux_push_event (qtdemux, event);
6639         }
6640       } else {
6641         GstEvent *event;
6642
6643         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6644         event = gst_event_new_eos ();
6645         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6646           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6647         gst_qtdemux_push_event (qtdemux, event);
6648       }
6649     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6650       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6651       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6652     }
6653     goto done;
6654   }
6655 }
6656
6657 /*
6658  * has_next_entry
6659  *
6660  * Returns if there are samples to be played.
6661  */
6662 static gboolean
6663 has_next_entry (GstQTDemux * demux)
6664 {
6665   QtDemuxStream *stream;
6666   gint i;
6667
6668   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6669
6670   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6671     stream = QTDEMUX_NTH_STREAM (demux, i);
6672
6673     if (stream->sample_index == -1) {
6674       stream->sample_index = 0;
6675       stream->offset_in_sample = 0;
6676     }
6677
6678     if (stream->sample_index >= stream->n_samples) {
6679       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6680       continue;
6681     }
6682     GST_DEBUG_OBJECT (demux, "Found a sample");
6683     return TRUE;
6684   }
6685
6686   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6687   return FALSE;
6688 }
6689
6690 /*
6691  * next_entry_size
6692  *
6693  * Returns the size of the first entry at the current offset.
6694  * If -1, there are none (which means EOS or empty file).
6695  */
6696 static guint64
6697 next_entry_size (GstQTDemux * demux)
6698 {
6699   QtDemuxStream *stream, *target_stream = NULL;
6700   guint64 smalloffs = (guint64) - 1;
6701   QtDemuxSample *sample;
6702   gint i;
6703
6704   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6705       demux->offset);
6706
6707   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6708     stream = QTDEMUX_NTH_STREAM (demux, i);
6709
6710     if (stream->sample_index == -1) {
6711       stream->sample_index = 0;
6712       stream->offset_in_sample = 0;
6713     }
6714
6715     if (stream->sample_index >= stream->n_samples) {
6716       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6717       continue;
6718     }
6719
6720     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6721       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6722           stream->sample_index);
6723       return -1;
6724     }
6725
6726     sample = &stream->samples[stream->sample_index];
6727
6728     GST_LOG_OBJECT (demux,
6729         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6730         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6731         stream->sample_index, sample->offset, sample->size);
6732
6733     if (((smalloffs == -1)
6734             || (sample->offset < smalloffs)) && (sample->size)) {
6735       smalloffs = sample->offset;
6736       target_stream = stream;
6737     }
6738   }
6739
6740   if (!target_stream)
6741     return -1;
6742
6743   GST_LOG_OBJECT (demux,
6744       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6745       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6746
6747   stream = target_stream;
6748   sample = &stream->samples[stream->sample_index];
6749
6750   if (sample->offset >= demux->offset) {
6751     demux->todrop = sample->offset - demux->offset;
6752     return sample->size + demux->todrop;
6753   }
6754
6755   GST_DEBUG_OBJECT (demux,
6756       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6757   return -1;
6758 }
6759
6760 static void
6761 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6762 {
6763   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6764
6765   gst_element_post_message (GST_ELEMENT_CAST (demux),
6766       gst_message_new_element (GST_OBJECT_CAST (demux),
6767           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6768 }
6769
6770 static gboolean
6771 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6772 {
6773   GstEvent *event;
6774   gboolean res = 0;
6775
6776   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6777
6778   event =
6779       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6780       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6781       GST_SEEK_TYPE_NONE, -1);
6782
6783   /* store seqnum to drop flush events, they don't need to reach downstream */
6784   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6785   res = gst_pad_push_event (demux->sinkpad, event);
6786   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6787
6788   return res;
6789 }
6790
6791 /* check for seekable upstream, above and beyond a mere query */
6792 static void
6793 gst_qtdemux_check_seekability (GstQTDemux * demux)
6794 {
6795   GstQuery *query;
6796   gboolean seekable = FALSE;
6797   gint64 start = -1, stop = -1;
6798
6799   if (demux->upstream_size)
6800     return;
6801
6802   if (demux->upstream_format_is_time)
6803     return;
6804
6805   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6806   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6807     GST_DEBUG_OBJECT (demux, "seeking query failed");
6808     goto done;
6809   }
6810
6811   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6812
6813   /* try harder to query upstream size if we didn't get it the first time */
6814   if (seekable && stop == -1) {
6815     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6816     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6817   }
6818
6819   /* if upstream doesn't know the size, it's likely that it's not seekable in
6820    * practice even if it technically may be seekable */
6821   if (seekable && (start != 0 || stop <= start)) {
6822     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6823     seekable = FALSE;
6824   }
6825
6826 done:
6827   gst_query_unref (query);
6828
6829   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6830       G_GUINT64_FORMAT ")", seekable, start, stop);
6831   demux->upstream_seekable = seekable;
6832   demux->upstream_size = seekable ? stop : -1;
6833 }
6834
6835 static void
6836 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6837 {
6838   g_return_if_fail (bytes <= demux->todrop);
6839
6840   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6841   gst_adapter_flush (demux->adapter, bytes);
6842   demux->neededbytes -= bytes;
6843   demux->offset += bytes;
6844   demux->todrop -= bytes;
6845 }
6846
6847 /* PUSH-MODE only: Send a segment, if not done already. */
6848 static void
6849 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6850 {
6851   if (G_UNLIKELY (demux->need_segment)) {
6852     gint i;
6853
6854     if (!demux->upstream_format_is_time) {
6855       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6856     } else {
6857       GstEvent *segment_event;
6858       segment_event = gst_event_new_segment (&demux->segment);
6859       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6860         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6861       gst_qtdemux_push_event (demux, segment_event);
6862     }
6863
6864     demux->need_segment = FALSE;
6865
6866     /* clear to send tags on all streams */
6867     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6868       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6869       gst_qtdemux_push_tags (demux, stream);
6870       if (CUR_STREAM (stream)->sparse) {
6871         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6872         gst_pad_push_event (stream->pad,
6873             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6874       }
6875     }
6876   }
6877 }
6878
6879 /* Used for push mode only. */
6880 static void
6881 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6882     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6883 {
6884   GstClockTime ts, dur;
6885
6886   ts = pos;
6887   dur =
6888       stream->segments[segment_index].duration - (pos -
6889       stream->segments[segment_index].time);
6890   stream->time_position += dur;
6891
6892   /* Only gaps with a duration of at least one second are propagated.
6893    * Same workaround as in pull mode.
6894    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6895   if (dur >= GST_SECOND) {
6896     GstEvent *gap;
6897     gap = gst_event_new_gap (ts, dur);
6898
6899     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6900         "segment: %" GST_PTR_FORMAT, gap);
6901     gst_pad_push_event (stream->pad, gap);
6902   }
6903 }
6904
6905 static GstFlowReturn
6906 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6907 {
6908   GstQTDemux *demux;
6909
6910   demux = GST_QTDEMUX (parent);
6911
6912   GST_DEBUG_OBJECT (demux,
6913       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6914       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6915       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6916       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6917       gst_buffer_get_size (inbuf), demux->offset);
6918
6919   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6920     gboolean is_gap_input = FALSE;
6921     gint i;
6922
6923     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6924
6925     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6926       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6927     }
6928
6929     /* Check if we can land back on our feet in the case where upstream is
6930      * handling the seeking/pushing of samples with gaps in between (like
6931      * in the case of trick-mode DASH for example) */
6932     if (demux->upstream_format_is_time
6933         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6934       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6935         guint32 res;
6936         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6937         GST_LOG_OBJECT (demux,
6938             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6939             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6940         res =
6941             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6942             stream, GST_BUFFER_OFFSET (inbuf));
6943         if (res != -1) {
6944           QtDemuxSample *sample = &stream->samples[res];
6945           GST_LOG_OBJECT (demux,
6946               "Checking if sample %d from track-id %u is valid (offset:%"
6947               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6948               stream->track_id, sample->offset, sample->size);
6949           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6950             GST_LOG_OBJECT (demux,
6951                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6952                 res);
6953             is_gap_input = TRUE;
6954             /* We can go back to standard playback mode */
6955             demux->state = QTDEMUX_STATE_MOVIE;
6956             /* Remember which sample this stream is at */
6957             stream->sample_index = res;
6958             /* Finally update all push-based values to the expected values */
6959             demux->neededbytes = stream->samples[res].size;
6960             demux->offset = GST_BUFFER_OFFSET (inbuf);
6961             demux->mdatleft =
6962                 demux->mdatsize - demux->offset + demux->mdatoffset;
6963             demux->todrop = 0;
6964           }
6965         }
6966       }
6967       if (!is_gap_input) {
6968         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6969         /* Reset state if it's a real discont */
6970         demux->neededbytes = 16;
6971         demux->state = QTDEMUX_STATE_INITIAL;
6972         demux->offset = GST_BUFFER_OFFSET (inbuf);
6973         gst_adapter_clear (demux->adapter);
6974       }
6975     }
6976     /* Reverse fragmented playback, need to flush all we have before
6977      * consuming a new fragment.
6978      * The samples array have the timestamps calculated by accumulating the
6979      * durations but this won't work for reverse playback of fragments as
6980      * the timestamps of a subsequent fragment should be smaller than the
6981      * previously received one. */
6982     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6983       gst_qtdemux_process_adapter (demux, TRUE);
6984       g_ptr_array_foreach (demux->active_streams,
6985           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6986     }
6987   }
6988
6989   gst_adapter_push (demux->adapter, inbuf);
6990
6991   GST_DEBUG_OBJECT (demux,
6992       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6993       demux->neededbytes, gst_adapter_available (demux->adapter));
6994
6995   return gst_qtdemux_process_adapter (demux, FALSE);
6996 }
6997
6998 static GstFlowReturn
6999 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7000 {
7001   GstFlowReturn ret = GST_FLOW_OK;
7002
7003   /* we never really mean to buffer that much */
7004   if (demux->neededbytes == -1) {
7005     goto eos;
7006   }
7007
7008   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7009       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7010
7011 #ifndef GST_DISABLE_GST_DEBUG
7012     {
7013       guint64 discont_offset, distance_from_discont;
7014
7015       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7016       distance_from_discont =
7017           gst_adapter_distance_from_discont (demux->adapter);
7018
7019       GST_DEBUG_OBJECT (demux,
7020           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7021           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7022           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7023           demux->offset, discont_offset, distance_from_discont);
7024     }
7025 #endif
7026
7027     switch (demux->state) {
7028       case QTDEMUX_STATE_INITIAL:{
7029         const guint8 *data;
7030         guint32 fourcc;
7031         guint64 size;
7032
7033         gst_qtdemux_check_seekability (demux);
7034
7035         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7036
7037         /* get fourcc/length, set neededbytes */
7038         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7039             &size, &fourcc);
7040         gst_adapter_unmap (demux->adapter);
7041         data = NULL;
7042         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7043             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7044         if (size == 0) {
7045           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7046               (_("This file is invalid and cannot be played.")),
7047               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7048                   GST_FOURCC_ARGS (fourcc)));
7049           ret = GST_FLOW_ERROR;
7050           break;
7051         }
7052         if (fourcc == FOURCC_mdat) {
7053           gint next_entry = next_entry_size (demux);
7054           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7055                   || !demux->fragmented)) {
7056             /* we have the headers, start playback */
7057             demux->state = QTDEMUX_STATE_MOVIE;
7058             demux->neededbytes = next_entry;
7059             demux->mdatleft = size;
7060             demux->mdatsize = demux->mdatleft;
7061           } else {
7062             /* no headers yet, try to get them */
7063             guint bs;
7064             gboolean res;
7065             guint64 old, target;
7066
7067           buffer_data:
7068             old = demux->offset;
7069             target = old + size;
7070
7071             /* try to jump over the atom with a seek */
7072             /* only bother if it seems worth doing so,
7073              * and avoids possible upstream/server problems */
7074             if (demux->upstream_seekable &&
7075                 demux->upstream_size > 4 * (1 << 20)) {
7076               res = qtdemux_seek_offset (demux, target);
7077             } else {
7078               GST_DEBUG_OBJECT (demux, "skipping seek");
7079               res = FALSE;
7080             }
7081
7082             if (res) {
7083               GST_DEBUG_OBJECT (demux, "seek success");
7084               /* remember the offset fo the first mdat so we can seek back to it
7085                * after we have the headers */
7086               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7087                 demux->first_mdat = old;
7088                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7089                     demux->first_mdat);
7090               }
7091               /* seek worked, continue reading */
7092               demux->offset = target;
7093               demux->neededbytes = 16;
7094               demux->state = QTDEMUX_STATE_INITIAL;
7095             } else {
7096               /* seek failed, need to buffer */
7097               demux->offset = old;
7098               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7099               /* there may be multiple mdat (or alike) buffers */
7100               /* sanity check */
7101               if (demux->mdatbuffer)
7102                 bs = gst_buffer_get_size (demux->mdatbuffer);
7103               else
7104                 bs = 0;
7105               if (size + bs > 10 * (1 << 20))
7106                 goto no_moov;
7107               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7108               demux->neededbytes = size;
7109               if (!demux->mdatbuffer)
7110                 demux->mdatoffset = demux->offset;
7111             }
7112           }
7113         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7114           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7115               (_("This file is invalid and cannot be played.")),
7116               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7117                   GST_FOURCC_ARGS (fourcc), size));
7118           ret = GST_FLOW_ERROR;
7119           break;
7120         } else {
7121           /* this means we already started buffering and still no moov header,
7122            * let's continue buffering everything till we get moov */
7123           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7124                   || fourcc == FOURCC_moof))
7125             goto buffer_data;
7126           demux->neededbytes = size;
7127           demux->state = QTDEMUX_STATE_HEADER;
7128         }
7129         break;
7130       }
7131       case QTDEMUX_STATE_HEADER:{
7132         const guint8 *data;
7133         guint32 fourcc;
7134
7135         GST_DEBUG_OBJECT (demux, "In header");
7136
7137         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7138
7139         /* parse the header */
7140         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7141             &fourcc);
7142         if (fourcc == FOURCC_moov) {
7143           /* in usual fragmented setup we could try to scan for more
7144            * and end up at the the moov (after mdat) again */
7145           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7146               (!demux->fragmented
7147                   || demux->last_moov_offset == demux->offset)) {
7148             GST_DEBUG_OBJECT (demux,
7149                 "Skipping moov atom as we have (this) one already");
7150           } else {
7151             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7152
7153             if (demux->got_moov && demux->fragmented) {
7154               GST_DEBUG_OBJECT (demux,
7155                   "Got a second moov, clean up data from old one");
7156               if (demux->moov_node_compressed) {
7157                 g_node_destroy (demux->moov_node_compressed);
7158                 if (demux->moov_node)
7159                   g_free (demux->moov_node->data);
7160               }
7161               demux->moov_node_compressed = NULL;
7162               if (demux->moov_node)
7163                 g_node_destroy (demux->moov_node);
7164               demux->moov_node = NULL;
7165             }
7166
7167             demux->last_moov_offset = demux->offset;
7168
7169             /* Update streams with new moov */
7170             gst_qtdemux_stream_concat (demux,
7171                 demux->old_streams, demux->active_streams);
7172
7173             qtdemux_parse_moov (demux, data, demux->neededbytes);
7174             qtdemux_node_dump (demux, demux->moov_node);
7175             qtdemux_parse_tree (demux);
7176             qtdemux_prepare_streams (demux);
7177             QTDEMUX_EXPOSE_LOCK (demux);
7178             qtdemux_expose_streams (demux);
7179             QTDEMUX_EXPOSE_UNLOCK (demux);
7180
7181             demux->got_moov = TRUE;
7182
7183             gst_qtdemux_check_send_pending_segment (demux);
7184
7185             if (demux->moov_node_compressed) {
7186               g_node_destroy (demux->moov_node_compressed);
7187               g_free (demux->moov_node->data);
7188             }
7189             demux->moov_node_compressed = NULL;
7190             g_node_destroy (demux->moov_node);
7191             demux->moov_node = NULL;
7192             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7193           }
7194         } else if (fourcc == FOURCC_moof) {
7195           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7196             guint64 dist = 0;
7197             GstClockTime prev_pts;
7198             guint64 prev_offset;
7199             guint64 adapter_discont_offset, adapter_discont_dist;
7200
7201             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7202
7203             /*
7204              * The timestamp of the moof buffer is relevant as some scenarios
7205              * won't have the initial timestamp in the atoms. Whenever a new
7206              * buffer has started, we get that buffer's PTS and use it as a base
7207              * timestamp for the trun entries.
7208              *
7209              * To keep track of the current buffer timestamp and starting point
7210              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7211              * from the beginning of the buffer, with the distance and demux->offset
7212              * we know if it is still the same buffer or not.
7213              */
7214             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7215             prev_offset = demux->offset - dist;
7216             if (demux->fragment_start_offset == -1
7217                 || prev_offset > demux->fragment_start_offset) {
7218               demux->fragment_start_offset = prev_offset;
7219               demux->fragment_start = prev_pts;
7220               GST_DEBUG_OBJECT (demux,
7221                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7222                   GST_TIME_FORMAT, demux->fragment_start_offset,
7223                   GST_TIME_ARGS (demux->fragment_start));
7224             }
7225
7226             /* We can't use prev_offset() here because this would require
7227              * upstream to set consistent and correct offsets on all buffers
7228              * since the discont. Nothing ever did that in the past and we
7229              * would break backwards compatibility here then.
7230              * Instead take the offset we had at the last discont and count
7231              * the bytes from there. This works with old code as there would
7232              * be no discont between moov and moof, and also works with
7233              * adaptivedemux which correctly sets offset and will set the
7234              * DISCONT flag accordingly when needed.
7235              *
7236              * We also only do this for upstream TIME segments as otherwise
7237              * there are potential backwards compatibility problems with
7238              * seeking in PUSH mode and upstream providing inconsistent
7239              * timestamps. */
7240             adapter_discont_offset =
7241                 gst_adapter_offset_at_discont (demux->adapter);
7242             adapter_discont_dist =
7243                 gst_adapter_distance_from_discont (demux->adapter);
7244
7245             GST_DEBUG_OBJECT (demux,
7246                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7247                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7248                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7249
7250             if (demux->upstream_format_is_time) {
7251               demux->moof_offset = adapter_discont_offset;
7252               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7253                 demux->moof_offset += adapter_discont_dist;
7254               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7255                 demux->moof_offset = demux->offset;
7256             } else {
7257               demux->moof_offset = demux->offset;
7258             }
7259
7260             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7261                     demux->moof_offset, NULL)) {
7262               gst_adapter_unmap (demux->adapter);
7263               ret = GST_FLOW_ERROR;
7264               goto done;
7265             }
7266
7267             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7268             if (demux->mss_mode && !demux->exposed) {
7269               QTDEMUX_EXPOSE_LOCK (demux);
7270               qtdemux_expose_streams (demux);
7271               QTDEMUX_EXPOSE_UNLOCK (demux);
7272             }
7273
7274             gst_qtdemux_check_send_pending_segment (demux);
7275           } else {
7276             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7277           }
7278         } else if (fourcc == FOURCC_ftyp) {
7279           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7280           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7281         } else if (fourcc == FOURCC_uuid) {
7282           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7283           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7284         } else if (fourcc == FOURCC_sidx) {
7285           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7286           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7287         } else {
7288           switch (fourcc) {
7289             case FOURCC_styp:
7290               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7291                * FALLTHROUGH */
7292             case FOURCC_skip:
7293             case FOURCC_free:
7294               /* [free] and [skip] are padding atoms */
7295               GST_DEBUG_OBJECT (demux,
7296                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7297                   GST_FOURCC_ARGS (fourcc));
7298               break;
7299             default:
7300               GST_WARNING_OBJECT (demux,
7301                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7302                   GST_FOURCC_ARGS (fourcc));
7303               /* Let's jump that one and go back to initial state */
7304               break;
7305           }
7306         }
7307         gst_adapter_unmap (demux->adapter);
7308         data = NULL;
7309
7310         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7311           gsize remaining_data_size = 0;
7312
7313           /* the mdat was before the header */
7314           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7315               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7316           /* restore our adapter/offset view of things with upstream;
7317            * put preceding buffered data ahead of current moov data.
7318            * This should also handle evil mdat, moov, mdat cases and alike */
7319           gst_adapter_flush (demux->adapter, demux->neededbytes);
7320
7321           /* Store any remaining data after the mdat for later usage */
7322           remaining_data_size = gst_adapter_available (demux->adapter);
7323           if (remaining_data_size > 0) {
7324             g_assert (demux->restoredata_buffer == NULL);
7325             demux->restoredata_buffer =
7326                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7327             demux->restoredata_offset = demux->offset + demux->neededbytes;
7328             GST_DEBUG_OBJECT (demux,
7329                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7330                 G_GUINT64_FORMAT, remaining_data_size,
7331                 demux->restoredata_offset);
7332           }
7333
7334           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7335           demux->mdatbuffer = NULL;
7336           demux->offset = demux->mdatoffset;
7337           demux->neededbytes = next_entry_size (demux);
7338           demux->state = QTDEMUX_STATE_MOVIE;
7339           demux->mdatleft = gst_adapter_available (demux->adapter);
7340           demux->mdatsize = demux->mdatleft;
7341         } else {
7342           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7343           gst_adapter_flush (demux->adapter, demux->neededbytes);
7344
7345           /* only go back to the mdat if there are samples to play */
7346           if (demux->got_moov && demux->first_mdat != -1
7347               && has_next_entry (demux)) {
7348             gboolean res;
7349
7350             /* we need to seek back */
7351             res = qtdemux_seek_offset (demux, demux->first_mdat);
7352             if (res) {
7353               demux->offset = demux->first_mdat;
7354             } else {
7355               GST_DEBUG_OBJECT (demux, "Seek back failed");
7356             }
7357           } else {
7358             demux->offset += demux->neededbytes;
7359           }
7360           demux->neededbytes = 16;
7361           demux->state = QTDEMUX_STATE_INITIAL;
7362         }
7363
7364         break;
7365       }
7366       case QTDEMUX_STATE_BUFFER_MDAT:{
7367         GstBuffer *buf;
7368         guint8 fourcc[4];
7369
7370         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7371             demux->offset);
7372         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7373         gst_buffer_extract (buf, 0, fourcc, 4);
7374         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7375             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7376         if (demux->mdatbuffer)
7377           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7378         else
7379           demux->mdatbuffer = buf;
7380         demux->offset += demux->neededbytes;
7381         demux->neededbytes = 16;
7382         demux->state = QTDEMUX_STATE_INITIAL;
7383         gst_qtdemux_post_progress (demux, 1, 1);
7384
7385         break;
7386       }
7387       case QTDEMUX_STATE_MOVIE:{
7388         QtDemuxStream *stream = NULL;
7389         QtDemuxSample *sample;
7390         GstClockTime dts, pts, duration;
7391         gboolean keyframe;
7392         gint i;
7393
7394         GST_DEBUG_OBJECT (demux,
7395             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7396
7397         if (demux->fragmented) {
7398           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7399               demux->mdatleft);
7400           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7401             /* if needed data starts within this atom,
7402              * then it should not exceed this atom */
7403             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7404               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7405                   (_("This file is invalid and cannot be played.")),
7406                   ("sample data crosses atom boundary"));
7407               ret = GST_FLOW_ERROR;
7408               break;
7409             }
7410             demux->mdatleft -= demux->neededbytes;
7411           } else {
7412             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7413             /* so we are dropping more than left in this atom */
7414             gst_qtdemux_drop_data (demux, demux->mdatleft);
7415             demux->mdatleft = 0;
7416
7417             /* need to resume atom parsing so we do not miss any other pieces */
7418             demux->state = QTDEMUX_STATE_INITIAL;
7419             demux->neededbytes = 16;
7420
7421             /* check if there was any stored post mdat data from previous buffers */
7422             if (demux->restoredata_buffer) {
7423               g_assert (gst_adapter_available (demux->adapter) == 0);
7424
7425               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7426               demux->restoredata_buffer = NULL;
7427               demux->offset = demux->restoredata_offset;
7428             }
7429
7430             break;
7431           }
7432         }
7433
7434         if (demux->todrop) {
7435           if (demux->cenc_aux_info_offset > 0) {
7436             GstByteReader br;
7437             const guint8 *data;
7438
7439             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7440             data = gst_adapter_map (demux->adapter, demux->todrop);
7441             gst_byte_reader_init (&br, data + 8, demux->todrop);
7442             if (!qtdemux_parse_cenc_aux_info (demux,
7443                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7444                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7445               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7446               ret = GST_FLOW_ERROR;
7447               gst_adapter_unmap (demux->adapter);
7448               g_free (demux->cenc_aux_info_sizes);
7449               demux->cenc_aux_info_sizes = NULL;
7450               goto done;
7451             }
7452             demux->cenc_aux_info_offset = 0;
7453             g_free (demux->cenc_aux_info_sizes);
7454             demux->cenc_aux_info_sizes = NULL;
7455             gst_adapter_unmap (demux->adapter);
7456           }
7457           gst_qtdemux_drop_data (demux, demux->todrop);
7458         }
7459
7460         /* first buffer? */
7461         /* initial newsegment sent here after having added pads,
7462          * possible others in sink_event */
7463         gst_qtdemux_check_send_pending_segment (demux);
7464
7465         /* Figure out which stream this packet belongs to */
7466         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7467           stream = QTDEMUX_NTH_STREAM (demux, i);
7468           if (stream->sample_index >= stream->n_samples) {
7469             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7470             stream = NULL;
7471             continue;
7472           }
7473           GST_LOG_OBJECT (demux,
7474               "Checking track-id %u (sample_index:%d / offset:%"
7475               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7476               stream->sample_index,
7477               stream->samples[stream->sample_index].offset,
7478               stream->samples[stream->sample_index].size);
7479
7480           if (stream->samples[stream->sample_index].offset == demux->offset)
7481             break;
7482         }
7483
7484         if (G_UNLIKELY (stream == NULL))
7485           goto unknown_stream;
7486
7487         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7488
7489         if (stream->new_caps) {
7490           gst_qtdemux_configure_stream (demux, stream);
7491         }
7492
7493         /* Put data in a buffer, set timestamps, caps, ... */
7494         sample = &stream->samples[stream->sample_index];
7495
7496         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7497           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7498               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7499
7500           dts = QTSAMPLE_DTS (stream, sample);
7501           pts = QTSAMPLE_PTS (stream, sample);
7502           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7503           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7504
7505           /* check for segment end */
7506           if (G_UNLIKELY (demux->segment.stop != -1
7507                   && demux->segment.stop <= pts && stream->on_keyframe)
7508               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7509             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7510             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7511
7512             /* skip this data, stream is EOS */
7513             gst_adapter_flush (demux->adapter, demux->neededbytes);
7514             demux->offset += demux->neededbytes;
7515
7516             /* check if all streams are eos */
7517             ret = GST_FLOW_EOS;
7518             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7519               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7520                 ret = GST_FLOW_OK;
7521                 break;
7522               }
7523             }
7524           } else {
7525             GstBuffer *outbuf;
7526
7527             outbuf =
7528                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7529
7530             /* FIXME: should either be an assert or a plain check */
7531             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7532
7533             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7534                 dts, pts, duration, keyframe, dts, demux->offset);
7535           }
7536
7537           /* combine flows */
7538           GST_OBJECT_LOCK (demux);
7539           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7540           GST_OBJECT_UNLOCK (demux);
7541         } else {
7542           /* skip this data, stream is EOS */
7543           gst_adapter_flush (demux->adapter, demux->neededbytes);
7544         }
7545
7546         stream->sample_index++;
7547         stream->offset_in_sample = 0;
7548
7549         /* update current offset and figure out size of next buffer */
7550         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7551             demux->offset, demux->neededbytes);
7552         demux->offset += demux->neededbytes;
7553         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7554             demux->offset);
7555
7556
7557         if (ret == GST_FLOW_EOS) {
7558           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7559           demux->neededbytes = -1;
7560           goto eos;
7561         }
7562
7563         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7564           if (demux->fragmented) {
7565             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7566             /* there may be more to follow, only finish this atom */
7567             demux->todrop = demux->mdatleft;
7568             demux->neededbytes = demux->todrop;
7569             break;
7570           }
7571           goto eos;
7572         }
7573         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7574           goto non_ok_unlinked_flow;
7575         }
7576         break;
7577       }
7578       default:
7579         goto invalid_state;
7580     }
7581   }
7582
7583   /* when buffering movie data, at least show user something is happening */
7584   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7585       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7586     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7587         demux->neededbytes);
7588   }
7589 done:
7590
7591   return ret;
7592
7593   /* ERRORS */
7594 non_ok_unlinked_flow:
7595   {
7596     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7597         gst_flow_get_name (ret));
7598     return ret;
7599   }
7600 unknown_stream:
7601   {
7602     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7603     ret = GST_FLOW_ERROR;
7604     goto done;
7605   }
7606 eos:
7607   {
7608     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7609     ret = GST_FLOW_EOS;
7610     goto done;
7611   }
7612 invalid_state:
7613   {
7614     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7615         (NULL), ("qtdemuxer invalid state %d", demux->state));
7616     ret = GST_FLOW_ERROR;
7617     goto done;
7618   }
7619 no_moov:
7620   {
7621     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7622         (NULL), ("no 'moov' atom within the first 10 MB"));
7623     ret = GST_FLOW_ERROR;
7624     goto done;
7625   }
7626 }
7627
7628 static gboolean
7629 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7630 {
7631   GstQuery *query;
7632   gboolean pull_mode;
7633
7634   query = gst_query_new_scheduling ();
7635
7636   if (!gst_pad_peer_query (sinkpad, query)) {
7637     gst_query_unref (query);
7638     goto activate_push;
7639   }
7640
7641   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7642       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7643   gst_query_unref (query);
7644
7645   if (!pull_mode)
7646     goto activate_push;
7647
7648   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7649   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7650
7651 activate_push:
7652   {
7653     GST_DEBUG_OBJECT (sinkpad, "activating push");
7654     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7655   }
7656 }
7657
7658 static gboolean
7659 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7660     GstPadMode mode, gboolean active)
7661 {
7662   gboolean res;
7663   GstQTDemux *demux = GST_QTDEMUX (parent);
7664
7665   switch (mode) {
7666     case GST_PAD_MODE_PUSH:
7667       demux->pullbased = FALSE;
7668       res = TRUE;
7669       break;
7670     case GST_PAD_MODE_PULL:
7671       if (active) {
7672         demux->pullbased = TRUE;
7673         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7674             sinkpad, NULL);
7675       } else {
7676         res = gst_pad_stop_task (sinkpad);
7677       }
7678       break;
7679     default:
7680       res = FALSE;
7681       break;
7682   }
7683   return res;
7684 }
7685
7686 #ifdef HAVE_ZLIB
7687 static void *
7688 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7689 {
7690   guint8 *buffer;
7691   z_stream z;
7692   int ret;
7693
7694   memset (&z, 0, sizeof (z));
7695   z.zalloc = NULL;
7696   z.zfree = NULL;
7697   z.opaque = NULL;
7698
7699   if ((ret = inflateInit (&z)) != Z_OK) {
7700     GST_ERROR ("inflateInit() returned %d", ret);
7701     return NULL;
7702   }
7703
7704   z.next_in = z_buffer;
7705   z.avail_in = z_length;
7706
7707   buffer = (guint8 *) g_malloc (*length);
7708   z.avail_out = *length;
7709   z.next_out = (Bytef *) buffer;
7710   do {
7711     ret = inflate (&z, Z_NO_FLUSH);
7712     if (ret == Z_STREAM_END) {
7713       break;
7714     } else if (ret != Z_OK) {
7715       GST_WARNING ("inflate() returned %d", ret);
7716       break;
7717     }
7718
7719     *length += 4096;
7720     buffer = (guint8 *) g_realloc (buffer, *length);
7721     z.next_out = (Bytef *) (buffer + z.total_out);
7722     z.avail_out += 4096;
7723   } while (z.avail_in > 0);
7724
7725   if (ret != Z_STREAM_END) {
7726     g_free (buffer);
7727     buffer = NULL;
7728     *length = 0;
7729   } else {
7730     *length = z.total_out;
7731   }
7732
7733   inflateEnd (&z);
7734
7735   return buffer;
7736 }
7737 #endif /* HAVE_ZLIB */
7738
7739 static gboolean
7740 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7741 {
7742   GNode *cmov;
7743
7744   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7745
7746   /* counts as header data */
7747   qtdemux->header_size += length;
7748
7749   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7750   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7751
7752   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7753   if (cmov) {
7754     guint32 method;
7755     GNode *dcom;
7756     GNode *cmvd;
7757     guint32 dcom_len;
7758
7759     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7760     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7761     if (dcom == NULL || cmvd == NULL)
7762       goto invalid_compression;
7763
7764     dcom_len = QT_UINT32 (dcom->data);
7765     if (dcom_len < 12)
7766       goto invalid_compression;
7767
7768     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7769     switch (method) {
7770 #ifdef HAVE_ZLIB
7771       case FOURCC_zlib:{
7772         guint uncompressed_length;
7773         guint compressed_length;
7774         guint8 *buf;
7775         guint32 cmvd_len;
7776
7777         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7778         if (cmvd_len < 12)
7779           goto invalid_compression;
7780
7781         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7782         compressed_length = cmvd_len - 12;
7783         GST_LOG ("length = %u", uncompressed_length);
7784
7785         buf =
7786             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7787             compressed_length, &uncompressed_length);
7788
7789         if (buf) {
7790           qtdemux->moov_node_compressed = qtdemux->moov_node;
7791           qtdemux->moov_node = g_node_new (buf);
7792
7793           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7794               uncompressed_length);
7795         }
7796         break;
7797       }
7798 #endif /* HAVE_ZLIB */
7799       default:
7800         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7801             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7802         break;
7803     }
7804   }
7805   return TRUE;
7806
7807   /* ERRORS */
7808 invalid_compression:
7809   {
7810     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7811     return FALSE;
7812   }
7813 }
7814
7815 static gboolean
7816 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7817     const guint8 * end)
7818 {
7819   while (G_UNLIKELY (buf < end)) {
7820     GNode *child;
7821     guint32 len;
7822
7823     if (G_UNLIKELY (buf + 4 > end)) {
7824       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7825       break;
7826     }
7827     len = QT_UINT32 (buf);
7828     if (G_UNLIKELY (len == 0)) {
7829       GST_LOG_OBJECT (qtdemux, "empty container");
7830       break;
7831     }
7832     if (G_UNLIKELY (len < 8)) {
7833       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7834       break;
7835     }
7836     if (G_UNLIKELY (len > (end - buf))) {
7837       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7838           (gint) (end - buf));
7839       break;
7840     }
7841
7842     child = g_node_new ((guint8 *) buf);
7843     g_node_append (node, child);
7844     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7845     qtdemux_parse_node (qtdemux, child, buf, len);
7846
7847     buf += len;
7848   }
7849   return TRUE;
7850 }
7851
7852 static gboolean
7853 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7854     GNode * xdxt)
7855 {
7856   int len = QT_UINT32 (xdxt->data);
7857   guint8 *buf = xdxt->data;
7858   guint8 *end = buf + len;
7859   GstBuffer *buffer;
7860
7861   /* skip size and type */
7862   buf += 8;
7863   end -= 8;
7864
7865   while (buf < end) {
7866     gint size;
7867     guint32 type;
7868
7869     size = QT_UINT32 (buf);
7870     type = QT_FOURCC (buf + 4);
7871
7872     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7873
7874     if (buf + size > end || size <= 0)
7875       break;
7876
7877     buf += 8;
7878     size -= 8;
7879
7880     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7881         GST_FOURCC_ARGS (type));
7882
7883     switch (type) {
7884       case FOURCC_tCtH:
7885         buffer = gst_buffer_new_and_alloc (size);
7886         gst_buffer_fill (buffer, 0, buf, size);
7887         stream->buffers = g_slist_append (stream->buffers, buffer);
7888         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7889         break;
7890       case FOURCC_tCt_:
7891         buffer = gst_buffer_new_and_alloc (size);
7892         gst_buffer_fill (buffer, 0, buf, size);
7893         stream->buffers = g_slist_append (stream->buffers, buffer);
7894         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7895         break;
7896       case FOURCC_tCtC:
7897         buffer = gst_buffer_new_and_alloc (size);
7898         gst_buffer_fill (buffer, 0, buf, size);
7899         stream->buffers = g_slist_append (stream->buffers, buffer);
7900         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7901         break;
7902       default:
7903         GST_WARNING_OBJECT (qtdemux,
7904             "unknown theora cookie %" GST_FOURCC_FORMAT,
7905             GST_FOURCC_ARGS (type));
7906         break;
7907     }
7908     buf += size;
7909   }
7910   return TRUE;
7911 }
7912
7913 static gboolean
7914 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7915     guint length)
7916 {
7917   guint32 fourcc = 0;
7918   guint32 node_length = 0;
7919   const QtNodeType *type;
7920   const guint8 *end;
7921
7922   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7923
7924   if (G_UNLIKELY (length < 8))
7925     goto not_enough_data;
7926
7927   node_length = QT_UINT32 (buffer);
7928   fourcc = QT_FOURCC (buffer + 4);
7929
7930   /* ignore empty nodes */
7931   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7932     return TRUE;
7933
7934   type = qtdemux_type_get (fourcc);
7935
7936   end = buffer + length;
7937
7938   GST_LOG_OBJECT (qtdemux,
7939       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7940       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7941
7942   if (node_length > length)
7943     goto broken_atom_size;
7944
7945   if (type->flags & QT_FLAG_CONTAINER) {
7946     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7947   } else {
7948     switch (fourcc) {
7949       case FOURCC_stsd:
7950       {
7951         if (node_length < 20) {
7952           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7953           break;
7954         }
7955         GST_DEBUG_OBJECT (qtdemux,
7956             "parsing stsd (sample table, sample description) atom");
7957         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7958         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7959         break;
7960       }
7961       case FOURCC_mp4a:
7962       case FOURCC_alac:
7963       case FOURCC_fLaC:
7964       case FOURCC_aavd:
7965       {
7966         guint32 version;
7967         guint32 offset;
7968         guint min_size;
7969
7970         /* also read alac (or whatever) in stead of mp4a in the following,
7971          * since a similar layout is used in other cases as well */
7972         if (fourcc == FOURCC_mp4a)
7973           min_size = 20;
7974         else if (fourcc == FOURCC_fLaC)
7975           min_size = 86;
7976         else
7977           min_size = 40;
7978
7979         /* There are two things we might encounter here: a true mp4a atom, and
7980            an mp4a entry in an stsd atom. The latter is what we're interested
7981            in, and it looks like an atom, but isn't really one. The true mp4a
7982            atom is short, so we detect it based on length here. */
7983         if (length < min_size) {
7984           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7985               GST_FOURCC_ARGS (fourcc));
7986           break;
7987         }
7988
7989         /* 'version' here is the sound sample description version. Types 0 and
7990            1 are documented in the QTFF reference, but type 2 is not: it's
7991            described in Apple header files instead (struct SoundDescriptionV2
7992            in Movies.h) */
7993         version = QT_UINT16 (buffer + 16);
7994
7995         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7996             GST_FOURCC_ARGS (fourcc), version);
7997
7998         /* parse any esds descriptors */
7999         switch (version) {
8000           case 0:
8001             offset = 0x24;
8002             break;
8003           case 1:
8004             offset = 0x34;
8005             break;
8006           case 2:
8007             offset = 0x48;
8008             break;
8009           default:
8010             GST_WARNING_OBJECT (qtdemux,
8011                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8012                 GST_FOURCC_ARGS (fourcc), version);
8013             offset = 0;
8014             break;
8015         }
8016         if (offset)
8017           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8018         break;
8019       }
8020       case FOURCC_mp4v:
8021       case FOURCC_MP4V:
8022       case FOURCC_fmp4:
8023       case FOURCC_FMP4:
8024       case FOURCC_apcs:
8025       case FOURCC_apch:
8026       case FOURCC_apcn:
8027       case FOURCC_apco:
8028       case FOURCC_ap4h:
8029       case FOURCC_xvid:
8030       case FOURCC_XVID:
8031       case FOURCC_H264:
8032       case FOURCC_avc1:
8033       case FOURCC_avc3:
8034       case FOURCC_H265:
8035       case FOURCC_hvc1:
8036       case FOURCC_hev1:
8037       case FOURCC_dvh1:
8038       case FOURCC_dvhe:
8039       case FOURCC_mjp2:
8040       case FOURCC_encv:
8041       {
8042         guint32 version;
8043         guint32 str_len;
8044
8045         /* codec_data is contained inside these atoms, which all have
8046          * the same format. */
8047         /* video sample description size is 86 bytes without extension.
8048          * node_length have to be bigger than 86 bytes because video sample
8049          * description can include extensions such as esds, fiel, glbl, etc. */
8050         if (node_length < 86) {
8051           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8052               " sample description length too short (%u < 86)",
8053               GST_FOURCC_ARGS (fourcc), node_length);
8054           break;
8055         }
8056
8057         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8058             GST_FOURCC_ARGS (fourcc));
8059
8060         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8061          *              its data format.
8062          * revision level (2 bytes) : must be set to 0. */
8063         version = QT_UINT32 (buffer + 16);
8064         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8065
8066         /* compressor name : PASCAL string and informative purposes
8067          * first byte : the number of bytes to be displayed.
8068          *              it has to be less than 32 because it is reserved
8069          *              space of 32 bytes total including itself. */
8070         str_len = QT_UINT8 (buffer + 50);
8071         if (str_len < 32)
8072           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8073               (char *) buffer + 51);
8074         else
8075           GST_WARNING_OBJECT (qtdemux,
8076               "compressorname length too big (%u > 31)", str_len);
8077
8078         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8079             end - buffer);
8080         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8081         break;
8082       }
8083       case FOURCC_meta:
8084       {
8085         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8086
8087         /* You are reading this correctly. QTFF specifies that the
8088          * metadata atom is a short atom, whereas ISO BMFF specifies
8089          * it's a full atom. But since so many people are doing things
8090          * differently, we actually peek into the atom to see which
8091          * variant it is */
8092         if (length < 16) {
8093           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8094               GST_FOURCC_ARGS (fourcc));
8095           break;
8096         }
8097         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8098           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8099            * starts with a 'hdlr' atom */
8100           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8101         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8102           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8103            * with version/flags both set to zero */
8104           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8105         } else
8106           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8107         break;
8108       }
8109       case FOURCC_mp4s:
8110       {
8111         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8112         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8113         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8114         break;
8115       }
8116       case FOURCC_XiTh:
8117       {
8118         guint32 version;
8119         guint32 offset;
8120
8121         if (length < 16) {
8122           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8123               GST_FOURCC_ARGS (fourcc));
8124           break;
8125         }
8126
8127         version = QT_UINT32 (buffer + 12);
8128         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8129
8130         switch (version) {
8131           case 0x00000001:
8132             offset = 0x62;
8133             break;
8134           default:
8135             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8136             offset = 0;
8137             break;
8138         }
8139         if (offset) {
8140           if (length < offset) {
8141             GST_WARNING_OBJECT (qtdemux,
8142                 "skipping too small %" GST_FOURCC_FORMAT " box",
8143                 GST_FOURCC_ARGS (fourcc));
8144             break;
8145           }
8146           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8147         }
8148         break;
8149       }
8150       case FOURCC_in24:
8151       {
8152         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8153         break;
8154       }
8155       case FOURCC_uuid:
8156       {
8157         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8158         break;
8159       }
8160       case FOURCC_enca:
8161       {
8162         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8163         break;
8164       }
8165       default:
8166         if (!strcmp (type->name, "unknown"))
8167           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8168         break;
8169     }
8170   }
8171   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8172       GST_FOURCC_ARGS (fourcc));
8173   return TRUE;
8174
8175 /* ERRORS */
8176 not_enough_data:
8177   {
8178     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8179         (_("This file is corrupt and cannot be played.")),
8180         ("Not enough data for an atom header, got only %u bytes", length));
8181     return FALSE;
8182   }
8183 broken_atom_size:
8184   {
8185     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8186         (_("This file is corrupt and cannot be played.")),
8187         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8188             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8189             length));
8190     return FALSE;
8191   }
8192 }
8193
8194 static void
8195 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8196 {
8197 /* FIXME: This can only reliably work if demuxers have a
8198  * separate streaming thread per srcpad. This should be
8199  * done in a demuxer base class, which integrates parts
8200  * of multiqueue
8201  *
8202  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8203  */
8204 #if 0
8205   GstQuery *query;
8206
8207   query = gst_query_new_allocation (stream->caps, FALSE);
8208
8209   if (!gst_pad_peer_query (stream->pad, query)) {
8210     /* not a problem, just debug a little */
8211     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8212   }
8213
8214   if (stream->allocator)
8215     gst_object_unref (stream->allocator);
8216
8217   if (gst_query_get_n_allocation_params (query) > 0) {
8218     /* try the allocator */
8219     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8220         &stream->params);
8221     stream->use_allocator = TRUE;
8222   } else {
8223     stream->allocator = NULL;
8224     gst_allocation_params_init (&stream->params);
8225     stream->use_allocator = FALSE;
8226   }
8227   gst_query_unref (query);
8228 #endif
8229 }
8230
8231 static gboolean
8232 pad_query (const GValue * item, GValue * value, gpointer user_data)
8233 {
8234   GstPad *pad = g_value_get_object (item);
8235   GstQuery *query = user_data;
8236   gboolean res;
8237
8238   res = gst_pad_peer_query (pad, query);
8239
8240   if (res) {
8241     g_value_set_boolean (value, TRUE);
8242     return FALSE;
8243   }
8244
8245   GST_INFO_OBJECT (pad, "pad peer query failed");
8246   return TRUE;
8247 }
8248
8249 static gboolean
8250 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8251     GstPadDirection direction)
8252 {
8253   GstIterator *it;
8254   GstIteratorFoldFunction func = pad_query;
8255   GValue res = { 0, };
8256
8257   g_value_init (&res, G_TYPE_BOOLEAN);
8258   g_value_set_boolean (&res, FALSE);
8259
8260   /* Ask neighbor */
8261   if (direction == GST_PAD_SRC)
8262     it = gst_element_iterate_src_pads (element);
8263   else
8264     it = gst_element_iterate_sink_pads (element);
8265
8266   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8267     gst_iterator_resync (it);
8268
8269   gst_iterator_free (it);
8270
8271   return g_value_get_boolean (&res);
8272 }
8273
8274 static void
8275 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8276     QtDemuxStream * stream)
8277 {
8278   GstQuery *query;
8279   GstContext *ctxt;
8280   GstElement *element = GST_ELEMENT (qtdemux);
8281   GstStructure *st;
8282   gchar **filtered_sys_ids;
8283   GValue event_list = G_VALUE_INIT;
8284   GList *walk;
8285
8286   /* 1. Check if we already have the context. */
8287   if (qtdemux->preferred_protection_system_id != NULL) {
8288     GST_LOG_OBJECT (element,
8289         "already have the protection context, no need to request it again");
8290     return;
8291   }
8292
8293   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8294   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8295       (const gchar **) qtdemux->protection_system_ids->pdata);
8296
8297   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8298       qtdemux->protection_system_ids->len - 1);
8299   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8300       "decryptors for %u of them, running context request",
8301       qtdemux->protection_system_ids->len,
8302       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8303
8304
8305   if (stream->protection_scheme_event_queue.length) {
8306     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8307         stream->protection_scheme_event_queue.length);
8308     walk = stream->protection_scheme_event_queue.tail;
8309   } else {
8310     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8311         qtdemux->protection_event_queue.length);
8312     walk = qtdemux->protection_event_queue.tail;
8313   }
8314
8315   g_value_init (&event_list, GST_TYPE_LIST);
8316   for (; walk; walk = g_list_previous (walk)) {
8317     GValue *event_value = g_new0 (GValue, 1);
8318     g_value_init (event_value, GST_TYPE_EVENT);
8319     g_value_set_boxed (event_value, walk->data);
8320     gst_value_list_append_and_take_value (&event_list, event_value);
8321   }
8322
8323   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8324    *      check if downstream already has a context of the specific type
8325    *  2b) Query upstream as above.
8326    */
8327   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8328   st = gst_query_writable_structure (query);
8329   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8330       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8331       NULL);
8332   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8333   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8334     gst_query_parse_context (query, &ctxt);
8335     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8336     gst_element_set_context (element, ctxt);
8337   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8338     gst_query_parse_context (query, &ctxt);
8339     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8340     gst_element_set_context (element, ctxt);
8341   } else {
8342     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8343      *    the required context type and afterwards check if a
8344      *    usable context was set now as in 1). The message could
8345      *    be handled by the parent bins of the element and the
8346      *    application.
8347      */
8348     GstMessage *msg;
8349
8350     GST_INFO_OBJECT (element, "posting need context message");
8351     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8352         "drm-preferred-decryption-system-id");
8353     st = (GstStructure *) gst_message_get_structure (msg);
8354     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8355         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8356         NULL);
8357
8358     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8359     gst_element_post_message (element, msg);
8360   }
8361
8362   g_strfreev (filtered_sys_ids);
8363   g_value_unset (&event_list);
8364   gst_query_unref (query);
8365 }
8366
8367 static gboolean
8368 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8369     QtDemuxStream * stream)
8370 {
8371   GstStructure *s;
8372   const gchar *selected_system = NULL;
8373
8374   g_return_val_if_fail (qtdemux != NULL, FALSE);
8375   g_return_val_if_fail (stream != NULL, FALSE);
8376   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8377       FALSE);
8378
8379   if (stream->protection_scheme_type == FOURCC_aavd) {
8380     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8381     if (!gst_structure_has_name (s, "application/x-aavd")) {
8382       gst_structure_set (s,
8383           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8384           NULL);
8385       gst_structure_set_name (s, "application/x-aavd");
8386     }
8387     return TRUE;
8388   }
8389
8390   if (stream->protection_scheme_type != FOURCC_cenc
8391       && stream->protection_scheme_type != FOURCC_cbcs) {
8392     GST_ERROR_OBJECT (qtdemux,
8393         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8394         GST_FOURCC_ARGS (stream->protection_scheme_type));
8395     return FALSE;
8396   }
8397
8398   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8399   if (!gst_structure_has_name (s, "application/x-cenc")) {
8400     gst_structure_set (s,
8401         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8402     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8403         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8404         NULL);
8405     gst_structure_set_name (s, "application/x-cenc");
8406   }
8407
8408   if (qtdemux->protection_system_ids == NULL) {
8409     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8410         "cenc protection system information has been found, not setting a "
8411         "protection system UUID");
8412     return TRUE;
8413   }
8414
8415   gst_qtdemux_request_protection_context (qtdemux, stream);
8416   if (qtdemux->preferred_protection_system_id != NULL) {
8417     const gchar *preferred_system_array[] =
8418         { qtdemux->preferred_protection_system_id, NULL };
8419
8420     selected_system = gst_protection_select_system (preferred_system_array);
8421
8422     if (selected_system) {
8423       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8424           qtdemux->preferred_protection_system_id);
8425     } else {
8426       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8427           "because there is no available decryptor",
8428           qtdemux->preferred_protection_system_id);
8429     }
8430   }
8431
8432   if (!selected_system) {
8433     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8434     selected_system = gst_protection_select_system ((const gchar **)
8435         qtdemux->protection_system_ids->pdata);
8436     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8437         qtdemux->protection_system_ids->len - 1);
8438   }
8439
8440   if (!selected_system) {
8441     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8442         "suitable decryptor element has been found");
8443     return FALSE;
8444   }
8445
8446   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8447       selected_system);
8448
8449   gst_structure_set (s,
8450       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8451       NULL);
8452
8453   return TRUE;
8454 }
8455
8456 static gboolean
8457 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8458 {
8459   /* fps is calculated base on the duration of the average framerate since
8460    * qt does not have a fixed framerate. */
8461   gboolean fps_available = TRUE;
8462   guint32 first_duration = 0;
8463
8464   if (stream->n_samples > 0)
8465     first_duration = stream->samples[0].duration;
8466
8467   if ((stream->n_samples == 1 && first_duration == 0)
8468       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8469     /* still frame */
8470     CUR_STREAM (stream)->fps_n = 0;
8471     CUR_STREAM (stream)->fps_d = 1;
8472   } else {
8473     if (stream->duration == 0 || stream->n_samples < 2) {
8474       CUR_STREAM (stream)->fps_n = stream->timescale;
8475       CUR_STREAM (stream)->fps_d = 1;
8476       fps_available = FALSE;
8477     } else {
8478       GstClockTime avg_duration;
8479       guint64 duration;
8480       guint32 n_samples;
8481
8482       /* duration and n_samples can be updated for fragmented format
8483        * so, framerate of fragmented format is calculated using data in a moof */
8484       if (qtdemux->fragmented && stream->n_samples_moof > 0
8485           && stream->duration_moof > 0) {
8486         n_samples = stream->n_samples_moof;
8487         duration = stream->duration_moof;
8488       } else {
8489         n_samples = stream->n_samples;
8490         duration = stream->duration;
8491       }
8492
8493       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8494       /* stream->duration is guint64, timescale, n_samples are guint32 */
8495       avg_duration =
8496           gst_util_uint64_scale_round (duration -
8497           first_duration, GST_SECOND,
8498           (guint64) (stream->timescale) * (n_samples - 1));
8499
8500       GST_LOG_OBJECT (qtdemux,
8501           "Calculating avg sample duration based on stream (or moof) duration %"
8502           G_GUINT64_FORMAT
8503           " minus first sample %u, leaving %d samples gives %"
8504           GST_TIME_FORMAT, duration, first_duration,
8505           n_samples - 1, GST_TIME_ARGS (avg_duration));
8506
8507       fps_available =
8508           gst_video_guess_framerate (avg_duration,
8509           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8510
8511       GST_DEBUG_OBJECT (qtdemux,
8512           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8513           stream->timescale, CUR_STREAM (stream)->fps_n,
8514           CUR_STREAM (stream)->fps_d);
8515     }
8516   }
8517
8518   return fps_available;
8519 }
8520
8521 static gboolean
8522 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8523 {
8524   if (stream->subtype == FOURCC_vide) {
8525     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8526
8527     if (CUR_STREAM (stream)->caps) {
8528       CUR_STREAM (stream)->caps =
8529           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8530
8531       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8532         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8533             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8534             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8535
8536       /* set framerate if calculated framerate is reliable */
8537       if (fps_available) {
8538         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8539             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8540             CUR_STREAM (stream)->fps_d, NULL);
8541       }
8542
8543       /* calculate pixel-aspect-ratio using display width and height */
8544       GST_DEBUG_OBJECT (qtdemux,
8545           "video size %dx%d, target display size %dx%d",
8546           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8547           stream->display_width, stream->display_height);
8548       /* qt file might have pasp atom */
8549       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8550         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8551             CUR_STREAM (stream)->par_h);
8552         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8553             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8554             CUR_STREAM (stream)->par_h, NULL);
8555       } else if (stream->display_width > 0 && stream->display_height > 0
8556           && CUR_STREAM (stream)->width > 0
8557           && CUR_STREAM (stream)->height > 0) {
8558         gint n, d;
8559
8560         /* calculate the pixel aspect ratio using the display and pixel w/h */
8561         n = stream->display_width * CUR_STREAM (stream)->height;
8562         d = stream->display_height * CUR_STREAM (stream)->width;
8563         if (n == d)
8564           n = d = 1;
8565         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8566         CUR_STREAM (stream)->par_w = n;
8567         CUR_STREAM (stream)->par_h = d;
8568         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8569             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8570             CUR_STREAM (stream)->par_h, NULL);
8571       }
8572
8573       if (CUR_STREAM (stream)->interlace_mode > 0) {
8574         if (CUR_STREAM (stream)->interlace_mode == 1) {
8575           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8576               G_TYPE_STRING, "progressive", NULL);
8577         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8578           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8579               G_TYPE_STRING, "interleaved", NULL);
8580           if (CUR_STREAM (stream)->field_order == 9) {
8581             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8582                 G_TYPE_STRING, "top-field-first", NULL);
8583           } else if (CUR_STREAM (stream)->field_order == 14) {
8584             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8585                 G_TYPE_STRING, "bottom-field-first", NULL);
8586           }
8587         }
8588       }
8589
8590       /* Create incomplete colorimetry here if needed */
8591       if (CUR_STREAM (stream)->colorimetry.range ||
8592           CUR_STREAM (stream)->colorimetry.matrix ||
8593           CUR_STREAM (stream)->colorimetry.transfer
8594           || CUR_STREAM (stream)->colorimetry.primaries) {
8595         gchar *colorimetry =
8596             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8597         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8598             G_TYPE_STRING, colorimetry, NULL);
8599         g_free (colorimetry);
8600       }
8601
8602       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8603         guint par_w = 1, par_h = 1;
8604
8605         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8606           par_w = CUR_STREAM (stream)->par_w;
8607           par_h = CUR_STREAM (stream)->par_h;
8608         }
8609
8610         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8611                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8612                 par_h)) {
8613           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8614         }
8615
8616         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8617             "multiview-mode", G_TYPE_STRING,
8618             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8619             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8620             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8621       }
8622     }
8623   }
8624
8625   else if (stream->subtype == FOURCC_soun) {
8626     if (CUR_STREAM (stream)->caps) {
8627       CUR_STREAM (stream)->caps =
8628           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8629       if (CUR_STREAM (stream)->rate > 0)
8630         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8631             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8632       if (CUR_STREAM (stream)->n_channels > 0)
8633         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8634             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8635       if (CUR_STREAM (stream)->n_channels > 2) {
8636         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8637          * correctly; this is just the minimum we can do - assume
8638          * we don't actually have any channel positions. */
8639         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8640             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8641       }
8642     }
8643   }
8644
8645   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8646     const GstStructure *s;
8647     QtDemuxStream *fps_stream = NULL;
8648     gboolean fps_available = FALSE;
8649
8650     /* CEA608 closed caption tracks are a bit special in that each sample
8651      * can contain CCs for multiple frames, and CCs can be omitted and have to
8652      * be inferred from the duration of the sample then.
8653      *
8654      * As such we take the framerate from the (first) video track here for
8655      * CEA608 as there must be one CC byte pair for every video frame
8656      * according to the spec.
8657      *
8658      * For CEA708 all is fine and there is one sample per frame.
8659      */
8660
8661     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8662     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8663       gint i;
8664
8665       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8666         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8667
8668         if (tmp->subtype == FOURCC_vide) {
8669           fps_stream = tmp;
8670           break;
8671         }
8672       }
8673
8674       if (fps_stream) {
8675         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8676         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8677         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8678       }
8679     } else {
8680       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8681       fps_stream = stream;
8682     }
8683
8684     CUR_STREAM (stream)->caps =
8685         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8686
8687     /* set framerate if calculated framerate is reliable */
8688     if (fps_available) {
8689       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8690           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8691           CUR_STREAM (stream)->fps_d, NULL);
8692     }
8693   }
8694
8695   if (stream->pad) {
8696     GstCaps *prev_caps = NULL;
8697
8698     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8699     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8700     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8701     gst_pad_set_active (stream->pad, TRUE);
8702
8703     gst_pad_use_fixed_caps (stream->pad);
8704
8705     if (stream->protected) {
8706       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8707         GST_ERROR_OBJECT (qtdemux,
8708             "Failed to configure protected stream caps.");
8709         return FALSE;
8710       }
8711     }
8712
8713     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8714         CUR_STREAM (stream)->caps);
8715     if (stream->new_stream) {
8716       GstEvent *event;
8717       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8718
8719       event =
8720           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8721           0);
8722       if (event) {
8723         gst_event_parse_stream_flags (event, &stream_flags);
8724         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8725           qtdemux->have_group_id = TRUE;
8726         else
8727           qtdemux->have_group_id = FALSE;
8728         gst_event_unref (event);
8729       } else if (!qtdemux->have_group_id) {
8730         qtdemux->have_group_id = TRUE;
8731         qtdemux->group_id = gst_util_group_id_next ();
8732       }
8733
8734       stream->new_stream = FALSE;
8735       event = gst_event_new_stream_start (stream->stream_id);
8736       if (qtdemux->have_group_id)
8737         gst_event_set_group_id (event, qtdemux->group_id);
8738       if (stream->disabled)
8739         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8740       if (CUR_STREAM (stream)->sparse) {
8741         stream_flags |= GST_STREAM_FLAG_SPARSE;
8742       } else {
8743         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8744       }
8745       gst_event_set_stream_flags (event, stream_flags);
8746       gst_pad_push_event (stream->pad, event);
8747     }
8748
8749     prev_caps = gst_pad_get_current_caps (stream->pad);
8750
8751     if (CUR_STREAM (stream)->caps) {
8752       if (!prev_caps
8753           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8754         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8755             CUR_STREAM (stream)->caps);
8756         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8757       } else {
8758         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8759       }
8760     } else {
8761       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8762     }
8763
8764     if (prev_caps)
8765       gst_caps_unref (prev_caps);
8766     stream->new_caps = FALSE;
8767   }
8768   return TRUE;
8769 }
8770
8771 static void
8772 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8773     QtDemuxStream * stream)
8774 {
8775   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8776     return;
8777
8778   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8779       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8780   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8781           stream->stsd_entries_length)) {
8782     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8783         (_("This file is invalid and cannot be played.")),
8784         ("New sample description id is out of bounds (%d >= %d)",
8785             stream->stsd_sample_description_id, stream->stsd_entries_length));
8786   } else {
8787     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8788     stream->new_caps = TRUE;
8789   }
8790 }
8791
8792 static gboolean
8793 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8794     QtDemuxStream * stream, GstTagList * list)
8795 {
8796   gboolean ret = TRUE;
8797
8798   if (stream->subtype == FOURCC_vide) {
8799     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8800
8801     stream->pad =
8802         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8803     g_free (name);
8804
8805     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8806       gst_object_unref (stream->pad);
8807       stream->pad = NULL;
8808       ret = FALSE;
8809       goto done;
8810     }
8811
8812     qtdemux->n_video_streams++;
8813   } else if (stream->subtype == FOURCC_soun) {
8814     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8815
8816     stream->pad =
8817         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8818     g_free (name);
8819     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8820       gst_object_unref (stream->pad);
8821       stream->pad = NULL;
8822       ret = FALSE;
8823       goto done;
8824     }
8825     qtdemux->n_audio_streams++;
8826   } else if (stream->subtype == FOURCC_strm) {
8827     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8828   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8829       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8830       || stream->subtype == FOURCC_clcp) {
8831     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8832
8833     stream->pad =
8834         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8835     g_free (name);
8836     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8837       gst_object_unref (stream->pad);
8838       stream->pad = NULL;
8839       ret = FALSE;
8840       goto done;
8841     }
8842     qtdemux->n_sub_streams++;
8843   } else if (CUR_STREAM (stream)->caps) {
8844     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8845
8846     stream->pad =
8847         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8848     g_free (name);
8849     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8850       gst_object_unref (stream->pad);
8851       stream->pad = NULL;
8852       ret = FALSE;
8853       goto done;
8854     }
8855     qtdemux->n_video_streams++;
8856   } else {
8857     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8858     goto done;
8859   }
8860
8861   if (stream->pad) {
8862     GList *l;
8863
8864     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8865         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8866     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8867     GST_OBJECT_LOCK (qtdemux);
8868     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8869     GST_OBJECT_UNLOCK (qtdemux);
8870
8871     if (stream->stream_tags)
8872       gst_tag_list_unref (stream->stream_tags);
8873     stream->stream_tags = list;
8874     list = NULL;
8875     /* global tags go on each pad anyway */
8876     stream->send_global_tags = TRUE;
8877     /* send upstream GST_EVENT_PROTECTION events that were received before
8878        this source pad was created */
8879     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8880       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8881   }
8882 done:
8883   if (list)
8884     gst_tag_list_unref (list);
8885   return ret;
8886 }
8887
8888 /* find next atom with @fourcc starting at @offset */
8889 static GstFlowReturn
8890 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8891     guint64 * length, guint32 fourcc)
8892 {
8893   GstFlowReturn ret;
8894   guint32 lfourcc;
8895   GstBuffer *buf;
8896
8897   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8898       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8899
8900   while (TRUE) {
8901     GstMapInfo map;
8902
8903     buf = NULL;
8904     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8905     if (G_UNLIKELY (ret != GST_FLOW_OK))
8906       goto locate_failed;
8907     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8908       /* likely EOF */
8909       ret = GST_FLOW_EOS;
8910       gst_buffer_unref (buf);
8911       goto locate_failed;
8912     }
8913     gst_buffer_map (buf, &map, GST_MAP_READ);
8914     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8915     gst_buffer_unmap (buf, &map);
8916     gst_buffer_unref (buf);
8917
8918     if (G_UNLIKELY (*length == 0)) {
8919       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8920       ret = GST_FLOW_ERROR;
8921       goto locate_failed;
8922     }
8923
8924     if (lfourcc == fourcc) {
8925       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
8926           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8927       break;
8928     } else {
8929       GST_LOG_OBJECT (qtdemux,
8930           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8931           GST_FOURCC_ARGS (lfourcc), *offset);
8932       if (*offset == G_MAXUINT64)
8933         goto locate_failed;
8934       *offset += *length;
8935     }
8936   }
8937
8938   return GST_FLOW_OK;
8939
8940 locate_failed:
8941   {
8942     /* might simply have had last one */
8943     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8944     return ret;
8945   }
8946 }
8947
8948 /* should only do something in pull mode */
8949 /* call with OBJECT lock */
8950 static GstFlowReturn
8951 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8952 {
8953   guint64 length, offset;
8954   GstBuffer *buf = NULL;
8955   GstFlowReturn ret = GST_FLOW_OK;
8956   GstFlowReturn res = GST_FLOW_OK;
8957   GstMapInfo map;
8958
8959   offset = qtdemux->moof_offset;
8960   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8961
8962   if (!offset) {
8963     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8964     return GST_FLOW_EOS;
8965   }
8966
8967   /* best not do pull etc with lock held */
8968   GST_OBJECT_UNLOCK (qtdemux);
8969
8970   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8971   if (ret != GST_FLOW_OK)
8972     goto flow_failed;
8973
8974   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8975   if (G_UNLIKELY (ret != GST_FLOW_OK))
8976     goto flow_failed;
8977   gst_buffer_map (buf, &map, GST_MAP_READ);
8978   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8979     gst_buffer_unmap (buf, &map);
8980     gst_buffer_unref (buf);
8981     buf = NULL;
8982     goto parse_failed;
8983   }
8984
8985   gst_buffer_unmap (buf, &map);
8986   gst_buffer_unref (buf);
8987   buf = NULL;
8988
8989   offset += length;
8990   /* look for next moof */
8991   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8992   if (G_UNLIKELY (ret != GST_FLOW_OK))
8993     goto flow_failed;
8994
8995 exit:
8996   GST_OBJECT_LOCK (qtdemux);
8997
8998   qtdemux->moof_offset = offset;
8999
9000   return res;
9001
9002 parse_failed:
9003   {
9004     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9005     offset = 0;
9006     res = GST_FLOW_ERROR;
9007     goto exit;
9008   }
9009 flow_failed:
9010   {
9011     /* maybe upstream temporarily flushing */
9012     if (ret != GST_FLOW_FLUSHING) {
9013       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9014       offset = 0;
9015     } else {
9016       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9017       /* resume at current position next time */
9018     }
9019     res = ret;
9020     goto exit;
9021   }
9022 }
9023
9024 static void
9025 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9026 {
9027   guint i;
9028   guint32 num_chunks;
9029   gint32 stts_duration;
9030   GstByteWriter stsc, stts, stsz;
9031
9032   /* Each sample has a different size, which we don't support for merging */
9033   if (stream->sample_size == 0) {
9034     GST_DEBUG_OBJECT (qtdemux,
9035         "Not all samples have the same size, not merging");
9036     return;
9037   }
9038
9039   /* The stream has a ctts table, we don't support that */
9040   if (stream->ctts_present) {
9041     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9042     return;
9043   }
9044
9045   /* If there's a sync sample table also ignore this stream */
9046   if (stream->stps_present || stream->stss_present) {
9047     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9048     return;
9049   }
9050
9051   /* If chunks are considered samples already ignore this stream */
9052   if (stream->chunks_are_samples) {
9053     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9054     return;
9055   }
9056
9057   /* Require that all samples have the same duration */
9058   if (stream->n_sample_times > 1) {
9059     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9060     return;
9061   }
9062
9063   /* Parse the stts to get the sample duration and number of samples */
9064   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9065   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9066
9067   /* Parse the number of chunks from the stco manually because the
9068    * reader is already behind that */
9069   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9070
9071   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9072       num_chunks);
9073
9074   /* Now parse stsc, convert chunks into single samples and generate a
9075    * new stsc, stts and stsz from this information */
9076   gst_byte_writer_init (&stsc);
9077   gst_byte_writer_init (&stts);
9078   gst_byte_writer_init (&stsz);
9079
9080   /* Note: we skip fourccs, size, version, flags and other fields of the new
9081    * atoms as the byte readers with them are already behind that position
9082    * anyway and only update the values of those inside the stream directly.
9083    */
9084   stream->n_sample_times = 0;
9085   stream->n_samples = 0;
9086   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9087     guint j;
9088     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9089
9090     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9091     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9092     sample_description_id =
9093         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9094
9095     if (i == stream->n_samples_per_chunk - 1) {
9096       /* +1 because first_chunk is 1-based */
9097       last_chunk = num_chunks + 1;
9098     } else {
9099       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9100     }
9101
9102     GST_DEBUG_OBJECT (qtdemux,
9103         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9104         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9105
9106     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9107     /* One sample in this chunk */
9108     gst_byte_writer_put_uint32_be (&stsc, 1);
9109     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9110
9111     /* For each chunk write a stts and stsz entry now */
9112     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9113     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9114     for (j = first_chunk; j < last_chunk; j++) {
9115       gst_byte_writer_put_uint32_be (&stsz,
9116           stream->sample_size * samples_per_chunk);
9117     }
9118
9119     stream->n_sample_times += 1;
9120     stream->n_samples += last_chunk - first_chunk;
9121   }
9122
9123   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9124
9125   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9126       stream->n_samples, stream->n_sample_times);
9127
9128   /* We don't have a fixed sample size anymore */
9129   stream->sample_size = 0;
9130
9131   /* Free old data for the atoms */
9132   g_free ((gpointer) stream->stsz.data);
9133   stream->stsz.data = NULL;
9134   g_free ((gpointer) stream->stsc.data);
9135   stream->stsc.data = NULL;
9136   g_free ((gpointer) stream->stts.data);
9137   stream->stts.data = NULL;
9138
9139   /* Store new data and replace byte readers */
9140   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9141   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9142   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9143   stream->stts.size = gst_byte_writer_get_size (&stts);
9144   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9145   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9146   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9147   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9148   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9149 }
9150
9151 /* initialise bytereaders for stbl sub-atoms */
9152 static gboolean
9153 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9154 {
9155   stream->stbl_index = -1;      /* no samples have yet been parsed */
9156   stream->sample_index = -1;
9157
9158   /* time-to-sample atom */
9159   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9160     goto corrupt_file;
9161
9162   /* copy atom data into a new buffer for later use */
9163   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9164
9165   /* skip version + flags */
9166   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9167       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9168     goto corrupt_file;
9169   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9170
9171   /* make sure there's enough data */
9172   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9173     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9174     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9175         stream->n_sample_times);
9176     if (!stream->n_sample_times)
9177       goto corrupt_file;
9178   }
9179
9180   /* sync sample atom */
9181   stream->stps_present = FALSE;
9182   if ((stream->stss_present =
9183           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9184               &stream->stss) ? TRUE : FALSE) == TRUE) {
9185     /* copy atom data into a new buffer for later use */
9186     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9187
9188     /* skip version + flags */
9189     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9190         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9191       goto corrupt_file;
9192
9193     if (stream->n_sample_syncs) {
9194       /* make sure there's enough data */
9195       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9196         goto corrupt_file;
9197     }
9198
9199     /* partial sync sample atom */
9200     if ((stream->stps_present =
9201             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9202                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9203       /* copy atom data into a new buffer for later use */
9204       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9205
9206       /* skip version + flags */
9207       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9208           !gst_byte_reader_get_uint32_be (&stream->stps,
9209               &stream->n_sample_partial_syncs))
9210         goto corrupt_file;
9211
9212       /* if there are no entries, the stss table contains the real
9213        * sync samples */
9214       if (stream->n_sample_partial_syncs) {
9215         /* make sure there's enough data */
9216         if (!qt_atom_parser_has_chunks (&stream->stps,
9217                 stream->n_sample_partial_syncs, 4))
9218           goto corrupt_file;
9219       }
9220     }
9221   }
9222
9223   /* sample size */
9224   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9225     goto no_samples;
9226
9227   /* copy atom data into a new buffer for later use */
9228   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9229
9230   /* skip version + flags */
9231   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9232       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9233     goto corrupt_file;
9234
9235   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9236     goto corrupt_file;
9237
9238   if (!stream->n_samples)
9239     goto no_samples;
9240
9241   /* sample-to-chunk atom */
9242   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9243     goto corrupt_file;
9244
9245   /* copy atom data into a new buffer for later use */
9246   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9247
9248   /* skip version + flags */
9249   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9250       !gst_byte_reader_get_uint32_be (&stream->stsc,
9251           &stream->n_samples_per_chunk))
9252     goto corrupt_file;
9253
9254   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9255       stream->n_samples_per_chunk);
9256
9257   /* make sure there's enough data */
9258   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9259           12))
9260     goto corrupt_file;
9261
9262
9263   /* chunk offset */
9264   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9265     stream->co_size = sizeof (guint32);
9266   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9267           &stream->stco))
9268     stream->co_size = sizeof (guint64);
9269   else
9270     goto corrupt_file;
9271
9272   /* copy atom data into a new buffer for later use */
9273   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9274
9275   /* skip version + flags */
9276   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9277     goto corrupt_file;
9278
9279   /* chunks_are_samples == TRUE means treat chunks as samples */
9280   stream->chunks_are_samples = stream->sample_size
9281       && !CUR_STREAM (stream)->sampled;
9282   if (stream->chunks_are_samples) {
9283     /* treat chunks as samples */
9284     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9285       goto corrupt_file;
9286   } else {
9287     /* skip number of entries */
9288     if (!gst_byte_reader_skip (&stream->stco, 4))
9289       goto corrupt_file;
9290
9291     /* make sure there are enough data in the stsz atom */
9292     if (!stream->sample_size) {
9293       /* different sizes for each sample */
9294       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9295         goto corrupt_file;
9296     }
9297   }
9298
9299   /* composition time-to-sample */
9300   if ((stream->ctts_present =
9301           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9302               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9303     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9304
9305     /* copy atom data into a new buffer for later use */
9306     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9307
9308     /* skip version + flags */
9309     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9310         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9311             &stream->n_composition_times))
9312       goto corrupt_file;
9313
9314     /* make sure there's enough data */
9315     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9316             4 + 4))
9317       goto corrupt_file;
9318
9319     /* This is optional, if missing we iterate the ctts */
9320     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9321       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9322           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9323         g_free ((gpointer) cslg.data);
9324         goto corrupt_file;
9325       }
9326     } else {
9327       gint32 cslg_least = 0;
9328       guint num_entries, pos;
9329       gint i;
9330
9331       pos = gst_byte_reader_get_pos (&stream->ctts);
9332       num_entries = stream->n_composition_times;
9333
9334       stream->cslg_shift = 0;
9335
9336       for (i = 0; i < num_entries; i++) {
9337         gint32 offset;
9338
9339         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9340         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9341         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9342          * slightly inaccurate PTS could be more usable than corrupted one */
9343         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9344           GST_WARNING_OBJECT (qtdemux,
9345               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9346               " larger than duration %" G_GUINT64_FORMAT,
9347               offset, stream->duration);
9348
9349           stream->cslg_shift = 0;
9350           stream->ctts_present = FALSE;
9351           goto done;
9352         }
9353
9354         if (offset < cslg_least)
9355           cslg_least = offset;
9356       }
9357
9358       if (cslg_least < 0)
9359         stream->cslg_shift = ABS (cslg_least);
9360       else
9361         stream->cslg_shift = 0;
9362
9363       /* reset the reader so we can generate sample table */
9364       gst_byte_reader_set_pos (&stream->ctts, pos);
9365     }
9366   } else {
9367     /* Ensure the cslg_shift value is consistent so we can use it
9368      * unconditionally to produce TS and Segment */
9369     stream->cslg_shift = 0;
9370   }
9371
9372   /* For raw audio streams especially we might want to merge the samples
9373    * to not output one audio sample per buffer. We're doing this here
9374    * before allocating the sample tables so that from this point onwards
9375    * the number of container samples are static */
9376   if (stream->min_buffer_size > 0) {
9377     qtdemux_merge_sample_table (qtdemux, stream);
9378   }
9379
9380 done:
9381   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9382       stream->n_samples, (guint) sizeof (QtDemuxSample),
9383       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9384
9385   if (stream->n_samples >=
9386       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9387     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9388         "be larger than %uMB (broken file?)", stream->n_samples,
9389         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9390     return FALSE;
9391   }
9392
9393   g_assert (stream->samples == NULL);
9394   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9395   if (!stream->samples) {
9396     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9397         stream->n_samples);
9398     return FALSE;
9399   }
9400
9401   return TRUE;
9402
9403 corrupt_file:
9404   {
9405     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9406         (_("This file is corrupt and cannot be played.")), (NULL));
9407     return FALSE;
9408   }
9409 no_samples:
9410   {
9411     gst_qtdemux_stbl_free (stream);
9412     if (!qtdemux->fragmented) {
9413       /* not quite good */
9414       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9415       return FALSE;
9416     } else {
9417       /* may pick up samples elsewhere */
9418       return TRUE;
9419     }
9420   }
9421 }
9422
9423 /* collect samples from the next sample to be parsed up to sample @n for @stream
9424  * by reading the info from @stbl
9425  *
9426  * This code can be executed from both the streaming thread and the seeking
9427  * thread so it takes the object lock to protect itself
9428  */
9429 static gboolean
9430 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9431 {
9432   gint i, j, k;
9433   QtDemuxSample *samples, *first, *cur, *last;
9434   guint32 n_samples_per_chunk;
9435   guint32 n_samples;
9436
9437   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9438       GST_FOURCC_FORMAT ", pad %s",
9439       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9440       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9441
9442   n_samples = stream->n_samples;
9443
9444   if (n >= n_samples)
9445     goto out_of_samples;
9446
9447   GST_OBJECT_LOCK (qtdemux);
9448   if (n <= stream->stbl_index)
9449     goto already_parsed;
9450
9451   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9452
9453   if (!stream->stsz.data) {
9454     /* so we already parsed and passed all the moov samples;
9455      * onto fragmented ones */
9456     g_assert (qtdemux->fragmented);
9457     goto done;
9458   }
9459
9460   /* pointer to the sample table */
9461   samples = stream->samples;
9462
9463   /* starts from -1, moves to the next sample index to parse */
9464   stream->stbl_index++;
9465
9466   /* keep track of the first and last sample to fill */
9467   first = &samples[stream->stbl_index];
9468   last = &samples[n];
9469
9470   if (!stream->chunks_are_samples) {
9471     /* set the sample sizes */
9472     if (stream->sample_size == 0) {
9473       /* different sizes for each sample */
9474       for (cur = first; cur <= last; cur++) {
9475         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9476         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9477             (guint) (cur - samples), cur->size);
9478       }
9479     } else {
9480       /* samples have the same size */
9481       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9482       for (cur = first; cur <= last; cur++)
9483         cur->size = stream->sample_size;
9484     }
9485   }
9486
9487   n_samples_per_chunk = stream->n_samples_per_chunk;
9488   cur = first;
9489
9490   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9491     guint32 last_chunk;
9492
9493     if (stream->stsc_chunk_index >= stream->last_chunk
9494         || stream->stsc_chunk_index < stream->first_chunk) {
9495       stream->first_chunk =
9496           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9497       stream->samples_per_chunk =
9498           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9499       /* starts from 1 */
9500       stream->stsd_sample_description_id =
9501           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9502
9503       /* chunk numbers are counted from 1 it seems */
9504       if (G_UNLIKELY (stream->first_chunk == 0))
9505         goto corrupt_file;
9506
9507       --stream->first_chunk;
9508
9509       /* the last chunk of each entry is calculated by taking the first chunk
9510        * of the next entry; except if there is no next, where we fake it with
9511        * INT_MAX */
9512       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9513         stream->last_chunk = G_MAXUINT32;
9514       } else {
9515         stream->last_chunk =
9516             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9517         if (G_UNLIKELY (stream->last_chunk == 0))
9518           goto corrupt_file;
9519
9520         --stream->last_chunk;
9521       }
9522
9523       GST_LOG_OBJECT (qtdemux,
9524           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9525           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9526           stream->samples_per_chunk, stream->stsd_sample_description_id);
9527
9528       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9529         goto corrupt_file;
9530
9531       if (stream->last_chunk != G_MAXUINT32) {
9532         if (!qt_atom_parser_peek_sub (&stream->stco,
9533                 stream->first_chunk * stream->co_size,
9534                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9535                 &stream->co_chunk))
9536           goto corrupt_file;
9537
9538       } else {
9539         stream->co_chunk = stream->stco;
9540         if (!gst_byte_reader_skip (&stream->co_chunk,
9541                 stream->first_chunk * stream->co_size))
9542           goto corrupt_file;
9543       }
9544
9545       stream->stsc_chunk_index = stream->first_chunk;
9546     }
9547
9548     last_chunk = stream->last_chunk;
9549
9550     if (stream->chunks_are_samples) {
9551       cur = &samples[stream->stsc_chunk_index];
9552
9553       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9554         if (j > n) {
9555           /* save state */
9556           stream->stsc_chunk_index = j;
9557           goto done;
9558         }
9559
9560         cur->offset =
9561             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9562             stream->co_size);
9563
9564         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9565             "%" G_GUINT64_FORMAT, j, cur->offset);
9566
9567         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9568             CUR_STREAM (stream)->bytes_per_frame > 0) {
9569           cur->size =
9570               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9571               CUR_STREAM (stream)->samples_per_frame *
9572               CUR_STREAM (stream)->bytes_per_frame;
9573         } else {
9574           cur->size = stream->samples_per_chunk;
9575         }
9576
9577         GST_DEBUG_OBJECT (qtdemux,
9578             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9579             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9580                     stream->stco_sample_index)), cur->size);
9581
9582         cur->timestamp = stream->stco_sample_index;
9583         cur->duration = stream->samples_per_chunk;
9584         cur->keyframe = TRUE;
9585         cur++;
9586
9587         stream->stco_sample_index += stream->samples_per_chunk;
9588       }
9589       stream->stsc_chunk_index = j;
9590     } else {
9591       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9592         guint32 samples_per_chunk;
9593         guint64 chunk_offset;
9594
9595         if (!stream->stsc_sample_index
9596             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9597                 &stream->chunk_offset))
9598           goto corrupt_file;
9599
9600         samples_per_chunk = stream->samples_per_chunk;
9601         chunk_offset = stream->chunk_offset;
9602
9603         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9604           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9605               G_GUINT64_FORMAT " and size %d",
9606               (guint) (cur - samples), chunk_offset, cur->size);
9607
9608           cur->offset = chunk_offset;
9609           chunk_offset += cur->size;
9610           cur++;
9611
9612           if (G_UNLIKELY (cur > last)) {
9613             /* save state */
9614             stream->stsc_sample_index = k + 1;
9615             stream->chunk_offset = chunk_offset;
9616             stream->stsc_chunk_index = j;
9617             goto done2;
9618           }
9619         }
9620         stream->stsc_sample_index = 0;
9621       }
9622       stream->stsc_chunk_index = j;
9623     }
9624     stream->stsc_index++;
9625   }
9626
9627   if (stream->chunks_are_samples)
9628     goto ctts;
9629 done2:
9630   {
9631     guint32 n_sample_times;
9632
9633     n_sample_times = stream->n_sample_times;
9634     cur = first;
9635
9636     for (i = stream->stts_index; i < n_sample_times; i++) {
9637       guint32 stts_samples;
9638       gint32 stts_duration;
9639       gint64 stts_time;
9640
9641       if (stream->stts_sample_index >= stream->stts_samples
9642           || !stream->stts_sample_index) {
9643
9644         stream->stts_samples =
9645             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9646         stream->stts_duration =
9647             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9648
9649         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9650             i, stream->stts_samples, stream->stts_duration);
9651
9652         stream->stts_sample_index = 0;
9653       }
9654
9655       stts_samples = stream->stts_samples;
9656       stts_duration = stream->stts_duration;
9657       stts_time = stream->stts_time;
9658
9659       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9660         GST_DEBUG_OBJECT (qtdemux,
9661             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9662             (guint) (cur - samples), j,
9663             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9664
9665         cur->timestamp = stts_time;
9666         cur->duration = stts_duration;
9667
9668         /* avoid 32-bit wrap-around,
9669          * but still mind possible 'negative' duration */
9670         stts_time += (gint64) stts_duration;
9671         cur++;
9672
9673         if (G_UNLIKELY (cur > last)) {
9674           /* save values */
9675           stream->stts_time = stts_time;
9676           stream->stts_sample_index = j + 1;
9677           if (stream->stts_sample_index >= stream->stts_samples)
9678             stream->stts_index++;
9679           goto done3;
9680         }
9681       }
9682       stream->stts_sample_index = 0;
9683       stream->stts_time = stts_time;
9684       stream->stts_index++;
9685     }
9686     /* fill up empty timestamps with the last timestamp, this can happen when
9687      * the last samples do not decode and so we don't have timestamps for them.
9688      * We however look at the last timestamp to estimate the track length so we
9689      * need something in here. */
9690     for (; cur < last; cur++) {
9691       GST_DEBUG_OBJECT (qtdemux,
9692           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9693           (guint) (cur - samples),
9694           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9695       cur->timestamp = stream->stts_time;
9696       cur->duration = -1;
9697     }
9698   }
9699 done3:
9700   {
9701     /* sample sync, can be NULL */
9702     if (stream->stss_present == TRUE) {
9703       guint32 n_sample_syncs;
9704
9705       n_sample_syncs = stream->n_sample_syncs;
9706
9707       if (!n_sample_syncs) {
9708         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9709         stream->all_keyframe = TRUE;
9710       } else {
9711         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9712           /* note that the first sample is index 1, not 0 */
9713           guint32 index;
9714
9715           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9716
9717           if (G_LIKELY (index > 0 && index <= n_samples)) {
9718             index -= 1;
9719             samples[index].keyframe = TRUE;
9720             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9721             /* and exit if we have enough samples */
9722             if (G_UNLIKELY (index >= n)) {
9723               i++;
9724               break;
9725             }
9726           }
9727         }
9728         /* save state */
9729         stream->stss_index = i;
9730       }
9731
9732       /* stps marks partial sync frames like open GOP I-Frames */
9733       if (stream->stps_present == TRUE) {
9734         guint32 n_sample_partial_syncs;
9735
9736         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9737
9738         /* if there are no entries, the stss table contains the real
9739          * sync samples */
9740         if (n_sample_partial_syncs) {
9741           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9742             /* note that the first sample is index 1, not 0 */
9743             guint32 index;
9744
9745             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9746
9747             if (G_LIKELY (index > 0 && index <= n_samples)) {
9748               index -= 1;
9749               samples[index].keyframe = TRUE;
9750               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9751               /* and exit if we have enough samples */
9752               if (G_UNLIKELY (index >= n)) {
9753                 i++;
9754                 break;
9755               }
9756             }
9757           }
9758           /* save state */
9759           stream->stps_index = i;
9760         }
9761       }
9762     } else {
9763       /* no stss, all samples are keyframes */
9764       stream->all_keyframe = TRUE;
9765       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9766     }
9767   }
9768
9769 ctts:
9770   /* composition time to sample */
9771   if (stream->ctts_present == TRUE) {
9772     guint32 n_composition_times;
9773     guint32 ctts_count;
9774     gint32 ctts_soffset;
9775
9776     /* Fill in the pts_offsets */
9777     cur = first;
9778     n_composition_times = stream->n_composition_times;
9779
9780     for (i = stream->ctts_index; i < n_composition_times; i++) {
9781       if (stream->ctts_sample_index >= stream->ctts_count
9782           || !stream->ctts_sample_index) {
9783         stream->ctts_count =
9784             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9785         stream->ctts_soffset =
9786             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9787         stream->ctts_sample_index = 0;
9788       }
9789
9790       ctts_count = stream->ctts_count;
9791       ctts_soffset = stream->ctts_soffset;
9792
9793       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9794         cur->pts_offset = ctts_soffset;
9795         cur++;
9796
9797         if (G_UNLIKELY (cur > last)) {
9798           /* save state */
9799           stream->ctts_sample_index = j + 1;
9800           goto done;
9801         }
9802       }
9803       stream->ctts_sample_index = 0;
9804       stream->ctts_index++;
9805     }
9806   }
9807 done:
9808   stream->stbl_index = n;
9809   /* if index has been completely parsed, free data that is no-longer needed */
9810   if (n + 1 == stream->n_samples) {
9811     gst_qtdemux_stbl_free (stream);
9812     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9813     if (qtdemux->pullbased) {
9814       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9815       while (n + 1 == stream->n_samples)
9816         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9817           break;
9818     }
9819   }
9820   GST_OBJECT_UNLOCK (qtdemux);
9821
9822   return TRUE;
9823
9824   /* SUCCESS */
9825 already_parsed:
9826   {
9827     GST_LOG_OBJECT (qtdemux,
9828         "Tried to parse up to sample %u but this sample has already been parsed",
9829         n);
9830     /* if fragmented, there may be more */
9831     if (qtdemux->fragmented && n == stream->stbl_index)
9832       goto done;
9833     GST_OBJECT_UNLOCK (qtdemux);
9834     return TRUE;
9835   }
9836   /* ERRORS */
9837 out_of_samples:
9838   {
9839     GST_LOG_OBJECT (qtdemux,
9840         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9841         stream->n_samples);
9842     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9843         (_("This file is corrupt and cannot be played.")), (NULL));
9844     return FALSE;
9845   }
9846 corrupt_file:
9847   {
9848     GST_OBJECT_UNLOCK (qtdemux);
9849     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9850         (_("This file is corrupt and cannot be played.")), (NULL));
9851     return FALSE;
9852   }
9853 }
9854
9855 /* collect all segment info for @stream.
9856  */
9857 static gboolean
9858 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9859     GNode * trak)
9860 {
9861   GNode *edts;
9862   /* accept edts if they contain gaps at start and there is only
9863    * one media segment */
9864   gboolean allow_pushbased_edts = TRUE;
9865   gint media_segments_count = 0;
9866
9867   /* parse and prepare segment info from the edit list */
9868   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9869   stream->n_segments = 0;
9870   stream->segments = NULL;
9871   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9872     GNode *elst;
9873     gint n_segments;
9874     gint segment_number, entry_size;
9875     guint64 time;
9876     GstClockTime stime;
9877     const guint8 *buffer;
9878     guint8 version;
9879     guint32 size;
9880
9881     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9882     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9883       goto done;
9884
9885     buffer = elst->data;
9886
9887     size = QT_UINT32 (buffer);
9888     /* version, flags, n_segments */
9889     if (size < 16) {
9890       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9891       goto done;
9892     }
9893     version = QT_UINT8 (buffer + 8);
9894     entry_size = (version == 1) ? 20 : 12;
9895
9896     n_segments = QT_UINT32 (buffer + 12);
9897
9898     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9899       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9900       goto done;
9901     }
9902
9903     /* we might allocate a bit too much, at least allocate 1 segment */
9904     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9905
9906     /* segments always start from 0 */
9907     time = 0;
9908     stime = 0;
9909     buffer += 16;
9910     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9911       guint64 duration;
9912       guint64 media_time;
9913       gboolean empty_edit = FALSE;
9914       QtDemuxSegment *segment;
9915       guint32 rate_int;
9916       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9917
9918       if (version == 1) {
9919         media_time = QT_UINT64 (buffer + 8);
9920         duration = QT_UINT64 (buffer);
9921         if (media_time == G_MAXUINT64)
9922           empty_edit = TRUE;
9923       } else {
9924         media_time = QT_UINT32 (buffer + 4);
9925         duration = QT_UINT32 (buffer);
9926         if (media_time == G_MAXUINT32)
9927           empty_edit = TRUE;
9928       }
9929
9930       if (!empty_edit)
9931         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9932
9933       segment = &stream->segments[segment_number];
9934
9935       /* time and duration expressed in global timescale */
9936       segment->time = stime;
9937       if (duration != 0 || empty_edit) {
9938         /* edge case: empty edits with duration=zero are treated here.
9939          * (files should not have these anyway). */
9940
9941         /* add non scaled values so we don't cause roundoff errors */
9942         time += duration;
9943         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9944         segment->duration = stime - segment->time;
9945       } else {
9946         /* zero duration does not imply media_start == media_stop
9947          * but, only specify media_start. The edit ends with the track. */
9948         stime = segment->duration = GST_CLOCK_TIME_NONE;
9949         /* Don't allow more edits after this one. */
9950         n_segments = segment_number + 1;
9951       }
9952       segment->stop_time = stime;
9953
9954       segment->trak_media_start = media_time;
9955       /* media_time expressed in stream timescale */
9956       if (!empty_edit) {
9957         segment->media_start = media_start;
9958         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9959             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9960         media_segments_count++;
9961       } else {
9962         segment->media_start = GST_CLOCK_TIME_NONE;
9963         segment->media_stop = GST_CLOCK_TIME_NONE;
9964       }
9965       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9966
9967       if (rate_int <= 1) {
9968         /* 0 is not allowed, some programs write 1 instead of the floating point
9969          * value */
9970         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9971             rate_int);
9972         segment->rate = 1;
9973       } else {
9974         segment->rate = rate_int / 65536.0;
9975       }
9976
9977       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9978           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9979           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9980           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9981           segment_number, GST_TIME_ARGS (segment->time),
9982           GST_TIME_ARGS (segment->duration),
9983           GST_TIME_ARGS (segment->media_start), media_time,
9984           GST_TIME_ARGS (segment->media_stop),
9985           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9986           stream->timescale);
9987       if (segment->stop_time > qtdemux->segment.stop &&
9988           !qtdemux->upstream_format_is_time) {
9989         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9990             " extends to %" GST_TIME_FORMAT
9991             " past the end of the declared movie duration %" GST_TIME_FORMAT
9992             " movie segment will be extended", segment_number,
9993             GST_TIME_ARGS (segment->stop_time),
9994             GST_TIME_ARGS (qtdemux->segment.stop));
9995         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9996       }
9997
9998       buffer += entry_size;
9999     }
10000     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10001     stream->n_segments = n_segments;
10002     if (media_segments_count != 1)
10003       allow_pushbased_edts = FALSE;
10004   }
10005 done:
10006
10007   /* push based does not handle segments, so act accordingly here,
10008    * and warn if applicable */
10009   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10010     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10011     /* remove and use default one below, we stream like it anyway */
10012     g_free (stream->segments);
10013     stream->segments = NULL;
10014     stream->n_segments = 0;
10015   }
10016
10017   /* no segments, create one to play the complete trak */
10018   if (stream->n_segments == 0) {
10019     GstClockTime stream_duration =
10020         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10021
10022     if (stream->segments == NULL)
10023       stream->segments = g_new (QtDemuxSegment, 1);
10024
10025     /* represent unknown our way */
10026     if (stream_duration == 0)
10027       stream_duration = GST_CLOCK_TIME_NONE;
10028
10029     stream->segments[0].time = 0;
10030     stream->segments[0].stop_time = stream_duration;
10031     stream->segments[0].duration = stream_duration;
10032     stream->segments[0].media_start = 0;
10033     stream->segments[0].media_stop = stream_duration;
10034     stream->segments[0].rate = 1.0;
10035     stream->segments[0].trak_media_start = 0;
10036
10037     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10038         GST_TIME_ARGS (stream_duration));
10039     stream->n_segments = 1;
10040     stream->dummy_segment = TRUE;
10041   }
10042   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10043
10044   return TRUE;
10045 }
10046
10047 /*
10048  * Parses the stsd atom of a svq3 trak looking for
10049  * the SMI and gama atoms.
10050  */
10051 static void
10052 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10053     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10054 {
10055   const guint8 *_gamma = NULL;
10056   GstBuffer *_seqh = NULL;
10057   const guint8 *stsd_data = stsd_entry_data;
10058   guint32 length = QT_UINT32 (stsd_data);
10059   guint16 version;
10060
10061   if (length < 32) {
10062     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10063     goto end;
10064   }
10065
10066   stsd_data += 16;
10067   length -= 16;
10068   version = QT_UINT16 (stsd_data);
10069   if (version == 3) {
10070     if (length >= 70) {
10071       length -= 70;
10072       stsd_data += 70;
10073       while (length > 8) {
10074         guint32 fourcc, size;
10075         const guint8 *data;
10076         size = QT_UINT32 (stsd_data);
10077         fourcc = QT_FOURCC (stsd_data + 4);
10078         data = stsd_data + 8;
10079
10080         if (size == 0) {
10081           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10082               "svq3 atom parsing");
10083           goto end;
10084         }
10085
10086         switch (fourcc) {
10087           case FOURCC_gama:{
10088             if (size == 12) {
10089               _gamma = data;
10090             } else {
10091               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10092                   " for gama atom, expected 12", size);
10093             }
10094             break;
10095           }
10096           case FOURCC_SMI_:{
10097             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10098               guint32 seqh_size;
10099               if (_seqh != NULL) {
10100                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10101                     " found, ignoring");
10102               } else {
10103                 seqh_size = QT_UINT32 (data + 4);
10104                 if (seqh_size > 0) {
10105                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10106                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10107                 }
10108               }
10109             }
10110             break;
10111           }
10112           default:{
10113             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10114                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10115           }
10116         }
10117
10118         if (size <= length) {
10119           length -= size;
10120           stsd_data += size;
10121         }
10122       }
10123     } else {
10124       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10125     }
10126   } else {
10127     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10128         G_GUINT16_FORMAT, version);
10129     goto end;
10130   }
10131
10132 end:
10133   if (gamma) {
10134     *gamma = _gamma;
10135   }
10136   if (seqh) {
10137     *seqh = _seqh;
10138   } else if (_seqh) {
10139     gst_buffer_unref (_seqh);
10140   }
10141 }
10142
10143 static gchar *
10144 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10145 {
10146   GNode *dinf;
10147   GstByteReader dref;
10148   gchar *uri = NULL;
10149
10150   /*
10151    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10152    * atom that might contain a 'data' atom with the rtsp uri.
10153    * This case was reported in bug #597497, some info about
10154    * the hndl atom can be found in TN1195
10155    */
10156   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10157   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10158
10159   if (dinf) {
10160     guint32 dref_num_entries = 0;
10161     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10162         gst_byte_reader_skip (&dref, 4) &&
10163         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10164       gint i;
10165
10166       /* search dref entries for hndl atom */
10167       for (i = 0; i < dref_num_entries; i++) {
10168         guint32 size = 0, type;
10169         guint8 string_len = 0;
10170         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10171             qt_atom_parser_get_fourcc (&dref, &type)) {
10172           if (type == FOURCC_hndl) {
10173             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10174
10175             /* skip data reference handle bytes and the
10176              * following pascal string and some extra 4
10177              * bytes I have no idea what are */
10178             if (!gst_byte_reader_skip (&dref, 4) ||
10179                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10180                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10181               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10182               break;
10183             }
10184
10185             /* iterate over the atoms to find the data atom */
10186             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10187               guint32 atom_size;
10188               guint32 atom_type;
10189
10190               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10191                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10192                 if (atom_type == FOURCC_data) {
10193                   const guint8 *uri_aux = NULL;
10194
10195                   /* found the data atom that might contain the rtsp uri */
10196                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10197                       "hndl atom, interpreting it as an URI");
10198                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10199                           &uri_aux)) {
10200                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10201                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10202                     else
10203                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10204                           "didn't contain a rtsp address");
10205                   } else {
10206                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10207                         "atom contents");
10208                   }
10209                   break;
10210                 }
10211                 /* skipping to the next entry */
10212                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10213                   break;
10214               } else {
10215                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10216                     "atom header");
10217                 break;
10218               }
10219             }
10220             break;
10221           }
10222           /* skip to the next entry */
10223           if (!gst_byte_reader_skip (&dref, size - 8))
10224             break;
10225         } else {
10226           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10227         }
10228       }
10229       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10230     }
10231   }
10232   return uri;
10233 }
10234
10235 #define AMR_NB_ALL_MODES        0x81ff
10236 #define AMR_WB_ALL_MODES        0x83ff
10237 static guint
10238 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10239 {
10240   /* The 'damr' atom is of the form:
10241    *
10242    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10243    *    32 b       8 b          16 b           8 b                 8 b
10244    *
10245    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10246    * represents the highest mode used in the stream (and thus the maximum
10247    * bitrate), with a couple of special cases as seen below.
10248    */
10249
10250   /* Map of frame type ID -> bitrate */
10251   static const guint nb_bitrates[] = {
10252     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10253   };
10254   static const guint wb_bitrates[] = {
10255     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10256   };
10257   GstMapInfo map;
10258   gsize max_mode;
10259   guint16 mode_set;
10260
10261   gst_buffer_map (buf, &map, GST_MAP_READ);
10262
10263   if (map.size != 0x11) {
10264     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10265     goto bad_data;
10266   }
10267
10268   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10269     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10270         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10271     goto bad_data;
10272   }
10273
10274   mode_set = QT_UINT16 (map.data + 13);
10275
10276   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10277     max_mode = 7 + (wb ? 1 : 0);
10278   else
10279     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10280     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10281
10282   if (max_mode == -1) {
10283     GST_DEBUG ("No mode indication was found (mode set) = %x",
10284         (guint) mode_set);
10285     goto bad_data;
10286   }
10287
10288   gst_buffer_unmap (buf, &map);
10289   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10290
10291 bad_data:
10292   gst_buffer_unmap (buf, &map);
10293   return 0;
10294 }
10295
10296 static gboolean
10297 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10298     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10299 {
10300   /*
10301    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10302    * [0 1 2]
10303    * [3 4 5]
10304    * [6 7 8]
10305    */
10306
10307   if (gst_byte_reader_get_remaining (reader) < 36)
10308     return FALSE;
10309
10310   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10311   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10312   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10313   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10314   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10315   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10316   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10317   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10318   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10319
10320   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10321   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10322       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10323       matrix[2] & 0xFF);
10324   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10325       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10326       matrix[5] & 0xFF);
10327   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10328       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10329       matrix[8] & 0xFF);
10330
10331   return TRUE;
10332 }
10333
10334 static void
10335 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10336     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10337 {
10338
10339 /* [a b c]
10340  * [d e f]
10341  * [g h i]
10342  *
10343  * This macro will only compare value abdegh, it expects cfi to have already
10344  * been checked
10345  */
10346 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10347                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10348
10349   /* only handle the cases where the last column has standard values */
10350   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10351     const gchar *rotation_tag = NULL;
10352
10353     /* no rotation needed */
10354     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10355       /* NOP */
10356     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10357       rotation_tag = "rotate-90";
10358     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10359       rotation_tag = "rotate-180";
10360     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10361       rotation_tag = "rotate-270";
10362     } else {
10363       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10364     }
10365
10366     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10367         GST_STR_NULL (rotation_tag));
10368     if (rotation_tag != NULL) {
10369       if (*taglist == NULL)
10370         *taglist = gst_tag_list_new_empty ();
10371       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10372           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10373     }
10374   } else {
10375     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10376   }
10377 }
10378
10379 static gboolean
10380 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10381     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10382 {
10383   GNode *adrm;
10384   guint32 adrm_size;
10385   GstBuffer *adrm_buf = NULL;
10386   QtDemuxAavdEncryptionInfo *info;
10387
10388   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10389   if (G_UNLIKELY (!adrm)) {
10390     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10391     return FALSE;
10392   }
10393   adrm_size = QT_UINT32 (adrm->data);
10394   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10395
10396   stream->protection_scheme_type = FOURCC_aavd;
10397
10398   if (!stream->protection_scheme_info)
10399     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10400
10401   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10402
10403   if (info->default_properties)
10404     gst_structure_free (info->default_properties);
10405   info->default_properties = gst_structure_new ("application/x-aavd",
10406       "encrypted", G_TYPE_BOOLEAN, TRUE,
10407       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10408   gst_buffer_unref (adrm_buf);
10409
10410   *original_fmt = FOURCC_mp4a;
10411   return TRUE;
10412 }
10413
10414 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10415  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10416  * Common Encryption (cenc), the function will also parse the tenc box (defined
10417  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10418  * (typically an enc[v|a|t|s] sample entry); the function will set
10419  * @original_fmt to the fourcc of the original unencrypted stream format.
10420  * Returns TRUE if successful; FALSE otherwise. */
10421 static gboolean
10422 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10423     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10424 {
10425   GNode *sinf;
10426   GNode *frma;
10427   GNode *schm;
10428   GNode *schi;
10429   QtDemuxCencSampleSetInfo *info;
10430   GNode *tenc;
10431   const guint8 *tenc_data;
10432
10433   g_return_val_if_fail (qtdemux != NULL, FALSE);
10434   g_return_val_if_fail (stream != NULL, FALSE);
10435   g_return_val_if_fail (container != NULL, FALSE);
10436   g_return_val_if_fail (original_fmt != NULL, FALSE);
10437
10438   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10439   if (G_UNLIKELY (!sinf)) {
10440     if (stream->protection_scheme_type == FOURCC_cenc
10441         || stream->protection_scheme_type == FOURCC_cbcs) {
10442       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10443           "mandatory for Common Encryption");
10444       return FALSE;
10445     }
10446     return TRUE;
10447   }
10448
10449   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10450   if (G_UNLIKELY (!frma)) {
10451     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10452     return FALSE;
10453   }
10454
10455   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10456   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10457       GST_FOURCC_ARGS (*original_fmt));
10458
10459   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10460   if (!schm) {
10461     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10462     return FALSE;
10463   }
10464   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10465   stream->protection_scheme_version =
10466       QT_UINT32 ((const guint8 *) schm->data + 16);
10467
10468   GST_DEBUG_OBJECT (qtdemux,
10469       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10470       "protection_scheme_version: %#010x",
10471       GST_FOURCC_ARGS (stream->protection_scheme_type),
10472       stream->protection_scheme_version);
10473
10474   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10475   if (!schi) {
10476     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10477     return FALSE;
10478   }
10479   if (stream->protection_scheme_type != FOURCC_cenc &&
10480       stream->protection_scheme_type != FOURCC_piff &&
10481       stream->protection_scheme_type != FOURCC_cbcs) {
10482     GST_ERROR_OBJECT (qtdemux,
10483         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10484         GST_FOURCC_ARGS (stream->protection_scheme_type));
10485     return FALSE;
10486   }
10487
10488   if (G_UNLIKELY (!stream->protection_scheme_info))
10489     stream->protection_scheme_info =
10490         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10491
10492   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10493
10494   if (stream->protection_scheme_type == FOURCC_cenc
10495       || stream->protection_scheme_type == FOURCC_cbcs) {
10496     guint8 is_encrypted;
10497     guint8 iv_size;
10498     guint8 constant_iv_size = 0;
10499     const guint8 *default_kid;
10500     guint8 crypt_byte_block = 0;
10501     guint8 skip_byte_block = 0;
10502     const guint8 *constant_iv = NULL;
10503
10504     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10505     if (!tenc) {
10506       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10507           "which is mandatory for Common Encryption");
10508       return FALSE;
10509     }
10510     tenc_data = (const guint8 *) tenc->data + 12;
10511     is_encrypted = QT_UINT8 (tenc_data + 2);
10512     iv_size = QT_UINT8 (tenc_data + 3);
10513     default_kid = (tenc_data + 4);
10514     if (stream->protection_scheme_type == FOURCC_cbcs) {
10515       guint8 possible_pattern_info;
10516       if (iv_size == 0) {
10517         constant_iv_size = QT_UINT8 (tenc_data + 20);
10518         if (constant_iv_size != 8 && constant_iv_size != 16) {
10519           GST_ERROR_OBJECT (qtdemux,
10520               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10521           return FALSE;
10522         }
10523         constant_iv = (tenc_data + 21);
10524       }
10525       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10526       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10527       skip_byte_block = possible_pattern_info & 0x0f;
10528     }
10529     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10530         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10531         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10532   } else if (stream->protection_scheme_type == FOURCC_piff) {
10533     GstByteReader br;
10534     static const guint8 piff_track_encryption_uuid[] = {
10535       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10536       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10537     };
10538
10539     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10540     if (!tenc) {
10541       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10542           "which is mandatory for Common Encryption");
10543       return FALSE;
10544     }
10545
10546     tenc_data = (const guint8 *) tenc->data + 8;
10547     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10548       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10549       GST_ERROR_OBJECT (qtdemux,
10550           "Unsupported track encryption box with uuid: %s", box_uuid);
10551       g_free (box_uuid);
10552       return FALSE;
10553     }
10554     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10555     gst_byte_reader_init (&br, tenc_data, 20);
10556     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10557       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10558       return FALSE;
10559     }
10560     stream->protection_scheme_type = FOURCC_cenc;
10561   }
10562
10563   return TRUE;
10564 }
10565
10566 static gint
10567 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10568     QtDemuxStream ** stream2)
10569 {
10570   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10571 }
10572
10573 static gboolean
10574 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10575     GNode * stbl)
10576 {
10577   GNode *svmi;
10578
10579   /*parse svmi header if existing */
10580   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10581   if (svmi) {
10582     guint len = QT_UINT32 ((guint8 *) svmi->data);
10583     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10584     if (!version) {
10585       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10586       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10587       guint8 frame_type, frame_layout;
10588       guint32 stereo_mono_change_count;
10589
10590       if (len < 18)
10591         return FALSE;
10592
10593       /* MPEG-A stereo video */
10594       if (qtdemux->major_brand == FOURCC_ss02)
10595         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10596
10597       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10598       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10599       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10600
10601       switch (frame_type) {
10602         case 0:
10603           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10604           break;
10605         case 1:
10606           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10607           break;
10608         case 2:
10609           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10610           break;
10611         case 3:
10612           /* mode 3 is primary/secondary view sequence, ie
10613            * left/right views in separate tracks. See section 7.2
10614            * of ISO/IEC 23000-11:2009 */
10615           /* In the future this might be supported using related
10616            * streams, like an enhancement track - if files like this
10617            * ever exist */
10618           GST_FIXME_OBJECT (qtdemux,
10619               "Implement stereo video in separate streams");
10620       }
10621
10622       if ((frame_layout & 0x1) == 0)
10623         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10624
10625       GST_LOG_OBJECT (qtdemux,
10626           "StereoVideo: composition type: %u, is_left_first: %u",
10627           frame_type, frame_layout);
10628
10629       if (stereo_mono_change_count > 1) {
10630         GST_FIXME_OBJECT (qtdemux,
10631             "Mixed-mono flags are not yet supported in qtdemux.");
10632       }
10633
10634       stream->multiview_mode = mode;
10635       stream->multiview_flags = flags;
10636     }
10637   }
10638
10639   return TRUE;
10640 }
10641
10642 /* parse the traks.
10643  * With each track we associate a new QtDemuxStream that contains all the info
10644  * about the trak.
10645  * traks that do not decode to something (like strm traks) will not have a pad.
10646  */
10647 static gboolean
10648 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10649 {
10650   GstByteReader tkhd;
10651   int offset;
10652   GNode *mdia;
10653   GNode *mdhd;
10654   GNode *hdlr;
10655   GNode *minf;
10656   GNode *stbl;
10657   GNode *stsd;
10658   GNode *mp4a;
10659   GNode *mp4v;
10660   GNode *esds;
10661   GNode *tref;
10662   GNode *udta;
10663
10664   QtDemuxStream *stream = NULL;
10665   const guint8 *stsd_data;
10666   const guint8 *stsd_entry_data;
10667   guint remaining_stsd_len;
10668   guint stsd_entry_count;
10669   guint stsd_index;
10670   guint16 lang_code;            /* quicktime lang code or packed iso code */
10671   guint32 version;
10672   guint32 tkhd_flags = 0;
10673   guint8 tkhd_version = 0;
10674   guint32 w = 0, h = 0;
10675   guint value_size, stsd_len, len;
10676   guint32 track_id;
10677   guint32 dummy;
10678
10679   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10680
10681   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10682       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10683       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10684     goto corrupt_file;
10685
10686   /* pick between 64 or 32 bits */
10687   value_size = tkhd_version == 1 ? 8 : 4;
10688   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10689       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10690     goto corrupt_file;
10691
10692   /* Check if current moov has duplicated track_id */
10693   if (qtdemux_find_stream (qtdemux, track_id))
10694     goto existing_stream;
10695
10696   stream = _create_stream (qtdemux, track_id);
10697   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10698
10699   /* need defaults for fragments */
10700   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10701
10702   if ((tkhd_flags & 1) == 0)
10703     stream->disabled = TRUE;
10704
10705   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10706       tkhd_version, tkhd_flags, stream->track_id);
10707
10708   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10709     goto corrupt_file;
10710
10711   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10712     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10713     if (qtdemux->major_brand != FOURCC_mjp2 ||
10714         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10715       goto corrupt_file;
10716   }
10717
10718   len = QT_UINT32 ((guint8 *) mdhd->data);
10719   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10720   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10721   if (version == 0x01000000) {
10722     if (len < 42)
10723       goto corrupt_file;
10724     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10725     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10726     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10727   } else {
10728     if (len < 30)
10729       goto corrupt_file;
10730     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10731     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10732     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10733   }
10734
10735   if (lang_code < 0x400) {
10736     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10737   } else if (lang_code == 0x7fff) {
10738     stream->lang_id[0] = 0;     /* unspecified */
10739   } else {
10740     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10741     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10742     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10743     stream->lang_id[3] = 0;
10744   }
10745
10746   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10747       stream->timescale);
10748   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10749       stream->duration);
10750   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10751       lang_code, stream->lang_id);
10752
10753   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10754     goto corrupt_file;
10755
10756   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10757     /* chapters track reference */
10758     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10759     if (chap) {
10760       gsize length = GST_READ_UINT32_BE (chap->data);
10761       if (qtdemux->chapters_track_id)
10762         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10763
10764       if (length >= 12) {
10765         qtdemux->chapters_track_id =
10766             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10767       }
10768     }
10769   }
10770
10771   /* fragmented files may have bogus duration in moov */
10772   if (!qtdemux->fragmented &&
10773       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10774     guint64 tdur1, tdur2;
10775
10776     /* don't overflow */
10777     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10778     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10779
10780     /* HACK:
10781      * some of those trailers, nowadays, have prologue images that are
10782      * themselves video tracks as well. I haven't really found a way to
10783      * identify those yet, except for just looking at their duration. */
10784     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10785       GST_WARNING_OBJECT (qtdemux,
10786           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10787           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10788           "found, assuming preview image or something; skipping track",
10789           stream->duration, stream->timescale, qtdemux->duration,
10790           qtdemux->timescale);
10791       gst_qtdemux_stream_unref (stream);
10792       return TRUE;
10793     }
10794   }
10795
10796   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10797     goto corrupt_file;
10798
10799   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10800       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10801
10802   len = QT_UINT32 ((guint8 *) hdlr->data);
10803   if (len >= 20)
10804     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10805   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10806       GST_FOURCC_ARGS (stream->subtype));
10807
10808   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10809     goto corrupt_file;
10810
10811   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10812     goto corrupt_file;
10813
10814   /* Parse out svmi (and later st3d/sv3d) atoms */
10815   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10816     goto corrupt_file;
10817
10818   /* parse rest of tkhd */
10819   if (stream->subtype == FOURCC_vide) {
10820     guint32 matrix[9];
10821
10822     /* version 1 uses some 64-bit ints */
10823     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10824       goto corrupt_file;
10825
10826     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10827       goto corrupt_file;
10828
10829     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10830         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10831       goto corrupt_file;
10832
10833     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10834         &stream->stream_tags);
10835   }
10836
10837   /* parse stsd */
10838   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10839     goto corrupt_file;
10840   stsd_data = (const guint8 *) stsd->data;
10841
10842   /* stsd should at least have one entry */
10843   stsd_len = QT_UINT32 (stsd_data);
10844   if (stsd_len < 24) {
10845     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10846     if (stream->subtype == FOURCC_vivo) {
10847       gst_qtdemux_stream_unref (stream);
10848       return TRUE;
10849     } else {
10850       goto corrupt_file;
10851     }
10852   }
10853
10854   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10855   /* each stsd entry must contain at least 8 bytes */
10856   if (stream->stsd_entries_length == 0
10857       || stream->stsd_entries_length > stsd_len / 8) {
10858     stream->stsd_entries_length = 0;
10859     goto corrupt_file;
10860   }
10861   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10862   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10863   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10864
10865   stsd_entry_data = stsd_data + 16;
10866   remaining_stsd_len = stsd_len - 16;
10867   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10868     guint32 fourcc;
10869     gchar *codec = NULL;
10870     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10871
10872     /* and that entry should fit within stsd */
10873     len = QT_UINT32 (stsd_entry_data);
10874     if (len > remaining_stsd_len)
10875       goto corrupt_file;
10876
10877     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10878     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10879         GST_FOURCC_ARGS (entry->fourcc));
10880     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10881
10882     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10883       goto error_encrypted;
10884
10885     if (fourcc == FOURCC_aavd) {
10886       if (stream->subtype != FOURCC_soun) {
10887         GST_ERROR_OBJECT (qtdemux,
10888             "Unexpeced stsd type 'aavd' outside 'soun' track");
10889       } else {
10890         /* encrypted audio with sound sample description v0 */
10891         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10892         stream->protected = TRUE;
10893         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
10894           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10895       }
10896     }
10897
10898     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10899       /* FIXME this looks wrong, there might be multiple children
10900        * with the same type */
10901       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10902       stream->protected = TRUE;
10903       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10904         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10905     }
10906
10907     if (stream->subtype == FOURCC_vide) {
10908       GNode *colr;
10909       GNode *fiel;
10910       GNode *pasp;
10911       gboolean gray;
10912       gint depth, palette_size, palette_count;
10913       guint32 *palette_data = NULL;
10914
10915       entry->sampled = TRUE;
10916
10917       stream->display_width = w >> 16;
10918       stream->display_height = h >> 16;
10919
10920       offset = 16;
10921       if (len < 86)             /* TODO verify */
10922         goto corrupt_file;
10923
10924       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10925       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10926       entry->fps_n = 0;         /* this is filled in later */
10927       entry->fps_d = 0;         /* this is filled in later */
10928       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10929       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10930
10931       /* if color_table_id is 0, ctab atom must follow; however some files
10932        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10933        * if color table is not present we'll correct the value */
10934       if (entry->color_table_id == 0 &&
10935           (len < 90
10936               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10937         entry->color_table_id = -1;
10938       }
10939
10940       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10941           entry->width, entry->height, entry->bits_per_sample,
10942           entry->color_table_id);
10943
10944       depth = entry->bits_per_sample;
10945
10946       /* more than 32 bits means grayscale */
10947       gray = (depth > 32);
10948       /* low 32 bits specify the depth  */
10949       depth &= 0x1F;
10950
10951       /* different number of palette entries is determined by depth. */
10952       palette_count = 0;
10953       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10954         palette_count = (1 << depth);
10955       palette_size = palette_count * 4;
10956
10957       if (entry->color_table_id) {
10958         switch (palette_count) {
10959           case 0:
10960             break;
10961           case 2:
10962             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
10963             break;
10964           case 4:
10965             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
10966             break;
10967           case 16:
10968             if (gray)
10969               palette_data =
10970                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
10971             else
10972               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
10973             break;
10974           case 256:
10975             if (gray)
10976               palette_data =
10977                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
10978             else
10979               palette_data =
10980                   g_memdup2 (ff_qt_default_palette_256, palette_size);
10981             break;
10982           default:
10983             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10984                 (_("The video in this file might not play correctly.")),
10985                 ("unsupported palette depth %d", depth));
10986             break;
10987         }
10988       } else {
10989         gint i, j, start, end;
10990
10991         if (len < 94)
10992           goto corrupt_file;
10993
10994         /* read table */
10995         start = QT_UINT32 (stsd_entry_data + offset + 70);
10996         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10997         end = QT_UINT16 (stsd_entry_data + offset + 76);
10998
10999         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11000             start, end, palette_count);
11001
11002         if (end > 255)
11003           end = 255;
11004         if (start > end)
11005           start = end;
11006
11007         if (len < 94 + (end - start) * 8)
11008           goto corrupt_file;
11009
11010         /* palette is always the same size */
11011         palette_data = g_malloc0 (256 * 4);
11012         palette_size = 256 * 4;
11013
11014         for (j = 0, i = start; i <= end; j++, i++) {
11015           guint32 a, r, g, b;
11016
11017           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11018           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11019           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11020           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11021
11022           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11023               (g & 0xff00) | (b >> 8);
11024         }
11025       }
11026
11027       if (entry->caps)
11028         gst_caps_unref (entry->caps);
11029
11030       entry->caps =
11031           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11032           &codec);
11033       if (G_UNLIKELY (!entry->caps)) {
11034         g_free (palette_data);
11035         goto unknown_stream;
11036       }
11037
11038       if (codec) {
11039         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11040             GST_TAG_VIDEO_CODEC, codec, NULL);
11041         g_free (codec);
11042         codec = NULL;
11043       }
11044
11045       if (palette_data) {
11046         GstStructure *s;
11047
11048         if (entry->rgb8_palette)
11049           gst_memory_unref (entry->rgb8_palette);
11050         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11051             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11052
11053         s = gst_caps_get_structure (entry->caps, 0);
11054
11055         /* non-raw video has a palette_data property. raw video has the palette as
11056          * an extra plane that we append to the output buffers before we push
11057          * them*/
11058         if (!gst_structure_has_name (s, "video/x-raw")) {
11059           GstBuffer *palette;
11060
11061           palette = gst_buffer_new ();
11062           gst_buffer_append_memory (palette, entry->rgb8_palette);
11063           entry->rgb8_palette = NULL;
11064
11065           gst_caps_set_simple (entry->caps, "palette_data",
11066               GST_TYPE_BUFFER, palette, NULL);
11067           gst_buffer_unref (palette);
11068         }
11069       } else if (palette_count != 0) {
11070         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11071             (NULL), ("Unsupported palette depth %d", depth));
11072       }
11073
11074       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11075           QT_UINT16 (stsd_entry_data + offset + 32));
11076
11077       esds = NULL;
11078       pasp = NULL;
11079       colr = NULL;
11080       fiel = NULL;
11081       /* pick 'the' stsd child */
11082       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11083       // We should skip parsing the stsd for non-protected streams if
11084       // the entry doesn't match the fourcc, since they don't change
11085       // format. However, for protected streams we can have partial
11086       // encryption, where parts of the stream are encrypted and parts
11087       // not. For both parts of such streams, we should ensure the
11088       // esds overrides are parsed for both from the stsd.
11089       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11090         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11091           mp4v = NULL;
11092         else if (!stream->protected)
11093           mp4v = NULL;
11094       }
11095
11096       if (mp4v) {
11097         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11098         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11099         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11100         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11101       }
11102
11103       if (pasp) {
11104         const guint8 *pasp_data = (const guint8 *) pasp->data;
11105         gint len = QT_UINT32 (pasp_data);
11106
11107         if (len == 16) {
11108           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11109           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11110         } else {
11111           CUR_STREAM (stream)->par_w = 0;
11112           CUR_STREAM (stream)->par_h = 0;
11113         }
11114       } else {
11115         CUR_STREAM (stream)->par_w = 0;
11116         CUR_STREAM (stream)->par_h = 0;
11117       }
11118
11119       if (fiel) {
11120         const guint8 *fiel_data = (const guint8 *) fiel->data;
11121         gint len = QT_UINT32 (fiel_data);
11122
11123         if (len == 10) {
11124           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11125           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11126         }
11127       }
11128
11129       if (colr) {
11130         const guint8 *colr_data = (const guint8 *) colr->data;
11131         gint len = QT_UINT32 (colr_data);
11132
11133         if (len == 19 || len == 18) {
11134           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11135
11136           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11137             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11138             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11139             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11140             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11141
11142             CUR_STREAM (stream)->colorimetry.primaries =
11143                 gst_video_color_primaries_from_iso (primaries);
11144             CUR_STREAM (stream)->colorimetry.transfer =
11145                 gst_video_transfer_function_from_iso (transfer_function);
11146             CUR_STREAM (stream)->colorimetry.matrix =
11147                 gst_video_color_matrix_from_iso (matrix);
11148             CUR_STREAM (stream)->colorimetry.range =
11149                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11150                 GST_VIDEO_COLOR_RANGE_16_235;
11151           } else {
11152             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11153           }
11154         } else {
11155           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11156         }
11157       }
11158
11159       if (esds) {
11160         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11161             stream->stream_tags);
11162       } else {
11163         switch (fourcc) {
11164           case FOURCC_H264:
11165           case FOURCC_avc1:
11166           case FOURCC_avc3:
11167           {
11168             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11169             const guint8 *avc_data = stsd_entry_data + 0x56;
11170
11171             /* find avcC */
11172             while (len >= 0x8) {
11173               gint size;
11174
11175               if (QT_UINT32 (avc_data) <= len)
11176                 size = QT_UINT32 (avc_data) - 0x8;
11177               else
11178                 size = len - 0x8;
11179
11180               if (size < 1)
11181                 /* No real data, so break out */
11182                 break;
11183
11184               switch (QT_FOURCC (avc_data + 0x4)) {
11185                 case FOURCC_avcC:
11186                 {
11187                   /* parse, if found */
11188                   GstBuffer *buf;
11189
11190                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11191
11192                   /* First 4 bytes are the length of the atom, the next 4 bytes
11193                    * are the fourcc, the next 1 byte is the version, and the
11194                    * subsequent bytes are profile_tier_level structure like data. */
11195                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11196                       avc_data + 8 + 1, size - 1);
11197                   buf = gst_buffer_new_and_alloc (size);
11198                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11199                   gst_caps_set_simple (entry->caps,
11200                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11201                   gst_buffer_unref (buf);
11202
11203                   break;
11204                 }
11205                 case FOURCC_strf:
11206                 {
11207                   GstBuffer *buf;
11208
11209                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11210
11211                   /* First 4 bytes are the length of the atom, the next 4 bytes
11212                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11213                    * next 1 byte is the version, and the
11214                    * subsequent bytes are sequence parameter set like data. */
11215
11216                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11217                   if (size > 1) {
11218                     gst_codec_utils_h264_caps_set_level_and_profile
11219                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11220
11221                     buf = gst_buffer_new_and_alloc (size);
11222                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11223                     gst_caps_set_simple (entry->caps,
11224                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11225                     gst_buffer_unref (buf);
11226                   }
11227                   break;
11228                 }
11229                 case FOURCC_btrt:
11230                 {
11231                   guint avg_bitrate, max_bitrate;
11232
11233                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11234                   if (size < 12)
11235                     break;
11236
11237                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11238                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11239
11240                   if (!max_bitrate && !avg_bitrate)
11241                     break;
11242
11243                   /* Some muxers seem to swap the average and maximum bitrates
11244                    * (I'm looking at you, YouTube), so we swap for sanity. */
11245                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11246                     guint temp = avg_bitrate;
11247
11248                     avg_bitrate = max_bitrate;
11249                     max_bitrate = temp;
11250                   }
11251
11252                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11253                     gst_tag_list_add (stream->stream_tags,
11254                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11255                         max_bitrate, NULL);
11256                   }
11257                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11258                     gst_tag_list_add (stream->stream_tags,
11259                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11260                         NULL);
11261                   }
11262
11263                   break;
11264                 }
11265
11266                 default:
11267                   break;
11268               }
11269
11270               len -= size + 8;
11271               avc_data += size + 8;
11272             }
11273
11274             break;
11275           }
11276           case FOURCC_H265:
11277           case FOURCC_hvc1:
11278           case FOURCC_hev1:
11279           case FOURCC_dvh1:
11280           case FOURCC_dvhe:
11281           {
11282             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11283             const guint8 *hevc_data = stsd_entry_data + 0x56;
11284
11285             /* find hevc */
11286             while (len >= 0x8) {
11287               gint size;
11288
11289               if (QT_UINT32 (hevc_data) <= len)
11290                 size = QT_UINT32 (hevc_data) - 0x8;
11291               else
11292                 size = len - 0x8;
11293
11294               if (size < 1)
11295                 /* No real data, so break out */
11296                 break;
11297
11298               switch (QT_FOURCC (hevc_data + 0x4)) {
11299                 case FOURCC_hvcC:
11300                 {
11301                   /* parse, if found */
11302                   GstBuffer *buf;
11303
11304                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11305
11306                   /* First 4 bytes are the length of the atom, the next 4 bytes
11307                    * are the fourcc, the next 1 byte is the version, and the
11308                    * subsequent bytes are sequence parameter set like data. */
11309                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11310                       (entry->caps, hevc_data + 8 + 1, size - 1);
11311
11312                   buf = gst_buffer_new_and_alloc (size);
11313                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11314                   gst_caps_set_simple (entry->caps,
11315                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11316                   gst_buffer_unref (buf);
11317                   break;
11318                 }
11319                 default:
11320                   break;
11321               }
11322               len -= size + 8;
11323               hevc_data += size + 8;
11324             }
11325             break;
11326           }
11327           case FOURCC_mp4v:
11328           case FOURCC_MP4V:
11329           case FOURCC_fmp4:
11330           case FOURCC_FMP4:
11331           case FOURCC_xvid:
11332           case FOURCC_XVID:
11333           {
11334             GNode *glbl;
11335
11336             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11337                 GST_FOURCC_ARGS (fourcc));
11338
11339             /* codec data might be in glbl extension atom */
11340             glbl = mp4v ?
11341                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11342             if (glbl) {
11343               guint8 *data;
11344               GstBuffer *buf;
11345               gint len;
11346
11347               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11348               data = glbl->data;
11349               len = QT_UINT32 (data);
11350               if (len > 0x8) {
11351                 len -= 0x8;
11352                 buf = gst_buffer_new_and_alloc (len);
11353                 gst_buffer_fill (buf, 0, data + 8, len);
11354                 gst_caps_set_simple (entry->caps,
11355                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11356                 gst_buffer_unref (buf);
11357               }
11358             }
11359             break;
11360           }
11361           case FOURCC_mjp2:
11362           {
11363             /* see annex I of the jpeg2000 spec */
11364             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11365             const guint8 *data;
11366             const gchar *colorspace = NULL;
11367             gint ncomp = 0;
11368             guint32 ncomp_map = 0;
11369             gint32 *comp_map = NULL;
11370             guint32 nchan_def = 0;
11371             gint32 *chan_def = NULL;
11372
11373             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11374             /* some required atoms */
11375             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11376             if (!mjp2)
11377               break;
11378             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11379             if (!jp2h)
11380               break;
11381
11382             /* number of components; redundant with info in codestream, but useful
11383                to a muxer */
11384             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11385             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11386               break;
11387             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11388
11389             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11390             if (!colr)
11391               break;
11392             GST_DEBUG_OBJECT (qtdemux, "found colr");
11393             /* extract colour space info */
11394             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11395               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11396                 case 16:
11397                   colorspace = "sRGB";
11398                   break;
11399                 case 17:
11400                   colorspace = "GRAY";
11401                   break;
11402                 case 18:
11403                   colorspace = "sYUV";
11404                   break;
11405                 default:
11406                   colorspace = NULL;
11407                   break;
11408               }
11409             }
11410             if (!colorspace)
11411               /* colr is required, and only values 16, 17, and 18 are specified,
11412                  so error if we have no colorspace */
11413               break;
11414
11415             /* extract component mapping */
11416             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11417             if (cmap) {
11418               guint32 cmap_len = 0;
11419               int i;
11420               cmap_len = QT_UINT32 (cmap->data);
11421               if (cmap_len >= 8) {
11422                 /* normal box, subtract off header */
11423                 cmap_len -= 8;
11424                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11425                 if (cmap_len % 4 == 0) {
11426                   ncomp_map = (cmap_len / 4);
11427                   comp_map = g_new0 (gint32, ncomp_map);
11428                   for (i = 0; i < ncomp_map; i++) {
11429                     guint16 cmp;
11430                     guint8 mtyp, pcol;
11431                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11432                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11433                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11434                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11435                   }
11436                 }
11437               }
11438             }
11439             /* extract channel definitions */
11440             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11441             if (cdef) {
11442               guint32 cdef_len = 0;
11443               int i;
11444               cdef_len = QT_UINT32 (cdef->data);
11445               if (cdef_len >= 10) {
11446                 /* normal box, subtract off header and len */
11447                 cdef_len -= 10;
11448                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11449                 if (cdef_len % 6 == 0) {
11450                   nchan_def = (cdef_len / 6);
11451                   chan_def = g_new0 (gint32, nchan_def);
11452                   for (i = 0; i < nchan_def; i++)
11453                     chan_def[i] = -1;
11454                   for (i = 0; i < nchan_def; i++) {
11455                     guint16 cn, typ, asoc;
11456                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11457                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11458                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11459                     if (cn < nchan_def) {
11460                       switch (typ) {
11461                         case 0:
11462                           chan_def[cn] = asoc;
11463                           break;
11464                         case 1:
11465                           chan_def[cn] = 0;     /* alpha */
11466                           break;
11467                         default:
11468                           chan_def[cn] = -typ;
11469                       }
11470                     }
11471                   }
11472                 }
11473               }
11474             }
11475
11476             gst_caps_set_simple (entry->caps,
11477                 "num-components", G_TYPE_INT, ncomp, NULL);
11478             gst_caps_set_simple (entry->caps,
11479                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11480
11481             if (comp_map) {
11482               GValue arr = { 0, };
11483               GValue elt = { 0, };
11484               int i;
11485               g_value_init (&arr, GST_TYPE_ARRAY);
11486               g_value_init (&elt, G_TYPE_INT);
11487               for (i = 0; i < ncomp_map; i++) {
11488                 g_value_set_int (&elt, comp_map[i]);
11489                 gst_value_array_append_value (&arr, &elt);
11490               }
11491               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11492                   "component-map", &arr);
11493               g_value_unset (&elt);
11494               g_value_unset (&arr);
11495               g_free (comp_map);
11496             }
11497
11498             if (chan_def) {
11499               GValue arr = { 0, };
11500               GValue elt = { 0, };
11501               int i;
11502               g_value_init (&arr, GST_TYPE_ARRAY);
11503               g_value_init (&elt, G_TYPE_INT);
11504               for (i = 0; i < nchan_def; i++) {
11505                 g_value_set_int (&elt, chan_def[i]);
11506                 gst_value_array_append_value (&arr, &elt);
11507               }
11508               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11509                   "channel-definitions", &arr);
11510               g_value_unset (&elt);
11511               g_value_unset (&arr);
11512               g_free (chan_def);
11513             }
11514
11515             /* some optional atoms */
11516             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11517             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11518
11519             /* indicate possible fields in caps */
11520             if (field) {
11521               data = (guint8 *) field->data + 8;
11522               if (*data != 1)
11523                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11524                     (gint) * data, NULL);
11525             }
11526             /* add codec_data if provided */
11527             if (prefix) {
11528               GstBuffer *buf;
11529               gint len;
11530
11531               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11532               data = prefix->data;
11533               len = QT_UINT32 (data);
11534               if (len > 0x8) {
11535                 len -= 0x8;
11536                 buf = gst_buffer_new_and_alloc (len);
11537                 gst_buffer_fill (buf, 0, data + 8, len);
11538                 gst_caps_set_simple (entry->caps,
11539                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11540                 gst_buffer_unref (buf);
11541               }
11542             }
11543             break;
11544           }
11545           case FOURCC_SVQ3:
11546           case FOURCC_VP31:
11547           {
11548             GstBuffer *buf;
11549             GstBuffer *seqh = NULL;
11550             const guint8 *gamma_data = NULL;
11551             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11552
11553             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11554                 &seqh);
11555             if (gamma_data) {
11556               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11557                   QT_FP32 (gamma_data), NULL);
11558             }
11559             if (seqh) {
11560               /* sorry for the bad name, but we don't know what this is, other
11561                * than its own fourcc */
11562               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11563                   NULL);
11564               gst_buffer_unref (seqh);
11565             }
11566
11567             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11568             buf = gst_buffer_new_and_alloc (len);
11569             gst_buffer_fill (buf, 0, stsd_data, len);
11570             gst_caps_set_simple (entry->caps,
11571                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11572             gst_buffer_unref (buf);
11573             break;
11574           }
11575           case FOURCC_jpeg:
11576           {
11577             /* https://developer.apple.com/standards/qtff-2001.pdf,
11578              * page 92, "Video Sample Description", under table 3.1 */
11579             GstByteReader br;
11580
11581             const gint compressor_offset =
11582                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11583             const gint min_size = compressor_offset + 32 + 2 + 2;
11584             GNode *jpeg;
11585             guint32 len;
11586             guint16 color_table_id = 0;
11587             gboolean ok;
11588
11589             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11590
11591             /* recover information on interlaced/progressive */
11592             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11593             if (!jpeg)
11594               break;
11595
11596             len = QT_UINT32 (jpeg->data);
11597             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11598                 min_size);
11599             if (len >= min_size) {
11600               gst_byte_reader_init (&br, jpeg->data, len);
11601
11602               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11603               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11604               if (color_table_id != 0) {
11605                 /* the spec says there can be concatenated chunks in the data, and we want
11606                  * to find one called field. Walk through them. */
11607                 gint offset = min_size;
11608                 while (offset + 8 < len) {
11609                   guint32 size = 0, tag;
11610                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11611                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11612                   if (!ok || size < 8) {
11613                     GST_WARNING_OBJECT (qtdemux,
11614                         "Failed to walk optional chunk list");
11615                     break;
11616                   }
11617                   GST_DEBUG_OBJECT (qtdemux,
11618                       "Found optional %4.4s chunk, size %u",
11619                       (const char *) &tag, size);
11620                   if (tag == FOURCC_fiel) {
11621                     guint8 n_fields = 0, ordering = 0;
11622                     gst_byte_reader_get_uint8 (&br, &n_fields);
11623                     gst_byte_reader_get_uint8 (&br, &ordering);
11624                     if (n_fields == 1 || n_fields == 2) {
11625                       GST_DEBUG_OBJECT (qtdemux,
11626                           "Found fiel tag with %u fields, ordering %u",
11627                           n_fields, ordering);
11628                       if (n_fields == 2)
11629                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11630                             "interlace-mode", G_TYPE_STRING, "interleaved",
11631                             NULL);
11632                     } else {
11633                       GST_WARNING_OBJECT (qtdemux,
11634                           "Found fiel tag with invalid fields (%u)", n_fields);
11635                     }
11636                   }
11637                   offset += size;
11638                 }
11639               } else {
11640                 GST_DEBUG_OBJECT (qtdemux,
11641                     "Color table ID is 0, not trying to get interlacedness");
11642               }
11643             } else {
11644               GST_WARNING_OBJECT (qtdemux,
11645                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11646             }
11647
11648             break;
11649           }
11650           case FOURCC_rle_:
11651           case FOURCC_WRLE:
11652           {
11653             gst_caps_set_simple (entry->caps,
11654                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11655                 NULL);
11656             break;
11657           }
11658           case FOURCC_XiTh:
11659           {
11660             GNode *xith, *xdxt;
11661
11662             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11663             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11664             if (!xith)
11665               break;
11666
11667             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11668             if (!xdxt)
11669               break;
11670
11671             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11672             /* collect the headers and store them in a stream list so that we can
11673              * send them out first */
11674             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11675             break;
11676           }
11677           case FOURCC_ovc1:
11678           {
11679             GNode *ovc1;
11680             guint8 *ovc1_data;
11681             guint ovc1_len;
11682             GstBuffer *buf;
11683
11684             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11685             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11686             if (!ovc1)
11687               break;
11688             ovc1_data = ovc1->data;
11689             ovc1_len = QT_UINT32 (ovc1_data);
11690             if (ovc1_len <= 198) {
11691               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11692               break;
11693             }
11694             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11695             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11696             gst_caps_set_simple (entry->caps,
11697                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11698             gst_buffer_unref (buf);
11699             break;
11700           }
11701           case FOURCC_vc_1:
11702           {
11703             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11704             const guint8 *vc1_data = stsd_entry_data + 0x56;
11705
11706             /* find dvc1 */
11707             while (len >= 8) {
11708               gint size;
11709
11710               if (QT_UINT32 (vc1_data) <= len)
11711                 size = QT_UINT32 (vc1_data) - 8;
11712               else
11713                 size = len - 8;
11714
11715               if (size < 1)
11716                 /* No real data, so break out */
11717                 break;
11718
11719               switch (QT_FOURCC (vc1_data + 0x4)) {
11720                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11721                 {
11722                   GstBuffer *buf;
11723
11724                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11725                   buf = gst_buffer_new_and_alloc (size);
11726                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11727                   gst_caps_set_simple (entry->caps,
11728                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11729                   gst_buffer_unref (buf);
11730                   break;
11731                 }
11732                 default:
11733                   break;
11734               }
11735               len -= size + 8;
11736               vc1_data += size + 8;
11737             }
11738             break;
11739           }
11740           case FOURCC_av01:
11741           {
11742             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11743             const guint8 *av1_data = stsd_entry_data + 0x56;
11744
11745             /* find av1C */
11746             while (len >= 0x8) {
11747               gint size;
11748
11749               if (QT_UINT32 (av1_data) <= len)
11750                 size = QT_UINT32 (av1_data) - 0x8;
11751               else
11752                 size = len - 0x8;
11753
11754               if (size < 1)
11755                 /* No real data, so break out */
11756                 break;
11757
11758               switch (QT_FOURCC (av1_data + 0x4)) {
11759                 case FOURCC_av1C:
11760                 {
11761                   /* parse, if found */
11762                   GstBuffer *buf;
11763                   guint8 pres_delay_field;
11764
11765                   GST_DEBUG_OBJECT (qtdemux,
11766                       "found av1C codec_data in stsd of size %d", size);
11767
11768                   /* not enough data, just ignore and hope for the best */
11769                   if (size < 5)
11770                     break;
11771
11772                   /* Content is:
11773                    * 4 bytes: atom length
11774                    * 4 bytes: fourcc
11775                    * 1 byte: version
11776                    * 3 bytes: flags
11777                    * 3 bits: reserved
11778                    * 1 bits:  initial_presentation_delay_present
11779                    * 4 bits: initial_presentation_delay (if present else reserved
11780                    * rest: OBUs.
11781                    */
11782
11783                   if (av1_data[9] != 0) {
11784                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11785                     break;
11786                   }
11787
11788                   /* We skip initial_presentation_delay* for now */
11789                   pres_delay_field = *(av1_data + 12);
11790                   if (pres_delay_field & (1 << 5)) {
11791                     gst_caps_set_simple (entry->caps,
11792                         "presentation-delay", G_TYPE_INT,
11793                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11794                   }
11795                   if (size > 5) {
11796                     buf = gst_buffer_new_and_alloc (size - 5);
11797                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11798                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11799                     gst_caps_set_simple (entry->caps,
11800                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11801                     gst_buffer_unref (buf);
11802                   }
11803                   break;
11804                 }
11805                 default:
11806                   break;
11807               }
11808
11809               len -= size + 8;
11810               av1_data += size + 8;
11811             }
11812
11813             break;
11814           }
11815
11816             /* TODO: Need to parse vpcC for VP8 codec too.
11817              * Note that VPCodecConfigurationBox (vpcC) is defined for
11818              * vp08, vp09, and vp10 fourcc. */
11819           case FOURCC_vp09:
11820           {
11821             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11822             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11823
11824             /* find vpcC */
11825             while (len >= 0x8) {
11826               gint size;
11827
11828               if (QT_UINT32 (vpcc_data) <= len)
11829                 size = QT_UINT32 (vpcc_data) - 0x8;
11830               else
11831                 size = len - 0x8;
11832
11833               if (size < 1)
11834                 /* No real data, so break out */
11835                 break;
11836
11837               switch (QT_FOURCC (vpcc_data + 0x4)) {
11838                 case FOURCC_vpcC:
11839                 {
11840                   const gchar *profile_str = NULL;
11841                   const gchar *chroma_format_str = NULL;
11842                   guint8 profile;
11843                   guint8 bitdepth;
11844                   guint8 chroma_format;
11845                   GstVideoColorimetry cinfo;
11846
11847                   /* parse, if found */
11848                   GST_DEBUG_OBJECT (qtdemux,
11849                       "found vp codec_data in stsd of size %d", size);
11850
11851                   /* the meaning of "size" is length of the atom body, excluding
11852                    * atom length and fourcc fields */
11853                   if (size < 12)
11854                     break;
11855
11856                   /* Content is:
11857                    * 4 bytes: atom length
11858                    * 4 bytes: fourcc
11859                    * 1 byte: version
11860                    * 3 bytes: flags
11861                    * 1 byte: profile
11862                    * 1 byte: level
11863                    * 4 bits: bitDepth
11864                    * 3 bits: chromaSubsampling
11865                    * 1 bit: videoFullRangeFlag
11866                    * 1 byte: colourPrimaries
11867                    * 1 byte: transferCharacteristics
11868                    * 1 byte: matrixCoefficients
11869                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11870                    * rest: codecIntializationData (not used for vp8 and vp9)
11871                    */
11872
11873                   if (vpcc_data[8] != 1) {
11874                     GST_WARNING_OBJECT (qtdemux,
11875                         "unknown vpcC version %d", vpcc_data[8]);
11876                     break;
11877                   }
11878
11879                   profile = vpcc_data[12];
11880                   switch (profile) {
11881                     case 0:
11882                       profile_str = "0";
11883                       break;
11884                     case 1:
11885                       profile_str = "1";
11886                       break;
11887                     case 2:
11888                       profile_str = "2";
11889                       break;
11890                     case 3:
11891                       profile_str = "3";
11892                       break;
11893                     default:
11894                       break;
11895                   }
11896
11897                   if (profile_str) {
11898                     gst_caps_set_simple (entry->caps,
11899                         "profile", G_TYPE_STRING, profile_str, NULL);
11900                   }
11901
11902                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11903                    * but webm spec define various ones. Add level to caps
11904                    * if we really need it then */
11905
11906                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11907                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11908                     gst_caps_set_simple (entry->caps,
11909                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11910                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11911                   }
11912
11913                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11914                   switch (chroma_format) {
11915                     case 0:
11916                     case 1:
11917                       chroma_format_str = "4:2:0";
11918                       break;
11919                     case 2:
11920                       chroma_format_str = "4:2:2";
11921                       break;
11922                     case 3:
11923                       chroma_format_str = "4:4:4";
11924                       break;
11925                     default:
11926                       break;
11927                   }
11928
11929                   if (chroma_format_str) {
11930                     gst_caps_set_simple (entry->caps,
11931                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11932                         NULL);
11933                   }
11934
11935                   if ((vpcc_data[14] & 0x1) != 0)
11936                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
11937                   else
11938                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
11939                   cinfo.primaries =
11940                       gst_video_color_primaries_from_iso (vpcc_data[15]);
11941                   cinfo.transfer =
11942                       gst_video_transfer_function_from_iso (vpcc_data[16]);
11943                   cinfo.matrix =
11944                       gst_video_color_matrix_from_iso (vpcc_data[17]);
11945
11946                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
11947                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
11948                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
11949                     /* set this only if all values are known, otherwise this
11950                      * might overwrite valid ones parsed from other color box */
11951                     CUR_STREAM (stream)->colorimetry = cinfo;
11952                   }
11953                   break;
11954                 }
11955                 default:
11956                   break;
11957               }
11958
11959               len -= size + 8;
11960               vpcc_data += size + 8;
11961             }
11962
11963             break;
11964           }
11965           default:
11966             break;
11967         }
11968       }
11969
11970       GST_INFO_OBJECT (qtdemux,
11971           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11972           GST_FOURCC_ARGS (fourcc), entry->caps);
11973
11974     } else if (stream->subtype == FOURCC_soun) {
11975       GNode *wave;
11976       int version, samplesize;
11977       guint16 compression_id;
11978       gboolean amrwb = FALSE;
11979
11980       offset = 16;
11981       /* sample description entry (16) + sound sample description v0 (20) */
11982       if (len < 36)
11983         goto corrupt_file;
11984
11985       version = QT_UINT32 (stsd_entry_data + offset);
11986       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11987       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11988       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11989       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11990
11991       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11992       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11993           QT_UINT32 (stsd_entry_data + offset + 4));
11994       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11995       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11996       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11997       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11998           QT_UINT16 (stsd_entry_data + offset + 14));
11999       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12000
12001       if (compression_id == 0xfffe)
12002         entry->sampled = TRUE;
12003
12004       /* first assume uncompressed audio */
12005       entry->bytes_per_sample = samplesize / 8;
12006       entry->samples_per_frame = entry->n_channels;
12007       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12008       entry->samples_per_packet = entry->samples_per_frame;
12009       entry->bytes_per_packet = entry->bytes_per_sample;
12010
12011       offset = 36;
12012
12013       if (version == 0x00010000) {
12014         /* sample description entry (16) + sound sample description v1 (20+16) */
12015         if (len < 52)
12016           goto corrupt_file;
12017
12018         /* take information from here over the normal sample description */
12019         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12020         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12021         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12022         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12023
12024         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12025         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12026             entry->samples_per_packet);
12027         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12028             entry->bytes_per_packet);
12029         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12030             entry->bytes_per_frame);
12031         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12032             entry->bytes_per_sample);
12033
12034         if (!entry->sampled && entry->bytes_per_packet) {
12035           entry->samples_per_frame = (entry->bytes_per_frame /
12036               entry->bytes_per_packet) * entry->samples_per_packet;
12037           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12038               entry->samples_per_frame);
12039         }
12040       } else if (version == 0x00020000) {
12041         /* sample description entry (16) + sound sample description v2 (56) */
12042         if (len < 72)
12043           goto corrupt_file;
12044
12045         /* take information from here over the normal sample description */
12046         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12047         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12048         entry->samples_per_frame = entry->n_channels;
12049         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12050         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12051         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12052         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12053
12054         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12055         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12056         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12057         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12058             entry->bytes_per_sample * 8);
12059         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12060             QT_UINT32 (stsd_entry_data + offset + 24));
12061         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12062             entry->bytes_per_packet);
12063         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12064             entry->samples_per_packet);
12065       } else if (version != 0x00000) {
12066         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12067             version);
12068       }
12069
12070       switch (fourcc) {
12071           /* Yes, these have to be hard-coded */
12072         case FOURCC_MAC6:
12073         {
12074           entry->samples_per_packet = 6;
12075           entry->bytes_per_packet = 1;
12076           entry->bytes_per_frame = 1 * entry->n_channels;
12077           entry->bytes_per_sample = 1;
12078           entry->samples_per_frame = 6 * entry->n_channels;
12079           break;
12080         }
12081         case FOURCC_MAC3:
12082         {
12083           entry->samples_per_packet = 3;
12084           entry->bytes_per_packet = 1;
12085           entry->bytes_per_frame = 1 * entry->n_channels;
12086           entry->bytes_per_sample = 1;
12087           entry->samples_per_frame = 3 * entry->n_channels;
12088           break;
12089         }
12090         case FOURCC_ima4:
12091         {
12092           entry->samples_per_packet = 64;
12093           entry->bytes_per_packet = 34;
12094           entry->bytes_per_frame = 34 * entry->n_channels;
12095           entry->bytes_per_sample = 2;
12096           entry->samples_per_frame = 64 * entry->n_channels;
12097           break;
12098         }
12099         case FOURCC_ulaw:
12100         case FOURCC_alaw:
12101         {
12102           entry->samples_per_packet = 1;
12103           entry->bytes_per_packet = 1;
12104           entry->bytes_per_frame = 1 * entry->n_channels;
12105           entry->bytes_per_sample = 1;
12106           entry->samples_per_frame = 1 * entry->n_channels;
12107           break;
12108         }
12109         case FOURCC_agsm:
12110         {
12111           entry->samples_per_packet = 160;
12112           entry->bytes_per_packet = 33;
12113           entry->bytes_per_frame = 33 * entry->n_channels;
12114           entry->bytes_per_sample = 2;
12115           entry->samples_per_frame = 160 * entry->n_channels;
12116           break;
12117         }
12118           /* fix up any invalid header information from above */
12119         case FOURCC_twos:
12120         case FOURCC_sowt:
12121         case FOURCC_raw_:
12122         case FOURCC_lpcm:
12123           /* Sometimes these are set to 0 in the sound sample descriptions so
12124            * let's try to infer useful values from the other information we
12125            * have available */
12126           if (entry->bytes_per_sample == 0)
12127             entry->bytes_per_sample =
12128                 entry->bytes_per_frame / entry->n_channels;
12129           if (entry->bytes_per_sample == 0)
12130             entry->bytes_per_sample = samplesize / 8;
12131
12132           if (entry->bytes_per_frame == 0)
12133             entry->bytes_per_frame =
12134                 entry->bytes_per_sample * entry->n_channels;
12135
12136           if (entry->bytes_per_packet == 0)
12137             entry->bytes_per_packet = entry->bytes_per_sample;
12138
12139           if (entry->samples_per_frame == 0)
12140             entry->samples_per_frame = entry->n_channels;
12141
12142           if (entry->samples_per_packet == 0)
12143             entry->samples_per_packet = entry->samples_per_frame;
12144
12145           break;
12146         case FOURCC_in24:
12147         case FOURCC_in32:
12148         case FOURCC_fl32:
12149         case FOURCC_fl64:
12150         case FOURCC_s16l:{
12151           switch (fourcc) {
12152             case FOURCC_in24:
12153               entry->bytes_per_sample = 3;
12154               break;
12155             case FOURCC_in32:
12156             case FOURCC_fl32:
12157               entry->bytes_per_sample = 4;
12158               break;
12159             case FOURCC_fl64:
12160               entry->bytes_per_sample = 8;
12161               break;
12162             case FOURCC_s16l:
12163               entry->bytes_per_sample = 2;
12164               break;
12165             default:
12166               g_assert_not_reached ();
12167               break;
12168           }
12169           entry->samples_per_frame = entry->n_channels;
12170           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12171           entry->samples_per_packet = entry->samples_per_frame;
12172           entry->bytes_per_packet = entry->bytes_per_sample;
12173           break;
12174         }
12175         default:
12176           break;
12177       }
12178
12179       if (entry->caps)
12180         gst_caps_unref (entry->caps);
12181
12182       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12183           stsd_entry_data + 32, len - 16, &codec);
12184
12185       switch (fourcc) {
12186         case FOURCC_in24:
12187         case FOURCC_in32:
12188         case FOURCC_fl32:
12189         case FOURCC_fl64:
12190         {
12191           GNode *enda;
12192           GNode *fmt;
12193
12194           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12195
12196           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12197           if (!enda) {
12198             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12199             if (wave)
12200               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12201           }
12202           if (enda) {
12203             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12204             const gchar *format_str;
12205
12206             switch (fourcc) {
12207               case FOURCC_in24:
12208                 format_str = (enda_value) ? "S24LE" : "S24BE";
12209                 break;
12210               case FOURCC_in32:
12211                 format_str = (enda_value) ? "S32LE" : "S32BE";
12212                 break;
12213               case FOURCC_fl32:
12214                 format_str = (enda_value) ? "F32LE" : "F32BE";
12215                 break;
12216               case FOURCC_fl64:
12217                 format_str = (enda_value) ? "F64LE" : "F64BE";
12218                 break;
12219               default:
12220                 g_assert_not_reached ();
12221                 break;
12222             }
12223             gst_caps_set_simple (entry->caps,
12224                 "format", G_TYPE_STRING, format_str, NULL);
12225           }
12226           break;
12227         }
12228         case FOURCC_owma:
12229         {
12230           const guint8 *owma_data;
12231           const gchar *codec_name = NULL;
12232           guint owma_len;
12233           GstBuffer *buf;
12234           gint version = 1;
12235           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12236           /* FIXME this should also be gst_riff_strf_auds,
12237            * but the latter one is actually missing bits-per-sample :( */
12238           typedef struct
12239           {
12240             gint16 wFormatTag;
12241             gint16 nChannels;
12242             gint32 nSamplesPerSec;
12243             gint32 nAvgBytesPerSec;
12244             gint16 nBlockAlign;
12245             gint16 wBitsPerSample;
12246             gint16 cbSize;
12247           } WAVEFORMATEX;
12248           WAVEFORMATEX *wfex;
12249
12250           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12251           owma_data = stsd_entry_data;
12252           owma_len = QT_UINT32 (owma_data);
12253           if (owma_len <= 54) {
12254             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12255             break;
12256           }
12257           wfex = (WAVEFORMATEX *) (owma_data + 36);
12258           buf = gst_buffer_new_and_alloc (owma_len - 54);
12259           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12260           if (wfex->wFormatTag == 0x0161) {
12261             codec_name = "Windows Media Audio";
12262             version = 2;
12263           } else if (wfex->wFormatTag == 0x0162) {
12264             codec_name = "Windows Media Audio 9 Pro";
12265             version = 3;
12266           } else if (wfex->wFormatTag == 0x0163) {
12267             codec_name = "Windows Media Audio 9 Lossless";
12268             /* is that correct? gstffmpegcodecmap.c is missing it, but
12269              * fluendo codec seems to support it */
12270             version = 4;
12271           }
12272
12273           gst_caps_set_simple (entry->caps,
12274               "codec_data", GST_TYPE_BUFFER, buf,
12275               "wmaversion", G_TYPE_INT, version,
12276               "block_align", G_TYPE_INT,
12277               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12278               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12279               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12280               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12281           gst_buffer_unref (buf);
12282
12283           if (codec_name) {
12284             g_free (codec);
12285             codec = g_strdup (codec_name);
12286           }
12287           break;
12288         }
12289         case FOURCC_wma_:
12290         {
12291           gint len = QT_UINT32 (stsd_entry_data) - offset;
12292           const guint8 *wfex_data = stsd_entry_data + offset;
12293           const gchar *codec_name = NULL;
12294           gint version = 1;
12295           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12296           /* FIXME this should also be gst_riff_strf_auds,
12297            * but the latter one is actually missing bits-per-sample :( */
12298           typedef struct
12299           {
12300             gint16 wFormatTag;
12301             gint16 nChannels;
12302             gint32 nSamplesPerSec;
12303             gint32 nAvgBytesPerSec;
12304             gint16 nBlockAlign;
12305             gint16 wBitsPerSample;
12306             gint16 cbSize;
12307           } WAVEFORMATEX;
12308           WAVEFORMATEX wfex;
12309
12310           /* FIXME: unify with similar wavformatex parsing code above */
12311           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12312
12313           /* find wfex */
12314           while (len >= 8) {
12315             gint size;
12316
12317             if (QT_UINT32 (wfex_data) <= len)
12318               size = QT_UINT32 (wfex_data) - 8;
12319             else
12320               size = len - 8;
12321
12322             if (size < 1)
12323               /* No real data, so break out */
12324               break;
12325
12326             switch (QT_FOURCC (wfex_data + 4)) {
12327               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12328               {
12329                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12330
12331                 if (size < 8 + 18)
12332                   break;
12333
12334                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12335                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12336                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12337                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12338                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12339                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12340                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12341
12342                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12343                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12344                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12345                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12346                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12347                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12348
12349                 if (wfex.wFormatTag == 0x0161) {
12350                   codec_name = "Windows Media Audio";
12351                   version = 2;
12352                 } else if (wfex.wFormatTag == 0x0162) {
12353                   codec_name = "Windows Media Audio 9 Pro";
12354                   version = 3;
12355                 } else if (wfex.wFormatTag == 0x0163) {
12356                   codec_name = "Windows Media Audio 9 Lossless";
12357                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12358                    * fluendo codec seems to support it */
12359                   version = 4;
12360                 }
12361
12362                 gst_caps_set_simple (entry->caps,
12363                     "wmaversion", G_TYPE_INT, version,
12364                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12365                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12366                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12367                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12368
12369                 if (size > wfex.cbSize) {
12370                   GstBuffer *buf;
12371
12372                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12373                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12374                       size - wfex.cbSize);
12375                   gst_caps_set_simple (entry->caps,
12376                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12377                   gst_buffer_unref (buf);
12378                 } else {
12379                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12380                 }
12381
12382                 if (codec_name) {
12383                   g_free (codec);
12384                   codec = g_strdup (codec_name);
12385                 }
12386                 break;
12387               }
12388               default:
12389                 break;
12390             }
12391             len -= size + 8;
12392             wfex_data += size + 8;
12393           }
12394           break;
12395         }
12396         case FOURCC_opus:
12397         {
12398           const guint8 *opus_data;
12399           guint8 *channel_mapping = NULL;
12400           guint32 rate;
12401           guint8 channels;
12402           guint8 channel_mapping_family;
12403           guint8 stream_count;
12404           guint8 coupled_count;
12405           guint8 i;
12406
12407           opus_data = stsd_entry_data;
12408
12409           channels = GST_READ_UINT8 (opus_data + 45);
12410           rate = GST_READ_UINT32_LE (opus_data + 48);
12411           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12412           stream_count = GST_READ_UINT8 (opus_data + 55);
12413           coupled_count = GST_READ_UINT8 (opus_data + 56);
12414
12415           if (channels > 0) {
12416             channel_mapping = g_malloc (channels * sizeof (guint8));
12417             for (i = 0; i < channels; i++)
12418               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12419           }
12420
12421           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12422               channel_mapping_family, stream_count, coupled_count,
12423               channel_mapping);
12424           break;
12425         }
12426         default:
12427           break;
12428       }
12429
12430       if (codec) {
12431         GstStructure *s;
12432         gint bitrate = 0;
12433
12434         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12435             GST_TAG_AUDIO_CODEC, codec, NULL);
12436         g_free (codec);
12437         codec = NULL;
12438
12439         /* some bitrate info may have ended up in caps */
12440         s = gst_caps_get_structure (entry->caps, 0);
12441         gst_structure_get_int (s, "bitrate", &bitrate);
12442         if (bitrate > 0)
12443           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12444               GST_TAG_BITRATE, bitrate, NULL);
12445       }
12446
12447       esds = NULL;
12448       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12449       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12450         if (stream->protected) {
12451           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12452             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12453           }
12454           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12455             mp4a = NULL;
12456           }
12457         } else {
12458           mp4a = NULL;
12459         }
12460       }
12461
12462       wave = NULL;
12463       if (mp4a) {
12464         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12465         if (wave)
12466           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12467         if (!esds)
12468           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12469       }
12470
12471
12472       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12473          16 bits is a byte-swapped wave-style codec identifier,
12474          and we can find a WAVE header internally to a 'wave' atom here.
12475          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12476          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12477          is big-endian).
12478        */
12479       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12480         if (len < offset + 20) {
12481           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12482         } else {
12483           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12484           const guint8 *data = stsd_entry_data + offset + 16;
12485           GNode *wavenode;
12486           GNode *waveheadernode;
12487
12488           wavenode = g_node_new ((guint8 *) data);
12489           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12490             const guint8 *waveheader;
12491             guint32 headerlen;
12492
12493             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12494             if (waveheadernode) {
12495               waveheader = (const guint8 *) waveheadernode->data;
12496               headerlen = QT_UINT32 (waveheader);
12497
12498               if (headerlen > 8) {
12499                 gst_riff_strf_auds *header = NULL;
12500                 GstBuffer *headerbuf;
12501                 GstBuffer *extra;
12502
12503                 waveheader += 8;
12504                 headerlen -= 8;
12505
12506                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12507                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12508
12509                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12510                         headerbuf, &header, &extra)) {
12511                   gst_caps_unref (entry->caps);
12512                   /* FIXME: Need to do something with the channel reorder map */
12513                   entry->caps =
12514                       gst_riff_create_audio_caps (header->format, NULL, header,
12515                       extra, NULL, NULL, NULL);
12516
12517                   if (extra)
12518                     gst_buffer_unref (extra);
12519                   g_free (header);
12520                 }
12521               }
12522             } else
12523               GST_DEBUG ("Didn't find waveheadernode for this codec");
12524           }
12525           g_node_destroy (wavenode);
12526         }
12527       } else if (esds) {
12528         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12529             stream->stream_tags);
12530       } else {
12531         switch (fourcc) {
12532 #if 0
12533             /* FIXME: what is in the chunk? */
12534           case FOURCC_QDMC:
12535           {
12536             gint len = QT_UINT32 (stsd_data);
12537
12538             /* seems to be always = 116 = 0x74 */
12539             break;
12540           }
12541 #endif
12542           case FOURCC_QDM2:
12543           {
12544             gint len = QT_UINT32 (stsd_entry_data);
12545
12546             if (len > 0x3C) {
12547               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12548
12549               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12550               gst_caps_set_simple (entry->caps,
12551                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12552               gst_buffer_unref (buf);
12553             }
12554             gst_caps_set_simple (entry->caps,
12555                 "samplesize", G_TYPE_INT, samplesize, NULL);
12556             break;
12557           }
12558           case FOURCC_alac:
12559           {
12560             GNode *alac, *wave = NULL;
12561
12562             /* apparently, m4a has this atom appended directly in the stsd entry,
12563              * while mov has it in a wave atom */
12564             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12565             if (alac) {
12566               /* alac now refers to stsd entry atom */
12567               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12568               if (wave)
12569                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12570               else
12571                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12572             }
12573             if (alac) {
12574               const guint8 *alac_data = alac->data;
12575               gint len = QT_UINT32 (alac->data);
12576               GstBuffer *buf;
12577
12578               if (len < 36) {
12579                 GST_DEBUG_OBJECT (qtdemux,
12580                     "discarding alac atom with unexpected len %d", len);
12581               } else {
12582                 /* codec-data contains alac atom size and prefix,
12583                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12584                 buf = gst_buffer_new_and_alloc (len);
12585                 gst_buffer_fill (buf, 0, alac->data, len);
12586                 gst_caps_set_simple (entry->caps,
12587                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12588                 gst_buffer_unref (buf);
12589
12590                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12591                 entry->n_channels = QT_UINT8 (alac_data + 21);
12592                 entry->rate = QT_UINT32 (alac_data + 32);
12593                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12594               }
12595             }
12596             gst_caps_set_simple (entry->caps,
12597                 "samplesize", G_TYPE_INT, samplesize, NULL);
12598             break;
12599           }
12600           case FOURCC_fLaC:
12601           {
12602             /* The codingname of the sample entry is 'fLaC' */
12603             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12604
12605             if (flac) {
12606               /* The 'dfLa' box is added to the sample entry to convey
12607                  initializing information for the decoder. */
12608               const GNode *dfla =
12609                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12610
12611               if (dfla) {
12612                 const guint32 len = QT_UINT32 (dfla->data);
12613
12614                 /* Must contain at least dfLa box header (12),
12615                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12616                 if (len < 50) {
12617                   GST_DEBUG_OBJECT (qtdemux,
12618                       "discarding dfla atom with unexpected len %d", len);
12619                 } else {
12620                   /* skip dfLa header to get the METADATA_BLOCKs */
12621                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12622                   const guint32 metadata_blocks_len = len - 12;
12623
12624                   gchar *stream_marker = g_strdup ("fLaC");
12625                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12626                       strlen (stream_marker));
12627
12628                   guint32 index = 0;
12629                   guint32 remainder = 0;
12630                   guint32 block_size = 0;
12631                   gboolean is_last = FALSE;
12632
12633                   GValue array = G_VALUE_INIT;
12634                   GValue value = G_VALUE_INIT;
12635
12636                   g_value_init (&array, GST_TYPE_ARRAY);
12637                   g_value_init (&value, GST_TYPE_BUFFER);
12638
12639                   gst_value_set_buffer (&value, block);
12640                   gst_value_array_append_value (&array, &value);
12641                   g_value_reset (&value);
12642
12643                   gst_buffer_unref (block);
12644
12645                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12646                    * of data, and we haven't already finished parsing */
12647                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12648                     remainder = metadata_blocks_len - index;
12649
12650                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12651                     block_size = 4 +
12652                         (metadata_blocks[index + 1] << 16) +
12653                         (metadata_blocks[index + 2] << 8) +
12654                         metadata_blocks[index + 3];
12655
12656                     /* be careful not to read off end of box */
12657                     if (block_size > remainder) {
12658                       break;
12659                     }
12660
12661                     is_last = metadata_blocks[index] >> 7;
12662
12663                     block = gst_buffer_new_and_alloc (block_size);
12664
12665                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12666                         block_size);
12667
12668                     gst_value_set_buffer (&value, block);
12669                     gst_value_array_append_value (&array, &value);
12670                     g_value_reset (&value);
12671
12672                     gst_buffer_unref (block);
12673
12674                     index += block_size;
12675                   }
12676
12677                   /* only append the metadata if we successfully read all of it */
12678                   if (is_last) {
12679                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12680                             (stream)->caps, 0), "streamheader", &array);
12681                   } else {
12682                     GST_WARNING_OBJECT (qtdemux,
12683                         "discarding all METADATA_BLOCKs due to invalid "
12684                         "block_size %d at idx %d, rem %d", block_size, index,
12685                         remainder);
12686                   }
12687
12688                   g_value_unset (&value);
12689                   g_value_unset (&array);
12690
12691                   /* The sample rate obtained from the stsd may not be accurate
12692                    * since it cannot represent rates greater than 65535Hz, so
12693                    * override that value with the sample rate from the
12694                    * METADATA_BLOCK_STREAMINFO block */
12695                   CUR_STREAM (stream)->rate =
12696                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12697                 }
12698               }
12699             }
12700             break;
12701           }
12702           case FOURCC_sawb:
12703             /* Fallthrough! */
12704             amrwb = TRUE;
12705           case FOURCC_samr:
12706           {
12707             gint len = QT_UINT32 (stsd_entry_data);
12708
12709             if (len > 0x24) {
12710               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12711               guint bitrate;
12712
12713               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12714
12715               /* If we have enough data, let's try to get the 'damr' atom. See
12716                * the 3GPP container spec (26.244) for more details. */
12717               if ((len - 0x34) > 8 &&
12718                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12719                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12720                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12721               }
12722
12723               gst_caps_set_simple (entry->caps,
12724                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12725               gst_buffer_unref (buf);
12726             }
12727             break;
12728           }
12729           case FOURCC_mp4a:
12730           {
12731             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12732             gint len = QT_UINT32 (stsd_entry_data);
12733             guint16 sound_version = 0;
12734             /* FIXME: Can this be determined somehow? There doesn't seem to be
12735              * anything in mp4a atom that specifis compression */
12736             gint profile = 2;
12737             guint16 channels = entry->n_channels;
12738             guint32 time_scale = (guint32) entry->rate;
12739             gint sample_rate_index = -1;
12740
12741             if (len >= 34) {
12742               sound_version = QT_UINT16 (stsd_entry_data + 16);
12743
12744               if (sound_version == 1) {
12745                 channels = QT_UINT16 (stsd_entry_data + 24);
12746                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12747               } else {
12748                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12749                     sound_version);
12750               }
12751             } else {
12752               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12753                   len);
12754             }
12755
12756             sample_rate_index =
12757                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12758             if (sample_rate_index >= 0 && channels > 0) {
12759               guint8 codec_data[2];
12760               GstBuffer *buf;
12761
12762               /* build AAC codec data */
12763               codec_data[0] = profile << 3;
12764               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12765               codec_data[1] = (sample_rate_index & 0x01) << 7;
12766               codec_data[1] |= (channels & 0xF) << 3;
12767
12768               buf = gst_buffer_new_and_alloc (2);
12769               gst_buffer_fill (buf, 0, codec_data, 2);
12770               gst_caps_set_simple (entry->caps,
12771                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12772               gst_buffer_unref (buf);
12773             }
12774             break;
12775           }
12776           case FOURCC_lpcm:
12777           case FOURCC_in24:
12778           case FOURCC_in32:
12779           case FOURCC_fl32:
12780           case FOURCC_fl64:
12781           case FOURCC_s16l:
12782             /* Fully handled elsewhere */
12783             break;
12784           default:
12785             GST_INFO_OBJECT (qtdemux,
12786                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12787             break;
12788         }
12789       }
12790       GST_INFO_OBJECT (qtdemux,
12791           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12792           GST_FOURCC_ARGS (fourcc), entry->caps);
12793
12794     } else if (stream->subtype == FOURCC_strm) {
12795       if (fourcc == FOURCC_rtsp) {
12796         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12797       } else {
12798         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12799             GST_FOURCC_ARGS (fourcc));
12800         goto unknown_stream;
12801       }
12802       entry->sampled = TRUE;
12803     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12804         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12805         || stream->subtype == FOURCC_clcp) {
12806
12807       entry->sampled = TRUE;
12808       entry->sparse = TRUE;
12809
12810       entry->caps =
12811           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12812           &codec);
12813       if (codec) {
12814         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12815             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12816         g_free (codec);
12817         codec = NULL;
12818       }
12819
12820       /* hunt for sort-of codec data */
12821       switch (fourcc) {
12822         case FOURCC_mp4s:
12823         {
12824           GNode *mp4s = NULL;
12825           GNode *esds = NULL;
12826
12827           /* look for palette in a stsd->mp4s->esds sub-atom */
12828           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12829           if (mp4s)
12830             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12831           if (esds == NULL) {
12832             /* Invalid STSD */
12833             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12834             break;
12835           }
12836
12837           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12838               stream->stream_tags);
12839           break;
12840         }
12841         default:
12842           GST_INFO_OBJECT (qtdemux,
12843               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12844           break;
12845       }
12846       GST_INFO_OBJECT (qtdemux,
12847           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12848           GST_FOURCC_ARGS (fourcc), entry->caps);
12849     } else {
12850       /* everything in 1 sample */
12851       entry->sampled = TRUE;
12852
12853       entry->caps =
12854           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12855           &codec);
12856
12857       if (entry->caps == NULL)
12858         goto unknown_stream;
12859
12860       if (codec) {
12861         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12862             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12863         g_free (codec);
12864         codec = NULL;
12865       }
12866     }
12867
12868     /* promote to sampled format */
12869     if (entry->fourcc == FOURCC_samr) {
12870       /* force mono 8000 Hz for AMR */
12871       entry->sampled = TRUE;
12872       entry->n_channels = 1;
12873       entry->rate = 8000;
12874     } else if (entry->fourcc == FOURCC_sawb) {
12875       /* force mono 16000 Hz for AMR-WB */
12876       entry->sampled = TRUE;
12877       entry->n_channels = 1;
12878       entry->rate = 16000;
12879     } else if (entry->fourcc == FOURCC_mp4a) {
12880       entry->sampled = TRUE;
12881     }
12882
12883
12884     stsd_entry_data += len;
12885     remaining_stsd_len -= len;
12886
12887   }
12888
12889   /* collect sample information */
12890   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12891     goto samples_failed;
12892
12893   if (qtdemux->fragmented) {
12894     guint64 offset;
12895
12896     /* need all moov samples as basis; probably not many if any at all */
12897     /* prevent moof parsing taking of at this time */
12898     offset = qtdemux->moof_offset;
12899     qtdemux->moof_offset = 0;
12900     if (stream->n_samples &&
12901         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12902       qtdemux->moof_offset = offset;
12903       goto samples_failed;
12904     }
12905     qtdemux->moof_offset = offset;
12906     /* movie duration more reliable in this case (e.g. mehd) */
12907     if (qtdemux->segment.duration &&
12908         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12909       stream->duration =
12910           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12911   }
12912
12913   /* configure segments */
12914   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12915     goto segments_failed;
12916
12917   /* add some language tag, if useful */
12918   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12919       strcmp (stream->lang_id, "und")) {
12920     const gchar *lang_code;
12921
12922     /* convert ISO 639-2 code to ISO 639-1 */
12923     lang_code = gst_tag_get_language_code (stream->lang_id);
12924     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12925         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12926   }
12927
12928   /* Check for UDTA tags */
12929   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12930     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12931   }
12932
12933   /* Insert and sort new stream in track-id order.
12934    * This will help in comparing old/new streams during stream update check */
12935   g_ptr_array_add (qtdemux->active_streams, stream);
12936   g_ptr_array_sort (qtdemux->active_streams,
12937       (GCompareFunc) qtdemux_track_id_compare_func);
12938   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12939       QTDEMUX_N_STREAMS (qtdemux));
12940
12941   return TRUE;
12942
12943 /* ERRORS */
12944 corrupt_file:
12945   {
12946     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12947         (_("This file is corrupt and cannot be played.")), (NULL));
12948     if (stream)
12949       gst_qtdemux_stream_unref (stream);
12950     return FALSE;
12951   }
12952 error_encrypted:
12953   {
12954     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12955     gst_qtdemux_stream_unref (stream);
12956     return FALSE;
12957   }
12958 samples_failed:
12959 segments_failed:
12960   {
12961     /* we posted an error already */
12962     /* free stbl sub-atoms */
12963     gst_qtdemux_stbl_free (stream);
12964     gst_qtdemux_stream_unref (stream);
12965     return FALSE;
12966   }
12967 existing_stream:
12968   {
12969     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12970         track_id);
12971     return TRUE;
12972   }
12973 unknown_stream:
12974   {
12975     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12976         GST_FOURCC_ARGS (stream->subtype));
12977     gst_qtdemux_stream_unref (stream);
12978     return TRUE;
12979   }
12980 }
12981
12982 /* If we can estimate the overall bitrate, and don't have information about the
12983  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12984  * the overall bitrate minus the sum of the bitrates of all other streams. This
12985  * should be useful for the common case where we have one audio and one video
12986  * stream and can estimate the bitrate of one, but not the other. */
12987 static void
12988 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12989 {
12990   QtDemuxStream *stream = NULL;
12991   gint64 size, sys_bitrate, sum_bitrate = 0;
12992   GstClockTime duration;
12993   guint bitrate;
12994   gint i;
12995
12996   if (qtdemux->fragmented)
12997     return;
12998
12999   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13000
13001   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13002       || size <= 0) {
13003     GST_DEBUG_OBJECT (qtdemux,
13004         "Size in bytes of the stream not known - bailing");
13005     return;
13006   }
13007
13008   /* Subtract the header size */
13009   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13010       size, qtdemux->header_size);
13011
13012   if (size < qtdemux->header_size)
13013     return;
13014
13015   size = size - qtdemux->header_size;
13016
13017   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13018     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13019     return;
13020   }
13021
13022   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13023     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13024     switch (str->subtype) {
13025       case FOURCC_soun:
13026       case FOURCC_vide:
13027         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13028             CUR_STREAM (str)->caps);
13029         /* retrieve bitrate, prefer avg then max */
13030         bitrate = 0;
13031         if (str->stream_tags) {
13032           if (gst_tag_list_get_uint (str->stream_tags,
13033                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13034             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13035           if (gst_tag_list_get_uint (str->stream_tags,
13036                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13037             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13038           if (gst_tag_list_get_uint (str->stream_tags,
13039                   GST_TAG_BITRATE, &bitrate))
13040             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13041         }
13042         if (bitrate)
13043           sum_bitrate += bitrate;
13044         else {
13045           if (stream) {
13046             GST_DEBUG_OBJECT (qtdemux,
13047                 ">1 stream with unknown bitrate - bailing");
13048             return;
13049           } else
13050             stream = str;
13051         }
13052
13053       default:
13054         /* For other subtypes, we assume no significant impact on bitrate */
13055         break;
13056     }
13057   }
13058
13059   if (!stream) {
13060     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13061     return;
13062   }
13063
13064   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13065
13066   if (sys_bitrate < sum_bitrate) {
13067     /* This can happen, since sum_bitrate might be derived from maximum
13068      * bitrates and not average bitrates */
13069     GST_DEBUG_OBJECT (qtdemux,
13070         "System bitrate less than sum bitrate - bailing");
13071     return;
13072   }
13073
13074   bitrate = sys_bitrate - sum_bitrate;
13075   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13076       ", Stream bitrate = %u", sys_bitrate, bitrate);
13077
13078   if (!stream->stream_tags)
13079     stream->stream_tags = gst_tag_list_new_empty ();
13080   else
13081     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13082
13083   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13084       GST_TAG_BITRATE, bitrate, NULL);
13085 }
13086
13087 static GstFlowReturn
13088 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13089 {
13090   GstFlowReturn ret = GST_FLOW_OK;
13091   gint i;
13092
13093   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13094
13095   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13096     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13097     guint32 sample_num = 0;
13098
13099     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13100         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13101
13102     if (qtdemux->fragmented && qtdemux->pullbased) {
13103       /* need all moov samples first */
13104       GST_OBJECT_LOCK (qtdemux);
13105       while (stream->n_samples == 0)
13106         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13107           break;
13108       GST_OBJECT_UNLOCK (qtdemux);
13109     } else {
13110       /* discard any stray moof */
13111       qtdemux->moof_offset = 0;
13112     }
13113
13114     /* prepare braking */
13115     if (ret != GST_FLOW_ERROR)
13116       ret = GST_FLOW_OK;
13117
13118     /* in pull mode, we should have parsed some sample info by now;
13119      * and quite some code will not handle no samples.
13120      * in push mode, we'll just have to deal with it */
13121     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13122       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13123       g_ptr_array_remove_index (qtdemux->active_streams, i);
13124       i--;
13125       continue;
13126     } else if (stream->track_id == qtdemux->chapters_track_id &&
13127         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13128       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13129          so that it doesn't look like a subtitle track */
13130       g_ptr_array_remove_index (qtdemux->active_streams, i);
13131       i--;
13132       continue;
13133     }
13134
13135     /* parse the initial sample for use in setting the frame rate cap */
13136     while (sample_num == 0 && sample_num < stream->n_samples) {
13137       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13138         break;
13139       ++sample_num;
13140     }
13141   }
13142
13143   return ret;
13144 }
13145
13146 static gboolean
13147 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13148 {
13149   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13150 }
13151
13152 static gboolean
13153 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13154 {
13155   gint i;
13156
13157   /* Different length, updated */
13158   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13159     return TRUE;
13160
13161   /* streams in list are sorted in track-id order */
13162   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13163     /* Different stream-id, updated */
13164     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13165             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13166       return TRUE;
13167   }
13168
13169   return FALSE;
13170 }
13171
13172 static gboolean
13173 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13174     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13175 {
13176   /* Connect old stream's srcpad to new stream */
13177   newstream->pad = oldstream->pad;
13178   oldstream->pad = NULL;
13179
13180   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13181    * case we need to force one through */
13182   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13183
13184   return gst_qtdemux_configure_stream (qtdemux, newstream);
13185 }
13186
13187 static gboolean
13188 qtdemux_update_streams (GstQTDemux * qtdemux)
13189 {
13190   gint i;
13191   g_assert (qtdemux->streams_aware);
13192
13193   /* At below, figure out which stream in active_streams has identical stream-id
13194    * with that of in old_streams. If there is matching stream-id,
13195    * corresponding newstream will not be exposed again,
13196    * but demux will reuse srcpad of matched old stream
13197    *
13198    * active_streams : newly created streams from the latest moov
13199    * old_streams : existing streams (belong to previous moov)
13200    */
13201
13202   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13203     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13204     QtDemuxStream *oldstream = NULL;
13205     guint target;
13206
13207     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13208         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13209
13210     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13211             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13212       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13213
13214       /* null pad stream cannot be reused */
13215       if (oldstream->pad == NULL)
13216         oldstream = NULL;
13217     }
13218
13219     if (oldstream) {
13220       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13221
13222       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13223         return FALSE;
13224
13225       /* we don't need to preserve order of old streams */
13226       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13227     } else {
13228       GstTagList *list;
13229
13230       /* now we have all info and can expose */
13231       list = stream->stream_tags;
13232       stream->stream_tags = NULL;
13233       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13234         return FALSE;
13235     }
13236   }
13237
13238   return TRUE;
13239 }
13240
13241 /* Must be called with expose lock */
13242 static GstFlowReturn
13243 qtdemux_expose_streams (GstQTDemux * qtdemux)
13244 {
13245   gint i;
13246
13247   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13248
13249   if (!qtdemux_is_streams_update (qtdemux)) {
13250     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13251     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13252       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13253       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13254       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13255         return GST_FLOW_ERROR;
13256     }
13257
13258     g_ptr_array_set_size (qtdemux->old_streams, 0);
13259     qtdemux->need_segment = TRUE;
13260
13261     return GST_FLOW_OK;
13262   }
13263
13264   if (qtdemux->streams_aware) {
13265     if (!qtdemux_update_streams (qtdemux))
13266       return GST_FLOW_ERROR;
13267   } else {
13268     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13269       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13270       GstTagList *list;
13271
13272       /* now we have all info and can expose */
13273       list = stream->stream_tags;
13274       stream->stream_tags = NULL;
13275       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13276         return GST_FLOW_ERROR;
13277
13278     }
13279   }
13280
13281   gst_qtdemux_guess_bitrate (qtdemux);
13282
13283   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13284
13285   /* If we have still old_streams, it's no more used stream */
13286   for (i = 0; i < qtdemux->old_streams->len; i++) {
13287     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13288
13289     if (stream->pad) {
13290       GstEvent *event;
13291
13292       event = gst_event_new_eos ();
13293       if (qtdemux->segment_seqnum)
13294         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13295
13296       gst_pad_push_event (stream->pad, event);
13297     }
13298   }
13299
13300   g_ptr_array_set_size (qtdemux->old_streams, 0);
13301
13302   /* check if we should post a redirect in case there is a single trak
13303    * and it is a redirecting trak */
13304   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13305       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13306     GstMessage *m;
13307
13308     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13309         "an external content");
13310     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13311         gst_structure_new ("redirect",
13312             "new-location", G_TYPE_STRING,
13313             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13314     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13315     g_free (qtdemux->redirect_location);
13316     qtdemux->redirect_location =
13317         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13318   }
13319
13320   g_ptr_array_foreach (qtdemux->active_streams,
13321       (GFunc) qtdemux_do_allocation, qtdemux);
13322
13323   qtdemux->need_segment = TRUE;
13324
13325   qtdemux->exposed = TRUE;
13326   return GST_FLOW_OK;
13327 }
13328
13329 typedef struct
13330 {
13331   GstStructure *structure;      /* helper for sort function */
13332   gchar *location;
13333   guint min_req_bitrate;
13334   guint min_req_qt_version;
13335 } GstQtReference;
13336
13337 static gint
13338 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13339 {
13340   GstQtReference *ref_a = (GstQtReference *) a;
13341   GstQtReference *ref_b = (GstQtReference *) b;
13342
13343   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13344     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13345
13346   /* known bitrates go before unknown; higher bitrates go first */
13347   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13348 }
13349
13350 /* sort the redirects and post a message for the application.
13351  */
13352 static void
13353 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13354 {
13355   GstQtReference *best;
13356   GstStructure *s;
13357   GstMessage *msg;
13358   GValue list_val = { 0, };
13359   GList *l;
13360
13361   g_assert (references != NULL);
13362
13363   references = g_list_sort (references, qtdemux_redirects_sort_func);
13364
13365   best = (GstQtReference *) references->data;
13366
13367   g_value_init (&list_val, GST_TYPE_LIST);
13368
13369   for (l = references; l != NULL; l = l->next) {
13370     GstQtReference *ref = (GstQtReference *) l->data;
13371     GValue struct_val = { 0, };
13372
13373     ref->structure = gst_structure_new ("redirect",
13374         "new-location", G_TYPE_STRING, ref->location, NULL);
13375
13376     if (ref->min_req_bitrate > 0) {
13377       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13378           ref->min_req_bitrate, NULL);
13379     }
13380
13381     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13382     g_value_set_boxed (&struct_val, ref->structure);
13383     gst_value_list_append_value (&list_val, &struct_val);
13384     g_value_unset (&struct_val);
13385     /* don't free anything here yet, since we need best->structure below */
13386   }
13387
13388   g_assert (best != NULL);
13389   s = gst_structure_copy (best->structure);
13390
13391   if (g_list_length (references) > 1) {
13392     gst_structure_set_value (s, "locations", &list_val);
13393   }
13394
13395   g_value_unset (&list_val);
13396
13397   for (l = references; l != NULL; l = l->next) {
13398     GstQtReference *ref = (GstQtReference *) l->data;
13399
13400     gst_structure_free (ref->structure);
13401     g_free (ref->location);
13402     g_free (ref);
13403   }
13404   g_list_free (references);
13405
13406   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13407   g_free (qtdemux->redirect_location);
13408   qtdemux->redirect_location =
13409       g_strdup (gst_structure_get_string (s, "new-location"));
13410   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13411   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13412 }
13413
13414 /* look for redirect nodes, collect all redirect information and
13415  * process it.
13416  */
13417 static gboolean
13418 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13419 {
13420   GNode *rmra, *rmda, *rdrf;
13421
13422   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13423   if (rmra) {
13424     GList *redirects = NULL;
13425
13426     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13427     while (rmda) {
13428       GstQtReference ref = { NULL, NULL, 0, 0 };
13429       GNode *rmdr, *rmvc;
13430
13431       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13432         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13433         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13434             ref.min_req_bitrate);
13435       }
13436
13437       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13438         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13439         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13440
13441 #ifndef GST_DISABLE_GST_DEBUG
13442         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13443 #endif
13444         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13445
13446         GST_LOG_OBJECT (qtdemux,
13447             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13448             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13449             bitmask, check_type);
13450         if (package == FOURCC_qtim && check_type == 0) {
13451           ref.min_req_qt_version = version;
13452         }
13453       }
13454
13455       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13456       if (rdrf) {
13457         guint32 ref_type;
13458         guint8 *ref_data;
13459         guint ref_len;
13460
13461         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13462         if (ref_len > 20) {
13463           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13464           ref_data = (guint8 *) rdrf->data + 20;
13465           if (ref_type == FOURCC_alis) {
13466             guint record_len, record_version, fn_len;
13467
13468             if (ref_len > 70) {
13469               /* MacOSX alias record, google for alias-layout.txt */
13470               record_len = QT_UINT16 (ref_data + 4);
13471               record_version = QT_UINT16 (ref_data + 4 + 2);
13472               fn_len = QT_UINT8 (ref_data + 50);
13473               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13474                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13475               }
13476             } else {
13477               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13478                   ref_len);
13479             }
13480           } else if (ref_type == FOURCC_url_) {
13481             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13482           } else {
13483             GST_DEBUG_OBJECT (qtdemux,
13484                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13485                 GST_FOURCC_ARGS (ref_type));
13486           }
13487           if (ref.location != NULL) {
13488             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13489             redirects =
13490                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13491           } else {
13492             GST_WARNING_OBJECT (qtdemux,
13493                 "Failed to extract redirect location from rdrf atom");
13494           }
13495         } else {
13496           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13497         }
13498       }
13499
13500       /* look for others */
13501       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13502     }
13503
13504     if (redirects != NULL) {
13505       qtdemux_process_redirects (qtdemux, redirects);
13506     }
13507   }
13508   return TRUE;
13509 }
13510
13511 static GstTagList *
13512 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13513 {
13514   const gchar *fmt;
13515
13516   if (tags == NULL) {
13517     tags = gst_tag_list_new_empty ();
13518     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13519   }
13520
13521   if (qtdemux->major_brand == FOURCC_mjp2)
13522     fmt = "Motion JPEG 2000";
13523   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13524     fmt = "3GP";
13525   else if (qtdemux->major_brand == FOURCC_qt__)
13526     fmt = "Quicktime";
13527   else if (qtdemux->fragmented)
13528     fmt = "ISO fMP4";
13529   else
13530     fmt = "ISO MP4/M4A";
13531
13532   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13533       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13534
13535   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13536       fmt, NULL);
13537
13538   return tags;
13539 }
13540
13541 /* we have read the complete moov node now.
13542  * This function parses all of the relevant info, creates the traks and
13543  * prepares all data structures for playback
13544  */
13545 static gboolean
13546 qtdemux_parse_tree (GstQTDemux * qtdemux)
13547 {
13548   GNode *mvhd;
13549   GNode *trak;
13550   GNode *udta;
13551   GNode *mvex;
13552   GNode *pssh;
13553   guint64 creation_time;
13554   GstDateTime *datetime = NULL;
13555   gint version;
13556
13557   /* make sure we have a usable taglist */
13558   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13559
13560   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13561   if (mvhd == NULL) {
13562     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13563     return qtdemux_parse_redirects (qtdemux);
13564   }
13565
13566   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13567   if (version == 1) {
13568     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13569     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13570     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13571   } else if (version == 0) {
13572     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13573     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13574     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13575   } else {
13576     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13577     return FALSE;
13578   }
13579
13580   /* Moving qt creation time (secs since 1904) to unix time */
13581   if (creation_time != 0) {
13582     /* Try to use epoch first as it should be faster and more commonly found */
13583     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13584       gint64 now_s;
13585
13586       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13587       /* some data cleansing sanity */
13588       now_s = g_get_real_time () / G_USEC_PER_SEC;
13589       if (now_s + 24 * 3600 < creation_time) {
13590         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13591       } else {
13592         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13593       }
13594     } else {
13595       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13596       GDateTime *dt, *dt_local;
13597
13598       dt = g_date_time_add_seconds (base_dt, creation_time);
13599       dt_local = g_date_time_to_local (dt);
13600       datetime = gst_date_time_new_from_g_date_time (dt_local);
13601
13602       g_date_time_unref (base_dt);
13603       g_date_time_unref (dt);
13604     }
13605   }
13606   if (datetime) {
13607     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13608     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13609         datetime, NULL);
13610     gst_date_time_unref (datetime);
13611   }
13612
13613   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13614   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13615
13616   /* check for fragmented file and get some (default) data */
13617   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13618   if (mvex) {
13619     GNode *mehd;
13620     GstByteReader mehd_data;
13621
13622     /* let track parsing or anyone know weird stuff might happen ... */
13623     qtdemux->fragmented = TRUE;
13624
13625     /* compensate for total duration */
13626     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13627     if (mehd)
13628       qtdemux_parse_mehd (qtdemux, &mehd_data);
13629   }
13630
13631   /* Update the movie segment duration, unless it was directly given to us
13632    * by upstream. Otherwise let it as is, as we don't want to mangle the
13633    * duration provided by upstream that may come e.g. from a MPD file. */
13634   if (!qtdemux->upstream_format_is_time) {
13635     GstClockTime duration;
13636     /* set duration in the segment info */
13637     gst_qtdemux_get_duration (qtdemux, &duration);
13638     qtdemux->segment.duration = duration;
13639     /* also do not exceed duration; stop is set that way post seek anyway,
13640      * and segment activation falls back to duration,
13641      * whereas loop only checks stop, so let's align this here as well */
13642     qtdemux->segment.stop = duration;
13643   }
13644
13645   /* parse all traks */
13646   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13647   while (trak) {
13648     qtdemux_parse_trak (qtdemux, trak);
13649     /* iterate all siblings */
13650     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13651   }
13652
13653   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13654
13655   /* find tags */
13656   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13657   if (udta) {
13658     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13659   } else {
13660     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13661   }
13662
13663   /* maybe also some tags in meta box */
13664   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13665   if (udta) {
13666     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13667     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13668   } else {
13669     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13670   }
13671
13672   /* parse any protection system info */
13673   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13674   while (pssh) {
13675     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13676     qtdemux_parse_pssh (qtdemux, pssh);
13677     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13678   }
13679
13680   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13681
13682   return TRUE;
13683 }
13684
13685 /* taken from ffmpeg */
13686 static int
13687 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13688 {
13689   int count = 4;
13690   int len = 0;
13691
13692   while (count--) {
13693     int c;
13694
13695     if (ptr >= end)
13696       return -1;
13697
13698     c = *ptr++;
13699     len = (len << 7) | (c & 0x7f);
13700     if (!(c & 0x80))
13701       break;
13702   }
13703   *end_out = ptr;
13704   return len;
13705 }
13706
13707 static GList *
13708 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13709     gsize codec_data_size)
13710 {
13711   GList *list = NULL;
13712   guint8 *p = codec_data;
13713   gint i, offset, num_packets;
13714   guint *length, last;
13715
13716   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13717
13718   if (codec_data == NULL || codec_data_size == 0)
13719     goto error;
13720
13721   /* start of the stream and vorbis audio or theora video, need to
13722    * send the codec_priv data as first three packets */
13723   num_packets = p[0] + 1;
13724   GST_DEBUG_OBJECT (qtdemux,
13725       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13726       (guint) num_packets, codec_data_size);
13727
13728   /* Let's put some limits, Don't think there even is a xiph codec
13729    * with more than 3-4 headers */
13730   if (G_UNLIKELY (num_packets > 16)) {
13731     GST_WARNING_OBJECT (qtdemux,
13732         "Unlikely number of xiph headers, most likely not valid");
13733     goto error;
13734   }
13735
13736   length = g_alloca (num_packets * sizeof (guint));
13737   last = 0;
13738   offset = 1;
13739
13740   /* first packets, read length values */
13741   for (i = 0; i < num_packets - 1; i++) {
13742     length[i] = 0;
13743     while (offset < codec_data_size) {
13744       length[i] += p[offset];
13745       if (p[offset++] != 0xff)
13746         break;
13747     }
13748     last += length[i];
13749   }
13750   if (offset + last > codec_data_size)
13751     goto error;
13752
13753   /* last packet is the remaining size */
13754   length[i] = codec_data_size - offset - last;
13755
13756   for (i = 0; i < num_packets; i++) {
13757     GstBuffer *hdr;
13758
13759     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13760
13761     if (offset + length[i] > codec_data_size)
13762       goto error;
13763
13764     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13765     list = g_list_append (list, hdr);
13766
13767     offset += length[i];
13768   }
13769
13770   return list;
13771
13772   /* ERRORS */
13773 error:
13774   {
13775     if (list != NULL)
13776       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13777     return NULL;
13778   }
13779
13780 }
13781
13782 /* this can change the codec originally present in @list */
13783 static void
13784 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13785     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13786 {
13787   int len = QT_UINT32 (esds->data);
13788   guint8 *ptr = esds->data;
13789   guint8 *end = ptr + len;
13790   int tag;
13791   guint8 *data_ptr = NULL;
13792   int data_len = 0;
13793   guint8 object_type_id = 0;
13794   guint8 stream_type = 0;
13795   const char *codec_name = NULL;
13796   GstCaps *caps = NULL;
13797
13798   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13799   ptr += 8;
13800   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13801   ptr += 4;
13802   while (ptr + 1 < end) {
13803     tag = QT_UINT8 (ptr);
13804     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13805     ptr++;
13806     len = read_descr_size (ptr, end, &ptr);
13807     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13808
13809     /* Check the stated amount of data is available for reading */
13810     if (len < 0 || ptr + len > end)
13811       break;
13812
13813     switch (tag) {
13814       case ES_DESCRIPTOR_TAG:
13815         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13816         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13817         ptr += 3;
13818         break;
13819       case DECODER_CONFIG_DESC_TAG:{
13820         guint max_bitrate, avg_bitrate;
13821
13822         object_type_id = QT_UINT8 (ptr);
13823         stream_type = QT_UINT8 (ptr + 1) >> 2;
13824         max_bitrate = QT_UINT32 (ptr + 5);
13825         avg_bitrate = QT_UINT32 (ptr + 9);
13826         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13827         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13828         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13829         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13830         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13831         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13832           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13833               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13834         }
13835         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13836           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13837               avg_bitrate, NULL);
13838         }
13839         ptr += 13;
13840         break;
13841       }
13842       case DECODER_SPECIFIC_INFO_TAG:
13843         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13844         if (object_type_id == 0xe0 && len == 0x40) {
13845           guint8 *data;
13846           GstStructure *s;
13847           guint32 clut[16];
13848           gint i;
13849
13850           GST_DEBUG_OBJECT (qtdemux,
13851               "Have VOBSUB palette. Creating palette event");
13852           /* move to decConfigDescr data and read palette */
13853           data = ptr;
13854           for (i = 0; i < 16; i++) {
13855             clut[i] = QT_UINT32 (data);
13856             data += 4;
13857           }
13858
13859           s = gst_structure_new ("application/x-gst-dvd", "event",
13860               G_TYPE_STRING, "dvd-spu-clut-change",
13861               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13862               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13863               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13864               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13865               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13866               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13867               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13868               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13869               NULL);
13870
13871           /* store event and trigger custom processing */
13872           stream->pending_event =
13873               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13874         } else {
13875           /* Generic codec_data handler puts it on the caps */
13876           data_ptr = ptr;
13877           data_len = len;
13878         }
13879
13880         ptr += len;
13881         break;
13882       case SL_CONFIG_DESC_TAG:
13883         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13884         ptr += 1;
13885         break;
13886       default:
13887         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13888             tag);
13889         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13890         ptr += len;
13891         break;
13892     }
13893   }
13894
13895   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13896    * in use, and should also be used to override some other parameters for some
13897    * codecs. */
13898   switch (object_type_id) {
13899     case 0x20:                 /* MPEG-4 */
13900       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13901        * profile_and_level_indication */
13902       if (data_ptr != NULL && data_len >= 5 &&
13903           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13904         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13905             data_ptr + 4, data_len - 4);
13906       }
13907       break;                    /* Nothing special needed here */
13908     case 0x21:                 /* H.264 */
13909       codec_name = "H.264 / AVC";
13910       caps = gst_caps_new_simple ("video/x-h264",
13911           "stream-format", G_TYPE_STRING, "avc",
13912           "alignment", G_TYPE_STRING, "au", NULL);
13913       break;
13914     case 0x40:                 /* AAC (any) */
13915     case 0x66:                 /* AAC Main */
13916     case 0x67:                 /* AAC LC */
13917     case 0x68:                 /* AAC SSR */
13918       /* Override channels and rate based on the codec_data, as it's often
13919        * wrong. */
13920       /* Only do so for basic setup without HE-AAC extension */
13921       if (data_ptr && data_len == 2) {
13922         guint channels, rate;
13923
13924         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13925         if (channels > 0)
13926           entry->n_channels = channels;
13927
13928         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13929         if (rate > 0)
13930           entry->rate = rate;
13931       }
13932
13933       /* Set level and profile if possible */
13934       if (data_ptr != NULL && data_len >= 2) {
13935         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13936             data_ptr, data_len);
13937       } else {
13938         const gchar *profile_str = NULL;
13939         GstBuffer *buffer;
13940         GstMapInfo map;
13941         guint8 *codec_data;
13942         gint rate_idx, profile;
13943
13944         /* No codec_data, let's invent something.
13945          * FIXME: This is wrong for SBR! */
13946
13947         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13948
13949         buffer = gst_buffer_new_and_alloc (2);
13950         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13951         codec_data = map.data;
13952
13953         rate_idx =
13954             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13955             (stream)->rate);
13956
13957         switch (object_type_id) {
13958           case 0x66:
13959             profile_str = "main";
13960             profile = 0;
13961             break;
13962           case 0x67:
13963             profile_str = "lc";
13964             profile = 1;
13965             break;
13966           case 0x68:
13967             profile_str = "ssr";
13968             profile = 2;
13969             break;
13970           default:
13971             profile = 3;
13972             break;
13973         }
13974
13975         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13976         codec_data[1] =
13977             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13978
13979         gst_buffer_unmap (buffer, &map);
13980         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13981             GST_TYPE_BUFFER, buffer, NULL);
13982         gst_buffer_unref (buffer);
13983
13984         if (profile_str) {
13985           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13986               G_TYPE_STRING, profile_str, NULL);
13987         }
13988       }
13989       break;
13990     case 0x60:                 /* MPEG-2, various profiles */
13991     case 0x61:
13992     case 0x62:
13993     case 0x63:
13994     case 0x64:
13995     case 0x65:
13996       codec_name = "MPEG-2 video";
13997       caps = gst_caps_new_simple ("video/mpeg",
13998           "mpegversion", G_TYPE_INT, 2,
13999           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14000       break;
14001     case 0x69:                 /* MPEG-2 BC audio */
14002     case 0x6B:                 /* MPEG-1 audio */
14003       caps = gst_caps_new_simple ("audio/mpeg",
14004           "mpegversion", G_TYPE_INT, 1, NULL);
14005       codec_name = "MPEG-1 audio";
14006       break;
14007     case 0x6A:                 /* MPEG-1 */
14008       codec_name = "MPEG-1 video";
14009       caps = gst_caps_new_simple ("video/mpeg",
14010           "mpegversion", G_TYPE_INT, 1,
14011           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14012       break;
14013     case 0x6C:                 /* MJPEG */
14014       caps =
14015           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14016           NULL);
14017       codec_name = "Motion-JPEG";
14018       break;
14019     case 0x6D:                 /* PNG */
14020       caps =
14021           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14022           NULL);
14023       codec_name = "PNG still images";
14024       break;
14025     case 0x6E:                 /* JPEG2000 */
14026       codec_name = "JPEG-2000";
14027       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14028       break;
14029     case 0xA4:                 /* Dirac */
14030       codec_name = "Dirac";
14031       caps = gst_caps_new_empty_simple ("video/x-dirac");
14032       break;
14033     case 0xA5:                 /* AC3 */
14034       codec_name = "AC-3 audio";
14035       caps = gst_caps_new_simple ("audio/x-ac3",
14036           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14037       break;
14038     case 0xA9:                 /* AC3 */
14039       codec_name = "DTS audio";
14040       caps = gst_caps_new_simple ("audio/x-dts",
14041           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14042       break;
14043     case 0xDD:
14044       if (stream_type == 0x05 && data_ptr) {
14045         GList *headers =
14046             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14047         if (headers) {
14048           GList *tmp;
14049           GValue arr_val = G_VALUE_INIT;
14050           GValue buf_val = G_VALUE_INIT;
14051           GstStructure *s;
14052
14053           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14054           codec_name = "Vorbis";
14055           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14056           g_value_init (&arr_val, GST_TYPE_ARRAY);
14057           g_value_init (&buf_val, GST_TYPE_BUFFER);
14058           for (tmp = headers; tmp; tmp = tmp->next) {
14059             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14060             gst_value_array_append_value (&arr_val, &buf_val);
14061           }
14062           s = gst_caps_get_structure (caps, 0);
14063           gst_structure_take_value (s, "streamheader", &arr_val);
14064           g_value_unset (&buf_val);
14065           g_list_free (headers);
14066
14067           data_ptr = NULL;
14068           data_len = 0;
14069         }
14070       }
14071       break;
14072     case 0xE1:                 /* QCELP */
14073       /* QCELP, the codec_data is a riff tag (little endian) with
14074        * 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). */
14075       caps = gst_caps_new_empty_simple ("audio/qcelp");
14076       codec_name = "QCELP";
14077       break;
14078     default:
14079       break;
14080   }
14081
14082   /* If we have a replacement caps, then change our caps for this stream */
14083   if (caps) {
14084     gst_caps_unref (entry->caps);
14085     entry->caps = caps;
14086   }
14087
14088   if (codec_name && list)
14089     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14090         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14091
14092   /* Add the codec_data attribute to caps, if we have it */
14093   if (data_ptr) {
14094     GstBuffer *buffer;
14095
14096     buffer = gst_buffer_new_and_alloc (data_len);
14097     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14098
14099     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14100     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14101
14102     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14103         buffer, NULL);
14104     gst_buffer_unref (buffer);
14105   }
14106
14107 }
14108
14109 static inline GstCaps *
14110 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14111 {
14112   GstCaps *caps;
14113   guint i;
14114   char *s, fourstr[5];
14115
14116   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14117   for (i = 0; i < 4; i++) {
14118     if (!g_ascii_isalnum (fourstr[i]))
14119       fourstr[i] = '_';
14120   }
14121   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14122   caps = gst_caps_new_empty_simple (s);
14123   g_free (s);
14124   return caps;
14125 }
14126
14127 #define _codec(name) \
14128   do { \
14129     if (codec_name) { \
14130       *codec_name = g_strdup (name); \
14131     } \
14132   } while (0)
14133
14134 static GstCaps *
14135 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14136     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14137     const guint8 * stsd_entry_data, gchar ** codec_name)
14138 {
14139   GstCaps *caps = NULL;
14140   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14141
14142   switch (fourcc) {
14143     case FOURCC_png:
14144       _codec ("PNG still images");
14145       caps = gst_caps_new_empty_simple ("image/png");
14146       break;
14147     case FOURCC_jpeg:
14148       _codec ("JPEG still images");
14149       caps =
14150           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14151           NULL);
14152       break;
14153     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14154     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14155     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14156     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14157       _codec ("Motion-JPEG");
14158       caps =
14159           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14160           NULL);
14161       break;
14162     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14163       _codec ("Motion-JPEG format B");
14164       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14165       break;
14166     case FOURCC_mjp2:
14167       _codec ("JPEG-2000");
14168       /* override to what it should be according to spec, avoid palette_data */
14169       entry->bits_per_sample = 24;
14170       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14171       break;
14172     case FOURCC_SVQ3:
14173       _codec ("Sorensen video v.3");
14174       caps = gst_caps_new_simple ("video/x-svq",
14175           "svqversion", G_TYPE_INT, 3, NULL);
14176       break;
14177     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14178     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14179       _codec ("Sorensen video v.1");
14180       caps = gst_caps_new_simple ("video/x-svq",
14181           "svqversion", G_TYPE_INT, 1, NULL);
14182       break;
14183     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14184       caps = gst_caps_new_empty_simple ("video/x-raw");
14185       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14186       _codec ("Windows Raw RGB");
14187       stream->alignment = 32;
14188       break;
14189     case FOURCC_raw_:
14190     {
14191       guint16 bps;
14192
14193       bps = QT_UINT16 (stsd_entry_data + 82);
14194       switch (bps) {
14195         case 15:
14196           format = GST_VIDEO_FORMAT_RGB15;
14197           break;
14198         case 16:
14199           format = GST_VIDEO_FORMAT_RGB16;
14200           break;
14201         case 24:
14202           format = GST_VIDEO_FORMAT_RGB;
14203           break;
14204         case 32:
14205           format = GST_VIDEO_FORMAT_ARGB;
14206           break;
14207         default:
14208           /* unknown */
14209           break;
14210       }
14211       break;
14212     }
14213     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14214       format = GST_VIDEO_FORMAT_I420;
14215       break;
14216     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14217     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14218       format = GST_VIDEO_FORMAT_I420;
14219       break;
14220     case FOURCC_2vuy:
14221     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14222       format = GST_VIDEO_FORMAT_UYVY;
14223       break;
14224     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14225       format = GST_VIDEO_FORMAT_v308;
14226       break;
14227     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14228       format = GST_VIDEO_FORMAT_v216;
14229       break;
14230     case FOURCC_v210:
14231       format = GST_VIDEO_FORMAT_v210;
14232       break;
14233     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14234       format = GST_VIDEO_FORMAT_r210;
14235       break;
14236       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14237          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14238          format = GST_VIDEO_FORMAT_v410;
14239          break;
14240        */
14241       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14242        * but different order than AYUV
14243        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14244        format = GST_VIDEO_FORMAT_v408;
14245        break;
14246        */
14247     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14248     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14249       _codec ("MPEG-1 video");
14250       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14251           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14252       break;
14253     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14254     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14255     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14256     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14257     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14258     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14259     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14260     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14261     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14262     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14263     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14264     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14265     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14266     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14267     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14268     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14269     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14270     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14271     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14272     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14273     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14274     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14275     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14276     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14277     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14278     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14279     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14280     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14281     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14282     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14283     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14284     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14285     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14286     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14287     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14288     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14289     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14290     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14291     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14292     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14293     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14294     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14295     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14296     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14297     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14298     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14299     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14300       _codec ("MPEG-2 video");
14301       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14302           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14303       break;
14304     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14305       _codec ("GIF still images");
14306       caps = gst_caps_new_empty_simple ("image/gif");
14307       break;
14308     case FOURCC_h263:
14309     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14310     case FOURCC_s263:
14311     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14312       _codec ("H.263");
14313       /* ffmpeg uses the height/width props, don't know why */
14314       caps = gst_caps_new_simple ("video/x-h263",
14315           "variant", G_TYPE_STRING, "itu", NULL);
14316       break;
14317     case FOURCC_mp4v:
14318     case FOURCC_MP4V:
14319       _codec ("MPEG-4 video");
14320       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14321           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14322       break;
14323     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14324     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14325       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14326       caps = gst_caps_new_simple ("video/x-msmpeg",
14327           "msmpegversion", G_TYPE_INT, 43, NULL);
14328       break;
14329     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14330       _codec ("DivX 3");
14331       caps = gst_caps_new_simple ("video/x-divx",
14332           "divxversion", G_TYPE_INT, 3, NULL);
14333       break;
14334     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14335     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14336       _codec ("DivX 4");
14337       caps = gst_caps_new_simple ("video/x-divx",
14338           "divxversion", G_TYPE_INT, 4, NULL);
14339       break;
14340     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14341       _codec ("DivX 5");
14342       caps = gst_caps_new_simple ("video/x-divx",
14343           "divxversion", G_TYPE_INT, 5, NULL);
14344       break;
14345
14346     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14347       _codec ("FFV1");
14348       caps = gst_caps_new_simple ("video/x-ffv",
14349           "ffvversion", G_TYPE_INT, 1, NULL);
14350       break;
14351
14352     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14353     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14354     case FOURCC_XVID:
14355     case FOURCC_xvid:
14356     case FOURCC_FMP4:
14357     case FOURCC_fmp4:
14358     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14359       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14360           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14361       _codec ("MPEG-4");
14362       break;
14363
14364     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14365       _codec ("Cinepak");
14366       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14367       break;
14368     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14369       _codec ("Apple QuickDraw");
14370       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14371       break;
14372     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14373       _codec ("Apple video");
14374       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14375       break;
14376     case FOURCC_H264:
14377     case FOURCC_avc1:
14378     case FOURCC_dva1:
14379       _codec ("H.264 / AVC");
14380       caps = gst_caps_new_simple ("video/x-h264",
14381           "stream-format", G_TYPE_STRING, "avc",
14382           "alignment", G_TYPE_STRING, "au", NULL);
14383       break;
14384     case FOURCC_avc3:
14385     case FOURCC_dvav:
14386       _codec ("H.264 / AVC");
14387       caps = gst_caps_new_simple ("video/x-h264",
14388           "stream-format", G_TYPE_STRING, "avc3",
14389           "alignment", G_TYPE_STRING, "au", NULL);
14390       break;
14391     case FOURCC_H265:
14392     case FOURCC_hvc1:
14393     case FOURCC_dvh1:
14394       _codec ("H.265 / HEVC");
14395       caps = gst_caps_new_simple ("video/x-h265",
14396           "stream-format", G_TYPE_STRING, "hvc1",
14397           "alignment", G_TYPE_STRING, "au", NULL);
14398       break;
14399     case FOURCC_hev1:
14400     case FOURCC_dvhe:
14401       _codec ("H.265 / HEVC");
14402       caps = gst_caps_new_simple ("video/x-h265",
14403           "stream-format", G_TYPE_STRING, "hev1",
14404           "alignment", G_TYPE_STRING, "au", NULL);
14405       break;
14406     case FOURCC_rle_:
14407       _codec ("Run-length encoding");
14408       caps = gst_caps_new_simple ("video/x-rle",
14409           "layout", G_TYPE_STRING, "quicktime", NULL);
14410       break;
14411     case FOURCC_WRLE:
14412       _codec ("Run-length encoding");
14413       caps = gst_caps_new_simple ("video/x-rle",
14414           "layout", G_TYPE_STRING, "microsoft", NULL);
14415       break;
14416     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14417     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14418       _codec ("Indeo Video 3");
14419       caps = gst_caps_new_simple ("video/x-indeo",
14420           "indeoversion", G_TYPE_INT, 3, NULL);
14421       break;
14422     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14423     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14424       _codec ("Intel Video 4");
14425       caps = gst_caps_new_simple ("video/x-indeo",
14426           "indeoversion", G_TYPE_INT, 4, NULL);
14427       break;
14428     case FOURCC_dvcp:
14429     case FOURCC_dvc_:
14430     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14431     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14432     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14433     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14434     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14435     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14436       _codec ("DV Video");
14437       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14438           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14439       break;
14440     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14441     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14442       _codec ("DVCPro50 Video");
14443       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14444           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14445       break;
14446     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14447     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14448       _codec ("DVCProHD Video");
14449       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14450           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14451       break;
14452     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14453       _codec ("Apple Graphics (SMC)");
14454       caps = gst_caps_new_empty_simple ("video/x-smc");
14455       break;
14456     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14457       _codec ("VP3");
14458       caps = gst_caps_new_empty_simple ("video/x-vp3");
14459       break;
14460     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14461       _codec ("VP6 Flash");
14462       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14463       break;
14464     case FOURCC_XiTh:
14465       _codec ("Theora");
14466       caps = gst_caps_new_empty_simple ("video/x-theora");
14467       /* theora uses one byte of padding in the data stream because it does not
14468        * allow 0 sized packets while theora does */
14469       entry->padding = 1;
14470       break;
14471     case FOURCC_drac:
14472       _codec ("Dirac");
14473       caps = gst_caps_new_empty_simple ("video/x-dirac");
14474       break;
14475     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14476       _codec ("TIFF still images");
14477       caps = gst_caps_new_empty_simple ("image/tiff");
14478       break;
14479     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14480       _codec ("Apple Intermediate Codec");
14481       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14482       break;
14483     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14484       _codec ("AVID DNxHD");
14485       caps = gst_caps_from_string ("video/x-dnxhd");
14486       break;
14487     case FOURCC_VP80:
14488     case FOURCC_vp08:
14489       _codec ("On2 VP8");
14490       caps = gst_caps_from_string ("video/x-vp8");
14491       break;
14492     case FOURCC_vp09:
14493       _codec ("Google VP9");
14494       caps = gst_caps_from_string ("video/x-vp9");
14495       break;
14496     case FOURCC_apcs:
14497       _codec ("Apple ProRes LT");
14498       caps =
14499           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14500           NULL);
14501       break;
14502     case FOURCC_apch:
14503       _codec ("Apple ProRes HQ");
14504       caps =
14505           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14506           NULL);
14507       break;
14508     case FOURCC_apcn:
14509       _codec ("Apple ProRes");
14510       caps =
14511           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14512           "standard", NULL);
14513       break;
14514     case FOURCC_apco:
14515       _codec ("Apple ProRes Proxy");
14516       caps =
14517           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14518           "proxy", NULL);
14519       break;
14520     case FOURCC_ap4h:
14521       _codec ("Apple ProRes 4444");
14522       caps =
14523           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14524           "4444", NULL);
14525
14526       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14527       if (entry->bits_per_sample > 0) {
14528         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14529             NULL);
14530       }
14531       break;
14532     case FOURCC_ap4x:
14533       _codec ("Apple ProRes 4444 XQ");
14534       caps =
14535           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14536           "4444xq", NULL);
14537
14538       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14539       if (entry->bits_per_sample > 0) {
14540         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14541             NULL);
14542       }
14543       break;
14544     case FOURCC_cfhd:
14545       _codec ("GoPro CineForm");
14546       caps = gst_caps_from_string ("video/x-cineform");
14547       break;
14548     case FOURCC_vc_1:
14549     case FOURCC_ovc1:
14550       _codec ("VC-1");
14551       caps = gst_caps_new_simple ("video/x-wmv",
14552           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14553       break;
14554     case FOURCC_av01:
14555       _codec ("AV1");
14556       caps = gst_caps_new_empty_simple ("video/x-av1");
14557       break;
14558     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14559     default:
14560     {
14561       caps = _get_unknown_codec_name ("video", fourcc);
14562       break;
14563     }
14564   }
14565
14566   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14567     GstVideoInfo info;
14568
14569     gst_video_info_init (&info);
14570     gst_video_info_set_format (&info, format, entry->width, entry->height);
14571
14572     caps = gst_video_info_to_caps (&info);
14573     *codec_name = gst_pb_utils_get_codec_description (caps);
14574
14575     /* enable clipping for raw video streams */
14576     stream->need_clip = TRUE;
14577     stream->alignment = 32;
14578   }
14579
14580   return caps;
14581 }
14582
14583 static guint
14584 round_up_pow2 (guint n)
14585 {
14586   n = n - 1;
14587   n = n | (n >> 1);
14588   n = n | (n >> 2);
14589   n = n | (n >> 4);
14590   n = n | (n >> 8);
14591   n = n | (n >> 16);
14592   return n + 1;
14593 }
14594
14595 static GstCaps *
14596 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14597     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14598     int len, gchar ** codec_name)
14599 {
14600   GstCaps *caps;
14601   const GstStructure *s;
14602   const gchar *name;
14603   gint endian = 0;
14604   GstAudioFormat format = 0;
14605   gint depth;
14606
14607   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14608
14609   depth = entry->bytes_per_packet * 8;
14610
14611   switch (fourcc) {
14612     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14613     case FOURCC_raw_:
14614       /* 8-bit audio is unsigned */
14615       if (depth == 8)
14616         format = GST_AUDIO_FORMAT_U8;
14617       /* otherwise it's signed and big-endian just like 'twos' */
14618     case FOURCC_twos:
14619       endian = G_BIG_ENDIAN;
14620       /* fall-through */
14621     case FOURCC_sowt:
14622     {
14623       gchar *str;
14624
14625       if (!endian)
14626         endian = G_LITTLE_ENDIAN;
14627
14628       if (!format)
14629         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14630
14631       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14632       _codec (str);
14633       g_free (str);
14634
14635       caps = gst_caps_new_simple ("audio/x-raw",
14636           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14637           "layout", G_TYPE_STRING, "interleaved", NULL);
14638       stream->alignment = GST_ROUND_UP_8 (depth);
14639       stream->alignment = round_up_pow2 (stream->alignment);
14640       break;
14641     }
14642     case FOURCC_fl64:
14643       _codec ("Raw 64-bit floating-point audio");
14644       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14645        * endian later */
14646       caps = gst_caps_new_simple ("audio/x-raw",
14647           "format", G_TYPE_STRING, "F64BE",
14648           "layout", G_TYPE_STRING, "interleaved", NULL);
14649       stream->alignment = 8;
14650       break;
14651     case FOURCC_fl32:
14652       _codec ("Raw 32-bit floating-point audio");
14653       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14654        * endian later */
14655       caps = gst_caps_new_simple ("audio/x-raw",
14656           "format", G_TYPE_STRING, "F32BE",
14657           "layout", G_TYPE_STRING, "interleaved", NULL);
14658       stream->alignment = 4;
14659       break;
14660     case FOURCC_in24:
14661       _codec ("Raw 24-bit PCM audio");
14662       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14663        * endian later */
14664       caps = gst_caps_new_simple ("audio/x-raw",
14665           "format", G_TYPE_STRING, "S24BE",
14666           "layout", G_TYPE_STRING, "interleaved", NULL);
14667       stream->alignment = 4;
14668       break;
14669     case FOURCC_in32:
14670       _codec ("Raw 32-bit PCM audio");
14671       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14672        * endian later */
14673       caps = gst_caps_new_simple ("audio/x-raw",
14674           "format", G_TYPE_STRING, "S32BE",
14675           "layout", G_TYPE_STRING, "interleaved", NULL);
14676       stream->alignment = 4;
14677       break;
14678     case FOURCC_s16l:
14679       _codec ("Raw 16-bit PCM audio");
14680       caps = gst_caps_new_simple ("audio/x-raw",
14681           "format", G_TYPE_STRING, "S16LE",
14682           "layout", G_TYPE_STRING, "interleaved", NULL);
14683       stream->alignment = 2;
14684       break;
14685     case FOURCC_ulaw:
14686       _codec ("Mu-law audio");
14687       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14688       break;
14689     case FOURCC_alaw:
14690       _codec ("A-law audio");
14691       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14692       break;
14693     case 0x0200736d:
14694     case 0x6d730002:
14695       _codec ("Microsoft ADPCM");
14696       /* Microsoft ADPCM-ACM code 2 */
14697       caps = gst_caps_new_simple ("audio/x-adpcm",
14698           "layout", G_TYPE_STRING, "microsoft", NULL);
14699       break;
14700     case 0x1100736d:
14701     case 0x6d730011:
14702       _codec ("DVI/IMA ADPCM");
14703       caps = gst_caps_new_simple ("audio/x-adpcm",
14704           "layout", G_TYPE_STRING, "dvi", NULL);
14705       break;
14706     case 0x1700736d:
14707     case 0x6d730017:
14708       _codec ("DVI/Intel IMA ADPCM");
14709       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14710       caps = gst_caps_new_simple ("audio/x-adpcm",
14711           "layout", G_TYPE_STRING, "quicktime", NULL);
14712       break;
14713     case 0x5500736d:
14714     case 0x6d730055:
14715       /* MPEG layer 3, CBR only (pre QT4.1) */
14716     case FOURCC__mp3:
14717     case FOURCC_mp3_:
14718       _codec ("MPEG-1 layer 3");
14719       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14720       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14721           "mpegversion", G_TYPE_INT, 1, NULL);
14722       break;
14723     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14724       _codec ("MPEG-1 layer 2");
14725       /* MPEG layer 2 */
14726       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14727           "mpegversion", G_TYPE_INT, 1, NULL);
14728       break;
14729     case 0x20736d:
14730     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14731       _codec ("EAC-3 audio");
14732       caps = gst_caps_new_simple ("audio/x-eac3",
14733           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14734       entry->sampled = TRUE;
14735       break;
14736     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14737     case FOURCC_ac_3:
14738       _codec ("AC-3 audio");
14739       caps = gst_caps_new_simple ("audio/x-ac3",
14740           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14741       entry->sampled = TRUE;
14742       break;
14743     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14744     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14745       _codec ("DTS audio");
14746       caps = gst_caps_new_simple ("audio/x-dts",
14747           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14748       entry->sampled = TRUE;
14749       break;
14750     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14751     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14752       _codec ("DTS-HD audio");
14753       caps = gst_caps_new_simple ("audio/x-dts",
14754           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14755       entry->sampled = TRUE;
14756       break;
14757     case FOURCC_MAC3:
14758       _codec ("MACE-3");
14759       caps = gst_caps_new_simple ("audio/x-mace",
14760           "maceversion", G_TYPE_INT, 3, NULL);
14761       break;
14762     case FOURCC_MAC6:
14763       _codec ("MACE-6");
14764       caps = gst_caps_new_simple ("audio/x-mace",
14765           "maceversion", G_TYPE_INT, 6, NULL);
14766       break;
14767     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14768       /* ogg/vorbis */
14769       caps = gst_caps_new_empty_simple ("application/ogg");
14770       break;
14771     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14772       _codec ("DV audio");
14773       caps = gst_caps_new_empty_simple ("audio/x-dv");
14774       break;
14775     case FOURCC_mp4a:
14776       _codec ("MPEG-4 AAC audio");
14777       caps = gst_caps_new_simple ("audio/mpeg",
14778           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14779           "stream-format", G_TYPE_STRING, "raw", NULL);
14780       break;
14781     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14782       _codec ("QDesign Music");
14783       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14784       break;
14785     case FOURCC_QDM2:
14786       _codec ("QDesign Music v.2");
14787       /* FIXME: QDesign music version 2 (no constant) */
14788       if (FALSE && data) {
14789         caps = gst_caps_new_simple ("audio/x-qdm2",
14790             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14791             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14792             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14793       } else {
14794         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14795       }
14796       break;
14797     case FOURCC_agsm:
14798       _codec ("GSM audio");
14799       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14800       break;
14801     case FOURCC_samr:
14802       _codec ("AMR audio");
14803       caps = gst_caps_new_empty_simple ("audio/AMR");
14804       break;
14805     case FOURCC_sawb:
14806       _codec ("AMR-WB audio");
14807       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14808       break;
14809     case FOURCC_ima4:
14810       _codec ("Quicktime IMA ADPCM");
14811       caps = gst_caps_new_simple ("audio/x-adpcm",
14812           "layout", G_TYPE_STRING, "quicktime", NULL);
14813       break;
14814     case FOURCC_alac:
14815       _codec ("Apple lossless audio");
14816       caps = gst_caps_new_empty_simple ("audio/x-alac");
14817       break;
14818     case FOURCC_fLaC:
14819       _codec ("Free Lossless Audio Codec");
14820       caps = gst_caps_new_simple ("audio/x-flac",
14821           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14822       break;
14823     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14824       _codec ("QualComm PureVoice");
14825       caps = gst_caps_from_string ("audio/qcelp");
14826       break;
14827     case FOURCC_wma_:
14828     case FOURCC_owma:
14829       _codec ("WMA");
14830       caps = gst_caps_new_empty_simple ("audio/x-wma");
14831       break;
14832     case FOURCC_opus:
14833       _codec ("Opus");
14834       caps = gst_caps_new_empty_simple ("audio/x-opus");
14835       break;
14836     case FOURCC_lpcm:
14837     {
14838       guint32 flags = 0;
14839       guint32 depth = 0;
14840       guint32 width = 0;
14841       GstAudioFormat format;
14842       enum
14843       {
14844         FLAG_IS_FLOAT = 0x1,
14845         FLAG_IS_BIG_ENDIAN = 0x2,
14846         FLAG_IS_SIGNED = 0x4,
14847         FLAG_IS_PACKED = 0x8,
14848         FLAG_IS_ALIGNED_HIGH = 0x10,
14849         FLAG_IS_NON_INTERLEAVED = 0x20
14850       };
14851       _codec ("Raw LPCM audio");
14852
14853       if (data && len >= 36) {
14854         depth = QT_UINT32 (data + 24);
14855         flags = QT_UINT32 (data + 28);
14856         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14857       }
14858       if ((flags & FLAG_IS_FLOAT) == 0) {
14859         if (depth == 0)
14860           depth = 16;
14861         if (width == 0)
14862           width = 16;
14863         if ((flags & FLAG_IS_ALIGNED_HIGH))
14864           depth = width;
14865
14866         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14867             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14868             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14869         caps = gst_caps_new_simple ("audio/x-raw",
14870             "format", G_TYPE_STRING,
14871             format !=
14872             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14873             "UNKNOWN", "layout", G_TYPE_STRING,
14874             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14875             "interleaved", NULL);
14876         stream->alignment = GST_ROUND_UP_8 (depth);
14877         stream->alignment = round_up_pow2 (stream->alignment);
14878       } else {
14879         if (width == 0)
14880           width = 32;
14881         if (width == 64) {
14882           if (flags & FLAG_IS_BIG_ENDIAN)
14883             format = GST_AUDIO_FORMAT_F64BE;
14884           else
14885             format = GST_AUDIO_FORMAT_F64LE;
14886         } else {
14887           if (flags & FLAG_IS_BIG_ENDIAN)
14888             format = GST_AUDIO_FORMAT_F32BE;
14889           else
14890             format = GST_AUDIO_FORMAT_F32LE;
14891         }
14892         caps = gst_caps_new_simple ("audio/x-raw",
14893             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14894             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14895             "non-interleaved" : "interleaved", NULL);
14896         stream->alignment = width / 8;
14897       }
14898       break;
14899     }
14900     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14901     {
14902       _codec ("AC4");
14903       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14904       break;
14905     }
14906     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14907       /* ? */
14908     default:
14909     {
14910       caps = _get_unknown_codec_name ("audio", fourcc);
14911       break;
14912     }
14913   }
14914
14915   if (caps) {
14916     GstCaps *templ_caps =
14917         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14918     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14919     gst_caps_unref (caps);
14920     gst_caps_unref (templ_caps);
14921     caps = intersection;
14922   }
14923
14924   /* enable clipping for raw audio streams */
14925   s = gst_caps_get_structure (caps, 0);
14926   name = gst_structure_get_name (s);
14927   if (g_str_has_prefix (name, "audio/x-raw")) {
14928     stream->need_clip = TRUE;
14929     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14930     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14931     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
14932         stream->max_buffer_size);
14933   }
14934   return caps;
14935 }
14936
14937 static GstCaps *
14938 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14939     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14940     const guint8 * stsd_entry_data, gchar ** codec_name)
14941 {
14942   GstCaps *caps;
14943
14944   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14945
14946   switch (fourcc) {
14947     case FOURCC_mp4s:
14948       _codec ("DVD subtitle");
14949       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14950       stream->need_process = TRUE;
14951       break;
14952     case FOURCC_text:
14953       _codec ("Quicktime timed text");
14954       goto text;
14955     case FOURCC_tx3g:
14956       _codec ("3GPP timed text");
14957     text:
14958       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14959           "utf8", NULL);
14960       /* actual text piece needs to be extracted */
14961       stream->need_process = TRUE;
14962       break;
14963     case FOURCC_stpp:
14964       _codec ("XML subtitles");
14965       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14966       break;
14967     case FOURCC_c608:
14968       _codec ("CEA 608 Closed Caption");
14969       caps =
14970           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14971           G_TYPE_STRING, "s334-1a", NULL);
14972       stream->need_process = TRUE;
14973       stream->need_split = TRUE;
14974       break;
14975     case FOURCC_c708:
14976       _codec ("CEA 708 Closed Caption");
14977       caps =
14978           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
14979           G_TYPE_STRING, "cdp", NULL);
14980       stream->need_process = TRUE;
14981       break;
14982
14983     default:
14984     {
14985       caps = _get_unknown_codec_name ("text", fourcc);
14986       break;
14987     }
14988   }
14989   return caps;
14990 }
14991
14992 static GstCaps *
14993 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14994     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14995     const guint8 * stsd_entry_data, gchar ** codec_name)
14996 {
14997   GstCaps *caps;
14998
14999   switch (fourcc) {
15000     case FOURCC_m1v:
15001       _codec ("MPEG 1 video");
15002       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15003           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15004       break;
15005     default:
15006       caps = NULL;
15007       break;
15008   }
15009   return caps;
15010 }
15011
15012 static void
15013 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15014     const gchar * system_id)
15015 {
15016   gint i;
15017
15018   if (!qtdemux->protection_system_ids)
15019     qtdemux->protection_system_ids =
15020         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15021   /* Check whether we already have an entry for this system ID. */
15022   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15023     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15024     if (g_ascii_strcasecmp (system_id, id) == 0) {
15025       return;
15026     }
15027   }
15028   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15029   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15030           -1));
15031 }