qtdemux: Allow streams with no specified protection system ID
[platform/upstream/gstreamer.git] / 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 "qtatomparser.h"
63 #include "qtdemux_types.h"
64 #include "qtdemux_dump.h"
65 #include "fourcc.h"
66 #include "descriptors.h"
67 #include "qtdemux_lang.h"
68 #include "qtdemux.h"
69 #include "qtpalette.h"
70 #include "qtdemux_tags.h"
71 #include "qtdemux_tree.h"
72
73 #include <stdlib.h>
74 #include <string.h>
75
76 #include <math.h>
77 #include <gst/math-compat.h>
78
79 #ifdef HAVE_ZLIB
80 # include <zlib.h>
81 #endif
82
83 /* max. size considered 'sane' for non-mdat atoms */
84 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
85
86 /* if the sample index is larger than this, something is likely wrong */
87 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
88
89 /* For converting qt creation times to unix epoch times */
90 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
91 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
92 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
93     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
94
95 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
96
97 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
98
99 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
100
101 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
102 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
103 #define QTDEMUX_NTH_STREAM(demux,idx) \
104    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
105 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
107
108 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
109
110 GST_DEBUG_CATEGORY (qtdemux_debug);
111 #define GST_CAT_DEFAULT qtdemux_debug
112
113 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
114 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
115
116 /* Macros for converting to/from timescale */
117 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
118 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
119
120 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
121 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
122
123 /* timestamp is the DTS */
124 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
125 /* timestamp + offset + cslg_shift is the outgoing PTS */
126 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
127 /* timestamp + offset is the PTS used for internal seek calculations */
128 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
129 /* timestamp + duration - dts is the duration */
130 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
131
132 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
133
134 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
135 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
136     GST_TRACE("Locking from thread %p", g_thread_self()); \
137     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
138     GST_TRACE("Locked from thread %p", g_thread_self()); \
139  } G_STMT_END
140
141 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
142     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
143     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
144  } G_STMT_END
145
146 /*
147  * Quicktime has tracks and segments. A track is a continuous piece of
148  * multimedia content. The track is not always played from start to finish but
149  * instead, pieces of the track are 'cut out' and played in sequence. This is
150  * what the segments do.
151  *
152  * Inside the track we have keyframes (K) and delta frames. The track has its
153  * own timing, which starts from 0 and extends to end. The position in the track
154  * is called the media_time.
155  *
156  * The segments now describe the pieces that should be played from this track
157  * and are basically tuples of media_time/duration/rate entries. We can have
158  * multiple segments and they are all played after one another. An example:
159  *
160  * segment 1: media_time: 1 second, duration: 1 second, rate 1
161  * segment 2: media_time: 3 second, duration: 2 second, rate 2
162  *
163  * To correctly play back this track, one must play: 1 second of media starting
164  * from media_time 1 followed by 2 seconds of media starting from media_time 3
165  * at a rate of 2.
166  *
167  * Each of the segments will be played at a specific time, the first segment at
168  * time 0, the second one after the duration of the first one, etc.. Note that
169  * the time in resulting playback is not identical to the media_time of the
170  * track anymore.
171  *
172  * Visually, assuming the track has 4 second of media_time:
173  *
174  *                (a)                   (b)          (c)              (d)
175  *         .-----------------------------------------------------------.
176  * track:  | K.....K.........K........K.......K.......K...........K... |
177  *         '-----------------------------------------------------------'
178  *         0              1              2              3              4
179  *           .------------^              ^   .----------^              ^
180  *          /              .-------------'  /       .------------------'
181  *         /              /          .-----'       /
182  *         .--------------.         .--------------.
183  *         | segment 1    |         | segment 2    |
184  *         '--------------'         '--------------'
185  *
186  * The challenge here is to cut out the right pieces of the track for each of
187  * the playback segments. This fortunately can easily be done with the SEGMENT
188  * events of GStreamer.
189  *
190  * For playback of segment 1, we need to provide the decoder with the keyframe
191  * (a), in the above figure, but we must instruct it only to output the decoded
192  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
193  * position set to the time of the segment: 0.
194  *
195  * We then proceed to push data from keyframe (a) to frame (b). The decoder
196  * decodes but clips all before media_time 1.
197  *
198  * After finishing a segment, we push out a new SEGMENT event with the clipping
199  * boundaries of the new data.
200  *
201  * This is a good usecase for the GStreamer accumulated SEGMENT events.
202  */
203
204 struct _QtDemuxSegment
205 {
206   /* global time and duration, all gst time */
207   GstClockTime time;
208   GstClockTime stop_time;
209   GstClockTime duration;
210   /* media time of trak, all gst time */
211   GstClockTime media_start;
212   GstClockTime media_stop;
213   gdouble rate;
214   /* Media start time in trak timescale units */
215   guint32 trak_media_start;
216 };
217
218 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
219
220 /* Used with fragmented MP4 files (mfra atom) */
221 struct _QtDemuxRandomAccessEntry
222 {
223   GstClockTime ts;
224   guint64 moof_offset;
225 };
226
227
228 /* Contains properties and cryptographic info for a set of samples from a
229  * track protected using Common Encryption (cenc) */
230 struct _QtDemuxCencSampleSetInfo
231 {
232   GstStructure *default_properties;
233
234   /* @crypto_info holds one GstStructure per sample */
235   GPtrArray *crypto_info;
236 };
237
238 struct _QtDemuxAavdEncryptionInfo
239 {
240   GstStructure *default_properties;
241 };
242
243 static const gchar *
244 qt_demux_state_string (enum QtDemuxState state)
245 {
246   switch (state) {
247     case QTDEMUX_STATE_INITIAL:
248       return "<INITIAL>";
249     case QTDEMUX_STATE_HEADER:
250       return "<HEADER>";
251     case QTDEMUX_STATE_MOVIE:
252       return "<MOVIE>";
253     case QTDEMUX_STATE_BUFFER_MDAT:
254       return "<BUFFER_MDAT>";
255     default:
256       return "<UNKNOWN>";
257   }
258 }
259
260 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
261
262 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
263
264 static GstStaticPadTemplate gst_qtdemux_sink_template =
265     GST_STATIC_PAD_TEMPLATE ("sink",
266     GST_PAD_SINK,
267     GST_PAD_ALWAYS,
268     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
269         "application/x-3gp")
270     );
271
272 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
273 GST_STATIC_PAD_TEMPLATE ("video_%u",
274     GST_PAD_SRC,
275     GST_PAD_SOMETIMES,
276     GST_STATIC_CAPS_ANY);
277
278 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
279 GST_STATIC_PAD_TEMPLATE ("audio_%u",
280     GST_PAD_SRC,
281     GST_PAD_SOMETIMES,
282     GST_STATIC_CAPS_ANY);
283
284 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
285 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
286     GST_PAD_SRC,
287     GST_PAD_SOMETIMES,
288     GST_STATIC_CAPS_ANY);
289
290 #define gst_qtdemux_parent_class parent_class
291 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
292
293 static void gst_qtdemux_dispose (GObject * object);
294 static void gst_qtdemux_finalize (GObject * object);
295
296 static guint32
297 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
298     GstClockTime media_time);
299 static guint32
300 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
301     QtDemuxStream * str, gint64 media_offset);
302
303 #if 0
304 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
305 static GstIndex *gst_qtdemux_get_index (GstElement * element);
306 #endif
307 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
308     GstStateChange transition);
309 static void gst_qtdemux_set_context (GstElement * element,
310     GstContext * context);
311 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
312 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
313     GstObject * parent, GstPadMode mode, gboolean active);
314
315 static void gst_qtdemux_loop (GstPad * pad);
316 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
317     GstBuffer * inbuf);
318 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
319     GstEvent * event);
320 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
321     GstQuery * query);
322 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
323 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
324     QtDemuxStream * stream);
325 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
326     QtDemuxStream * stream);
327 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
328     gboolean force);
329
330 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
331
332 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
333     const guint8 * buffer, guint length);
334 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
335     const guint8 * buffer, guint length);
336 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
337
338 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
339     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
340     GstTagList * list);
341 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
342     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
343     const guint8 * stsd_entry_data, gchar ** codec_name);
344 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
345     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
346     const guint8 * data, int len, gchar ** codec_name);
347 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
348     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
349     gchar ** codec_name);
350 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
351     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
352     const guint8 * stsd_entry_data, gchar ** codec_name);
353
354 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, guint32 n);
356 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
357 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
358 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
359 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
360 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
361 static void qtdemux_do_allocation (QtDemuxStream * stream,
362     GstQTDemux * qtdemux);
363 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
364     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
365 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
366     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
367     GstClockTime * _start, GstClockTime * _stop);
368 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
369     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
370
371 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
372 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
373
374 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
375
376 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, guint sample_index);
378 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
379     const gchar * id);
380 static void qtdemux_gst_structure_free (GstStructure * gststructure);
381 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
382
383 static void
384 gst_qtdemux_class_init (GstQTDemuxClass * klass)
385 {
386   GObjectClass *gobject_class;
387   GstElementClass *gstelement_class;
388
389   gobject_class = (GObjectClass *) klass;
390   gstelement_class = (GstElementClass *) klass;
391
392   parent_class = g_type_class_peek_parent (klass);
393
394   gobject_class->dispose = gst_qtdemux_dispose;
395   gobject_class->finalize = gst_qtdemux_finalize;
396
397   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
398 #if 0
399   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
400   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
401 #endif
402   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
403
404   gst_tag_register_musicbrainz_tags ();
405
406   gst_element_class_add_static_pad_template (gstelement_class,
407       &gst_qtdemux_sink_template);
408   gst_element_class_add_static_pad_template (gstelement_class,
409       &gst_qtdemux_videosrc_template);
410   gst_element_class_add_static_pad_template (gstelement_class,
411       &gst_qtdemux_audiosrc_template);
412   gst_element_class_add_static_pad_template (gstelement_class,
413       &gst_qtdemux_subsrc_template);
414   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
415       "Codec/Demuxer",
416       "Demultiplex a QuickTime file into audio and video streams",
417       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
418
419   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
420   gst_riff_init ();
421 }
422
423 static void
424 gst_qtdemux_init (GstQTDemux * qtdemux)
425 {
426   qtdemux->sinkpad =
427       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
428   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
429   gst_pad_set_activatemode_function (qtdemux->sinkpad,
430       qtdemux_sink_activate_mode);
431   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
432   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
433   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
434   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
435
436   qtdemux->adapter = gst_adapter_new ();
437   g_queue_init (&qtdemux->protection_event_queue);
438   qtdemux->flowcombiner = gst_flow_combiner_new ();
439   g_mutex_init (&qtdemux->expose_lock);
440
441   qtdemux->active_streams = g_ptr_array_new_with_free_func
442       ((GDestroyNotify) gst_qtdemux_stream_unref);
443   qtdemux->old_streams = g_ptr_array_new_with_free_func
444       ((GDestroyNotify) gst_qtdemux_stream_unref);
445
446   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
447
448   gst_qtdemux_reset (qtdemux, TRUE);
449 }
450
451 static void
452 gst_qtdemux_finalize (GObject * object)
453 {
454   GstQTDemux *qtdemux = GST_QTDEMUX (object);
455
456   g_free (qtdemux->redirect_location);
457
458   G_OBJECT_CLASS (parent_class)->finalize (object);
459 }
460
461 static void
462 gst_qtdemux_dispose (GObject * object)
463 {
464   GstQTDemux *qtdemux = GST_QTDEMUX (object);
465
466   if (qtdemux->adapter) {
467     g_object_unref (G_OBJECT (qtdemux->adapter));
468     qtdemux->adapter = NULL;
469   }
470   gst_tag_list_unref (qtdemux->tag_list);
471   gst_flow_combiner_free (qtdemux->flowcombiner);
472   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
473       NULL);
474   g_queue_clear (&qtdemux->protection_event_queue);
475
476   g_free (qtdemux->cenc_aux_info_sizes);
477   qtdemux->cenc_aux_info_sizes = NULL;
478   g_mutex_clear (&qtdemux->expose_lock);
479
480   g_ptr_array_free (qtdemux->active_streams, TRUE);
481   g_ptr_array_free (qtdemux->old_streams, TRUE);
482
483   G_OBJECT_CLASS (parent_class)->dispose (object);
484 }
485
486 static void
487 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
488 {
489   if (qtdemux->redirect_location) {
490     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
491         (_("This file contains no playable streams.")),
492         ("no known streams found, a redirect message has been posted"),
493         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
494   } else {
495     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
496         (_("This file contains no playable streams.")),
497         ("no known streams found"));
498   }
499 }
500
501 static GstBuffer *
502 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
503 {
504   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
505       mem, size, 0, size, mem, free_func);
506 }
507
508 static GstFlowReturn
509 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
510     GstBuffer ** buf)
511 {
512   GstFlowReturn flow;
513   GstMapInfo map;
514   gsize bsize;
515
516   if (G_UNLIKELY (size == 0)) {
517     GstFlowReturn ret;
518     GstBuffer *tmp = NULL;
519
520     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
521     if (ret != GST_FLOW_OK)
522       return ret;
523
524     gst_buffer_map (tmp, &map, GST_MAP_READ);
525     size = QT_UINT32 (map.data);
526     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
527
528     gst_buffer_unmap (tmp, &map);
529     gst_buffer_unref (tmp);
530   }
531
532   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
533   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
534     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
535       /* we're pulling header but already got most interesting bits,
536        * so never mind the rest (e.g. tags) (that much) */
537       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
538           size);
539       return GST_FLOW_EOS;
540     } else {
541       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
542           (_("This file is invalid and cannot be played.")),
543           ("atom has bogus size %" G_GUINT64_FORMAT, size));
544       return GST_FLOW_ERROR;
545     }
546   }
547
548   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
549
550   if (G_UNLIKELY (flow != GST_FLOW_OK))
551     return flow;
552
553   bsize = gst_buffer_get_size (*buf);
554   /* Catch short reads - we don't want any partial atoms */
555   if (G_UNLIKELY (bsize < size)) {
556     GST_WARNING_OBJECT (qtdemux,
557         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
558     gst_buffer_unref (*buf);
559     *buf = NULL;
560     return GST_FLOW_EOS;
561   }
562
563   return flow;
564 }
565
566 #if 1
567 static gboolean
568 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
569     GstFormat src_format, gint64 src_value, GstFormat dest_format,
570     gint64 * dest_value)
571 {
572   gboolean res = TRUE;
573   QtDemuxStream *stream = gst_pad_get_element_private (pad);
574   gint32 index;
575
576   if (stream->subtype != FOURCC_vide) {
577     res = FALSE;
578     goto done;
579   }
580
581   switch (src_format) {
582     case GST_FORMAT_TIME:
583       switch (dest_format) {
584         case GST_FORMAT_BYTES:{
585           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
586           if (-1 == index) {
587             res = FALSE;
588             goto done;
589           }
590
591           *dest_value = stream->samples[index].offset;
592
593           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
594               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
595               GST_TIME_ARGS (src_value), *dest_value);
596           break;
597         }
598         default:
599           res = FALSE;
600           break;
601       }
602       break;
603     case GST_FORMAT_BYTES:
604       switch (dest_format) {
605         case GST_FORMAT_TIME:{
606           index =
607               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
608               stream, src_value);
609
610           if (-1 == index) {
611             res = FALSE;
612             goto done;
613           }
614
615           *dest_value =
616               QTSTREAMTIME_TO_GSTTIME (stream,
617               stream->samples[index].timestamp);
618           GST_DEBUG_OBJECT (qtdemux,
619               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
620               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
621           break;
622         }
623         default:
624           res = FALSE;
625           break;
626       }
627       break;
628     default:
629       res = FALSE;
630       break;
631   }
632
633 done:
634   return res;
635 }
636 #endif
637
638 static gboolean
639 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
640 {
641   gboolean res = FALSE;
642
643   *duration = GST_CLOCK_TIME_NONE;
644
645   if (qtdemux->duration != 0 &&
646       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
647     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
648     res = TRUE;
649   } else {
650     *duration = GST_CLOCK_TIME_NONE;
651   }
652
653   return res;
654 }
655
656 static gboolean
657 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
658     GstQuery * query)
659 {
660   gboolean res = FALSE;
661   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
662
663   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
664
665   switch (GST_QUERY_TYPE (query)) {
666     case GST_QUERY_POSITION:{
667       GstFormat fmt;
668
669       gst_query_parse_position (query, &fmt, NULL);
670       if (fmt == GST_FORMAT_TIME
671           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
672         gst_query_set_position (query, GST_FORMAT_TIME,
673             qtdemux->segment.position);
674         res = TRUE;
675       }
676     }
677       break;
678     case GST_QUERY_DURATION:{
679       GstFormat fmt;
680
681       gst_query_parse_duration (query, &fmt, NULL);
682       if (fmt == GST_FORMAT_TIME) {
683         /* First try to query upstream */
684         res = gst_pad_query_default (pad, parent, query);
685         if (!res) {
686           GstClockTime duration;
687           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
688             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
689             res = TRUE;
690           }
691         }
692       }
693       break;
694     }
695     case GST_QUERY_CONVERT:{
696       GstFormat src_fmt, dest_fmt;
697       gint64 src_value, dest_value = 0;
698
699       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
700
701       res = gst_qtdemux_src_convert (qtdemux, pad,
702           src_fmt, src_value, dest_fmt, &dest_value);
703       if (res)
704         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
705
706       break;
707     }
708     case GST_QUERY_FORMATS:
709       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
710       res = TRUE;
711       break;
712     case GST_QUERY_SEEKING:{
713       GstFormat fmt;
714       gboolean seekable;
715
716       /* try upstream first */
717       res = gst_pad_query_default (pad, parent, query);
718
719       if (!res) {
720         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
721         if (fmt == GST_FORMAT_TIME) {
722           GstClockTime duration;
723
724           gst_qtdemux_get_duration (qtdemux, &duration);
725           seekable = TRUE;
726           if (!qtdemux->pullbased) {
727             GstQuery *q;
728
729             /* we might be able with help from upstream */
730             seekable = FALSE;
731             q = gst_query_new_seeking (GST_FORMAT_BYTES);
732             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
733               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
734               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
735             }
736             gst_query_unref (q);
737           }
738           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
739           res = TRUE;
740         }
741       }
742       break;
743     }
744     case GST_QUERY_SEGMENT:
745     {
746       GstFormat format;
747       gint64 start, stop;
748
749       format = qtdemux->segment.format;
750
751       start =
752           gst_segment_to_stream_time (&qtdemux->segment, format,
753           qtdemux->segment.start);
754       if ((stop = qtdemux->segment.stop) == -1)
755         stop = qtdemux->segment.duration;
756       else
757         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
758
759       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
760       res = TRUE;
761       break;
762     }
763     default:
764       res = gst_pad_query_default (pad, parent, query);
765       break;
766   }
767
768   return res;
769 }
770
771 static void
772 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
773 {
774   if (G_LIKELY (stream->pad)) {
775     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
776         GST_DEBUG_PAD_NAME (stream->pad));
777
778     if (!gst_tag_list_is_empty (stream->stream_tags)) {
779       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
780           stream->stream_tags);
781       gst_pad_push_event (stream->pad,
782           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
783     }
784
785     if (G_UNLIKELY (stream->send_global_tags)) {
786       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
787           qtdemux->tag_list);
788       gst_pad_push_event (stream->pad,
789           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
790       stream->send_global_tags = FALSE;
791     }
792   }
793 }
794
795 /* push event on all source pads; takes ownership of the event */
796 static void
797 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
798 {
799   gboolean has_valid_stream = FALSE;
800   GstEventType etype = GST_EVENT_TYPE (event);
801   guint i;
802
803   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
804       GST_EVENT_TYPE_NAME (event));
805
806   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
807     GstPad *pad;
808     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
809     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
810
811     if ((pad = stream->pad)) {
812       has_valid_stream = TRUE;
813
814       if (etype == GST_EVENT_EOS) {
815         /* let's not send twice */
816         if (stream->sent_eos)
817           continue;
818         stream->sent_eos = TRUE;
819       }
820
821       gst_pad_push_event (pad, gst_event_ref (event));
822     }
823   }
824
825   gst_event_unref (event);
826
827   /* if it is EOS and there are no pads, post an error */
828   if (!has_valid_stream && etype == GST_EVENT_EOS) {
829     gst_qtdemux_post_no_playable_stream_error (qtdemux);
830   }
831 }
832
833 typedef struct
834 {
835   guint64 media_time;
836 } FindData;
837
838 static gint
839 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
840 {
841   if ((gint64) s1->timestamp > *media_time)
842     return 1;
843   if ((gint64) s1->timestamp == *media_time)
844     return 0;
845
846   return -1;
847 }
848
849 /* find the index of the sample that includes the data for @media_time using a
850  * binary search.  Only to be called in optimized cases of linear search below.
851  *
852  * Returns the index of the sample with the corresponding *DTS*.
853  */
854 static guint32
855 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
856     guint64 media_time)
857 {
858   QtDemuxSample *result;
859   guint32 index;
860
861   /* convert media_time to mov format */
862   media_time =
863       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
864
865   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
866       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
867       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
868
869   if (G_LIKELY (result))
870     index = result - str->samples;
871   else
872     index = 0;
873
874   return index;
875 }
876
877
878
879 /* find the index of the sample that includes the data for @media_offset using a
880  * linear search
881  *
882  * Returns the index of the sample.
883  */
884 static guint32
885 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
886     QtDemuxStream * str, gint64 media_offset)
887 {
888   QtDemuxSample *result = str->samples;
889   guint32 index = 0;
890
891   if (result == NULL || str->n_samples == 0)
892     return -1;
893
894   if (media_offset == result->offset)
895     return index;
896
897   result++;
898   while (index < str->n_samples - 1) {
899     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
900       goto parse_failed;
901
902     if (media_offset < result->offset)
903       break;
904
905     index++;
906     result++;
907   }
908   return index;
909
910   /* ERRORS */
911 parse_failed:
912   {
913     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
914     return -1;
915   }
916 }
917
918 /* find the index of the sample that includes the data for @media_time using a
919  * linear search, and keeping in mind that not all samples may have been parsed
920  * yet.  If possible, it will delegate to binary search.
921  *
922  * Returns the index of the sample.
923  */
924 static guint32
925 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
926     GstClockTime media_time)
927 {
928   guint32 index = 0;
929   guint64 mov_time;
930   QtDemuxSample *sample;
931
932   /* convert media_time to mov format */
933   mov_time =
934       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
935
936   sample = str->samples;
937   if (mov_time == sample->timestamp + sample->pts_offset)
938     return index;
939
940   /* use faster search if requested time in already parsed range */
941   sample = str->samples + str->stbl_index;
942   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
943     index = gst_qtdemux_find_index (qtdemux, str, media_time);
944     sample = str->samples + index;
945   } else {
946     while (index < str->n_samples - 1) {
947       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
948         goto parse_failed;
949
950       sample = str->samples + index + 1;
951       if (mov_time < sample->timestamp) {
952         sample = str->samples + index;
953         break;
954       }
955
956       index++;
957     }
958   }
959
960   /* sample->timestamp is now <= media_time, need to find the corresponding
961    * PTS now by looking backwards */
962   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
963     index--;
964     sample = str->samples + index;
965   }
966
967   return index;
968
969   /* ERRORS */
970 parse_failed:
971   {
972     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
973     return -1;
974   }
975 }
976
977 /* find the index of the keyframe needed to decode the sample at @index
978  * of stream @str, or of a subsequent keyframe (depending on @next)
979  *
980  * Returns the index of the keyframe.
981  */
982 static guint32
983 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
984     guint32 index, gboolean next)
985 {
986   guint32 new_index = index;
987
988   if (index >= str->n_samples) {
989     new_index = str->n_samples;
990     goto beach;
991   }
992
993   /* all keyframes, return index */
994   if (str->all_keyframe) {
995     new_index = index;
996     goto beach;
997   }
998
999   /* else search until we have a keyframe */
1000   while (new_index < str->n_samples) {
1001     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1002       goto parse_failed;
1003
1004     if (str->samples[new_index].keyframe)
1005       break;
1006
1007     if (new_index == 0)
1008       break;
1009
1010     if (next)
1011       new_index++;
1012     else
1013       new_index--;
1014   }
1015
1016   if (new_index == str->n_samples) {
1017     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1018     new_index = -1;
1019   }
1020
1021 beach:
1022   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1023       "gave %u", next ? "after" : "before", index, new_index);
1024
1025   return new_index;
1026
1027   /* ERRORS */
1028 parse_failed:
1029   {
1030     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1031     return -1;
1032   }
1033 }
1034
1035 /* find the segment for @time_position for @stream
1036  *
1037  * Returns the index of the segment containing @time_position.
1038  * Returns the last segment and sets the @eos variable to TRUE
1039  * if the time is beyond the end. @eos may be NULL
1040  */
1041 static guint32
1042 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1043     GstClockTime time_position)
1044 {
1045   gint i;
1046   guint32 seg_idx;
1047
1048   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1049       GST_TIME_ARGS (time_position));
1050
1051   seg_idx = -1;
1052   for (i = 0; i < stream->n_segments; i++) {
1053     QtDemuxSegment *segment = &stream->segments[i];
1054
1055     GST_LOG_OBJECT (stream->pad,
1056         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1057         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1058
1059     /* For the last segment we include stop_time in the last segment */
1060     if (i < stream->n_segments - 1) {
1061       if (segment->time <= time_position && time_position < segment->stop_time) {
1062         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1063         seg_idx = i;
1064         break;
1065       }
1066     } else {
1067       /* Last segment always matches */
1068       seg_idx = i;
1069       break;
1070     }
1071   }
1072   return seg_idx;
1073 }
1074
1075 /* move the stream @str to the sample position @index.
1076  *
1077  * Updates @str->sample_index and marks discontinuity if needed.
1078  */
1079 static void
1080 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1081     guint32 index)
1082 {
1083   /* no change needed */
1084   if (index == str->sample_index)
1085     return;
1086
1087   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1088       str->n_samples);
1089
1090   /* position changed, we have a discont */
1091   str->sample_index = index;
1092   str->offset_in_sample = 0;
1093   /* Each time we move in the stream we store the position where we are
1094    * starting from */
1095   str->from_sample = index;
1096   str->discont = TRUE;
1097 }
1098
1099 static void
1100 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1101     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1102 {
1103   guint64 min_offset;
1104   gint64 min_byte_offset = -1;
1105   guint i;
1106
1107   min_offset = desired_time;
1108
1109   /* for each stream, find the index of the sample in the segment
1110    * and move back to the previous keyframe. */
1111   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1112     QtDemuxStream *str;
1113     guint32 index, kindex;
1114     guint32 seg_idx;
1115     GstClockTime media_start;
1116     GstClockTime media_time;
1117     GstClockTime seg_time;
1118     QtDemuxSegment *seg;
1119     gboolean empty_segment = FALSE;
1120
1121     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1122
1123     if (CUR_STREAM (str)->sparse && !use_sparse)
1124       continue;
1125
1126     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1127     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1128
1129     /* get segment and time in the segment */
1130     seg = &str->segments[seg_idx];
1131     seg_time = (desired_time - seg->time) * seg->rate;
1132
1133     while (QTSEGMENT_IS_EMPTY (seg)) {
1134       seg_time = 0;
1135       empty_segment = TRUE;
1136       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1137           seg_idx);
1138       seg_idx++;
1139       if (seg_idx == str->n_segments)
1140         break;
1141       seg = &str->segments[seg_idx];
1142     }
1143
1144     if (seg_idx == str->n_segments) {
1145       /* FIXME track shouldn't have the last segment as empty, but if it
1146        * happens we better handle it */
1147       continue;
1148     }
1149
1150     /* get the media time in the segment */
1151     media_start = seg->media_start + seg_time;
1152
1153     /* get the index of the sample with media time */
1154     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1155     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1156         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1157         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1158         empty_segment);
1159
1160     /* shift to next frame if we are looking for next keyframe */
1161     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1162         && index < str->stbl_index)
1163       index++;
1164
1165     if (!empty_segment) {
1166       /* find previous keyframe */
1167       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1168
1169       /* we will settle for one before if none found after */
1170       if (next && kindex == -1)
1171         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1172
1173       /* Update the requested time whenever a keyframe was found, to make it
1174        * accurate and avoid having the first buffer fall outside of the segment
1175        */
1176       if (kindex != -1) {
1177         index = kindex;
1178
1179         /* get timestamp of keyframe */
1180         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1181         GST_DEBUG_OBJECT (qtdemux,
1182             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1183             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1184             str->samples[kindex].offset);
1185
1186         /* keyframes in the segment get a chance to change the
1187          * desired_offset. keyframes out of the segment are
1188          * ignored. */
1189         if (media_time >= seg->media_start) {
1190           GstClockTime seg_time;
1191
1192           /* this keyframe is inside the segment, convert back to
1193            * segment time */
1194           seg_time = (media_time - seg->media_start) + seg->time;
1195           if ((!next && (seg_time < min_offset)) ||
1196               (next && (seg_time > min_offset)))
1197             min_offset = seg_time;
1198         }
1199       }
1200     }
1201
1202     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1203       min_byte_offset = str->samples[index].offset;
1204   }
1205
1206   if (key_time)
1207     *key_time = min_offset;
1208   if (key_offset)
1209     *key_offset = min_byte_offset;
1210 }
1211
1212 static gboolean
1213 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1214     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1215 {
1216   gboolean res;
1217
1218   g_return_val_if_fail (format != NULL, FALSE);
1219   g_return_val_if_fail (cur != NULL, FALSE);
1220   g_return_val_if_fail (stop != NULL, FALSE);
1221
1222   if (*format == GST_FORMAT_TIME)
1223     return TRUE;
1224
1225   res = TRUE;
1226   if (cur_type != GST_SEEK_TYPE_NONE)
1227     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1228   if (res && stop_type != GST_SEEK_TYPE_NONE)
1229     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1230
1231   if (res)
1232     *format = GST_FORMAT_TIME;
1233
1234   return res;
1235 }
1236
1237 /* perform seek in push based mode:
1238    find BYTE position to move to based on time and delegate to upstream
1239 */
1240 static gboolean
1241 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1242 {
1243   gdouble rate;
1244   GstFormat format;
1245   GstSeekFlags flags;
1246   GstSeekType cur_type, stop_type;
1247   gint64 cur, stop, key_cur;
1248   gboolean res;
1249   gint64 byte_cur;
1250   gint64 original_stop;
1251   guint32 seqnum;
1252
1253   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1254
1255   gst_event_parse_seek (event, &rate, &format, &flags,
1256       &cur_type, &cur, &stop_type, &stop);
1257   seqnum = gst_event_get_seqnum (event);
1258
1259   /* Directly send the instant-rate-change event here before taking the
1260    * stream-lock so that it can be applied as soon as possible */
1261   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1262     GstEvent *ev;
1263
1264     /* instant rate change only supported if direction does not change. All
1265      * other requirements are already checked before creating the seek event
1266      * but let's double-check here to be sure */
1267     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1268         (qtdemux->segment.rate < 0 && rate > 0) ||
1269         cur_type != GST_SEEK_TYPE_NONE ||
1270         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1271       GST_ERROR_OBJECT (qtdemux,
1272           "Instant rate change seeks only supported in the "
1273           "same direction, without flushing and position change");
1274       return FALSE;
1275     }
1276
1277     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1278         (GstSegmentFlags) flags);
1279     gst_event_set_seqnum (ev, seqnum);
1280     gst_qtdemux_push_event (qtdemux, ev);
1281     return TRUE;
1282   }
1283
1284   /* only forward streaming and seeking is possible */
1285   if (rate <= 0)
1286     goto unsupported_seek;
1287
1288   /* convert to TIME if needed and possible */
1289   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1290           stop_type, &stop))
1291     goto no_format;
1292
1293   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1294    * the original stop position to use when upstream pushes the new segment
1295    * for this seek */
1296   original_stop = stop;
1297   stop = -1;
1298
1299   /* find reasonable corresponding BYTE position,
1300    * also try to mind about keyframes, since we can not go back a bit for them
1301    * later on */
1302   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1303    * mostly just work, but let's not yet boldly go there  ... */
1304   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1305
1306   if (byte_cur == -1)
1307     goto abort_seek;
1308
1309   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1310       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1311       stop);
1312
1313   GST_OBJECT_LOCK (qtdemux);
1314   qtdemux->seek_offset = byte_cur;
1315   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1316     qtdemux->push_seek_start = cur;
1317   } else {
1318     qtdemux->push_seek_start = key_cur;
1319   }
1320
1321   if (stop_type == GST_SEEK_TYPE_NONE) {
1322     qtdemux->push_seek_stop = qtdemux->segment.stop;
1323   } else {
1324     qtdemux->push_seek_stop = original_stop;
1325   }
1326   GST_OBJECT_UNLOCK (qtdemux);
1327
1328   qtdemux->segment_seqnum = seqnum;
1329   /* BYTE seek event */
1330   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1331       stop_type, stop);
1332   gst_event_set_seqnum (event, seqnum);
1333   res = gst_pad_push_event (qtdemux->sinkpad, event);
1334
1335   return res;
1336
1337   /* ERRORS */
1338 abort_seek:
1339   {
1340     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1341         "seek aborted.");
1342     return FALSE;
1343   }
1344 unsupported_seek:
1345   {
1346     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1347     return FALSE;
1348   }
1349 no_format:
1350   {
1351     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1352     return FALSE;
1353   }
1354 }
1355
1356 /* perform the seek.
1357  *
1358  * We set all segment_indexes in the streams to unknown and
1359  * adjust the time_position to the desired position. this is enough
1360  * to trigger a segment switch in the streaming thread to start
1361  * streaming from the desired position.
1362  *
1363  * Keyframe seeking is a little more complicated when dealing with
1364  * segments. Ideally we want to move to the previous keyframe in
1365  * the segment but there might not be a keyframe in the segment. In
1366  * fact, none of the segments could contain a keyframe. We take a
1367  * practical approach: seek to the previous keyframe in the segment,
1368  * if there is none, seek to the beginning of the segment.
1369  *
1370  * Called with STREAM_LOCK
1371  */
1372 static gboolean
1373 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1374     guint32 seqnum, GstSeekFlags flags)
1375 {
1376   gint64 desired_offset;
1377   guint i;
1378
1379   desired_offset = segment->position;
1380
1381   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1382       GST_TIME_ARGS (desired_offset));
1383
1384   /* may not have enough fragmented info to do this adjustment,
1385    * and we can't scan (and probably should not) at this time with
1386    * possibly flushing upstream */
1387   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1388     gint64 min_offset;
1389     gboolean next, before, after;
1390
1391     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1392     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1393     next = after && !before;
1394     if (segment->rate < 0)
1395       next = !next;
1396
1397     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1398         NULL);
1399     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1400         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1401     desired_offset = min_offset;
1402   }
1403
1404   /* and set all streams to the final position */
1405   GST_OBJECT_LOCK (qtdemux);
1406   gst_flow_combiner_reset (qtdemux->flowcombiner);
1407   GST_OBJECT_UNLOCK (qtdemux);
1408   qtdemux->segment_seqnum = seqnum;
1409   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1410     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1411
1412     stream->time_position = desired_offset;
1413     stream->accumulated_base = 0;
1414     stream->sample_index = -1;
1415     stream->offset_in_sample = 0;
1416     stream->segment_index = -1;
1417     stream->sent_eos = FALSE;
1418     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1419
1420     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1421       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1422   }
1423   segment->position = desired_offset;
1424   if (segment->rate >= 0) {
1425     segment->start = desired_offset;
1426     /* We need to update time as we update start in that direction */
1427     segment->time = desired_offset;
1428
1429     /* we stop at the end */
1430     if (segment->stop == -1)
1431       segment->stop = segment->duration;
1432   } else {
1433     segment->stop = desired_offset;
1434   }
1435
1436   if (qtdemux->fragmented)
1437     qtdemux->fragmented_seek_pending = TRUE;
1438
1439   return TRUE;
1440 }
1441
1442 /* do a seek in pull based mode */
1443 static gboolean
1444 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1445 {
1446   gdouble rate = 1.0;
1447   GstFormat format;
1448   GstSeekFlags flags;
1449   GstSeekType cur_type, stop_type;
1450   gint64 cur, stop;
1451   gboolean flush, instant_rate_change;
1452   gboolean update;
1453   GstSegment seeksegment;
1454   guint32 seqnum = GST_SEQNUM_INVALID;
1455   GstEvent *flush_event;
1456   gboolean ret;
1457
1458   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1459
1460   gst_event_parse_seek (event, &rate, &format, &flags,
1461       &cur_type, &cur, &stop_type, &stop);
1462   seqnum = gst_event_get_seqnum (event);
1463
1464   /* we have to have a format as the segment format. Try to convert
1465    * if not. */
1466   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1467           stop_type, &stop))
1468     goto no_format;
1469
1470   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1471
1472   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1473   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1474
1475   /* Directly send the instant-rate-change event here before taking the
1476    * stream-lock so that it can be applied as soon as possible */
1477   if (instant_rate_change) {
1478     GstEvent *ev;
1479
1480     /* instant rate change only supported if direction does not change. All
1481      * other requirements are already checked before creating the seek event
1482      * but let's double-check here to be sure */
1483     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1484         (qtdemux->segment.rate < 0 && rate > 0) ||
1485         cur_type != GST_SEEK_TYPE_NONE ||
1486         stop_type != GST_SEEK_TYPE_NONE || flush) {
1487       GST_ERROR_OBJECT (qtdemux,
1488           "Instant rate change seeks only supported in the "
1489           "same direction, without flushing and position change");
1490       return FALSE;
1491     }
1492
1493     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1494         (GstSegmentFlags) flags);
1495     gst_event_set_seqnum (ev, seqnum);
1496     gst_qtdemux_push_event (qtdemux, ev);
1497     return TRUE;
1498   }
1499
1500   /* stop streaming, either by flushing or by pausing the task */
1501   if (flush) {
1502     flush_event = gst_event_new_flush_start ();
1503     if (seqnum != GST_SEQNUM_INVALID)
1504       gst_event_set_seqnum (flush_event, seqnum);
1505     /* unlock upstream pull_range */
1506     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1507     /* make sure out loop function exits */
1508     gst_qtdemux_push_event (qtdemux, flush_event);
1509   } else {
1510     /* non flushing seek, pause the task */
1511     gst_pad_pause_task (qtdemux->sinkpad);
1512   }
1513
1514   /* wait for streaming to finish */
1515   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1516
1517   /* copy segment, we need this because we still need the old
1518    * segment when we close the current segment. */
1519   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1520
1521   /* configure the segment with the seek variables */
1522   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1523   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1524           cur_type, cur, stop_type, stop, &update)) {
1525     ret = FALSE;
1526     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1527   } else {
1528     /* now do the seek */
1529     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1530   }
1531
1532   /* prepare for streaming again */
1533   if (flush) {
1534     flush_event = gst_event_new_flush_stop (TRUE);
1535     if (seqnum != GST_SEQNUM_INVALID)
1536       gst_event_set_seqnum (flush_event, seqnum);
1537
1538     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1539     gst_qtdemux_push_event (qtdemux, flush_event);
1540   }
1541
1542   /* commit the new segment */
1543   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1544
1545   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1546     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1547         qtdemux->segment.format, qtdemux->segment.position);
1548     if (seqnum != GST_SEQNUM_INVALID)
1549       gst_message_set_seqnum (msg, seqnum);
1550     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1551   }
1552
1553   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1554   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1555       qtdemux->sinkpad, NULL);
1556
1557   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1558
1559   return ret;
1560
1561   /* ERRORS */
1562 no_format:
1563   {
1564     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1565     return FALSE;
1566   }
1567 }
1568
1569 static gboolean
1570 qtdemux_ensure_index (GstQTDemux * qtdemux)
1571 {
1572   guint i;
1573
1574   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1575
1576   /* Build complete index */
1577   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1578     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1579
1580     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1581       GST_LOG_OBJECT (qtdemux,
1582           "Building complete index of track-id %u for seeking failed!",
1583           stream->track_id);
1584       return FALSE;
1585     }
1586   }
1587
1588   return TRUE;
1589 }
1590
1591 static gboolean
1592 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1593     GstEvent * event)
1594 {
1595   gboolean res = TRUE;
1596   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1597
1598   switch (GST_EVENT_TYPE (event)) {
1599     case GST_EVENT_RECONFIGURE:
1600       GST_OBJECT_LOCK (qtdemux);
1601       gst_flow_combiner_reset (qtdemux->flowcombiner);
1602       GST_OBJECT_UNLOCK (qtdemux);
1603       res = gst_pad_event_default (pad, parent, event);
1604       break;
1605     case GST_EVENT_SEEK:
1606     {
1607       GstSeekFlags flags = 0;
1608       gboolean instant_rate_change;
1609
1610 #ifndef GST_DISABLE_GST_DEBUG
1611       GstClockTime ts = gst_util_get_timestamp ();
1612 #endif
1613       guint32 seqnum = gst_event_get_seqnum (event);
1614
1615       qtdemux->received_seek = TRUE;
1616
1617       gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL);
1618       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1619
1620       if (seqnum == qtdemux->segment_seqnum) {
1621         GST_LOG_OBJECT (pad,
1622             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1623         gst_event_unref (event);
1624         return TRUE;
1625       }
1626
1627       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1628         /* seek should be handled by upstream, we might need to re-download fragments */
1629         GST_DEBUG_OBJECT (qtdemux,
1630             "let upstream handle seek for fragmented playback");
1631         goto upstream;
1632       }
1633
1634       gst_event_parse_seek_trickmode_interval (event,
1635           &qtdemux->trickmode_interval);
1636
1637       /* Build complete index for seeking;
1638        * if not a fragmented file at least and we're really doing a seek,
1639        * not just an instant-rate-change */
1640       if (!qtdemux->fragmented && !instant_rate_change) {
1641         if (!qtdemux_ensure_index (qtdemux))
1642           goto index_failed;
1643       }
1644 #ifndef GST_DISABLE_GST_DEBUG
1645       ts = gst_util_get_timestamp () - ts;
1646       GST_INFO_OBJECT (qtdemux,
1647           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1648 #endif
1649       if (qtdemux->pullbased) {
1650         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1651       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1652         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1653         res = TRUE;
1654       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1655           && QTDEMUX_N_STREAMS (qtdemux)
1656           && !qtdemux->fragmented) {
1657         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1658       } else {
1659         GST_DEBUG_OBJECT (qtdemux,
1660             "ignoring seek in push mode in current state");
1661         res = FALSE;
1662       }
1663       gst_event_unref (event);
1664     }
1665       break;
1666     default:
1667     upstream:
1668       res = gst_pad_event_default (pad, parent, event);
1669       break;
1670   }
1671
1672 done:
1673   return res;
1674
1675   /* ERRORS */
1676 index_failed:
1677   {
1678     GST_ERROR_OBJECT (qtdemux, "Index failed");
1679     gst_event_unref (event);
1680     res = FALSE;
1681     goto done;
1682   }
1683 }
1684
1685 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1686  *
1687  * If @fw is false, the coding order is explored backwards.
1688  *
1689  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1690  * sample is found for that track.
1691  *
1692  * The stream and sample index of the sample with the minimum offset in the direction explored
1693  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1694  *
1695  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1696  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1697  * @_stream and @_index. */
1698 static void
1699 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1700     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1701 {
1702   gint i, index;
1703   gint64 time, min_time;
1704   QtDemuxStream *stream;
1705   gint iter;
1706
1707   min_time = -1;
1708   stream = NULL;
1709   index = -1;
1710
1711   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1712     QtDemuxStream *str;
1713     gint inc;
1714     gboolean set_sample;
1715
1716     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1717     set_sample = !set;
1718
1719     if (fw) {
1720       i = 0;
1721       inc = 1;
1722     } else {
1723       i = str->n_samples - 1;
1724       inc = -1;
1725     }
1726
1727     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1728       if (str->samples[i].size == 0)
1729         continue;
1730
1731       if (fw && (str->samples[i].offset < byte_pos))
1732         continue;
1733
1734       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1735         continue;
1736
1737       /* move stream to first available sample */
1738       if (set) {
1739         gst_qtdemux_move_stream (qtdemux, str, i);
1740         set_sample = TRUE;
1741       }
1742
1743       /* avoid index from sparse streams since they might be far away */
1744       if (!CUR_STREAM (str)->sparse) {
1745         /* determine min/max time */
1746         time = QTSAMPLE_PTS (str, &str->samples[i]);
1747         if (min_time == -1 || (!fw && time > min_time) ||
1748             (fw && time < min_time)) {
1749           min_time = time;
1750         }
1751
1752         /* determine stream with leading sample, to get its position */
1753         if (!stream ||
1754             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1755             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1756           stream = str;
1757           index = i;
1758         }
1759       }
1760       break;
1761     }
1762
1763     /* no sample for this stream, mark eos */
1764     if (!set_sample)
1765       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1766   }
1767
1768   if (_time)
1769     *_time = min_time;
1770   if (_stream)
1771     *_stream = stream;
1772   if (_index)
1773     *_index = index;
1774 }
1775
1776 /* Copied from mpegtsbase code */
1777 /* FIXME: replace this function when we add new util function for stream-id creation */
1778 static gchar *
1779 _get_upstream_id (GstQTDemux * demux)
1780 {
1781   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1782
1783   if (!upstream_id) {
1784     /* Try to create one from the upstream URI, else use a randome number */
1785     GstQuery *query;
1786     gchar *uri = NULL;
1787
1788     /* Try to generate one from the URI query and
1789      * if it fails take a random number instead */
1790     query = gst_query_new_uri ();
1791     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1792       gst_query_parse_uri (query, &uri);
1793     }
1794
1795     if (uri) {
1796       GChecksum *cs;
1797
1798       /* And then generate an SHA256 sum of the URI */
1799       cs = g_checksum_new (G_CHECKSUM_SHA256);
1800       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1801       g_free (uri);
1802       upstream_id = g_strdup (g_checksum_get_string (cs));
1803       g_checksum_free (cs);
1804     } else {
1805       /* Just get some random number if the URI query fails */
1806       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1807           "implementing a deterministic way of creating a stream-id");
1808       upstream_id =
1809           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1810           g_random_int (), g_random_int ());
1811     }
1812
1813     gst_query_unref (query);
1814   }
1815   return upstream_id;
1816 }
1817
1818 static QtDemuxStream *
1819 _create_stream (GstQTDemux * demux, guint32 track_id)
1820 {
1821   QtDemuxStream *stream;
1822   gchar *upstream_id;
1823
1824   stream = g_new0 (QtDemuxStream, 1);
1825   stream->demux = demux;
1826   stream->track_id = track_id;
1827   upstream_id = _get_upstream_id (demux);
1828   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1829   g_free (upstream_id);
1830   /* new streams always need a discont */
1831   stream->discont = TRUE;
1832   /* we enable clipping for raw audio/video streams */
1833   stream->need_clip = FALSE;
1834   stream->need_process = FALSE;
1835   stream->segment_index = -1;
1836   stream->time_position = 0;
1837   stream->sample_index = -1;
1838   stream->offset_in_sample = 0;
1839   stream->new_stream = TRUE;
1840   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1841   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1842   stream->protected = FALSE;
1843   stream->protection_scheme_type = 0;
1844   stream->protection_scheme_version = 0;
1845   stream->protection_scheme_info = NULL;
1846   stream->n_samples_moof = 0;
1847   stream->duration_moof = 0;
1848   stream->duration_last_moof = 0;
1849   stream->alignment = 1;
1850   stream->stream_tags = gst_tag_list_new_empty ();
1851   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1852   g_queue_init (&stream->protection_scheme_event_queue);
1853   stream->ref_count = 1;
1854   /* consistent default for push based mode */
1855   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1856   return stream;
1857 }
1858
1859 static gboolean
1860 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1861 {
1862   GstStructure *structure;
1863   const gchar *variant;
1864   const GstCaps *mediacaps = NULL;
1865
1866   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1867
1868   structure = gst_caps_get_structure (caps, 0);
1869   variant = gst_structure_get_string (structure, "variant");
1870
1871   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1872     QtDemuxStream *stream;
1873     const GValue *value;
1874
1875     demux->fragmented = TRUE;
1876     demux->mss_mode = TRUE;
1877
1878     if (QTDEMUX_N_STREAMS (demux) > 1) {
1879       /* can't do this, we can only renegotiate for another mss format */
1880       return FALSE;
1881     }
1882
1883     value = gst_structure_get_value (structure, "media-caps");
1884     /* create stream */
1885     if (value) {
1886       const GValue *timescale_v;
1887
1888       /* TODO update when stream changes during playback */
1889
1890       if (QTDEMUX_N_STREAMS (demux) == 0) {
1891         stream = _create_stream (demux, 1);
1892         g_ptr_array_add (demux->active_streams, stream);
1893         /* mss has no stsd/stsd entry, use id 0 as default */
1894         stream->stsd_entries_length = 1;
1895         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1896         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1897       } else {
1898         stream = QTDEMUX_NTH_STREAM (demux, 0);
1899       }
1900
1901       timescale_v = gst_structure_get_value (structure, "timescale");
1902       if (timescale_v) {
1903         stream->timescale = g_value_get_uint64 (timescale_v);
1904       } else {
1905         /* default mss timescale */
1906         stream->timescale = 10000000;
1907       }
1908       demux->timescale = stream->timescale;
1909
1910       mediacaps = gst_value_get_caps (value);
1911       if (!CUR_STREAM (stream)->caps
1912           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1913         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1914             mediacaps);
1915         stream->new_caps = TRUE;
1916       }
1917       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1918       structure = gst_caps_get_structure (mediacaps, 0);
1919       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1920         stream->subtype = FOURCC_vide;
1921
1922         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1923         gst_structure_get_int (structure, "height",
1924             &CUR_STREAM (stream)->height);
1925         gst_structure_get_fraction (structure, "framerate",
1926             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1927       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1928         gint rate = 0;
1929         stream->subtype = FOURCC_soun;
1930         gst_structure_get_int (structure, "channels",
1931             &CUR_STREAM (stream)->n_channels);
1932         gst_structure_get_int (structure, "rate", &rate);
1933         CUR_STREAM (stream)->rate = rate;
1934       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1935         if (gst_structure_has_field (structure, "original-media-type")) {
1936           const gchar *media_type =
1937               gst_structure_get_string (structure, "original-media-type");
1938           if (g_str_has_prefix (media_type, "video")) {
1939             stream->subtype = FOURCC_vide;
1940           } else if (g_str_has_prefix (media_type, "audio")) {
1941             stream->subtype = FOURCC_soun;
1942           }
1943         }
1944       }
1945     }
1946     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1947   } else {
1948     demux->mss_mode = FALSE;
1949   }
1950
1951   return TRUE;
1952 }
1953
1954 static void
1955 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1956 {
1957   gint i;
1958
1959   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1960   gst_pad_stop_task (qtdemux->sinkpad);
1961
1962   if (hard || qtdemux->upstream_format_is_time) {
1963     qtdemux->state = QTDEMUX_STATE_INITIAL;
1964     qtdemux->neededbytes = 16;
1965     qtdemux->todrop = 0;
1966     qtdemux->pullbased = FALSE;
1967     g_clear_pointer (&qtdemux->redirect_location, g_free);
1968     qtdemux->first_mdat = -1;
1969     qtdemux->header_size = 0;
1970     qtdemux->mdatoffset = -1;
1971     qtdemux->restoredata_offset = -1;
1972     if (qtdemux->mdatbuffer)
1973       gst_buffer_unref (qtdemux->mdatbuffer);
1974     if (qtdemux->restoredata_buffer)
1975       gst_buffer_unref (qtdemux->restoredata_buffer);
1976     qtdemux->mdatbuffer = NULL;
1977     qtdemux->restoredata_buffer = NULL;
1978     qtdemux->mdatleft = 0;
1979     qtdemux->mdatsize = 0;
1980     if (qtdemux->comp_brands)
1981       gst_buffer_unref (qtdemux->comp_brands);
1982     qtdemux->comp_brands = NULL;
1983     qtdemux->last_moov_offset = -1;
1984     if (qtdemux->moov_node_compressed) {
1985       g_node_destroy (qtdemux->moov_node_compressed);
1986       if (qtdemux->moov_node)
1987         g_free (qtdemux->moov_node->data);
1988     }
1989     qtdemux->moov_node_compressed = NULL;
1990     if (qtdemux->moov_node)
1991       g_node_destroy (qtdemux->moov_node);
1992     qtdemux->moov_node = NULL;
1993     if (qtdemux->tag_list)
1994       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1995     qtdemux->tag_list = gst_tag_list_new_empty ();
1996     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
1997 #if 0
1998     if (qtdemux->element_index)
1999       gst_object_unref (qtdemux->element_index);
2000     qtdemux->element_index = NULL;
2001 #endif
2002     qtdemux->major_brand = 0;
2003     qtdemux->upstream_format_is_time = FALSE;
2004     qtdemux->upstream_seekable = FALSE;
2005     qtdemux->upstream_size = 0;
2006
2007     qtdemux->fragment_start = -1;
2008     qtdemux->fragment_start_offset = -1;
2009     qtdemux->duration = 0;
2010     qtdemux->moof_offset = 0;
2011     qtdemux->chapters_track_id = 0;
2012     qtdemux->have_group_id = FALSE;
2013     qtdemux->group_id = G_MAXUINT;
2014
2015     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2016         NULL);
2017     g_queue_clear (&qtdemux->protection_event_queue);
2018
2019     qtdemux->received_seek = FALSE;
2020     qtdemux->first_moof_already_parsed = FALSE;
2021   }
2022   qtdemux->offset = 0;
2023   gst_adapter_clear (qtdemux->adapter);
2024   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2025   qtdemux->need_segment = TRUE;
2026
2027   if (hard) {
2028     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2029     qtdemux->trickmode_interval = 0;
2030     g_ptr_array_set_size (qtdemux->active_streams, 0);
2031     g_ptr_array_set_size (qtdemux->old_streams, 0);
2032     qtdemux->n_video_streams = 0;
2033     qtdemux->n_audio_streams = 0;
2034     qtdemux->n_sub_streams = 0;
2035     qtdemux->exposed = FALSE;
2036     qtdemux->fragmented = FALSE;
2037     qtdemux->mss_mode = FALSE;
2038     gst_caps_replace (&qtdemux->media_caps, NULL);
2039     qtdemux->timescale = 0;
2040     qtdemux->got_moov = FALSE;
2041     qtdemux->cenc_aux_info_offset = 0;
2042     qtdemux->cenc_aux_info_sizes = NULL;
2043     qtdemux->cenc_aux_sample_count = 0;
2044     if (qtdemux->protection_system_ids) {
2045       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2046       qtdemux->protection_system_ids = NULL;
2047     }
2048     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2049         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2050         GST_BIN_FLAG_STREAMS_AWARE);
2051
2052     if (qtdemux->preferred_protection_system_id) {
2053       g_free (qtdemux->preferred_protection_system_id);
2054       qtdemux->preferred_protection_system_id = NULL;
2055     }
2056   } else if (qtdemux->mss_mode) {
2057     gst_flow_combiner_reset (qtdemux->flowcombiner);
2058     g_ptr_array_foreach (qtdemux->active_streams,
2059         (GFunc) gst_qtdemux_stream_clear, NULL);
2060   } else {
2061     gst_flow_combiner_reset (qtdemux->flowcombiner);
2062     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2063       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2064       stream->sent_eos = FALSE;
2065       stream->time_position = 0;
2066       stream->accumulated_base = 0;
2067       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2068     }
2069   }
2070 }
2071
2072
2073 /* Maps the @segment to the qt edts internal segments and pushes
2074  * the corresponding segment event.
2075  *
2076  * If it ends up being at a empty segment, a gap will be pushed and the next
2077  * edts segment will be activated in sequence.
2078  *
2079  * To be used in push-mode only */
2080 static void
2081 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2082 {
2083   gint i, iter;
2084
2085   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2086     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2087
2088     stream->time_position = segment->start;
2089
2090     /* in push mode we should be guaranteed that we will have empty segments
2091      * at the beginning and then one segment after, other scenarios are not
2092      * supported and are discarded when parsing the edts */
2093     for (i = 0; i < stream->n_segments; i++) {
2094       if (stream->segments[i].stop_time > segment->start) {
2095         /* push the empty segment and move to the next one */
2096         gst_qtdemux_activate_segment (qtdemux, stream, i,
2097             stream->time_position);
2098         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2099           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2100               stream->time_position);
2101
2102           /* accumulate previous segments */
2103           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2104             stream->accumulated_base +=
2105                 (stream->segment.stop -
2106                 stream->segment.start) / ABS (stream->segment.rate);
2107           continue;
2108         }
2109
2110         g_assert (i == stream->n_segments - 1);
2111       }
2112     }
2113   }
2114 }
2115
2116 static void
2117 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2118     GPtrArray * src)
2119 {
2120   guint i;
2121   guint len;
2122
2123   len = src->len;
2124
2125   if (len == 0)
2126     return;
2127
2128   for (i = 0; i < len; i++) {
2129     QtDemuxStream *stream = g_ptr_array_index (src, i);
2130
2131 #ifndef GST_DISABLE_GST_DEBUG
2132     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2133         stream, GST_STR_NULL (stream->stream_id), dest);
2134 #endif
2135     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2136   }
2137
2138   g_ptr_array_set_size (src, 0);
2139 }
2140
2141 static gboolean
2142 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2143     GstEvent * event)
2144 {
2145   GstQTDemux *demux = GST_QTDEMUX (parent);
2146   gboolean res = TRUE;
2147
2148   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2149
2150   switch (GST_EVENT_TYPE (event)) {
2151     case GST_EVENT_SEGMENT:
2152     {
2153       gint64 offset = 0;
2154       QtDemuxStream *stream;
2155       gint idx;
2156       GstSegment segment;
2157
2158       /* some debug output */
2159       gst_event_copy_segment (event, &segment);
2160       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2161           &segment);
2162
2163       if (segment.format == GST_FORMAT_TIME) {
2164         demux->upstream_format_is_time = TRUE;
2165         demux->segment_seqnum = gst_event_get_seqnum (event);
2166       } else {
2167         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2168             "not in time format");
2169
2170         /* chain will send initial newsegment after pads have been added */
2171         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2172           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2173           goto exit;
2174         }
2175       }
2176
2177       /* check if this matches a time seek we received previously
2178        * FIXME for backwards compatibility reasons we use the
2179        * seek_offset here to compare. In the future we might want to
2180        * change this to use the seqnum as it uniquely should identify
2181        * the segment that corresponds to the seek. */
2182       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2183           ", received segment offset %" G_GINT64_FORMAT,
2184           demux->seek_offset, segment.start);
2185       if (segment.format == GST_FORMAT_BYTES
2186           && demux->seek_offset == segment.start) {
2187         GST_OBJECT_LOCK (demux);
2188         offset = segment.start;
2189
2190         segment.format = GST_FORMAT_TIME;
2191         segment.start = demux->push_seek_start;
2192         segment.stop = demux->push_seek_stop;
2193         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2194             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2195             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2196         GST_OBJECT_UNLOCK (demux);
2197       }
2198
2199       /* we only expect a BYTE segment, e.g. following a seek */
2200       if (segment.format == GST_FORMAT_BYTES) {
2201         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2202           offset = segment.start;
2203
2204           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2205               NULL, (gint64 *) & segment.start);
2206           if ((gint64) segment.start < 0)
2207             segment.start = 0;
2208         }
2209         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2210           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2211               NULL, (gint64 *) & segment.stop);
2212           /* keyframe seeking should already arrange for start >= stop,
2213            * but make sure in other rare cases */
2214           segment.stop = MAX (segment.stop, segment.start);
2215         }
2216       } else if (segment.format == GST_FORMAT_TIME) {
2217         /* push all data on the adapter before starting this
2218          * new segment */
2219         gst_qtdemux_process_adapter (demux, TRUE);
2220       } else {
2221         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2222         goto exit;
2223       }
2224
2225       /* We shouldn't modify upstream driven TIME FORMAT segment */
2226       if (!demux->upstream_format_is_time) {
2227         /* accept upstream's notion of segment and distribute along */
2228         segment.format = GST_FORMAT_TIME;
2229         segment.position = segment.time = segment.start;
2230         segment.duration = demux->segment.duration;
2231         segment.base = gst_segment_to_running_time (&demux->segment,
2232             GST_FORMAT_TIME, demux->segment.position);
2233       }
2234
2235       gst_segment_copy_into (&segment, &demux->segment);
2236       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2237
2238       /* map segment to internal qt segments and push on each stream */
2239       if (QTDEMUX_N_STREAMS (demux)) {
2240         demux->need_segment = TRUE;
2241         gst_qtdemux_check_send_pending_segment (demux);
2242       }
2243
2244       /* clear leftover in current segment, if any */
2245       gst_adapter_clear (demux->adapter);
2246
2247       /* set up streaming thread */
2248       demux->offset = offset;
2249       if (demux->upstream_format_is_time) {
2250         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2251             "set values to restart reading from a new atom");
2252         demux->neededbytes = 16;
2253         demux->todrop = 0;
2254       } else {
2255         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2256             NULL);
2257         if (stream) {
2258           demux->todrop = stream->samples[idx].offset - offset;
2259           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2260         } else {
2261           /* set up for EOS */
2262           demux->neededbytes = -1;
2263           demux->todrop = 0;
2264         }
2265       }
2266     exit:
2267       gst_event_unref (event);
2268       res = TRUE;
2269       goto drop;
2270     }
2271     case GST_EVENT_FLUSH_START:
2272     {
2273       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2274         gst_event_unref (event);
2275         goto drop;
2276       }
2277       QTDEMUX_EXPOSE_LOCK (demux);
2278       res = gst_pad_event_default (demux->sinkpad, parent, event);
2279       QTDEMUX_EXPOSE_UNLOCK (demux);
2280       goto drop;
2281     }
2282     case GST_EVENT_FLUSH_STOP:
2283     {
2284       guint64 dur;
2285
2286       dur = demux->segment.duration;
2287       gst_qtdemux_reset (demux, FALSE);
2288       demux->segment.duration = dur;
2289
2290       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2291         gst_event_unref (event);
2292         goto drop;
2293       }
2294       break;
2295     }
2296     case GST_EVENT_EOS:
2297       /* If we are in push mode, and get an EOS before we've seen any streams,
2298        * then error out - we have nowhere to send the EOS */
2299       if (!demux->pullbased) {
2300         gint i;
2301         gboolean has_valid_stream = FALSE;
2302         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2303           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2304             has_valid_stream = TRUE;
2305             break;
2306           }
2307         }
2308         if (!has_valid_stream)
2309           gst_qtdemux_post_no_playable_stream_error (demux);
2310         else {
2311           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2312               (guint) gst_adapter_available (demux->adapter));
2313           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2314             res = FALSE;
2315           }
2316         }
2317       }
2318       break;
2319     case GST_EVENT_CAPS:{
2320       GstCaps *caps = NULL;
2321
2322       gst_event_parse_caps (event, &caps);
2323       gst_qtdemux_setcaps (demux, caps);
2324       res = TRUE;
2325       gst_event_unref (event);
2326       goto drop;
2327     }
2328     case GST_EVENT_PROTECTION:
2329     {
2330       const gchar *system_id = NULL;
2331
2332       gst_event_parse_protection (event, &system_id, NULL, NULL);
2333       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2334           system_id);
2335       gst_qtdemux_append_protection_system_id (demux, system_id);
2336       /* save the event for later, for source pads that have not been created */
2337       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2338       /* send it to all pads that already exist */
2339       gst_qtdemux_push_event (demux, event);
2340       res = TRUE;
2341       goto drop;
2342     }
2343     case GST_EVENT_STREAM_START:
2344     {
2345       res = TRUE;
2346       gst_event_unref (event);
2347
2348       /* Drain all the buffers */
2349       gst_qtdemux_process_adapter (demux, TRUE);
2350       gst_qtdemux_reset (demux, FALSE);
2351       /* We expect new moov box after new stream-start event */
2352       if (demux->exposed) {
2353         gst_qtdemux_stream_concat (demux,
2354             demux->old_streams, demux->active_streams);
2355       }
2356
2357       goto drop;
2358     }
2359     default:
2360       break;
2361   }
2362
2363   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2364
2365 drop:
2366   return res;
2367 }
2368
2369 static gboolean
2370 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2371     GstQuery * query)
2372 {
2373   GstQTDemux *demux = GST_QTDEMUX (parent);
2374   gboolean res = FALSE;
2375
2376   switch (GST_QUERY_TYPE (query)) {
2377     case GST_QUERY_BITRATE:
2378     {
2379       GstClockTime duration;
2380
2381       /* populate demux->upstream_size if not done yet */
2382       gst_qtdemux_check_seekability (demux);
2383
2384       if (demux->upstream_size != -1
2385           && gst_qtdemux_get_duration (demux, &duration)) {
2386         guint bitrate =
2387             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2388             duration);
2389
2390         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2391             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2392             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2393
2394         /* TODO: better results based on ranges/index tables */
2395         gst_query_set_bitrate (query, bitrate);
2396         res = TRUE;
2397       }
2398       break;
2399     }
2400     default:
2401       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2402       break;
2403   }
2404
2405   return res;
2406 }
2407
2408
2409 #if 0
2410 static void
2411 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2412 {
2413   GstQTDemux *demux = GST_QTDEMUX (element);
2414
2415   GST_OBJECT_LOCK (demux);
2416   if (demux->element_index)
2417     gst_object_unref (demux->element_index);
2418   if (index) {
2419     demux->element_index = gst_object_ref (index);
2420   } else {
2421     demux->element_index = NULL;
2422   }
2423   GST_OBJECT_UNLOCK (demux);
2424   /* object lock might be taken again */
2425   if (index)
2426     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2427   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2428       demux->element_index, demux->index_id);
2429 }
2430
2431 static GstIndex *
2432 gst_qtdemux_get_index (GstElement * element)
2433 {
2434   GstIndex *result = NULL;
2435   GstQTDemux *demux = GST_QTDEMUX (element);
2436
2437   GST_OBJECT_LOCK (demux);
2438   if (demux->element_index)
2439     result = gst_object_ref (demux->element_index);
2440   GST_OBJECT_UNLOCK (demux);
2441
2442   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2443
2444   return result;
2445 }
2446 #endif
2447
2448 static void
2449 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2450 {
2451   g_free ((gpointer) stream->stco.data);
2452   stream->stco.data = NULL;
2453   g_free ((gpointer) stream->stsz.data);
2454   stream->stsz.data = NULL;
2455   g_free ((gpointer) stream->stsc.data);
2456   stream->stsc.data = NULL;
2457   g_free ((gpointer) stream->stts.data);
2458   stream->stts.data = NULL;
2459   g_free ((gpointer) stream->stss.data);
2460   stream->stss.data = NULL;
2461   g_free ((gpointer) stream->stps.data);
2462   stream->stps.data = NULL;
2463   g_free ((gpointer) stream->ctts.data);
2464   stream->ctts.data = NULL;
2465 }
2466
2467 static void
2468 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2469 {
2470   g_free (stream->segments);
2471   stream->segments = NULL;
2472   stream->segment_index = -1;
2473   stream->accumulated_base = 0;
2474 }
2475
2476 static void
2477 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2478 {
2479   g_free (stream->samples);
2480   stream->samples = NULL;
2481   gst_qtdemux_stbl_free (stream);
2482
2483   /* fragments */
2484   g_free (stream->ra_entries);
2485   stream->ra_entries = NULL;
2486   stream->n_ra_entries = 0;
2487
2488   stream->sample_index = -1;
2489   stream->stbl_index = -1;
2490   stream->n_samples = 0;
2491   stream->time_position = 0;
2492
2493   stream->n_samples_moof = 0;
2494   stream->duration_moof = 0;
2495   stream->duration_last_moof = 0;
2496 }
2497
2498 static void
2499 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2500 {
2501   gint i;
2502   if (stream->allocator)
2503     gst_object_unref (stream->allocator);
2504   while (stream->buffers) {
2505     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2506     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2507   }
2508   for (i = 0; i < stream->stsd_entries_length; i++) {
2509     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2510     if (entry->rgb8_palette) {
2511       gst_memory_unref (entry->rgb8_palette);
2512       entry->rgb8_palette = NULL;
2513     }
2514     entry->sparse = FALSE;
2515   }
2516
2517   if (stream->stream_tags)
2518     gst_tag_list_unref (stream->stream_tags);
2519
2520   stream->stream_tags = gst_tag_list_new_empty ();
2521   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2522   g_free (stream->redirect_uri);
2523   stream->redirect_uri = NULL;
2524   stream->sent_eos = FALSE;
2525   stream->protected = FALSE;
2526   if (stream->protection_scheme_info) {
2527     if (stream->protection_scheme_type == FOURCC_cenc) {
2528       QtDemuxCencSampleSetInfo *info =
2529           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2530       if (info->default_properties)
2531         gst_structure_free (info->default_properties);
2532       if (info->crypto_info)
2533         g_ptr_array_free (info->crypto_info, TRUE);
2534     }
2535     if (stream->protection_scheme_type == FOURCC_aavd) {
2536       QtDemuxAavdEncryptionInfo *info =
2537           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2538       if (info->default_properties)
2539         gst_structure_free (info->default_properties);
2540     }
2541     g_free (stream->protection_scheme_info);
2542     stream->protection_scheme_info = NULL;
2543   }
2544   stream->protection_scheme_type = 0;
2545   stream->protection_scheme_version = 0;
2546   g_queue_foreach (&stream->protection_scheme_event_queue,
2547       (GFunc) gst_event_unref, NULL);
2548   g_queue_clear (&stream->protection_scheme_event_queue);
2549   gst_qtdemux_stream_flush_segments_data (stream);
2550   gst_qtdemux_stream_flush_samples_data (stream);
2551 }
2552
2553 static void
2554 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2555 {
2556   gint i;
2557   gst_qtdemux_stream_clear (stream);
2558   for (i = 0; i < stream->stsd_entries_length; i++) {
2559     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2560     if (entry->caps) {
2561       gst_caps_unref (entry->caps);
2562       entry->caps = NULL;
2563     }
2564   }
2565   g_free (stream->stsd_entries);
2566   stream->stsd_entries = NULL;
2567   stream->stsd_entries_length = 0;
2568 }
2569
2570 static QtDemuxStream *
2571 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2572 {
2573   g_atomic_int_add (&stream->ref_count, 1);
2574
2575   return stream;
2576 }
2577
2578 static void
2579 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2580 {
2581   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2582     gst_qtdemux_stream_reset (stream);
2583     gst_tag_list_unref (stream->stream_tags);
2584     if (stream->pad) {
2585       GstQTDemux *demux = stream->demux;
2586       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2587       GST_OBJECT_LOCK (demux);
2588       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2589       GST_OBJECT_UNLOCK (demux);
2590     }
2591     g_free (stream->stream_id);
2592     g_free (stream);
2593   }
2594 }
2595
2596 static GstStateChangeReturn
2597 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2598 {
2599   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2600   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2601
2602   switch (transition) {
2603     case GST_STATE_CHANGE_READY_TO_PAUSED:
2604       gst_qtdemux_reset (qtdemux, TRUE);
2605       break;
2606     default:
2607       break;
2608   }
2609
2610   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2611
2612   switch (transition) {
2613     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2614       gst_qtdemux_reset (qtdemux, TRUE);
2615       break;
2616     }
2617     default:
2618       break;
2619   }
2620
2621   return result;
2622 }
2623
2624 static void
2625 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2626 {
2627   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2628
2629   g_return_if_fail (GST_IS_CONTEXT (context));
2630
2631   if (gst_context_has_context_type (context,
2632           "drm-preferred-decryption-system-id")) {
2633     const GstStructure *s;
2634
2635     s = gst_context_get_structure (context);
2636     g_free (qtdemux->preferred_protection_system_id);
2637     qtdemux->preferred_protection_system_id =
2638         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2639     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2640         qtdemux->preferred_protection_system_id);
2641   }
2642
2643   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2644 }
2645
2646 static void
2647 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2648 {
2649   /* counts as header data */
2650   qtdemux->header_size += length;
2651
2652   /* only consider at least a sufficiently complete ftyp atom */
2653   if (length >= 20) {
2654     GstBuffer *buf;
2655
2656     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2657     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2658         GST_FOURCC_ARGS (qtdemux->major_brand));
2659     if (qtdemux->comp_brands)
2660       gst_buffer_unref (qtdemux->comp_brands);
2661     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2662     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2663   }
2664 }
2665
2666 static void
2667 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2668     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2669     const guint8 * kid)
2670 {
2671   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2672   gst_buffer_fill (kid_buf, 0, kid, 16);
2673   if (info->default_properties)
2674     gst_structure_free (info->default_properties);
2675   info->default_properties =
2676       gst_structure_new ("application/x-cenc",
2677       "iv_size", G_TYPE_UINT, iv_size,
2678       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2679       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2680   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2681       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2682   gst_buffer_unref (kid_buf);
2683 }
2684
2685 static gboolean
2686 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2687     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2688 {
2689   guint32 algorithm_id = 0;
2690   const guint8 *kid;
2691   gboolean is_encrypted = TRUE;
2692   guint8 iv_size = 8;
2693
2694   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2695     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2696     return FALSE;
2697   }
2698
2699   algorithm_id >>= 8;
2700   if (algorithm_id == 0) {
2701     is_encrypted = FALSE;
2702   } else if (algorithm_id == 1) {
2703     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2704   } else if (algorithm_id == 2) {
2705     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2706   }
2707
2708   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2709     return FALSE;
2710
2711   if (!gst_byte_reader_get_data (br, 16, &kid))
2712     return FALSE;
2713
2714   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2715       is_encrypted, iv_size, kid);
2716   gst_structure_set (info->default_properties, "piff_algorithm_id",
2717       G_TYPE_UINT, algorithm_id, NULL);
2718   return TRUE;
2719 }
2720
2721
2722 static void
2723 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2724     guint offset)
2725 {
2726   GstByteReader br;
2727   guint8 version;
2728   guint32 flags = 0;
2729   guint i;
2730   guint iv_size = 8;
2731   QtDemuxStream *stream;
2732   GstStructure *structure;
2733   QtDemuxCencSampleSetInfo *ss_info = NULL;
2734   const gchar *system_id;
2735   gboolean uses_sub_sample_encryption = FALSE;
2736   guint32 sample_count;
2737
2738   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2739     return;
2740
2741   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2742
2743   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2744   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2745     GST_WARNING_OBJECT (qtdemux,
2746         "Attempting PIFF box parsing on an unencrypted stream.");
2747     return;
2748   }
2749
2750   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2751       G_TYPE_STRING, &system_id, NULL);
2752   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2753
2754   stream->protected = TRUE;
2755   stream->protection_scheme_type = FOURCC_cenc;
2756
2757   if (!stream->protection_scheme_info)
2758     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2759
2760   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2761   if (!ss_info->default_properties) {
2762     ss_info->default_properties =
2763         gst_structure_new ("application/x-cenc",
2764         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2765         NULL);
2766
2767   }
2768
2769   if (ss_info->crypto_info) {
2770     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2771     g_ptr_array_free (ss_info->crypto_info, TRUE);
2772     ss_info->crypto_info = NULL;
2773   }
2774
2775   /* skip UUID */
2776   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2777
2778   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2779     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2780     return;
2781   }
2782
2783   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2784     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2785     return;
2786   }
2787
2788   if ((flags & 0x000001)) {
2789     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2790             &br))
2791       return;
2792   } else if ((flags & 0x000002)) {
2793     uses_sub_sample_encryption = TRUE;
2794   }
2795
2796   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2797           &iv_size)) {
2798     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2799     return;
2800   }
2801
2802   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2803     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2804     return;
2805   }
2806
2807   ss_info->crypto_info =
2808       g_ptr_array_new_full (sample_count,
2809       (GDestroyNotify) qtdemux_gst_structure_free);
2810
2811   for (i = 0; i < sample_count; ++i) {
2812     GstStructure *properties;
2813     guint8 *data;
2814     GstBuffer *buf;
2815
2816     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2817     if (properties == NULL) {
2818       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2819       qtdemux->cenc_aux_sample_count = i;
2820       return;
2821     }
2822
2823     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2824       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2825       gst_structure_free (properties);
2826       qtdemux->cenc_aux_sample_count = i;
2827       return;
2828     }
2829     buf = gst_buffer_new_wrapped (data, iv_size);
2830     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2831     gst_buffer_unref (buf);
2832
2833     if (uses_sub_sample_encryption) {
2834       guint16 n_subsamples;
2835       const GValue *kid_buf_value;
2836
2837       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2838           || n_subsamples == 0) {
2839         GST_ERROR_OBJECT (qtdemux,
2840             "failed to get subsample count for sample %u", i);
2841         gst_structure_free (properties);
2842         qtdemux->cenc_aux_sample_count = i;
2843         return;
2844       }
2845       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2846       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2847         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2848             i);
2849         gst_structure_free (properties);
2850         qtdemux->cenc_aux_sample_count = i;
2851         return;
2852       }
2853       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2854
2855       kid_buf_value =
2856           gst_structure_get_value (ss_info->default_properties, "kid");
2857
2858       gst_structure_set (properties,
2859           "subsample_count", G_TYPE_UINT, n_subsamples,
2860           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2861       gst_structure_set_value (properties, "kid", kid_buf_value);
2862       gst_buffer_unref (buf);
2863     } else {
2864       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2865     }
2866
2867     g_ptr_array_add (ss_info->crypto_info, properties);
2868   }
2869
2870   qtdemux->cenc_aux_sample_count = sample_count;
2871 }
2872
2873 static void
2874 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2875 {
2876   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2877     0x97, 0xA9, 0x42, 0xE8,
2878     0x9C, 0x71, 0x99, 0x94,
2879     0x91, 0xE3, 0xAF, 0xAC
2880   };
2881   static const guint8 playready_uuid[] = {
2882     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2883     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2884   };
2885
2886   static const guint8 piff_sample_encryption_uuid[] = {
2887     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2888     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2889   };
2890
2891   guint offset;
2892
2893   /* counts as header data */
2894   qtdemux->header_size += length;
2895
2896   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2897
2898   if (length <= offset + 16) {
2899     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2900     return;
2901   }
2902
2903   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2904     GstBuffer *buf;
2905     GstTagList *taglist;
2906
2907     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2908         length - offset - 16, NULL);
2909     taglist = gst_tag_list_from_xmp_buffer (buf);
2910     gst_buffer_unref (buf);
2911
2912     /* make sure we have a usable taglist */
2913     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2914
2915     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2916
2917   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2918     int len;
2919     const gunichar2 *s_utf16;
2920     char *contents;
2921
2922     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2923     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2924     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2925     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2926
2927     g_free (contents);
2928
2929     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2930         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2931         (NULL));
2932   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2933     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2934   } else {
2935     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2936         GST_READ_UINT32_LE (buffer + offset),
2937         GST_READ_UINT32_LE (buffer + offset + 4),
2938         GST_READ_UINT32_LE (buffer + offset + 8),
2939         GST_READ_UINT32_LE (buffer + offset + 12));
2940   }
2941 }
2942
2943 static void
2944 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2945 {
2946   GstSidxParser sidx_parser;
2947   GstIsoffParserResult res;
2948   guint consumed;
2949
2950   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2951
2952   res =
2953       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2954       &consumed);
2955   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2956   if (res == GST_ISOFF_QT_PARSER_DONE) {
2957     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2958   }
2959   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2960 }
2961
2962 /* caller verifies at least 8 bytes in buf */
2963 static void
2964 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2965     guint64 * plength, guint32 * pfourcc)
2966 {
2967   guint64 length;
2968   guint32 fourcc;
2969
2970   length = QT_UINT32 (data);
2971   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2972   fourcc = QT_FOURCC (data + 4);
2973   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2974
2975   if (length == 0) {
2976     length = G_MAXUINT64;
2977   } else if (length == 1 && size >= 16) {
2978     /* this means we have an extended size, which is the 64 bit value of
2979      * the next 8 bytes */
2980     length = QT_UINT64 (data + 8);
2981     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2982   }
2983
2984   if (plength)
2985     *plength = length;
2986   if (pfourcc)
2987     *pfourcc = fourcc;
2988 }
2989
2990 static gboolean
2991 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2992 {
2993   guint32 version = 0;
2994   GstClockTime duration = 0;
2995
2996   if (!gst_byte_reader_get_uint32_be (br, &version))
2997     goto failed;
2998
2999   version >>= 24;
3000   if (version == 1) {
3001     if (!gst_byte_reader_get_uint64_be (br, &duration))
3002       goto failed;
3003   } else {
3004     guint32 dur = 0;
3005
3006     if (!gst_byte_reader_get_uint32_be (br, &dur))
3007       goto failed;
3008     duration = dur;
3009   }
3010
3011   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3012   qtdemux->duration = duration;
3013
3014   return TRUE;
3015
3016 failed:
3017   {
3018     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3019     return FALSE;
3020   }
3021 }
3022
3023 static gboolean
3024 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3025     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3026 {
3027   if (!stream->parsed_trex && qtdemux->moov_node) {
3028     GNode *mvex, *trex;
3029     GstByteReader trex_data;
3030
3031     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3032     if (mvex) {
3033       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3034           &trex_data);
3035       while (trex) {
3036         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3037
3038         /* skip version/flags */
3039         if (!gst_byte_reader_skip (&trex_data, 4))
3040           goto next;
3041         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3042           goto next;
3043         if (id != stream->track_id)
3044           goto next;
3045         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3046           goto next;
3047         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3048           goto next;
3049         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3050           goto next;
3051         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3052           goto next;
3053
3054         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3055             "duration %d,  size %d, flags 0x%x", stream->track_id,
3056             dur, size, flags);
3057
3058         stream->parsed_trex = TRUE;
3059         stream->def_sample_description_index = sdi;
3060         stream->def_sample_duration = dur;
3061         stream->def_sample_size = size;
3062         stream->def_sample_flags = flags;
3063
3064       next:
3065         /* iterate all siblings */
3066         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3067             &trex_data);
3068       }
3069     }
3070   }
3071
3072   *ds_duration = stream->def_sample_duration;
3073   *ds_size = stream->def_sample_size;
3074   *ds_flags = stream->def_sample_flags;
3075
3076   /* even then, above values are better than random ... */
3077   if (G_UNLIKELY (!stream->parsed_trex)) {
3078     GST_WARNING_OBJECT (qtdemux,
3079         "failed to find fragment defaults for stream %d", stream->track_id);
3080     return FALSE;
3081   }
3082
3083   return TRUE;
3084 }
3085
3086 /* This method should be called whenever a more accurate duration might
3087  * have been found. It will update all relevant variables if/where needed
3088  */
3089 static void
3090 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3091 {
3092   guint i;
3093   guint64 movdur;
3094   GstClockTime prevdur;
3095
3096   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3097
3098   if (movdur > qtdemux->duration) {
3099     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3100     GST_DEBUG_OBJECT (qtdemux,
3101         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3102         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3103     qtdemux->duration = movdur;
3104     GST_DEBUG_OBJECT (qtdemux,
3105         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3106         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3107         GST_TIME_ARGS (qtdemux->segment.stop));
3108     if (qtdemux->segment.duration == prevdur) {
3109       /* If the current segment has duration/stop identical to previous duration
3110        * update them also (because they were set at that point in time with
3111        * the wrong duration */
3112       /* We convert the value *from* the timescale version to avoid rounding errors */
3113       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3114       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3115       qtdemux->segment.duration = fixeddur;
3116       qtdemux->segment.stop = fixeddur;
3117     }
3118   }
3119
3120   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3121     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3122
3123     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3124     if (movdur > stream->duration) {
3125       GST_DEBUG_OBJECT (qtdemux,
3126           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3127           GST_TIME_ARGS (duration));
3128       stream->duration = movdur;
3129       /* internal duration tracking state has been updated above, so */
3130       /* preserve an open-ended dummy segment rather than repeatedly updating
3131        * it and spamming downstream accordingly with segment events */
3132       /* also mangle the edit list end time when fragmented with a single edit
3133        * list that may only cover any non-fragmented data */
3134       if ((stream->dummy_segment ||
3135               (qtdemux->fragmented && stream->n_segments == 1)) &&
3136           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3137         /* Update all dummy values to new duration */
3138         stream->segments[0].stop_time = duration;
3139         stream->segments[0].duration = duration;
3140         stream->segments[0].media_stop = duration;
3141
3142         /* let downstream know we possibly have a new stop time */
3143         if (stream->segment_index != -1) {
3144           GstClockTime pos;
3145
3146           if (qtdemux->segment.rate >= 0) {
3147             pos = stream->segment.start;
3148           } else {
3149             pos = stream->segment.stop;
3150           }
3151
3152           gst_qtdemux_stream_update_segment (qtdemux, stream,
3153               stream->segment_index, pos, NULL, NULL);
3154         }
3155       }
3156     }
3157   }
3158 }
3159
3160 static gboolean
3161 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3162     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3163     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3164     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3165     gboolean has_tfdt)
3166 {
3167   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3168   guint64 timestamp;
3169   gint32 data_offset = 0;
3170   guint32 flags = 0, first_flags = 0, samples_count = 0;
3171   gint i;
3172   guint8 *data;
3173   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3174   QtDemuxSample *sample;
3175   gboolean ismv = FALSE;
3176   gint64 initial_offset;
3177
3178   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3179       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3180       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3181       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3182
3183   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3184     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3185     return TRUE;
3186   }
3187
3188   /* presence of stss or not can't really tell us much,
3189    * and flags and so on tend to be marginally reliable in these files */
3190   if (stream->subtype == FOURCC_soun) {
3191     GST_DEBUG_OBJECT (qtdemux,
3192         "sound track in fragmented file; marking all keyframes");
3193     stream->all_keyframe = TRUE;
3194   }
3195
3196   if (!gst_byte_reader_skip (trun, 1) ||
3197       !gst_byte_reader_get_uint24_be (trun, &flags))
3198     goto fail;
3199
3200   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3201     goto fail;
3202
3203   if (flags & TR_DATA_OFFSET) {
3204     /* note this is really signed */
3205     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3206       goto fail;
3207     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3208     /* default base offset = first byte of moof */
3209     if (*base_offset == -1) {
3210       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3211       *base_offset = moof_offset;
3212     }
3213     *running_offset = *base_offset + data_offset;
3214   } else {
3215     /* if no offset at all, that would mean data starts at moof start,
3216      * which is a bit wrong and is ismv crappy way, so compensate
3217      * assuming data is in mdat following moof */
3218     if (*base_offset == -1) {
3219       *base_offset = moof_offset + moof_length + 8;
3220       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3221       ismv = TRUE;
3222     }
3223     if (*running_offset == -1)
3224       *running_offset = *base_offset;
3225   }
3226
3227   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3228       *running_offset);
3229   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3230       data_offset, flags, samples_count);
3231
3232   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3233     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3234       GST_DEBUG_OBJECT (qtdemux,
3235           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3236       flags ^= TR_FIRST_SAMPLE_FLAGS;
3237     } else {
3238       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3239         goto fail;
3240       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3241     }
3242   }
3243
3244   /* FIXME ? spec says other bits should also be checked to determine
3245    * entry size (and prefix size for that matter) */
3246   entry_size = 0;
3247   dur_offset = size_offset = 0;
3248   if (flags & TR_SAMPLE_DURATION) {
3249     GST_LOG_OBJECT (qtdemux, "entry duration present");
3250     dur_offset = entry_size;
3251     entry_size += 4;
3252   }
3253   if (flags & TR_SAMPLE_SIZE) {
3254     GST_LOG_OBJECT (qtdemux, "entry size present");
3255     size_offset = entry_size;
3256     entry_size += 4;
3257   }
3258   if (flags & TR_SAMPLE_FLAGS) {
3259     GST_LOG_OBJECT (qtdemux, "entry flags present");
3260     flags_offset = entry_size;
3261     entry_size += 4;
3262   }
3263   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3264     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3265     ct_offset = entry_size;
3266     entry_size += 4;
3267   }
3268
3269   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3270     goto fail;
3271   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3272
3273   if (stream->n_samples + samples_count >=
3274       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3275     goto index_too_big;
3276
3277   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3278       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3279       (stream->n_samples + samples_count) *
3280       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3281
3282   /* create a new array of samples if it's the first sample parsed */
3283   if (stream->n_samples == 0) {
3284     g_assert (stream->samples == NULL);
3285     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3286     /* or try to reallocate it with space enough to insert the new samples */
3287   } else
3288     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3289         stream->n_samples + samples_count);
3290   if (stream->samples == NULL)
3291     goto out_of_memory;
3292
3293   if (qtdemux->fragment_start != -1) {
3294     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3295     qtdemux->fragment_start = -1;
3296   } else {
3297     if (stream->n_samples == 0) {
3298       if (decode_ts > 0) {
3299         timestamp = decode_ts;
3300       } else if (stream->pending_seek != NULL) {
3301         /* if we don't have a timestamp from a tfdt box, we'll use the one
3302          * from the mfra seek table */
3303         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3304             GST_TIME_ARGS (stream->pending_seek->ts));
3305
3306         /* FIXME: this is not fully correct, the timestamp refers to the random
3307          * access sample refered to in the tfra entry, which may not necessarily
3308          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3309         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3310       } else {
3311         timestamp = 0;
3312       }
3313
3314       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3315       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3316           GST_TIME_ARGS (gst_ts));
3317     } else {
3318       /* subsequent fragments extend stream */
3319       timestamp =
3320           stream->samples[stream->n_samples - 1].timestamp +
3321           stream->samples[stream->n_samples - 1].duration;
3322
3323       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3324        * difference (1 sec.) between decode_ts and timestamp, prefer the
3325        * former */
3326       if (has_tfdt && !qtdemux->upstream_format_is_time
3327           && ABSDIFF (decode_ts, timestamp) >
3328           MAX (stream->duration_last_moof / 2,
3329               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3330         GST_INFO_OBJECT (qtdemux,
3331             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3332             ") are significantly different (more than %" GST_TIME_FORMAT
3333             "), using decode_ts",
3334             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3335             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3336             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3337                     MAX (stream->duration_last_moof / 2,
3338                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3339         timestamp = decode_ts;
3340       }
3341
3342       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3343       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3344           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3345     }
3346   }
3347
3348   initial_offset = *running_offset;
3349
3350   sample = stream->samples + stream->n_samples;
3351   for (i = 0; i < samples_count; i++) {
3352     guint32 dur, size, sflags, ct;
3353
3354     /* first read sample data */
3355     if (flags & TR_SAMPLE_DURATION) {
3356       dur = QT_UINT32 (data + dur_offset);
3357     } else {
3358       dur = d_sample_duration;
3359     }
3360     if (flags & TR_SAMPLE_SIZE) {
3361       size = QT_UINT32 (data + size_offset);
3362     } else {
3363       size = d_sample_size;
3364     }
3365     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3366       if (i == 0) {
3367         sflags = first_flags;
3368       } else {
3369         sflags = d_sample_flags;
3370       }
3371     } else if (flags & TR_SAMPLE_FLAGS) {
3372       sflags = QT_UINT32 (data + flags_offset);
3373     } else {
3374       sflags = d_sample_flags;
3375     }
3376     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3377       ct = QT_UINT32 (data + ct_offset);
3378     } else {
3379       ct = 0;
3380     }
3381     data += entry_size;
3382
3383     /* fill the sample information */
3384     sample->offset = *running_offset;
3385     sample->pts_offset = ct;
3386     sample->size = size;
3387     sample->timestamp = timestamp;
3388     sample->duration = dur;
3389     /* sample-is-difference-sample */
3390     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3391      * now idea how it relates to bitfield other than massive LE/BE confusion */
3392     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3393     *running_offset += size;
3394     timestamp += dur;
3395     stream->duration_moof += dur;
3396     sample++;
3397   }
3398
3399   /* Update total duration if needed */
3400   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3401
3402   /* Pre-emptively figure out size of mdat based on trun information.
3403    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3404    * size, else we will still be able to use this when dealing with gap'ed
3405    * input */
3406   qtdemux->mdatleft = *running_offset - initial_offset;
3407   qtdemux->mdatoffset = initial_offset;
3408   qtdemux->mdatsize = qtdemux->mdatleft;
3409
3410   stream->n_samples += samples_count;
3411   stream->n_samples_moof += samples_count;
3412
3413   if (stream->pending_seek != NULL)
3414     stream->pending_seek = NULL;
3415
3416   return TRUE;
3417
3418 fail:
3419   {
3420     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3421     return FALSE;
3422   }
3423 out_of_memory:
3424   {
3425     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3426         stream->n_samples);
3427     return FALSE;
3428   }
3429 index_too_big:
3430   {
3431     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3432         "be larger than %uMB (broken file?)", stream->n_samples,
3433         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3434     return FALSE;
3435   }
3436 }
3437
3438 /* find stream with @id */
3439 static inline QtDemuxStream *
3440 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3441 {
3442   QtDemuxStream *stream;
3443   gint i;
3444
3445   /* check */
3446   if (G_UNLIKELY (!id)) {
3447     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3448     return NULL;
3449   }
3450
3451   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3452     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3453     if (stream->track_id == id)
3454       return stream;
3455   }
3456   if (qtdemux->mss_mode) {
3457     /* mss should have only 1 stream anyway */
3458     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3459   }
3460
3461   return NULL;
3462 }
3463
3464 static gboolean
3465 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3466     guint32 * fragment_number)
3467 {
3468   if (!gst_byte_reader_skip (mfhd, 4))
3469     goto fail;
3470   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3471     goto fail;
3472   return TRUE;
3473 fail:
3474   {
3475     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3476     return FALSE;
3477   }
3478 }
3479
3480 static gboolean
3481 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3482     QtDemuxStream ** stream, guint32 * default_sample_duration,
3483     guint32 * default_sample_size, guint32 * default_sample_flags,
3484     gint64 * base_offset)
3485 {
3486   guint32 flags = 0;
3487   guint32 track_id = 0;
3488
3489   if (!gst_byte_reader_skip (tfhd, 1) ||
3490       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3491     goto invalid_track;
3492
3493   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3494     goto invalid_track;
3495
3496   *stream = qtdemux_find_stream (qtdemux, track_id);
3497   if (G_UNLIKELY (!*stream))
3498     goto unknown_stream;
3499
3500   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3501     *base_offset = qtdemux->moof_offset;
3502
3503   if (flags & TF_BASE_DATA_OFFSET)
3504     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3505       goto invalid_track;
3506
3507   /* obtain stream defaults */
3508   qtdemux_parse_trex (qtdemux, *stream,
3509       default_sample_duration, default_sample_size, default_sample_flags);
3510
3511   (*stream)->stsd_sample_description_id =
3512       (*stream)->def_sample_description_index - 1;
3513
3514   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3515     guint32 sample_description_index;
3516     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3517       goto invalid_track;
3518     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3519   }
3520
3521   if (qtdemux->mss_mode) {
3522     /* mss has no stsd entry */
3523     (*stream)->stsd_sample_description_id = 0;
3524   }
3525
3526   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3527     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3528       goto invalid_track;
3529
3530   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3531     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3532       goto invalid_track;
3533
3534   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3535     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3536       goto invalid_track;
3537
3538   return TRUE;
3539
3540 invalid_track:
3541   {
3542     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3543     return FALSE;
3544   }
3545 unknown_stream:
3546   {
3547     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3548     return TRUE;
3549   }
3550 }
3551
3552 static gboolean
3553 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3554     guint64 * decode_time)
3555 {
3556   guint32 version = 0;
3557
3558   if (!gst_byte_reader_get_uint32_be (br, &version))
3559     return FALSE;
3560
3561   version >>= 24;
3562   if (version == 1) {
3563     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3564       goto failed;
3565   } else {
3566     guint32 dec_time = 0;
3567     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3568       goto failed;
3569     *decode_time = dec_time;
3570   }
3571
3572   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3573       *decode_time);
3574
3575   return TRUE;
3576
3577 failed:
3578   {
3579     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3580     return FALSE;
3581   }
3582 }
3583
3584 /* Returns a pointer to a GstStructure containing the properties of
3585  * the stream sample identified by @sample_index. The caller must unref
3586  * the returned object after use. Returns NULL if unsuccessful. */
3587 static GstStructure *
3588 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3589     QtDemuxStream * stream, guint sample_index)
3590 {
3591   QtDemuxCencSampleSetInfo *info = NULL;
3592
3593   g_return_val_if_fail (stream != NULL, NULL);
3594   g_return_val_if_fail (stream->protected, NULL);
3595   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3596
3597   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3598
3599   /* Currently, cenc properties for groups of samples are not supported, so
3600    * simply return a copy of the default sample properties */
3601   return gst_structure_copy (info->default_properties);
3602 }
3603
3604 /* Parses the sizes of sample auxiliary information contained within a stream,
3605  * as given in a saiz box. Returns array of sample_count guint8 size values,
3606  * or NULL on failure */
3607 static guint8 *
3608 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3609     GstByteReader * br, guint32 * sample_count)
3610 {
3611   guint32 flags = 0;
3612   guint8 *info_sizes;
3613   guint8 default_info_size;
3614
3615   g_return_val_if_fail (qtdemux != NULL, NULL);
3616   g_return_val_if_fail (stream != NULL, NULL);
3617   g_return_val_if_fail (br != NULL, NULL);
3618   g_return_val_if_fail (sample_count != NULL, NULL);
3619
3620   if (!gst_byte_reader_get_uint32_be (br, &flags))
3621     return NULL;
3622
3623   if (flags & 0x1) {
3624     /* aux_info_type and aux_info_type_parameter are ignored */
3625     if (!gst_byte_reader_skip (br, 8))
3626       return NULL;
3627   }
3628
3629   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3630     return NULL;
3631   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3632
3633   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3634     return NULL;
3635   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3636
3637
3638   if (default_info_size == 0) {
3639     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3640       return NULL;
3641     }
3642   } else {
3643     info_sizes = g_new (guint8, *sample_count);
3644     memset (info_sizes, default_info_size, *sample_count);
3645   }
3646
3647   return info_sizes;
3648 }
3649
3650 /* Parses the offset of sample auxiliary information contained within a stream,
3651  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3652 static gboolean
3653 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3654     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3655     guint64 * offset)
3656 {
3657   guint8 version = 0;
3658   guint32 flags = 0;
3659   guint32 aux_info_type = 0;
3660   guint32 aux_info_type_parameter = 0;
3661   guint32 entry_count;
3662   guint32 off_32;
3663   guint64 off_64;
3664   const guint8 *aux_info_type_data = NULL;
3665
3666   g_return_val_if_fail (qtdemux != NULL, FALSE);
3667   g_return_val_if_fail (stream != NULL, FALSE);
3668   g_return_val_if_fail (br != NULL, FALSE);
3669   g_return_val_if_fail (offset != NULL, FALSE);
3670
3671   if (!gst_byte_reader_get_uint8 (br, &version))
3672     return FALSE;
3673
3674   if (!gst_byte_reader_get_uint24_be (br, &flags))
3675     return FALSE;
3676
3677   if (flags & 0x1) {
3678
3679     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3680       return FALSE;
3681     aux_info_type = QT_FOURCC (aux_info_type_data);
3682
3683     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3684       return FALSE;
3685   } else if (stream->protected) {
3686     aux_info_type = stream->protection_scheme_type;
3687   } else {
3688     aux_info_type = CUR_STREAM (stream)->fourcc;
3689   }
3690
3691   if (info_type)
3692     *info_type = aux_info_type;
3693   if (info_type_parameter)
3694     *info_type_parameter = aux_info_type_parameter;
3695
3696   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3697       "aux_info_type_parameter:  %#06x",
3698       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3699
3700   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3701     return FALSE;
3702
3703   if (entry_count != 1) {
3704     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3705     return FALSE;
3706   }
3707
3708   if (version == 0) {
3709     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3710       return FALSE;
3711     *offset = (guint64) off_32;
3712   } else {
3713     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3714       return FALSE;
3715     *offset = off_64;
3716   }
3717
3718   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3719   return TRUE;
3720 }
3721
3722 static void
3723 qtdemux_gst_structure_free (GstStructure * gststructure)
3724 {
3725   if (gststructure) {
3726     gst_structure_free (gststructure);
3727   }
3728 }
3729
3730 /* Parses auxiliary information relating to samples protected using Common
3731  * Encryption (cenc); the format of this information is defined in
3732  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3733 static gboolean
3734 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3735     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3736 {
3737   QtDemuxCencSampleSetInfo *ss_info = NULL;
3738   guint8 size;
3739   gint i;
3740   GPtrArray *old_crypto_info = NULL;
3741   guint old_entries = 0;
3742
3743   g_return_val_if_fail (qtdemux != NULL, FALSE);
3744   g_return_val_if_fail (stream != NULL, FALSE);
3745   g_return_val_if_fail (br != NULL, FALSE);
3746   g_return_val_if_fail (stream->protected, FALSE);
3747   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3748
3749   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3750
3751   if (ss_info->crypto_info) {
3752     old_crypto_info = ss_info->crypto_info;
3753     /* Count number of non-null entries remaining at the tail end */
3754     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3755       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3756         break;
3757       old_entries++;
3758     }
3759   }
3760
3761   ss_info->crypto_info =
3762       g_ptr_array_new_full (sample_count + old_entries,
3763       (GDestroyNotify) qtdemux_gst_structure_free);
3764
3765   /* We preserve old entries because we parse the next moof in advance
3766    * of consuming all samples from the previous moof, and otherwise
3767    * we'd discard the corresponding crypto info for the samples
3768    * from the previous fragment. */
3769   if (old_entries) {
3770     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3771         old_entries);
3772     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3773       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3774               i));
3775       g_ptr_array_index (old_crypto_info, i) = NULL;
3776     }
3777   }
3778
3779   if (old_crypto_info) {
3780     /* Everything now belongs to the new array */
3781     g_ptr_array_free (old_crypto_info, TRUE);
3782   }
3783
3784   for (i = 0; i < sample_count; ++i) {
3785     GstStructure *properties;
3786     guint16 n_subsamples = 0;
3787     guint8 *data;
3788     guint iv_size;
3789     GstBuffer *buf;
3790
3791     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3792     if (properties == NULL) {
3793       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3794       return FALSE;
3795     }
3796     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3797       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3798       gst_structure_free (properties);
3799       return FALSE;
3800     }
3801     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3802       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3803       gst_structure_free (properties);
3804       return FALSE;
3805     }
3806     buf = gst_buffer_new_wrapped (data, iv_size);
3807     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3808     gst_buffer_unref (buf);
3809     size = info_sizes[i];
3810     if (size > iv_size) {
3811       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3812           || !(n_subsamples > 0)) {
3813         gst_structure_free (properties);
3814         GST_ERROR_OBJECT (qtdemux,
3815             "failed to get subsample count for sample %u", i);
3816         return FALSE;
3817       }
3818       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3819       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3820         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3821             i);
3822         gst_structure_free (properties);
3823         return FALSE;
3824       }
3825       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3826       if (!buf) {
3827         gst_structure_free (properties);
3828         return FALSE;
3829       }
3830       gst_structure_set (properties,
3831           "subsample_count", G_TYPE_UINT, n_subsamples,
3832           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3833       gst_buffer_unref (buf);
3834     } else {
3835       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3836     }
3837     g_ptr_array_add (ss_info->crypto_info, properties);
3838   }
3839   return TRUE;
3840 }
3841
3842 /* Converts a UUID in raw byte form to a string representation, as defined in
3843  * RFC 4122. The caller takes ownership of the returned string and is
3844  * responsible for freeing it after use. */
3845 static gchar *
3846 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3847 {
3848   const guint8 *uuid = (const guint8 *) uuid_bytes;
3849
3850   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3851       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3852       uuid[0], uuid[1], uuid[2], uuid[3],
3853       uuid[4], uuid[5], uuid[6], uuid[7],
3854       uuid[8], uuid[9], uuid[10], uuid[11],
3855       uuid[12], uuid[13], uuid[14], uuid[15]);
3856 }
3857
3858 /* Parses a Protection System Specific Header box (pssh), as defined in the
3859  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3860  * information needed by a specific content protection system in order to
3861  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3862  * otherwise. */
3863 static gboolean
3864 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3865 {
3866   gchar *sysid_string;
3867   guint32 pssh_size = QT_UINT32 (node->data);
3868   GstBuffer *pssh = NULL;
3869   GstEvent *event = NULL;
3870   guint32 parent_box_type;
3871   gint i;
3872
3873   if (G_UNLIKELY (pssh_size < 32U)) {
3874     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3875     return FALSE;
3876   }
3877
3878   sysid_string =
3879       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3880
3881   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3882
3883   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3884   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3885       gst_buffer_get_size (pssh));
3886
3887   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3888
3889   /* Push an event containing the pssh box onto the queues of all streams. */
3890   event = gst_event_new_protection (sysid_string, pssh,
3891       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3892   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3893     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3894     GST_TRACE_OBJECT (qtdemux,
3895         "adding protection event for stream %s and system %s",
3896         stream->stream_id, sysid_string);
3897     g_queue_push_tail (&stream->protection_scheme_event_queue,
3898         gst_event_ref (event));
3899   }
3900   g_free (sysid_string);
3901   gst_event_unref (event);
3902   gst_buffer_unref (pssh);
3903   return TRUE;
3904 }
3905
3906 static gboolean
3907 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3908     guint64 moof_offset, QtDemuxStream * stream)
3909 {
3910   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3911   GNode *uuid_node;
3912   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3913   GNode *saiz_node, *saio_node, *pssh_node;
3914   GstByteReader saiz_data, saio_data;
3915   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3916   gint64 base_offset, running_offset;
3917   guint32 frag_num;
3918   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3919
3920   /* NOTE @stream ignored */
3921
3922   moof_node = g_node_new ((guint8 *) buffer);
3923   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3924   qtdemux_node_dump (qtdemux, moof_node);
3925
3926   /* Get fragment number from mfhd and check it's valid */
3927   mfhd_node =
3928       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3929   if (mfhd_node == NULL)
3930     goto missing_mfhd;
3931   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3932     goto fail;
3933   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3934
3935   /* unknown base_offset to start with */
3936   base_offset = running_offset = -1;
3937   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3938   while (traf_node) {
3939     guint64 decode_time = 0;
3940
3941     /* Fragment Header node */
3942     tfhd_node =
3943         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3944         &tfhd_data);
3945     if (!tfhd_node)
3946       goto missing_tfhd;
3947     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3948             &ds_size, &ds_flags, &base_offset))
3949       goto missing_tfhd;
3950
3951     /* The following code assumes at most a single set of sample auxiliary
3952      * data in the fragment (consisting of a saiz box and a corresponding saio
3953      * box); in theory, however, there could be multiple sets of sample
3954      * auxiliary data in a fragment. */
3955     saiz_node =
3956         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3957         &saiz_data);
3958     if (saiz_node) {
3959       guint32 info_type = 0;
3960       guint64 offset = 0;
3961       guint32 info_type_parameter = 0;
3962
3963       g_free (qtdemux->cenc_aux_info_sizes);
3964
3965       qtdemux->cenc_aux_info_sizes =
3966           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3967           &qtdemux->cenc_aux_sample_count);
3968       if (qtdemux->cenc_aux_info_sizes == NULL) {
3969         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3970         goto fail;
3971       }
3972       saio_node =
3973           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3974           &saio_data);
3975       if (!saio_node) {
3976         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3977         g_free (qtdemux->cenc_aux_info_sizes);
3978         qtdemux->cenc_aux_info_sizes = NULL;
3979         goto fail;
3980       }
3981
3982       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3983                   &info_type, &info_type_parameter, &offset))) {
3984         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3985         g_free (qtdemux->cenc_aux_info_sizes);
3986         qtdemux->cenc_aux_info_sizes = NULL;
3987         goto fail;
3988       }
3989       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3990         offset += (guint64) (base_offset - qtdemux->moof_offset);
3991       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3992         GstByteReader br;
3993         if (offset > length) {
3994           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3995           qtdemux->cenc_aux_info_offset = offset;
3996         } else {
3997           gst_byte_reader_init (&br, buffer + offset, length - offset);
3998           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3999                   qtdemux->cenc_aux_info_sizes,
4000                   qtdemux->cenc_aux_sample_count)) {
4001             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4002             g_free (qtdemux->cenc_aux_info_sizes);
4003             qtdemux->cenc_aux_info_sizes = NULL;
4004             goto fail;
4005           }
4006         }
4007       }
4008     }
4009
4010     tfdt_node =
4011         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4012         &tfdt_data);
4013     if (tfdt_node) {
4014       /* We'll use decode_time to interpolate timestamps
4015        * in case the input timestamps are missing */
4016       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4017
4018       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4019           " (%" GST_TIME_FORMAT ")", decode_time,
4020           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4021                   decode_time) : GST_CLOCK_TIME_NONE));
4022
4023       /* Discard the fragment buffer timestamp info to avoid using it.
4024        * Rely on tfdt instead as it is more accurate than the timestamp
4025        * that is fetched from a manifest/playlist and is usually
4026        * less accurate. */
4027       qtdemux->fragment_start = -1;
4028     }
4029
4030     if (G_UNLIKELY (!stream)) {
4031       /* we lost track of offset, we'll need to regain it,
4032        * but can delay complaining until later or avoid doing so altogether */
4033       base_offset = -2;
4034       goto next;
4035     }
4036     if (G_UNLIKELY (base_offset < -1))
4037       goto lost_offset;
4038
4039     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4040
4041     if (!qtdemux->pullbased) {
4042       /* Sample tables can grow enough to be problematic if the system memory
4043        * is very low (e.g. embedded devices) and the videos very long
4044        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4045        * Fortunately, we can easily discard them for each new fragment when
4046        * we know qtdemux will not receive seeks outside of the current fragment.
4047        * adaptivedemux honors this assumption.
4048        * This optimization is also useful for applications that use qtdemux as
4049        * a push-based simple demuxer, like Media Source Extensions. */
4050       gst_qtdemux_stream_flush_samples_data (stream);
4051     }
4052
4053     /* initialise moof sample data */
4054     stream->n_samples_moof = 0;
4055     stream->duration_last_moof = stream->duration_moof;
4056     stream->duration_moof = 0;
4057
4058     /* Track Run node */
4059     trun_node =
4060         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4061         &trun_data);
4062     while (trun_node) {
4063       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4064           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4065           &running_offset, decode_time, (tfdt_node != NULL));
4066       /* iterate all siblings */
4067       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4068           &trun_data);
4069     }
4070
4071     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4072     if (uuid_node) {
4073       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4074       guint32 box_length = QT_UINT32 (uuid_buffer);
4075
4076       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4077     }
4078
4079     /* if no new base_offset provided for next traf,
4080      * base is end of current traf */
4081     base_offset = running_offset;
4082     running_offset = -1;
4083
4084     if (stream->n_samples_moof && stream->duration_moof)
4085       stream->new_caps = TRUE;
4086
4087   next:
4088     /* iterate all siblings */
4089     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4090   }
4091
4092   /* parse any protection system info */
4093   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4094   while (pssh_node) {
4095     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4096     qtdemux_parse_pssh (qtdemux, pssh_node);
4097     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4098   }
4099
4100   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4101       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4102       && min_dts != 0) {
4103     /* Unless the user has explicitly requested another seek, perform an
4104      * internal seek to the time specified in the tfdt.
4105      *
4106      * This way if the user opens a file where the first tfdt is 1 hour
4107      * into the presentation, they will not have to wait 1 hour for run
4108      * time to catch up and actual playback to start. */
4109     gint i;
4110
4111     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4112         "performing an internal seek to %" GST_TIME_FORMAT,
4113         GST_TIME_ARGS (min_dts));
4114
4115     qtdemux->segment.start = min_dts;
4116     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4117
4118     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4119       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4120       stream->time_position = min_dts;
4121     }
4122
4123     /* Before this code was run a segment was already sent when the moov was
4124      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4125      * be emitted after a moov, and we can emit a second segment anyway for
4126      * special cases like this. */
4127     qtdemux->need_segment = TRUE;
4128   }
4129
4130   qtdemux->first_moof_already_parsed = TRUE;
4131
4132   g_node_destroy (moof_node);
4133   return TRUE;
4134
4135 missing_tfhd:
4136   {
4137     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4138     goto fail;
4139   }
4140 missing_mfhd:
4141   {
4142     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4143     goto fail;
4144   }
4145 lost_offset:
4146   {
4147     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4148     goto fail;
4149   }
4150 fail:
4151   {
4152     g_node_destroy (moof_node);
4153     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4154         (_("This file is corrupt and cannot be played.")), (NULL));
4155     return FALSE;
4156   }
4157 }
4158
4159 #if 0
4160 /* might be used if some day we actually use mfra & co
4161  * for random access to fragments,
4162  * but that will require quite some modifications and much less relying
4163  * on a sample array */
4164 #endif
4165
4166 static gboolean
4167 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4168 {
4169   QtDemuxStream *stream;
4170   guint32 ver_flags, track_id, len, num_entries, i;
4171   guint value_size, traf_size, trun_size, sample_size;
4172   guint64 time = 0, moof_offset = 0;
4173 #if 0
4174   GstBuffer *buf = NULL;
4175   GstFlowReturn ret;
4176 #endif
4177   GstByteReader tfra;
4178
4179   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4180
4181   if (!gst_byte_reader_skip (&tfra, 8))
4182     return FALSE;
4183
4184   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4185     return FALSE;
4186
4187   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4188       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4189       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4190     return FALSE;
4191
4192   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4193
4194   stream = qtdemux_find_stream (qtdemux, track_id);
4195   if (stream == NULL)
4196     goto unknown_trackid;
4197
4198   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4199   sample_size = (len & 3) + 1;
4200   trun_size = ((len & 12) >> 2) + 1;
4201   traf_size = ((len & 48) >> 4) + 1;
4202
4203   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4204       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4205
4206   if (num_entries == 0)
4207     goto no_samples;
4208
4209   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4210           value_size + value_size + traf_size + trun_size + sample_size))
4211     goto corrupt_file;
4212
4213   g_free (stream->ra_entries);
4214   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4215   stream->n_ra_entries = num_entries;
4216
4217   for (i = 0; i < num_entries; i++) {
4218     qt_atom_parser_get_offset (&tfra, value_size, &time);
4219     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4220     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4221     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4222     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4223
4224     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4225
4226     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4227         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4228
4229     stream->ra_entries[i].ts = time;
4230     stream->ra_entries[i].moof_offset = moof_offset;
4231
4232     /* don't want to go through the entire file and read all moofs at startup */
4233 #if 0
4234     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4235     if (ret != GST_FLOW_OK)
4236       goto corrupt_file;
4237     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4238         moof_offset, stream);
4239     gst_buffer_unref (buf);
4240 #endif
4241   }
4242
4243   check_update_duration (qtdemux, time);
4244
4245   return TRUE;
4246
4247 /* ERRORS */
4248 unknown_trackid:
4249   {
4250     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4251     return FALSE;
4252   }
4253 corrupt_file:
4254   {
4255     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4256     return FALSE;
4257   }
4258 no_samples:
4259   {
4260     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4261     return FALSE;
4262   }
4263 }
4264
4265 static gboolean
4266 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4267 {
4268   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4269   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4270   GstBuffer *mfro = NULL, *mfra = NULL;
4271   GstFlowReturn flow;
4272   gboolean ret = FALSE;
4273   GNode *mfra_node, *tfra_node;
4274   guint64 mfra_offset = 0;
4275   guint32 fourcc, mfra_size;
4276   gint64 len;
4277
4278   /* query upstream size in bytes */
4279   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4280     goto size_query_failed;
4281
4282   /* mfro box should be at the very end of the file */
4283   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4284   if (flow != GST_FLOW_OK)
4285     goto exit;
4286
4287   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4288
4289   fourcc = QT_FOURCC (mfro_map.data + 4);
4290   if (fourcc != FOURCC_mfro)
4291     goto exit;
4292
4293   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4294   if (mfro_map.size < 16)
4295     goto invalid_mfro_size;
4296
4297   mfra_size = QT_UINT32 (mfro_map.data + 12);
4298   if (mfra_size >= len)
4299     goto invalid_mfra_size;
4300
4301   mfra_offset = len - mfra_size;
4302
4303   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4304       mfra_offset, mfra_size);
4305
4306   /* now get and parse mfra box */
4307   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4308   if (flow != GST_FLOW_OK)
4309     goto broken_file;
4310
4311   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4312
4313   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4314   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4315
4316   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4317
4318   while (tfra_node) {
4319     qtdemux_parse_tfra (qtdemux, tfra_node);
4320     /* iterate all siblings */
4321     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4322   }
4323   g_node_destroy (mfra_node);
4324
4325   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4326   ret = TRUE;
4327
4328 exit:
4329
4330   if (mfro) {
4331     if (mfro_map.memory != NULL)
4332       gst_buffer_unmap (mfro, &mfro_map);
4333     gst_buffer_unref (mfro);
4334   }
4335   if (mfra) {
4336     if (mfra_map.memory != NULL)
4337       gst_buffer_unmap (mfra, &mfra_map);
4338     gst_buffer_unref (mfra);
4339   }
4340   return ret;
4341
4342 /* ERRORS */
4343 size_query_failed:
4344   {
4345     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4346     goto exit;
4347   }
4348 invalid_mfro_size:
4349   {
4350     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4351     goto exit;
4352   }
4353 invalid_mfra_size:
4354   {
4355     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4356     goto exit;
4357   }
4358 broken_file:
4359   {
4360     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4361     goto exit;
4362   }
4363 }
4364
4365 static guint64
4366 add_offset (guint64 offset, guint64 advance)
4367 {
4368   /* Avoid 64-bit overflow by clamping */
4369   if (offset > G_MAXUINT64 - advance)
4370     return G_MAXUINT64;
4371   return offset + advance;
4372 }
4373
4374 static GstFlowReturn
4375 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4376 {
4377   guint64 length = 0;
4378   guint32 fourcc = 0;
4379   GstBuffer *buf = NULL;
4380   GstFlowReturn ret = GST_FLOW_OK;
4381   guint64 cur_offset = qtdemux->offset;
4382   GstMapInfo map;
4383
4384   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4385   if (G_UNLIKELY (ret != GST_FLOW_OK))
4386     goto beach;
4387   gst_buffer_map (buf, &map, GST_MAP_READ);
4388   if (G_LIKELY (map.size >= 8))
4389     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4390   gst_buffer_unmap (buf, &map);
4391   gst_buffer_unref (buf);
4392
4393   /* maybe we already got most we needed, so only consider this eof */
4394   if (G_UNLIKELY (length == 0)) {
4395     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4396         (_("Invalid atom size.")),
4397         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4398             GST_FOURCC_ARGS (fourcc)));
4399     ret = GST_FLOW_EOS;
4400     goto beach;
4401   }
4402
4403   switch (fourcc) {
4404     case FOURCC_moof:
4405       /* record for later parsing when needed */
4406       if (!qtdemux->moof_offset) {
4407         qtdemux->moof_offset = qtdemux->offset;
4408       }
4409       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4410         /* FIXME */
4411       } else {
4412         qtdemux->offset += length;      /* skip moof and keep going */
4413       }
4414       if (qtdemux->got_moov) {
4415         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4416         ret = GST_FLOW_EOS;
4417         goto beach;
4418       }
4419       break;
4420     case FOURCC_mdat:
4421     case FOURCC_free:
4422     case FOURCC_skip:
4423     case FOURCC_wide:
4424     case FOURCC_PICT:
4425     case FOURCC_pnot:
4426     {
4427       GST_LOG_OBJECT (qtdemux,
4428           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4429           GST_FOURCC_ARGS (fourcc), cur_offset);
4430       qtdemux->offset = add_offset (qtdemux->offset, length);
4431       break;
4432     }
4433     case FOURCC_moov:
4434     {
4435       GstBuffer *moov = NULL;
4436
4437       if (qtdemux->got_moov) {
4438         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4439         qtdemux->offset = add_offset (qtdemux->offset, length);
4440         goto beach;
4441       }
4442
4443       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4444       if (ret != GST_FLOW_OK)
4445         goto beach;
4446       gst_buffer_map (moov, &map, GST_MAP_READ);
4447
4448       if (length != map.size) {
4449         /* Some files have a 'moov' atom at the end of the file which contains
4450          * a terminal 'free' atom where the body of the atom is missing.
4451          * Check for, and permit, this special case.
4452          */
4453         if (map.size >= 8) {
4454           guint8 *final_data = map.data + (map.size - 8);
4455           guint32 final_length = QT_UINT32 (final_data);
4456           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4457
4458           if (final_fourcc == FOURCC_free
4459               && map.size + final_length - 8 == length) {
4460             /* Ok, we've found that special case. Allocate a new buffer with
4461              * that free atom actually present. */
4462             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4463             gst_buffer_fill (newmoov, 0, map.data, map.size);
4464             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4465             gst_buffer_unmap (moov, &map);
4466             gst_buffer_unref (moov);
4467             moov = newmoov;
4468             gst_buffer_map (moov, &map, GST_MAP_READ);
4469           }
4470         }
4471       }
4472
4473       if (length != map.size) {
4474         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4475             (_("This file is incomplete and cannot be played.")),
4476             ("We got less than expected (received %" G_GSIZE_FORMAT
4477                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4478                 (guint) length, cur_offset));
4479         gst_buffer_unmap (moov, &map);
4480         gst_buffer_unref (moov);
4481         ret = GST_FLOW_ERROR;
4482         goto beach;
4483       }
4484       qtdemux->offset += length;
4485
4486       qtdemux_parse_moov (qtdemux, map.data, length);
4487       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4488
4489       qtdemux_parse_tree (qtdemux);
4490       if (qtdemux->moov_node_compressed) {
4491         g_node_destroy (qtdemux->moov_node_compressed);
4492         g_free (qtdemux->moov_node->data);
4493       }
4494       qtdemux->moov_node_compressed = NULL;
4495       g_node_destroy (qtdemux->moov_node);
4496       qtdemux->moov_node = NULL;
4497       gst_buffer_unmap (moov, &map);
4498       gst_buffer_unref (moov);
4499       qtdemux->got_moov = TRUE;
4500
4501       break;
4502     }
4503     case FOURCC_ftyp:
4504     {
4505       GstBuffer *ftyp = NULL;
4506
4507       /* extract major brand; might come in handy for ISO vs QT issues */
4508       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4509       if (ret != GST_FLOW_OK)
4510         goto beach;
4511       qtdemux->offset += length;
4512       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4513       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4514       gst_buffer_unmap (ftyp, &map);
4515       gst_buffer_unref (ftyp);
4516       break;
4517     }
4518     case FOURCC_uuid:
4519     {
4520       GstBuffer *uuid = NULL;
4521
4522       /* uuid are extension atoms */
4523       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4524       if (ret != GST_FLOW_OK)
4525         goto beach;
4526       qtdemux->offset += length;
4527       gst_buffer_map (uuid, &map, GST_MAP_READ);
4528       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4529       gst_buffer_unmap (uuid, &map);
4530       gst_buffer_unref (uuid);
4531       break;
4532     }
4533     case FOURCC_sidx:
4534     {
4535       GstBuffer *sidx = NULL;
4536       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4537       if (ret != GST_FLOW_OK)
4538         goto beach;
4539       qtdemux->offset += length;
4540       gst_buffer_map (sidx, &map, GST_MAP_READ);
4541       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4542       gst_buffer_unmap (sidx, &map);
4543       gst_buffer_unref (sidx);
4544       break;
4545     }
4546     default:
4547     {
4548       GstBuffer *unknown = NULL;
4549
4550       GST_LOG_OBJECT (qtdemux,
4551           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4552           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4553           cur_offset);
4554       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4555       if (ret != GST_FLOW_OK)
4556         goto beach;
4557       gst_buffer_map (unknown, &map, GST_MAP_READ);
4558       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4559       gst_buffer_unmap (unknown, &map);
4560       gst_buffer_unref (unknown);
4561       qtdemux->offset += length;
4562       break;
4563     }
4564   }
4565
4566 beach:
4567   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4568     /* digested all data, show what we have */
4569     qtdemux_prepare_streams (qtdemux);
4570     QTDEMUX_EXPOSE_LOCK (qtdemux);
4571     ret = qtdemux_expose_streams (qtdemux);
4572     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4573
4574     qtdemux->state = QTDEMUX_STATE_MOVIE;
4575     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4576         qtdemux->state);
4577     return ret;
4578   }
4579   return ret;
4580 }
4581
4582 /* Seeks to the previous keyframe of the indexed stream and
4583  * aligns other streams with respect to the keyframe timestamp
4584  * of indexed stream. Only called in case of Reverse Playback
4585  */
4586 static GstFlowReturn
4587 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4588 {
4589   guint32 seg_idx = 0, k_index = 0;
4590   guint32 ref_seg_idx, ref_k_index;
4591   GstClockTime k_pos = 0, last_stop = 0;
4592   QtDemuxSegment *seg = NULL;
4593   QtDemuxStream *ref_str = NULL;
4594   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4595   guint64 target_ts;
4596   gint i;
4597
4598   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4599    * and finally align all the other streams on that timestamp with their
4600    * respective keyframes */
4601   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4602     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4603
4604     /* No candidate yet, take the first stream */
4605     if (!ref_str) {
4606       ref_str = str;
4607       continue;
4608     }
4609
4610     /* So that stream has a segment, we prefer video streams */
4611     if (str->subtype == FOURCC_vide) {
4612       ref_str = str;
4613       break;
4614     }
4615   }
4616
4617   if (G_UNLIKELY (!ref_str)) {
4618     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4619     goto eos;
4620   }
4621
4622   if (G_UNLIKELY (!ref_str->from_sample)) {
4623     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4624     goto eos;
4625   }
4626
4627   /* So that stream has been playing from from_sample to to_sample. We will
4628    * get the timestamp of the previous sample and search for a keyframe before
4629    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4630   if (ref_str->subtype == FOURCC_vide) {
4631     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4632         ref_str->from_sample - 1, FALSE);
4633   } else {
4634     if (ref_str->from_sample >= 10)
4635       k_index = ref_str->from_sample - 10;
4636     else
4637       k_index = 0;
4638   }
4639
4640   target_ts =
4641       ref_str->samples[k_index].timestamp +
4642       ref_str->samples[k_index].pts_offset;
4643
4644   /* get current segment for that stream */
4645   seg = &ref_str->segments[ref_str->segment_index];
4646   /* Use segment start in original timescale for comparisons */
4647   seg_media_start_mov = seg->trak_media_start;
4648
4649   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4650       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4651       k_index, target_ts, seg_media_start_mov,
4652       GST_TIME_ARGS (seg->media_start));
4653
4654   /* Crawl back through segments to find the one containing this I frame */
4655   while (target_ts < seg_media_start_mov) {
4656     GST_DEBUG_OBJECT (qtdemux,
4657         "keyframe position (sample %u) is out of segment %u " " target %"
4658         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4659         ref_str->segment_index, target_ts, seg_media_start_mov);
4660
4661     if (G_UNLIKELY (!ref_str->segment_index)) {
4662       /* Reached first segment, let's consider it's EOS */
4663       goto eos;
4664     }
4665     ref_str->segment_index--;
4666     seg = &ref_str->segments[ref_str->segment_index];
4667     /* Use segment start in original timescale for comparisons */
4668     seg_media_start_mov = seg->trak_media_start;
4669   }
4670   /* Calculate time position of the keyframe and where we should stop */
4671   k_pos =
4672       QTSTREAMTIME_TO_GSTTIME (ref_str,
4673       target_ts - seg->trak_media_start) + seg->time;
4674   last_stop =
4675       QTSTREAMTIME_TO_GSTTIME (ref_str,
4676       ref_str->samples[ref_str->from_sample].timestamp -
4677       seg->trak_media_start) + seg->time;
4678
4679   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4680       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4681       k_index, GST_TIME_ARGS (k_pos));
4682
4683   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4684   qtdemux->segment.position = last_stop;
4685   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4686       GST_TIME_ARGS (last_stop));
4687
4688   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4689     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4690     goto eos;
4691   }
4692
4693   ref_seg_idx = ref_str->segment_index;
4694   ref_k_index = k_index;
4695
4696   /* Align them all on this */
4697   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4698     guint32 index = 0;
4699     GstClockTime seg_time = 0;
4700     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4701
4702     /* aligning reference stream again might lead to backing up to yet another
4703      * keyframe (due to timestamp rounding issues),
4704      * potentially putting more load on downstream; so let's try to avoid */
4705     if (str == ref_str) {
4706       seg_idx = ref_seg_idx;
4707       seg = &str->segments[seg_idx];
4708       k_index = ref_k_index;
4709       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4710           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4711     } else {
4712       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4713       GST_DEBUG_OBJECT (qtdemux,
4714           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4715           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4716
4717       /* get segment and time in the segment */
4718       seg = &str->segments[seg_idx];
4719       seg_time = k_pos - seg->time;
4720
4721       /* get the media time in the segment.
4722        * No adjustment for empty "filler" segments */
4723       if (seg->media_start != GST_CLOCK_TIME_NONE)
4724         seg_time += seg->media_start;
4725
4726       /* get the index of the sample with media time */
4727       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4728       GST_DEBUG_OBJECT (qtdemux,
4729           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4730           GST_TIME_ARGS (seg_time), index);
4731
4732       /* find previous keyframe */
4733       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4734     }
4735
4736     /* Remember until where we want to go */
4737     str->to_sample = str->from_sample - 1;
4738     /* Define our time position */
4739     target_ts =
4740         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4741     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4742     if (seg->media_start != GST_CLOCK_TIME_NONE)
4743       str->time_position -= seg->media_start;
4744
4745     /* Now seek back in time */
4746     gst_qtdemux_move_stream (qtdemux, str, k_index);
4747     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4748         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4749         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4750   }
4751
4752   return GST_FLOW_OK;
4753
4754 eos:
4755   return GST_FLOW_EOS;
4756 }
4757
4758 /*
4759  * Gets the current qt segment start, stop and position for the
4760  * given time offset. This is used in update_segment()
4761  */
4762 static void
4763 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4764     QtDemuxStream * stream, GstClockTime offset,
4765     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4766 {
4767   GstClockTime seg_time;
4768   GstClockTime start, stop, time;
4769   QtDemuxSegment *segment;
4770
4771   segment = &stream->segments[stream->segment_index];
4772
4773   /* get time in this segment */
4774   seg_time = (offset - segment->time) * segment->rate;
4775
4776   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4777       GST_TIME_ARGS (seg_time));
4778
4779   if (G_UNLIKELY (seg_time > segment->duration)) {
4780     GST_LOG_OBJECT (stream->pad,
4781         "seg_time > segment->duration %" GST_TIME_FORMAT,
4782         GST_TIME_ARGS (segment->duration));
4783     seg_time = segment->duration;
4784   }
4785
4786   /* qtdemux->segment.stop is in outside-time-realm, whereas
4787    * segment->media_stop is in track-time-realm.
4788    *
4789    * In order to compare the two, we need to bring segment.stop
4790    * into the track-time-realm
4791    *
4792    * FIXME - does this comment still hold? Don't see any conversion here */
4793
4794   stop = qtdemux->segment.stop;
4795   if (stop == GST_CLOCK_TIME_NONE)
4796     stop = qtdemux->segment.duration;
4797   if (stop == GST_CLOCK_TIME_NONE)
4798     stop = segment->media_stop;
4799   else
4800     stop =
4801         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4802
4803   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4804     start = segment->time + seg_time;
4805     time = offset;
4806     stop = start - seg_time + segment->duration;
4807   } else if (qtdemux->segment.rate >= 0) {
4808     start = MIN (segment->media_start + seg_time, stop);
4809     time = offset;
4810   } else {
4811     if (segment->media_start >= qtdemux->segment.start) {
4812       time = segment->time;
4813     } else {
4814       time = segment->time + (qtdemux->segment.start - segment->media_start);
4815     }
4816
4817     start = MAX (segment->media_start, qtdemux->segment.start);
4818     stop = MIN (segment->media_start + seg_time, stop);
4819   }
4820
4821   *_start = start;
4822   *_stop = stop;
4823   *_time = time;
4824 }
4825
4826 /*
4827  * Updates the qt segment used for the stream and pushes a new segment event
4828  * downstream on this stream's pad.
4829  */
4830 static gboolean
4831 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4832     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4833     GstClockTime * _stop)
4834 {
4835   QtDemuxSegment *segment;
4836   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4837   gdouble rate;
4838   GstEvent *event;
4839
4840   /* update the current segment */
4841   stream->segment_index = seg_idx;
4842
4843   /* get the segment */
4844   segment = &stream->segments[seg_idx];
4845
4846   if (G_UNLIKELY (offset < segment->time)) {
4847     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4848         GST_TIME_ARGS (segment->time));
4849     return FALSE;
4850   }
4851
4852   /* segment lies beyond total indicated duration */
4853   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4854           segment->time > qtdemux->segment.duration)) {
4855     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4856         " < segment->time %" GST_TIME_FORMAT,
4857         GST_TIME_ARGS (qtdemux->segment.duration),
4858         GST_TIME_ARGS (segment->time));
4859     return FALSE;
4860   }
4861
4862   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4863       &start, &stop, &time);
4864
4865   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4866       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4867       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4868
4869   /* combine global rate with that of the segment */
4870   rate = segment->rate * qtdemux->segment.rate;
4871
4872   /* Copy flags from main segment */
4873   stream->segment.flags = qtdemux->segment.flags;
4874
4875   /* update the segment values used for clipping */
4876   stream->segment.offset = qtdemux->segment.offset;
4877   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4878   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4879   stream->segment.rate = rate;
4880   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4881       stream->cslg_shift);
4882   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4883       stream->cslg_shift);
4884   stream->segment.time = time;
4885   stream->segment.position = stream->segment.start;
4886
4887   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4888       &stream->segment);
4889
4890   /* now prepare and send the segment */
4891   if (stream->pad) {
4892     event = gst_event_new_segment (&stream->segment);
4893     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4894       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4895     }
4896     gst_pad_push_event (stream->pad, event);
4897     /* assume we can send more data now */
4898     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4899     /* clear to send tags on this pad now */
4900     gst_qtdemux_push_tags (qtdemux, stream);
4901   }
4902
4903   if (_start)
4904     *_start = start;
4905   if (_stop)
4906     *_stop = stop;
4907
4908   return TRUE;
4909 }
4910
4911 /* activate the given segment number @seg_idx of @stream at time @offset.
4912  * @offset is an absolute global position over all the segments.
4913  *
4914  * This will push out a NEWSEGMENT event with the right values and
4915  * position the stream index to the first decodable sample before
4916  * @offset.
4917  */
4918 static gboolean
4919 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4920     guint32 seg_idx, GstClockTime offset)
4921 {
4922   QtDemuxSegment *segment;
4923   guint32 index, kf_index;
4924   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4925
4926   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4927       seg_idx, GST_TIME_ARGS (offset));
4928
4929   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4930           &start, &stop))
4931     return FALSE;
4932
4933   segment = &stream->segments[stream->segment_index];
4934
4935   /* in the fragmented case, we pick a fragment that starts before our
4936    * desired position and rely on downstream to wait for a keyframe
4937    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4938    * tfra entries tells us which trun/sample the key unit is in, but we don't
4939    * make use of this additional information at the moment) */
4940   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4941     stream->to_sample = G_MAXUINT32;
4942     return TRUE;
4943   } else {
4944     /* well, it will be taken care of below */
4945     qtdemux->fragmented_seek_pending = FALSE;
4946     /* FIXME ideally the do_fragmented_seek can be done right here,
4947      * rather than at loop level
4948      * (which might even allow handling edit lists in a fragmented file) */
4949   }
4950
4951   /* We don't need to look for a sample in push-based */
4952   if (!qtdemux->pullbased)
4953     return TRUE;
4954
4955   /* and move to the keyframe before the indicated media time of the
4956    * segment */
4957   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4958     if (qtdemux->segment.rate >= 0) {
4959       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4960       stream->to_sample = G_MAXUINT32;
4961       GST_DEBUG_OBJECT (stream->pad,
4962           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4963           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4964           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4965     } else {
4966       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4967       stream->to_sample = index;
4968       GST_DEBUG_OBJECT (stream->pad,
4969           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4970           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4971           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4972     }
4973   } else {
4974     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4975         "this is an empty segment");
4976     return TRUE;
4977   }
4978
4979   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4980    * encountered an error and printed a message so we return appropriately */
4981   if (index == -1)
4982     return FALSE;
4983
4984   /* we're at the right spot */
4985   if (index == stream->sample_index) {
4986     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4987     return TRUE;
4988   }
4989
4990   /* find keyframe of the target index */
4991   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4992
4993   /* go back two frames to provide lead-in for non-raw audio decoders */
4994   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
4995     guint32 lead_in = 2;
4996     guint32 old_index = kf_index;
4997     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
4998
4999     if (gst_structure_has_name (s, "audio/mpeg")) {
5000       gint mpegversion;
5001       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5002           && mpegversion == 1) {
5003         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5004         lead_in = 30;
5005       }
5006     }
5007
5008     kf_index = MAX (kf_index, lead_in) - lead_in;
5009     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5010       GST_DEBUG_OBJECT (stream->pad,
5011           "Moving backwards %u frames to ensure sufficient sound lead-in",
5012           old_index - kf_index);
5013     } else {
5014       kf_index = old_index;
5015     }
5016   }
5017
5018   /* if we move forwards, we don't have to go back to the previous
5019    * keyframe since we already sent that. We can also just jump to
5020    * the keyframe right before the target index if there is one. */
5021   if (index > stream->sample_index) {
5022     /* moving forwards check if we move past a keyframe */
5023     if (kf_index > stream->sample_index) {
5024       GST_DEBUG_OBJECT (stream->pad,
5025           "moving forwards to keyframe at %u "
5026           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5027           kf_index,
5028           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5029           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5030       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5031     } else {
5032       GST_DEBUG_OBJECT (stream->pad,
5033           "moving forwards, keyframe at %u "
5034           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5035           kf_index,
5036           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5037           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5038     }
5039   } else {
5040     GST_DEBUG_OBJECT (stream->pad,
5041         "moving backwards to %sframe at %u "
5042         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5043         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5044         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5045         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5046     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5047   }
5048
5049   return TRUE;
5050 }
5051
5052 /* prepare to get the current sample of @stream, getting essential values.
5053  *
5054  * This function will also prepare and send the segment when needed.
5055  *
5056  * Return FALSE if the stream is EOS.
5057  *
5058  * PULL-BASED
5059  */
5060 static gboolean
5061 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5062     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5063     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5064     gboolean * keyframe)
5065 {
5066   QtDemuxSample *sample;
5067   GstClockTime time_position;
5068   guint32 seg_idx;
5069
5070   g_return_val_if_fail (stream != NULL, FALSE);
5071
5072   time_position = stream->time_position;
5073   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5074     goto eos;
5075
5076   seg_idx = stream->segment_index;
5077   if (G_UNLIKELY (seg_idx == -1)) {
5078     /* find segment corresponding to time_position if we are looking
5079      * for a segment. */
5080     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5081   }
5082
5083   /* different segment, activate it, sample_index will be set. */
5084   if (G_UNLIKELY (stream->segment_index != seg_idx))
5085     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5086
5087   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5088               segments[stream->segment_index]))) {
5089     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5090
5091     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5092         " prepare empty sample");
5093
5094     *empty = TRUE;
5095     *pts = *dts = time_position;
5096     *duration = seg->duration - (time_position - seg->time);
5097
5098     return TRUE;
5099   }
5100
5101   *empty = FALSE;
5102
5103   if (stream->sample_index == -1)
5104     stream->sample_index = 0;
5105
5106   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5107       stream->sample_index, stream->n_samples);
5108
5109   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5110     if (!qtdemux->fragmented)
5111       goto eos;
5112
5113     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5114     do {
5115       GstFlowReturn flow;
5116
5117       GST_OBJECT_LOCK (qtdemux);
5118       flow = qtdemux_add_fragmented_samples (qtdemux);
5119       GST_OBJECT_UNLOCK (qtdemux);
5120
5121       if (flow != GST_FLOW_OK)
5122         goto eos;
5123     }
5124     while (stream->sample_index >= stream->n_samples);
5125   }
5126
5127   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5128     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5129         stream->sample_index);
5130     return FALSE;
5131   }
5132
5133   /* now get the info for the sample we're at */
5134   sample = &stream->samples[stream->sample_index];
5135
5136   *dts = QTSAMPLE_DTS (stream, sample);
5137   *pts = QTSAMPLE_PTS (stream, sample);
5138   *offset = sample->offset;
5139   *size = sample->size;
5140   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5141   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5142
5143   return TRUE;
5144
5145   /* special cases */
5146 eos:
5147   {
5148     stream->time_position = GST_CLOCK_TIME_NONE;
5149     return FALSE;
5150   }
5151 }
5152
5153 /* move to the next sample in @stream.
5154  *
5155  * Moves to the next segment when needed.
5156  */
5157 static void
5158 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5159 {
5160   QtDemuxSample *sample;
5161   QtDemuxSegment *segment;
5162
5163   /* get current segment */
5164   segment = &stream->segments[stream->segment_index];
5165
5166   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5167     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5168     goto next_segment;
5169   }
5170
5171   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5172     /* Mark the stream as EOS */
5173     GST_DEBUG_OBJECT (qtdemux,
5174         "reached max allowed sample %u, mark EOS", stream->to_sample);
5175     stream->time_position = GST_CLOCK_TIME_NONE;
5176     return;
5177   }
5178
5179   /* move to next sample */
5180   stream->sample_index++;
5181   stream->offset_in_sample = 0;
5182
5183   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5184       stream->n_samples);
5185
5186   /* reached the last sample, we need the next segment */
5187   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5188     goto next_segment;
5189
5190   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5191     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5192         stream->sample_index);
5193     return;
5194   }
5195
5196   /* get next sample */
5197   sample = &stream->samples[stream->sample_index];
5198
5199   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5200       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5201       GST_TIME_ARGS (segment->media_stop));
5202
5203   /* see if we are past the segment */
5204   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5205     goto next_segment;
5206
5207   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5208     /* inside the segment, update time_position, looks very familiar to
5209      * GStreamer segments, doesn't it? */
5210     stream->time_position =
5211         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5212   } else {
5213     /* not yet in segment, time does not yet increment. This means
5214      * that we are still prerolling keyframes to the decoder so it can
5215      * decode the first sample of the segment. */
5216     stream->time_position = segment->time;
5217   }
5218   return;
5219
5220   /* move to the next segment */
5221 next_segment:
5222   {
5223     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5224
5225     if (stream->segment_index == stream->n_segments - 1) {
5226       /* are we at the end of the last segment, we're EOS */
5227       stream->time_position = GST_CLOCK_TIME_NONE;
5228     } else {
5229       /* else we're only at the end of the current segment */
5230       stream->time_position = segment->stop_time;
5231     }
5232     /* make sure we select a new segment */
5233
5234     /* accumulate previous segments */
5235     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5236       stream->accumulated_base +=
5237           (stream->segment.stop -
5238           stream->segment.start) / ABS (stream->segment.rate);
5239
5240     stream->segment_index = -1;
5241   }
5242 }
5243
5244 static void
5245 gst_qtdemux_sync_streams (GstQTDemux * demux)
5246 {
5247   gint i;
5248
5249   if (QTDEMUX_N_STREAMS (demux) <= 1)
5250     return;
5251
5252   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5253     QtDemuxStream *stream;
5254     GstClockTime end_time;
5255
5256     stream = QTDEMUX_NTH_STREAM (demux, i);
5257
5258     if (!stream->pad)
5259       continue;
5260
5261     /* TODO advance time on subtitle streams here, if any some day */
5262
5263     /* some clips/trailers may have unbalanced streams at the end,
5264      * so send EOS on shorter stream to prevent stalling others */
5265
5266     /* do not mess with EOS if SEGMENT seeking */
5267     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5268       continue;
5269
5270     if (demux->pullbased) {
5271       /* loop mode is sample time based */
5272       if (!STREAM_IS_EOS (stream))
5273         continue;
5274     } else {
5275       /* push mode is byte position based */
5276       if (stream->n_samples &&
5277           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5278         continue;
5279     }
5280
5281     if (stream->sent_eos)
5282       continue;
5283
5284     /* only act if some gap */
5285     end_time = stream->segments[stream->n_segments - 1].stop_time;
5286     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5287         ", stream end: %" GST_TIME_FORMAT,
5288         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5289     if (GST_CLOCK_TIME_IS_VALID (end_time)
5290         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5291       GstEvent *event;
5292
5293       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5294           GST_PAD_NAME (stream->pad));
5295       stream->sent_eos = TRUE;
5296       event = gst_event_new_eos ();
5297       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5298         gst_event_set_seqnum (event, demux->segment_seqnum);
5299       gst_pad_push_event (stream->pad, event);
5300     }
5301   }
5302 }
5303
5304 /* EOS and NOT_LINKED need to be combined. This means that we return:
5305  *
5306  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5307  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5308  */
5309 static GstFlowReturn
5310 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5311     GstFlowReturn ret)
5312 {
5313   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5314
5315   if (stream->pad)
5316     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5317         ret);
5318   else
5319     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5320
5321   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5322   return ret;
5323 }
5324
5325 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5326  * completely clipped
5327  *
5328  * Should be used only with raw buffers */
5329 static GstBuffer *
5330 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5331     GstBuffer * buf)
5332 {
5333   guint64 start, stop, cstart, cstop, diff;
5334   GstClockTime pts, duration;
5335   gsize size, osize;
5336   gint num_rate, denom_rate;
5337   gint frame_size;
5338   gboolean clip_data;
5339   guint offset;
5340
5341   osize = size = gst_buffer_get_size (buf);
5342   offset = 0;
5343
5344   /* depending on the type, setup the clip parameters */
5345   if (stream->subtype == FOURCC_soun) {
5346     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5347     num_rate = GST_SECOND;
5348     denom_rate = (gint) CUR_STREAM (stream)->rate;
5349     clip_data = TRUE;
5350   } else if (stream->subtype == FOURCC_vide) {
5351     frame_size = size;
5352     num_rate = CUR_STREAM (stream)->fps_n;
5353     denom_rate = CUR_STREAM (stream)->fps_d;
5354     clip_data = FALSE;
5355   } else
5356     goto wrong_type;
5357
5358   if (frame_size <= 0)
5359     goto bad_frame_size;
5360
5361   /* we can only clip if we have a valid pts */
5362   pts = GST_BUFFER_PTS (buf);
5363   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5364     goto no_pts;
5365
5366   duration = GST_BUFFER_DURATION (buf);
5367
5368   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5369     duration =
5370         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5371   }
5372
5373   start = pts;
5374   stop = start + duration;
5375
5376   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5377               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5378     goto clipped;
5379
5380   /* see if some clipping happened */
5381   diff = cstart - start;
5382   if (diff > 0) {
5383     pts += diff;
5384     duration -= diff;
5385
5386     if (clip_data) {
5387       /* bring clipped time to samples and to bytes */
5388       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5389       diff *= frame_size;
5390
5391       GST_DEBUG_OBJECT (qtdemux,
5392           "clipping start to %" GST_TIME_FORMAT " %"
5393           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5394
5395       offset = diff;
5396       size -= diff;
5397     }
5398   }
5399   diff = stop - cstop;
5400   if (diff > 0) {
5401     duration -= diff;
5402
5403     if (clip_data) {
5404       /* bring clipped time to samples and then to bytes */
5405       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5406       diff *= frame_size;
5407       GST_DEBUG_OBJECT (qtdemux,
5408           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5409           " bytes", GST_TIME_ARGS (cstop), diff);
5410       size -= diff;
5411     }
5412   }
5413
5414   if (offset != 0 || size != osize)
5415     gst_buffer_resize (buf, offset, size);
5416
5417   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5418   GST_BUFFER_PTS (buf) = pts;
5419   GST_BUFFER_DURATION (buf) = duration;
5420
5421   return buf;
5422
5423   /* dropped buffer */
5424 wrong_type:
5425   {
5426     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5427     return buf;
5428   }
5429 bad_frame_size:
5430   {
5431     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5432     return buf;
5433   }
5434 no_pts:
5435   {
5436     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5437     return buf;
5438   }
5439 clipped:
5440   {
5441     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5442     gst_buffer_unref (buf);
5443     return NULL;
5444   }
5445 }
5446
5447 static GstBuffer *
5448 gst_qtdemux_align_buffer (GstQTDemux * demux,
5449     GstBuffer * buffer, gsize alignment)
5450 {
5451   GstMapInfo map;
5452
5453   gst_buffer_map (buffer, &map, GST_MAP_READ);
5454
5455   if (map.size < sizeof (guintptr)) {
5456     gst_buffer_unmap (buffer, &map);
5457     return buffer;
5458   }
5459
5460   if (((guintptr) map.data) & (alignment - 1)) {
5461     GstBuffer *new_buffer;
5462     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5463
5464     new_buffer = gst_buffer_new_allocate (NULL,
5465         gst_buffer_get_size (buffer), &params);
5466
5467     /* Copy data "by hand", so ensure alignment is kept: */
5468     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5469
5470     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5471     GST_DEBUG_OBJECT (demux,
5472         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5473         alignment);
5474
5475     gst_buffer_unmap (buffer, &map);
5476     gst_buffer_unref (buffer);
5477
5478     return new_buffer;
5479   }
5480
5481   gst_buffer_unmap (buffer, &map);
5482   return buffer;
5483 }
5484
5485 static guint8 *
5486 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5487     gsize * res)
5488 {
5489   guint8 *storage;
5490   gsize i;
5491
5492   /* We are converting from pairs to triplets */
5493   *res = ccpair_size / 2 * 3;
5494   storage = g_malloc (*res);
5495   for (i = 0; i * 2 < ccpair_size; i += 1) {
5496     /* FIXME: Use line offset 0 as we simply can't know here */
5497     if (field == 1)
5498       storage[i * 3] = 0x80 | 0x00;
5499     else
5500       storage[i * 3] = 0x00 | 0x00;
5501     storage[i * 3 + 1] = ccpair[i * 2];
5502     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5503   }
5504
5505   return storage;
5506 }
5507
5508 static guint8 *
5509 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5510     gsize * cclen)
5511 {
5512   guint8 *res = NULL;
5513   guint32 atom_length, fourcc;
5514   QtDemuxStreamStsdEntry *stsd_entry;
5515
5516   GST_MEMDUMP ("caption atom", data, size);
5517
5518   /* There might be multiple atoms */
5519
5520   *cclen = 0;
5521   if (size < 8)
5522     goto invalid_cdat;
5523   atom_length = QT_UINT32 (data);
5524   fourcc = QT_FOURCC (data + 4);
5525   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5526     goto invalid_cdat;
5527
5528   GST_DEBUG_OBJECT (stream->pad, "here");
5529
5530   /* Check if we have something compatible */
5531   stsd_entry = CUR_STREAM (stream);
5532   switch (stsd_entry->fourcc) {
5533     case FOURCC_c608:{
5534       guint8 *cdat = NULL, *cdt2 = NULL;
5535       gsize cdat_size = 0, cdt2_size = 0;
5536       /* Should be cdat or cdt2 */
5537       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5538         GST_WARNING_OBJECT (stream->pad,
5539             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5540             GST_FOURCC_ARGS (fourcc));
5541         goto invalid_cdat;
5542       }
5543
5544       /* Convert to S334-1 Annex A byte triplet */
5545       if (fourcc == FOURCC_cdat)
5546         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5547       else
5548         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5549       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5550           size, atom_length);
5551
5552       /* Check for another atom ? */
5553       if (size > atom_length + 8) {
5554         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5555         if (size >= atom_length + new_atom_length) {
5556           fourcc = QT_FOURCC (data + atom_length + 4);
5557           if (fourcc == FOURCC_cdat) {
5558             if (cdat == NULL)
5559               cdat =
5560                   convert_to_s334_1a (data + atom_length + 8,
5561                   new_atom_length - 8, 1, &cdat_size);
5562             else
5563               GST_WARNING_OBJECT (stream->pad,
5564                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5565           } else {
5566             if (cdt2 == NULL)
5567               cdt2 =
5568                   convert_to_s334_1a (data + atom_length + 8,
5569                   new_atom_length - 8, 2, &cdt2_size);
5570             else
5571               GST_WARNING_OBJECT (stream->pad,
5572                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5573           }
5574         }
5575       }
5576
5577       *cclen = cdat_size + cdt2_size;
5578       res = g_malloc (*cclen);
5579       if (cdat_size)
5580         memcpy (res, cdat, cdat_size);
5581       if (cdt2_size)
5582         memcpy (res + cdat_size, cdt2, cdt2_size);
5583       g_free (cdat);
5584       g_free (cdt2);
5585     }
5586       break;
5587     case FOURCC_c708:
5588       if (fourcc != FOURCC_ccdp) {
5589         GST_WARNING_OBJECT (stream->pad,
5590             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5591             GST_FOURCC_ARGS (fourcc));
5592         goto invalid_cdat;
5593       }
5594       *cclen = atom_length - 8;
5595       res = g_memdup (data + 8, *cclen);
5596       break;
5597     default:
5598       /* Keep this here in case other closed caption formats are added */
5599       g_assert_not_reached ();
5600       break;
5601   }
5602
5603   GST_MEMDUMP ("Output", res, *cclen);
5604   return res;
5605
5606   /* Errors */
5607 invalid_cdat:
5608   GST_WARNING ("[cdat] atom is too small or invalid");
5609   return NULL;
5610 }
5611
5612 /* the input buffer metadata must be writable,
5613  * but time/duration etc not yet set and need not be preserved */
5614 static GstBuffer *
5615 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5616     GstBuffer * buf)
5617 {
5618   GstMapInfo map;
5619   guint nsize = 0;
5620   gchar *str;
5621
5622   /* not many cases for now */
5623   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5624     /* send a one time dvd clut event */
5625     if (stream->pending_event && stream->pad)
5626       gst_pad_push_event (stream->pad, stream->pending_event);
5627     stream->pending_event = NULL;
5628   }
5629
5630   if (G_UNLIKELY (stream->subtype != FOURCC_text
5631           && stream->subtype != FOURCC_sbtl &&
5632           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5633     return buf;
5634   }
5635
5636   gst_buffer_map (buf, &map, GST_MAP_READ);
5637
5638   /* empty buffer is sent to terminate previous subtitle */
5639   if (map.size <= 2) {
5640     gst_buffer_unmap (buf, &map);
5641     gst_buffer_unref (buf);
5642     return NULL;
5643   }
5644   if (stream->subtype == FOURCC_subp) {
5645     /* That's all the processing needed for subpictures */
5646     gst_buffer_unmap (buf, &map);
5647     return buf;
5648   }
5649
5650   if (stream->subtype == FOURCC_clcp) {
5651     guint8 *cc;
5652     gsize cclen = 0;
5653     /* For closed caption, we need to extract the information from the
5654      * [cdat],[cdt2] or [ccdp] atom */
5655     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5656     gst_buffer_unmap (buf, &map);
5657     gst_buffer_unref (buf);
5658     if (cc) {
5659       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5660     } else {
5661       /* Conversion failed or there's nothing */
5662       buf = NULL;
5663     }
5664     return buf;
5665   }
5666
5667   nsize = GST_READ_UINT16_BE (map.data);
5668   nsize = MIN (nsize, map.size - 2);
5669
5670   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5671       nsize, map.size);
5672
5673   /* takes care of UTF-8 validation or UTF-16 recognition,
5674    * no other encoding expected */
5675   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5676   gst_buffer_unmap (buf, &map);
5677   if (str) {
5678     gst_buffer_unref (buf);
5679     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5680   } else {
5681     /* this should not really happen unless the subtitle is corrupted */
5682     gst_buffer_unref (buf);
5683     buf = NULL;
5684   }
5685
5686   /* FIXME ? convert optional subsequent style info to markup */
5687
5688   return buf;
5689 }
5690
5691 static GstFlowReturn
5692 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5693     GstBuffer * buf)
5694 {
5695   GstFlowReturn ret = GST_FLOW_OK;
5696   GstClockTime pts, duration;
5697
5698   if (stream->need_clip)
5699     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5700
5701   if (G_UNLIKELY (buf == NULL))
5702     goto exit;
5703
5704   if (G_UNLIKELY (stream->discont)) {
5705     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5706     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5707     stream->discont = FALSE;
5708   } else {
5709     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5710   }
5711
5712   GST_LOG_OBJECT (qtdemux,
5713       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5714       ", duration %" GST_TIME_FORMAT " on pad %s",
5715       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5716       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5717       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5718
5719   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5720     GstStructure *crypto_info;
5721     QtDemuxAavdEncryptionInfo *info =
5722         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5723
5724     crypto_info = gst_structure_copy (info->default_properties);
5725     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5726       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5727   }
5728
5729   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5730     GstStructure *crypto_info;
5731     QtDemuxCencSampleSetInfo *info =
5732         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5733     gint index;
5734     GstEvent *event;
5735
5736     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5737       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5738           GST_PTR_FORMAT, event);
5739       gst_pad_push_event (stream->pad, event);
5740     }
5741
5742     if (info->crypto_info == NULL) {
5743       GST_DEBUG_OBJECT (qtdemux,
5744           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5745     } else {
5746       /* The end of the crypto_info array matches our n_samples position,
5747        * so count backward from there */
5748       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5749       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5750         /* steal structure from array */
5751         crypto_info = g_ptr_array_index (info->crypto_info, index);
5752         g_ptr_array_index (info->crypto_info, index) = NULL;
5753         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5754             info->crypto_info->len);
5755         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5756           GST_ERROR_OBJECT (qtdemux,
5757               "failed to attach cenc metadata to buffer");
5758       } else {
5759         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5760             index, stream->sample_index);
5761       }
5762     }
5763   }
5764
5765   if (stream->alignment > 1)
5766     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5767
5768   pts = GST_BUFFER_PTS (buf);
5769   duration = GST_BUFFER_DURATION (buf);
5770
5771   ret = gst_pad_push (stream->pad, buf);
5772
5773   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5774     /* mark position in stream, we'll need this to know when to send GAP event */
5775     stream->segment.position = pts + duration;
5776   }
5777
5778 exit:
5779
5780   return ret;
5781 }
5782
5783 static GstFlowReturn
5784 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5785     GstBuffer * buf)
5786 {
5787   GstFlowReturn ret = GST_FLOW_OK;
5788
5789   if (stream->subtype == FOURCC_clcp
5790       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5791     GstMapInfo map;
5792     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5793     guint n_triplets, i;
5794     guint field1_off = 0, field2_off = 0;
5795
5796     /* We have to split CEA608 buffers so that each outgoing buffer contains
5797      * one byte pair per field according to the framerate of the video track.
5798      *
5799      * If there is only a single byte pair per field we don't have to do
5800      * anything
5801      */
5802
5803     gst_buffer_map (buf, &map, GST_MAP_READ);
5804
5805     n_triplets = map.size / 3;
5806     for (i = 0; i < n_triplets; i++) {
5807       if (map.data[3 * i] & 0x80)
5808         n_field1++;
5809       else
5810         n_field2++;
5811     }
5812
5813     g_assert (n_field1 || n_field2);
5814
5815     /* If there's more than 1 frame we have to split, otherwise we can just
5816      * pass through */
5817     if (n_field1 > 1 || n_field2 > 1) {
5818       n_output_buffers =
5819           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5820           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5821
5822       for (i = 0; i < n_output_buffers; i++) {
5823         GstBuffer *outbuf =
5824             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5825         GstMapInfo outmap;
5826         guint8 *outptr;
5827
5828         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5829         outptr = outmap.data;
5830
5831         if (n_field1) {
5832           gboolean found = FALSE;
5833
5834           while (map.data + field1_off < map.data + map.size) {
5835             if (map.data[field1_off] & 0x80) {
5836               memcpy (outptr, &map.data[field1_off], 3);
5837               field1_off += 3;
5838               found = TRUE;
5839               break;
5840             }
5841             field1_off += 3;
5842           }
5843
5844           if (!found) {
5845             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5846
5847             memcpy (outptr, empty, 3);
5848           }
5849
5850           outptr += 3;
5851         }
5852
5853         if (n_field2) {
5854           gboolean found = FALSE;
5855
5856           while (map.data + field2_off < map.data + map.size) {
5857             if ((map.data[field2_off] & 0x80) == 0) {
5858               memcpy (outptr, &map.data[field2_off], 3);
5859               field2_off += 3;
5860               found = TRUE;
5861               break;
5862             }
5863             field2_off += 3;
5864           }
5865
5866           if (!found) {
5867             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5868
5869             memcpy (outptr, empty, 3);
5870           }
5871
5872           outptr += 3;
5873         }
5874
5875         gst_buffer_unmap (outbuf, &outmap);
5876
5877         GST_BUFFER_PTS (outbuf) =
5878             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5879             GST_SECOND * CUR_STREAM (stream)->fps_d,
5880             CUR_STREAM (stream)->fps_n);
5881         GST_BUFFER_DURATION (outbuf) =
5882             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5883             CUR_STREAM (stream)->fps_n);
5884         GST_BUFFER_OFFSET (outbuf) = -1;
5885         GST_BUFFER_OFFSET_END (outbuf) = -1;
5886
5887         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
5888
5889         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
5890           break;
5891       }
5892       gst_buffer_unmap (buf, &map);
5893       gst_buffer_unref (buf);
5894     } else {
5895       gst_buffer_unmap (buf, &map);
5896       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5897     }
5898   } else {
5899     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5900   }
5901
5902   return ret;
5903 }
5904
5905 /* Sets a buffer's attributes properly and pushes it downstream.
5906  * Also checks for additional actions and custom processing that may
5907  * need to be done first.
5908  */
5909 static GstFlowReturn
5910 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5911     QtDemuxStream * stream, GstBuffer * buf,
5912     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5913     gboolean keyframe, GstClockTime position, guint64 byte_position)
5914 {
5915   GstFlowReturn ret = GST_FLOW_OK;
5916
5917   /* offset the timestamps according to the edit list */
5918
5919   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5920     gchar *url;
5921     GstMapInfo map;
5922
5923     gst_buffer_map (buf, &map, GST_MAP_READ);
5924     url = g_strndup ((gchar *) map.data, map.size);
5925     gst_buffer_unmap (buf, &map);
5926     if (url != NULL && strlen (url) != 0) {
5927       /* we have RTSP redirect now */
5928       g_free (qtdemux->redirect_location);
5929       qtdemux->redirect_location = g_strdup (url);
5930       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5931           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5932               gst_structure_new ("redirect",
5933                   "new-location", G_TYPE_STRING, url, NULL)));
5934     } else {
5935       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5936           "posting");
5937     }
5938     g_free (url);
5939   }
5940
5941   /* position reporting */
5942   if (qtdemux->segment.rate >= 0) {
5943     qtdemux->segment.position = position;
5944     gst_qtdemux_sync_streams (qtdemux);
5945   }
5946
5947   if (G_UNLIKELY (!stream->pad)) {
5948     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5949     gst_buffer_unref (buf);
5950     goto exit;
5951   }
5952
5953   /* send out pending buffers */
5954   while (stream->buffers) {
5955     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5956
5957     if (G_UNLIKELY (stream->discont)) {
5958       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5959       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5960       stream->discont = FALSE;
5961     } else {
5962       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5963     }
5964
5965     if (stream->alignment > 1)
5966       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5967     gst_pad_push (stream->pad, buffer);
5968
5969     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5970   }
5971
5972   /* we're going to modify the metadata */
5973   buf = gst_buffer_make_writable (buf);
5974
5975   if (G_UNLIKELY (stream->need_process))
5976     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5977
5978   if (!buf) {
5979     goto exit;
5980   }
5981
5982   GST_BUFFER_DTS (buf) = dts;
5983   GST_BUFFER_PTS (buf) = pts;
5984   GST_BUFFER_DURATION (buf) = duration;
5985   GST_BUFFER_OFFSET (buf) = -1;
5986   GST_BUFFER_OFFSET_END (buf) = -1;
5987
5988   if (!keyframe) {
5989     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5990     stream->on_keyframe = FALSE;
5991   } else {
5992     stream->on_keyframe = TRUE;
5993   }
5994
5995   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5996     gst_buffer_append_memory (buf,
5997         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5998
5999   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6000     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6001   }
6002 #if 0
6003   if (G_UNLIKELY (qtdemux->element_index)) {
6004     GstClockTime stream_time;
6005
6006     stream_time =
6007         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6008         timestamp);
6009     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6010       GST_LOG_OBJECT (qtdemux,
6011           "adding association %" GST_TIME_FORMAT "-> %"
6012           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6013       gst_index_add_association (qtdemux->element_index,
6014           qtdemux->index_id,
6015           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6016           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6017           GST_FORMAT_BYTES, byte_position, NULL);
6018     }
6019   }
6020 #endif
6021
6022   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6023
6024 exit:
6025   return ret;
6026 }
6027
6028 static const QtDemuxRandomAccessEntry *
6029 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6030     GstClockTime pos, gboolean after)
6031 {
6032   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6033   guint n_entries = stream->n_ra_entries;
6034   guint i;
6035
6036   /* we assume the table is sorted */
6037   for (i = 0; i < n_entries; ++i) {
6038     if (entries[i].ts > pos)
6039       break;
6040   }
6041
6042   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6043    * probably okay to assume that the index lists the very first fragment */
6044   if (i == 0)
6045     return &entries[0];
6046
6047   if (after)
6048     return &entries[i];
6049   else
6050     return &entries[i - 1];
6051 }
6052
6053 static gboolean
6054 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6055 {
6056   const QtDemuxRandomAccessEntry *best_entry = NULL;
6057   gint i;
6058
6059   GST_OBJECT_LOCK (qtdemux);
6060
6061   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6062
6063   /* first see if we can determine where to go to using mfra,
6064    * before we start clearing things */
6065   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6066     const QtDemuxRandomAccessEntry *entry;
6067     QtDemuxStream *stream;
6068     gboolean is_audio_or_video;
6069
6070     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6071
6072     if (stream->ra_entries == NULL)
6073       continue;
6074
6075     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6076       is_audio_or_video = TRUE;
6077     else
6078       is_audio_or_video = FALSE;
6079
6080     entry =
6081         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6082         stream->time_position, !is_audio_or_video);
6083
6084     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6085         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6086
6087     stream->pending_seek = entry;
6088
6089     /* decide position to jump to just based on audio/video tracks, not subs */
6090     if (!is_audio_or_video)
6091       continue;
6092
6093     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6094       best_entry = entry;
6095   }
6096
6097   /* no luck, will handle seek otherwise */
6098   if (best_entry == NULL) {
6099     GST_OBJECT_UNLOCK (qtdemux);
6100     return FALSE;
6101   }
6102
6103   /* ok, now we can prepare for processing as of located moof */
6104   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6105     QtDemuxStream *stream;
6106
6107     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6108
6109     g_free (stream->samples);
6110     stream->samples = NULL;
6111     stream->n_samples = 0;
6112     stream->stbl_index = -1;    /* no samples have yet been parsed */
6113     stream->sample_index = -1;
6114
6115     if (stream->protection_scheme_info) {
6116       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6117       if (stream->protection_scheme_type == FOURCC_cenc) {
6118         QtDemuxCencSampleSetInfo *info =
6119             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6120         if (info->crypto_info) {
6121           g_ptr_array_free (info->crypto_info, TRUE);
6122           info->crypto_info = NULL;
6123         }
6124       }
6125     }
6126   }
6127
6128   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6129       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6130       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6131       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6132
6133   qtdemux->moof_offset = best_entry->moof_offset;
6134
6135   qtdemux_add_fragmented_samples (qtdemux);
6136
6137   GST_OBJECT_UNLOCK (qtdemux);
6138   return TRUE;
6139 }
6140
6141 static GstFlowReturn
6142 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6143 {
6144   GstFlowReturn ret = GST_FLOW_OK;
6145   GstBuffer *buf = NULL;
6146   QtDemuxStream *stream, *target_stream = NULL;
6147   GstClockTime min_time;
6148   guint64 offset = 0;
6149   GstClockTime dts = GST_CLOCK_TIME_NONE;
6150   GstClockTime pts = GST_CLOCK_TIME_NONE;
6151   GstClockTime duration = 0;
6152   gboolean keyframe = FALSE;
6153   guint sample_size = 0;
6154   guint num_samples = 1;
6155   gboolean empty = 0;
6156   guint size;
6157   gint i;
6158
6159   if (qtdemux->fragmented_seek_pending) {
6160     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6161     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6162       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6163       qtdemux->fragmented_seek_pending = FALSE;
6164     } else {
6165       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6166     }
6167   }
6168
6169   /* Figure out the next stream sample to output, min_time is expressed in
6170    * global time and runs over the edit list segments. */
6171   min_time = G_MAXUINT64;
6172   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6173     GstClockTime position;
6174
6175     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6176     position = stream->time_position;
6177
6178     if (!GST_CLOCK_TIME_IS_VALID (position))
6179       continue;
6180
6181     if (stream->segment_index != -1) {
6182       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6183       position += segment->media_start;
6184     }
6185
6186     /* position of -1 is EOS */
6187     if (position < min_time) {
6188       min_time = position;
6189       target_stream = stream;
6190     }
6191   }
6192   /* all are EOS */
6193   if (G_UNLIKELY (target_stream == NULL)) {
6194     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6195     goto eos;
6196   }
6197
6198   /* check for segment end */
6199   if (G_UNLIKELY (qtdemux->segment.stop != -1
6200           && qtdemux->segment.rate >= 0
6201           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6202     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6203     target_stream->time_position = GST_CLOCK_TIME_NONE;
6204     goto eos_stream;
6205   }
6206
6207   /* gap events for subtitle streams */
6208   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6209     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6210     if (stream->pad) {
6211       GstClockTime gap_threshold;
6212
6213       /* Only send gap events on non-subtitle streams if lagging way behind. */
6214       if (stream->subtype == FOURCC_subp
6215           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)
6216         gap_threshold = 1 * GST_SECOND;
6217       else
6218         gap_threshold = 3 * GST_SECOND;
6219
6220       /* send gap events until the stream catches up */
6221       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6222       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6223           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6224           stream->segment.position + gap_threshold < min_time) {
6225         GstEvent *gap =
6226             gst_event_new_gap (stream->segment.position, gap_threshold);
6227         gst_pad_push_event (stream->pad, gap);
6228         stream->segment.position += gap_threshold;
6229       }
6230     }
6231   }
6232
6233   stream = target_stream;
6234   /* fetch info for the current sample of this stream */
6235   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6236               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6237     goto eos_stream;
6238
6239   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6240   if (stream->new_caps) {
6241     gst_qtdemux_configure_stream (qtdemux, stream);
6242     qtdemux_do_allocation (stream, qtdemux);
6243   }
6244
6245   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6246   if (G_UNLIKELY (qtdemux->segment.
6247           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6248     if (stream->subtype == FOURCC_vide) {
6249       if (!keyframe) {
6250         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6251             stream->track_id);
6252         goto next;
6253       } else if (qtdemux->trickmode_interval > 0) {
6254         GstClockTimeDiff interval;
6255
6256         if (qtdemux->segment.rate > 0)
6257           interval = stream->time_position - stream->last_keyframe_dts;
6258         else
6259           interval = stream->last_keyframe_dts - stream->time_position;
6260
6261         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6262             && interval < qtdemux->trickmode_interval) {
6263           GST_LOG_OBJECT (qtdemux,
6264               "Skipping keyframe within interval on track-id %u",
6265               stream->track_id);
6266           goto next;
6267         } else {
6268           stream->last_keyframe_dts = stream->time_position;
6269         }
6270       }
6271     }
6272   }
6273
6274   GST_DEBUG_OBJECT (qtdemux,
6275       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6276       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6277       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6278       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6279       GST_TIME_ARGS (duration));
6280
6281   if (G_UNLIKELY (empty)) {
6282     /* empty segment, push a gap if there's a second or more
6283      * difference and move to the next one */
6284     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6285       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6286     stream->segment.position = pts + duration;
6287     goto next;
6288   }
6289
6290   /* hmm, empty sample, skip and move to next sample */
6291   if (G_UNLIKELY (sample_size <= 0))
6292     goto next;
6293
6294   /* last pushed sample was out of boundary, goto next sample */
6295   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6296     goto next;
6297
6298   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6299     GST_DEBUG_OBJECT (qtdemux,
6300         "size %d larger than stream max_buffer_size %d, trimming",
6301         sample_size, stream->max_buffer_size);
6302     size =
6303         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6304   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6305       && sample_size < stream->min_buffer_size) {
6306     guint start_sample_index = stream->sample_index;
6307     guint accumulated_size = sample_size;
6308     guint64 expected_next_offset = offset + sample_size;
6309
6310     GST_DEBUG_OBJECT (qtdemux,
6311         "size %d smaller than stream min_buffer_size %d, combining with the next",
6312         sample_size, stream->min_buffer_size);
6313
6314     while (stream->sample_index < stream->to_sample
6315         && stream->sample_index + 1 < stream->n_samples) {
6316       const QtDemuxSample *next_sample;
6317
6318       /* Increment temporarily */
6319       stream->sample_index++;
6320
6321       /* Failed to parse sample so let's go back to the previous one that was
6322        * still successful */
6323       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6324         stream->sample_index--;
6325         break;
6326       }
6327
6328       next_sample = &stream->samples[stream->sample_index];
6329
6330       /* Not contiguous with the previous sample so let's go back to the
6331        * previous one that was still successful */
6332       if (next_sample->offset != expected_next_offset) {
6333         stream->sample_index--;
6334         break;
6335       }
6336
6337       accumulated_size += next_sample->size;
6338       expected_next_offset += next_sample->size;
6339       if (accumulated_size >= stream->min_buffer_size)
6340         break;
6341     }
6342
6343     num_samples = stream->sample_index + 1 - start_sample_index;
6344     stream->sample_index = start_sample_index;
6345     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6346         num_samples, accumulated_size);
6347     size = accumulated_size;
6348   } else {
6349     size = sample_size;
6350   }
6351
6352   if (qtdemux->cenc_aux_info_offset > 0) {
6353     GstMapInfo map;
6354     GstByteReader br;
6355     GstBuffer *aux_info = NULL;
6356
6357     /* pull the data stored before the sample */
6358     ret =
6359         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6360         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6361     if (G_UNLIKELY (ret != GST_FLOW_OK))
6362       goto beach;
6363     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6364     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6365     gst_byte_reader_init (&br, map.data + 8, map.size);
6366     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6367             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6368       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6369       gst_buffer_unmap (aux_info, &map);
6370       gst_buffer_unref (aux_info);
6371       ret = GST_FLOW_ERROR;
6372       goto beach;
6373     }
6374     gst_buffer_unmap (aux_info, &map);
6375     gst_buffer_unref (aux_info);
6376   }
6377
6378   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6379       offset);
6380
6381   if (stream->use_allocator) {
6382     /* if we have a per-stream allocator, use it */
6383     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6384   }
6385
6386   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6387       size, &buf);
6388   if (G_UNLIKELY (ret != GST_FLOW_OK))
6389     goto beach;
6390
6391   /* Update for both splitting and combining of samples */
6392   if (size != sample_size) {
6393     pts += gst_util_uint64_scale_int (GST_SECOND,
6394         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6395         stream->timescale);
6396     dts +=
6397         gst_util_uint64_scale_int (GST_SECOND,
6398         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6399         stream->timescale);
6400     duration =
6401         gst_util_uint64_scale_int (GST_SECOND,
6402         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6403   }
6404
6405   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6406       dts, pts, duration, keyframe, min_time, offset);
6407
6408   if (size < sample_size) {
6409     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6410     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6411
6412     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6413         sample->timestamp +
6414         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6415     if (time_position >= segment->media_start) {
6416       /* inside the segment, update time_position, looks very familiar to
6417        * GStreamer segments, doesn't it? */
6418       stream->time_position = (time_position - segment->media_start) +
6419           segment->time;
6420     } else {
6421       /* not yet in segment, time does not yet increment. This means
6422        * that we are still prerolling keyframes to the decoder so it can
6423        * decode the first sample of the segment. */
6424       stream->time_position = segment->time;
6425     }
6426   } else if (size > sample_size) {
6427     /* Increase to the last sample we already pulled so that advancing
6428      * below brings us to the next sample we need to pull */
6429     stream->sample_index += num_samples - 1;
6430   }
6431
6432   /* combine flows */
6433   GST_OBJECT_LOCK (qtdemux);
6434   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6435   GST_OBJECT_UNLOCK (qtdemux);
6436   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6437    * we have no more data for the pad to push */
6438   if (ret == GST_FLOW_EOS)
6439     ret = GST_FLOW_OK;
6440
6441   stream->offset_in_sample += size;
6442   if (stream->offset_in_sample >= sample_size) {
6443     gst_qtdemux_advance_sample (qtdemux, stream);
6444   }
6445   goto beach;
6446
6447 next:
6448   gst_qtdemux_advance_sample (qtdemux, stream);
6449
6450 beach:
6451   return ret;
6452
6453   /* special cases */
6454 eos:
6455   {
6456     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6457     ret = GST_FLOW_EOS;
6458     goto beach;
6459   }
6460 eos_stream:
6461   {
6462     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6463     /* EOS will be raised if all are EOS */
6464     ret = GST_FLOW_OK;
6465     goto beach;
6466   }
6467 }
6468
6469 static void
6470 gst_qtdemux_loop (GstPad * pad)
6471 {
6472   GstQTDemux *qtdemux;
6473   guint64 cur_offset;
6474   GstFlowReturn ret;
6475
6476   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6477
6478   cur_offset = qtdemux->offset;
6479   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6480       cur_offset, qt_demux_state_string (qtdemux->state));
6481
6482   switch (qtdemux->state) {
6483     case QTDEMUX_STATE_INITIAL:
6484     case QTDEMUX_STATE_HEADER:
6485       ret = gst_qtdemux_loop_state_header (qtdemux);
6486       break;
6487     case QTDEMUX_STATE_MOVIE:
6488       ret = gst_qtdemux_loop_state_movie (qtdemux);
6489       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6490         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6491       }
6492       break;
6493     default:
6494       /* ouch */
6495       goto invalid_state;
6496   }
6497
6498   /* if something went wrong, pause */
6499   if (ret != GST_FLOW_OK)
6500     goto pause;
6501
6502 done:
6503   gst_object_unref (qtdemux);
6504   return;
6505
6506   /* ERRORS */
6507 invalid_state:
6508   {
6509     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6510         (NULL), ("streaming stopped, invalid state"));
6511     gst_pad_pause_task (pad);
6512     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6513     goto done;
6514   }
6515 pause:
6516   {
6517     const gchar *reason = gst_flow_get_name (ret);
6518
6519     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6520
6521     gst_pad_pause_task (pad);
6522
6523     /* fatal errors need special actions */
6524     /* check EOS */
6525     if (ret == GST_FLOW_EOS) {
6526       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6527         /* we have no streams, post an error */
6528         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6529       }
6530       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6531         gint64 stop;
6532
6533         if ((stop = qtdemux->segment.stop) == -1)
6534           stop = qtdemux->segment.duration;
6535
6536         if (qtdemux->segment.rate >= 0) {
6537           GstMessage *message;
6538           GstEvent *event;
6539
6540           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6541           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6542               GST_FORMAT_TIME, stop);
6543           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6544           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6545             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6546             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6547           }
6548           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6549           gst_qtdemux_push_event (qtdemux, event);
6550         } else {
6551           GstMessage *message;
6552           GstEvent *event;
6553
6554           /*  For Reverse Playback */
6555           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6556           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6557               GST_FORMAT_TIME, qtdemux->segment.start);
6558           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6559               qtdemux->segment.start);
6560           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6561             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6562             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6563           }
6564           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6565           gst_qtdemux_push_event (qtdemux, event);
6566         }
6567       } else {
6568         GstEvent *event;
6569
6570         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6571         event = gst_event_new_eos ();
6572         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6573           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6574         gst_qtdemux_push_event (qtdemux, event);
6575       }
6576     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6577       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6578       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6579     }
6580     goto done;
6581   }
6582 }
6583
6584 /*
6585  * has_next_entry
6586  *
6587  * Returns if there are samples to be played.
6588  */
6589 static gboolean
6590 has_next_entry (GstQTDemux * demux)
6591 {
6592   QtDemuxStream *stream;
6593   gint i;
6594
6595   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6596
6597   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6598     stream = QTDEMUX_NTH_STREAM (demux, i);
6599
6600     if (stream->sample_index == -1) {
6601       stream->sample_index = 0;
6602       stream->offset_in_sample = 0;
6603     }
6604
6605     if (stream->sample_index >= stream->n_samples) {
6606       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6607       continue;
6608     }
6609     GST_DEBUG_OBJECT (demux, "Found a sample");
6610     return TRUE;
6611   }
6612
6613   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6614   return FALSE;
6615 }
6616
6617 /*
6618  * next_entry_size
6619  *
6620  * Returns the size of the first entry at the current offset.
6621  * If -1, there are none (which means EOS or empty file).
6622  */
6623 static guint64
6624 next_entry_size (GstQTDemux * demux)
6625 {
6626   QtDemuxStream *stream, *target_stream = NULL;
6627   guint64 smalloffs = (guint64) - 1;
6628   QtDemuxSample *sample;
6629   gint i;
6630
6631   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6632       demux->offset);
6633
6634   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6635     stream = QTDEMUX_NTH_STREAM (demux, i);
6636
6637     if (stream->sample_index == -1) {
6638       stream->sample_index = 0;
6639       stream->offset_in_sample = 0;
6640     }
6641
6642     if (stream->sample_index >= stream->n_samples) {
6643       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6644       continue;
6645     }
6646
6647     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6648       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6649           stream->sample_index);
6650       return -1;
6651     }
6652
6653     sample = &stream->samples[stream->sample_index];
6654
6655     GST_LOG_OBJECT (demux,
6656         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6657         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6658         stream->sample_index, sample->offset, sample->size);
6659
6660     if (((smalloffs == -1)
6661             || (sample->offset < smalloffs)) && (sample->size)) {
6662       smalloffs = sample->offset;
6663       target_stream = stream;
6664     }
6665   }
6666
6667   if (!target_stream)
6668     return -1;
6669
6670   GST_LOG_OBJECT (demux,
6671       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6672       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6673
6674   stream = target_stream;
6675   sample = &stream->samples[stream->sample_index];
6676
6677   if (sample->offset >= demux->offset) {
6678     demux->todrop = sample->offset - demux->offset;
6679     return sample->size + demux->todrop;
6680   }
6681
6682   GST_DEBUG_OBJECT (demux,
6683       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6684   return -1;
6685 }
6686
6687 static void
6688 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6689 {
6690   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6691
6692   gst_element_post_message (GST_ELEMENT_CAST (demux),
6693       gst_message_new_element (GST_OBJECT_CAST (demux),
6694           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6695 }
6696
6697 static gboolean
6698 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6699 {
6700   GstEvent *event;
6701   gboolean res = 0;
6702
6703   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6704
6705   event =
6706       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6707       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6708       GST_SEEK_TYPE_NONE, -1);
6709
6710   /* store seqnum to drop flush events, they don't need to reach downstream */
6711   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6712   res = gst_pad_push_event (demux->sinkpad, event);
6713   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6714
6715   return res;
6716 }
6717
6718 /* check for seekable upstream, above and beyond a mere query */
6719 static void
6720 gst_qtdemux_check_seekability (GstQTDemux * demux)
6721 {
6722   GstQuery *query;
6723   gboolean seekable = FALSE;
6724   gint64 start = -1, stop = -1;
6725
6726   if (demux->upstream_size)
6727     return;
6728
6729   if (demux->upstream_format_is_time)
6730     return;
6731
6732   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6733   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6734     GST_DEBUG_OBJECT (demux, "seeking query failed");
6735     goto done;
6736   }
6737
6738   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6739
6740   /* try harder to query upstream size if we didn't get it the first time */
6741   if (seekable && stop == -1) {
6742     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6743     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6744   }
6745
6746   /* if upstream doesn't know the size, it's likely that it's not seekable in
6747    * practice even if it technically may be seekable */
6748   if (seekable && (start != 0 || stop <= start)) {
6749     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6750     seekable = FALSE;
6751   }
6752
6753 done:
6754   gst_query_unref (query);
6755
6756   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6757       G_GUINT64_FORMAT ")", seekable, start, stop);
6758   demux->upstream_seekable = seekable;
6759   demux->upstream_size = seekable ? stop : -1;
6760 }
6761
6762 static void
6763 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6764 {
6765   g_return_if_fail (bytes <= demux->todrop);
6766
6767   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6768   gst_adapter_flush (demux->adapter, bytes);
6769   demux->neededbytes -= bytes;
6770   demux->offset += bytes;
6771   demux->todrop -= bytes;
6772 }
6773
6774 /* PUSH-MODE only: Send a segment, if not done already. */
6775 static void
6776 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6777 {
6778   if (G_UNLIKELY (demux->need_segment)) {
6779     gint i;
6780
6781     if (!demux->upstream_format_is_time) {
6782       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6783     } else {
6784       GstEvent *segment_event;
6785       segment_event = gst_event_new_segment (&demux->segment);
6786       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6787         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6788       gst_qtdemux_push_event (demux, segment_event);
6789     }
6790
6791     demux->need_segment = FALSE;
6792
6793     /* clear to send tags on all streams */
6794     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6795       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6796       gst_qtdemux_push_tags (demux, stream);
6797       if (CUR_STREAM (stream)->sparse) {
6798         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6799         gst_pad_push_event (stream->pad,
6800             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6801       }
6802     }
6803   }
6804 }
6805
6806 /* Used for push mode only. */
6807 static void
6808 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6809     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6810 {
6811   GstClockTime ts, dur;
6812
6813   ts = pos;
6814   dur =
6815       stream->segments[segment_index].duration - (pos -
6816       stream->segments[segment_index].time);
6817   stream->time_position += dur;
6818
6819   /* Only gaps with a duration of at least one second are propagated.
6820    * Same workaround as in pull mode.
6821    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6822   if (dur >= GST_SECOND) {
6823     GstEvent *gap;
6824     gap = gst_event_new_gap (ts, dur);
6825
6826     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6827         "segment: %" GST_PTR_FORMAT, gap);
6828     gst_pad_push_event (stream->pad, gap);
6829   }
6830 }
6831
6832 static GstFlowReturn
6833 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6834 {
6835   GstQTDemux *demux;
6836
6837   demux = GST_QTDEMUX (parent);
6838
6839   GST_DEBUG_OBJECT (demux,
6840       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6841       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6842       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6843       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6844       gst_buffer_get_size (inbuf), demux->offset);
6845
6846   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6847     gboolean is_gap_input = FALSE;
6848     gint i;
6849
6850     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6851
6852     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6853       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6854     }
6855
6856     /* Check if we can land back on our feet in the case where upstream is
6857      * handling the seeking/pushing of samples with gaps in between (like
6858      * in the case of trick-mode DASH for example) */
6859     if (demux->upstream_format_is_time
6860         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6861       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6862         guint32 res;
6863         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6864         GST_LOG_OBJECT (demux,
6865             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6866             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6867         res =
6868             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6869             stream, GST_BUFFER_OFFSET (inbuf));
6870         if (res != -1) {
6871           QtDemuxSample *sample = &stream->samples[res];
6872           GST_LOG_OBJECT (demux,
6873               "Checking if sample %d from track-id %u is valid (offset:%"
6874               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6875               stream->track_id, sample->offset, sample->size);
6876           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6877             GST_LOG_OBJECT (demux,
6878                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6879                 res);
6880             is_gap_input = TRUE;
6881             /* We can go back to standard playback mode */
6882             demux->state = QTDEMUX_STATE_MOVIE;
6883             /* Remember which sample this stream is at */
6884             stream->sample_index = res;
6885             /* Finally update all push-based values to the expected values */
6886             demux->neededbytes = stream->samples[res].size;
6887             demux->offset = GST_BUFFER_OFFSET (inbuf);
6888             demux->mdatleft =
6889                 demux->mdatsize - demux->offset + demux->mdatoffset;
6890             demux->todrop = 0;
6891           }
6892         }
6893       }
6894       if (!is_gap_input) {
6895         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6896         /* Reset state if it's a real discont */
6897         demux->neededbytes = 16;
6898         demux->state = QTDEMUX_STATE_INITIAL;
6899         demux->offset = GST_BUFFER_OFFSET (inbuf);
6900         gst_adapter_clear (demux->adapter);
6901       }
6902     }
6903     /* Reverse fragmented playback, need to flush all we have before
6904      * consuming a new fragment.
6905      * The samples array have the timestamps calculated by accumulating the
6906      * durations but this won't work for reverse playback of fragments as
6907      * the timestamps of a subsequent fragment should be smaller than the
6908      * previously received one. */
6909     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6910       gst_qtdemux_process_adapter (demux, TRUE);
6911       g_ptr_array_foreach (demux->active_streams,
6912           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6913     }
6914   }
6915
6916   gst_adapter_push (demux->adapter, inbuf);
6917
6918   GST_DEBUG_OBJECT (demux,
6919       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6920       demux->neededbytes, gst_adapter_available (demux->adapter));
6921
6922   return gst_qtdemux_process_adapter (demux, FALSE);
6923 }
6924
6925 static GstFlowReturn
6926 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6927 {
6928   GstFlowReturn ret = GST_FLOW_OK;
6929
6930   /* we never really mean to buffer that much */
6931   if (demux->neededbytes == -1) {
6932     goto eos;
6933   }
6934
6935   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6936       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6937
6938 #ifndef GST_DISABLE_GST_DEBUG
6939     {
6940       guint64 discont_offset, distance_from_discont;
6941
6942       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6943       distance_from_discont =
6944           gst_adapter_distance_from_discont (demux->adapter);
6945
6946       GST_DEBUG_OBJECT (demux,
6947           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6948           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6949           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6950           demux->offset, discont_offset, distance_from_discont);
6951     }
6952 #endif
6953
6954     switch (demux->state) {
6955       case QTDEMUX_STATE_INITIAL:{
6956         const guint8 *data;
6957         guint32 fourcc;
6958         guint64 size;
6959
6960         gst_qtdemux_check_seekability (demux);
6961
6962         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6963
6964         /* get fourcc/length, set neededbytes */
6965         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6966             &size, &fourcc);
6967         gst_adapter_unmap (demux->adapter);
6968         data = NULL;
6969         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6970             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6971         if (size == 0) {
6972           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6973               (_("This file is invalid and cannot be played.")),
6974               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6975                   GST_FOURCC_ARGS (fourcc)));
6976           ret = GST_FLOW_ERROR;
6977           break;
6978         }
6979         if (fourcc == FOURCC_mdat) {
6980           gint next_entry = next_entry_size (demux);
6981           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
6982                   || !demux->fragmented)) {
6983             /* we have the headers, start playback */
6984             demux->state = QTDEMUX_STATE_MOVIE;
6985             demux->neededbytes = next_entry;
6986             demux->mdatleft = size;
6987             demux->mdatsize = demux->mdatleft;
6988           } else {
6989             /* no headers yet, try to get them */
6990             guint bs;
6991             gboolean res;
6992             guint64 old, target;
6993
6994           buffer_data:
6995             old = demux->offset;
6996             target = old + size;
6997
6998             /* try to jump over the atom with a seek */
6999             /* only bother if it seems worth doing so,
7000              * and avoids possible upstream/server problems */
7001             if (demux->upstream_seekable &&
7002                 demux->upstream_size > 4 * (1 << 20)) {
7003               res = qtdemux_seek_offset (demux, target);
7004             } else {
7005               GST_DEBUG_OBJECT (demux, "skipping seek");
7006               res = FALSE;
7007             }
7008
7009             if (res) {
7010               GST_DEBUG_OBJECT (demux, "seek success");
7011               /* remember the offset fo the first mdat so we can seek back to it
7012                * after we have the headers */
7013               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7014                 demux->first_mdat = old;
7015                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7016                     demux->first_mdat);
7017               }
7018               /* seek worked, continue reading */
7019               demux->offset = target;
7020               demux->neededbytes = 16;
7021               demux->state = QTDEMUX_STATE_INITIAL;
7022             } else {
7023               /* seek failed, need to buffer */
7024               demux->offset = old;
7025               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7026               /* there may be multiple mdat (or alike) buffers */
7027               /* sanity check */
7028               if (demux->mdatbuffer)
7029                 bs = gst_buffer_get_size (demux->mdatbuffer);
7030               else
7031                 bs = 0;
7032               if (size + bs > 10 * (1 << 20))
7033                 goto no_moov;
7034               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7035               demux->neededbytes = size;
7036               if (!demux->mdatbuffer)
7037                 demux->mdatoffset = demux->offset;
7038             }
7039           }
7040         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7041           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7042               (_("This file is invalid and cannot be played.")),
7043               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7044                   GST_FOURCC_ARGS (fourcc), size));
7045           ret = GST_FLOW_ERROR;
7046           break;
7047         } else {
7048           /* this means we already started buffering and still no moov header,
7049            * let's continue buffering everything till we get moov */
7050           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7051                   || fourcc == FOURCC_moof))
7052             goto buffer_data;
7053           demux->neededbytes = size;
7054           demux->state = QTDEMUX_STATE_HEADER;
7055         }
7056         break;
7057       }
7058       case QTDEMUX_STATE_HEADER:{
7059         const guint8 *data;
7060         guint32 fourcc;
7061
7062         GST_DEBUG_OBJECT (demux, "In header");
7063
7064         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7065
7066         /* parse the header */
7067         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7068             &fourcc);
7069         if (fourcc == FOURCC_moov) {
7070           /* in usual fragmented setup we could try to scan for more
7071            * and end up at the the moov (after mdat) again */
7072           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7073               (!demux->fragmented
7074                   || demux->last_moov_offset == demux->offset)) {
7075             GST_DEBUG_OBJECT (demux,
7076                 "Skipping moov atom as we have (this) one already");
7077           } else {
7078             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7079
7080             if (demux->got_moov && demux->fragmented) {
7081               GST_DEBUG_OBJECT (demux,
7082                   "Got a second moov, clean up data from old one");
7083               if (demux->moov_node_compressed) {
7084                 g_node_destroy (demux->moov_node_compressed);
7085                 if (demux->moov_node)
7086                   g_free (demux->moov_node->data);
7087               }
7088               demux->moov_node_compressed = NULL;
7089               if (demux->moov_node)
7090                 g_node_destroy (demux->moov_node);
7091               demux->moov_node = NULL;
7092             }
7093
7094             demux->last_moov_offset = demux->offset;
7095
7096             /* Update streams with new moov */
7097             gst_qtdemux_stream_concat (demux,
7098                 demux->old_streams, demux->active_streams);
7099
7100             qtdemux_parse_moov (demux, data, demux->neededbytes);
7101             qtdemux_node_dump (demux, demux->moov_node);
7102             qtdemux_parse_tree (demux);
7103             qtdemux_prepare_streams (demux);
7104             QTDEMUX_EXPOSE_LOCK (demux);
7105             qtdemux_expose_streams (demux);
7106             QTDEMUX_EXPOSE_UNLOCK (demux);
7107
7108             demux->got_moov = TRUE;
7109
7110             gst_qtdemux_check_send_pending_segment (demux);
7111
7112             if (demux->moov_node_compressed) {
7113               g_node_destroy (demux->moov_node_compressed);
7114               g_free (demux->moov_node->data);
7115             }
7116             demux->moov_node_compressed = NULL;
7117             g_node_destroy (demux->moov_node);
7118             demux->moov_node = NULL;
7119             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7120           }
7121         } else if (fourcc == FOURCC_moof) {
7122           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7123             guint64 dist = 0;
7124             GstClockTime prev_pts;
7125             guint64 prev_offset;
7126             guint64 adapter_discont_offset, adapter_discont_dist;
7127
7128             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7129
7130             /*
7131              * The timestamp of the moof buffer is relevant as some scenarios
7132              * won't have the initial timestamp in the atoms. Whenever a new
7133              * buffer has started, we get that buffer's PTS and use it as a base
7134              * timestamp for the trun entries.
7135              *
7136              * To keep track of the current buffer timestamp and starting point
7137              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7138              * from the beginning of the buffer, with the distance and demux->offset
7139              * we know if it is still the same buffer or not.
7140              */
7141             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7142             prev_offset = demux->offset - dist;
7143             if (demux->fragment_start_offset == -1
7144                 || prev_offset > demux->fragment_start_offset) {
7145               demux->fragment_start_offset = prev_offset;
7146               demux->fragment_start = prev_pts;
7147               GST_DEBUG_OBJECT (demux,
7148                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7149                   GST_TIME_FORMAT, demux->fragment_start_offset,
7150                   GST_TIME_ARGS (demux->fragment_start));
7151             }
7152
7153             /* We can't use prev_offset() here because this would require
7154              * upstream to set consistent and correct offsets on all buffers
7155              * since the discont. Nothing ever did that in the past and we
7156              * would break backwards compatibility here then.
7157              * Instead take the offset we had at the last discont and count
7158              * the bytes from there. This works with old code as there would
7159              * be no discont between moov and moof, and also works with
7160              * adaptivedemux which correctly sets offset and will set the
7161              * DISCONT flag accordingly when needed.
7162              *
7163              * We also only do this for upstream TIME segments as otherwise
7164              * there are potential backwards compatibility problems with
7165              * seeking in PUSH mode and upstream providing inconsistent
7166              * timestamps. */
7167             adapter_discont_offset =
7168                 gst_adapter_offset_at_discont (demux->adapter);
7169             adapter_discont_dist =
7170                 gst_adapter_distance_from_discont (demux->adapter);
7171
7172             GST_DEBUG_OBJECT (demux,
7173                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7174                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7175                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7176
7177             if (demux->upstream_format_is_time) {
7178               demux->moof_offset = adapter_discont_offset;
7179               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7180                 demux->moof_offset += adapter_discont_dist;
7181               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7182                 demux->moof_offset = demux->offset;
7183             } else {
7184               demux->moof_offset = demux->offset;
7185             }
7186
7187             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7188                     demux->moof_offset, NULL)) {
7189               gst_adapter_unmap (demux->adapter);
7190               ret = GST_FLOW_ERROR;
7191               goto done;
7192             }
7193
7194             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7195             if (demux->mss_mode && !demux->exposed) {
7196               QTDEMUX_EXPOSE_LOCK (demux);
7197               qtdemux_expose_streams (demux);
7198               QTDEMUX_EXPOSE_UNLOCK (demux);
7199             }
7200
7201             gst_qtdemux_check_send_pending_segment (demux);
7202           } else {
7203             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7204           }
7205         } else if (fourcc == FOURCC_ftyp) {
7206           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7207           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7208         } else if (fourcc == FOURCC_uuid) {
7209           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7210           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7211         } else if (fourcc == FOURCC_sidx) {
7212           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7213           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7214         } else {
7215           switch (fourcc) {
7216             case FOURCC_styp:
7217               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7218                * FALLTHROUGH */
7219             case FOURCC_skip:
7220             case FOURCC_free:
7221               /* [free] and [skip] are padding atoms */
7222               GST_DEBUG_OBJECT (demux,
7223                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7224                   GST_FOURCC_ARGS (fourcc));
7225               break;
7226             default:
7227               GST_WARNING_OBJECT (demux,
7228                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7229                   GST_FOURCC_ARGS (fourcc));
7230               /* Let's jump that one and go back to initial state */
7231               break;
7232           }
7233         }
7234         gst_adapter_unmap (demux->adapter);
7235         data = NULL;
7236
7237         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7238           gsize remaining_data_size = 0;
7239
7240           /* the mdat was before the header */
7241           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7242               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7243           /* restore our adapter/offset view of things with upstream;
7244            * put preceding buffered data ahead of current moov data.
7245            * This should also handle evil mdat, moov, mdat cases and alike */
7246           gst_adapter_flush (demux->adapter, demux->neededbytes);
7247
7248           /* Store any remaining data after the mdat for later usage */
7249           remaining_data_size = gst_adapter_available (demux->adapter);
7250           if (remaining_data_size > 0) {
7251             g_assert (demux->restoredata_buffer == NULL);
7252             demux->restoredata_buffer =
7253                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7254             demux->restoredata_offset = demux->offset + demux->neededbytes;
7255             GST_DEBUG_OBJECT (demux,
7256                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7257                 G_GUINT64_FORMAT, remaining_data_size,
7258                 demux->restoredata_offset);
7259           }
7260
7261           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7262           demux->mdatbuffer = NULL;
7263           demux->offset = demux->mdatoffset;
7264           demux->neededbytes = next_entry_size (demux);
7265           demux->state = QTDEMUX_STATE_MOVIE;
7266           demux->mdatleft = gst_adapter_available (demux->adapter);
7267           demux->mdatsize = demux->mdatleft;
7268         } else {
7269           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7270           gst_adapter_flush (demux->adapter, demux->neededbytes);
7271
7272           /* only go back to the mdat if there are samples to play */
7273           if (demux->got_moov && demux->first_mdat != -1
7274               && has_next_entry (demux)) {
7275             gboolean res;
7276
7277             /* we need to seek back */
7278             res = qtdemux_seek_offset (demux, demux->first_mdat);
7279             if (res) {
7280               demux->offset = demux->first_mdat;
7281             } else {
7282               GST_DEBUG_OBJECT (demux, "Seek back failed");
7283             }
7284           } else {
7285             demux->offset += demux->neededbytes;
7286           }
7287           demux->neededbytes = 16;
7288           demux->state = QTDEMUX_STATE_INITIAL;
7289         }
7290
7291         break;
7292       }
7293       case QTDEMUX_STATE_BUFFER_MDAT:{
7294         GstBuffer *buf;
7295         guint8 fourcc[4];
7296
7297         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7298             demux->offset);
7299         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7300         gst_buffer_extract (buf, 0, fourcc, 4);
7301         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7302             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7303         if (demux->mdatbuffer)
7304           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7305         else
7306           demux->mdatbuffer = buf;
7307         demux->offset += demux->neededbytes;
7308         demux->neededbytes = 16;
7309         demux->state = QTDEMUX_STATE_INITIAL;
7310         gst_qtdemux_post_progress (demux, 1, 1);
7311
7312         break;
7313       }
7314       case QTDEMUX_STATE_MOVIE:{
7315         QtDemuxStream *stream = NULL;
7316         QtDemuxSample *sample;
7317         GstClockTime dts, pts, duration;
7318         gboolean keyframe;
7319         gint i;
7320
7321         GST_DEBUG_OBJECT (demux,
7322             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7323
7324         if (demux->fragmented) {
7325           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7326               demux->mdatleft);
7327           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7328             /* if needed data starts within this atom,
7329              * then it should not exceed this atom */
7330             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7331               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7332                   (_("This file is invalid and cannot be played.")),
7333                   ("sample data crosses atom boundary"));
7334               ret = GST_FLOW_ERROR;
7335               break;
7336             }
7337             demux->mdatleft -= demux->neededbytes;
7338           } else {
7339             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7340             /* so we are dropping more than left in this atom */
7341             gst_qtdemux_drop_data (demux, demux->mdatleft);
7342             demux->mdatleft = 0;
7343
7344             /* need to resume atom parsing so we do not miss any other pieces */
7345             demux->state = QTDEMUX_STATE_INITIAL;
7346             demux->neededbytes = 16;
7347
7348             /* check if there was any stored post mdat data from previous buffers */
7349             if (demux->restoredata_buffer) {
7350               g_assert (gst_adapter_available (demux->adapter) == 0);
7351
7352               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7353               demux->restoredata_buffer = NULL;
7354               demux->offset = demux->restoredata_offset;
7355             }
7356
7357             break;
7358           }
7359         }
7360
7361         if (demux->todrop) {
7362           if (demux->cenc_aux_info_offset > 0) {
7363             GstByteReader br;
7364             const guint8 *data;
7365
7366             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7367             data = gst_adapter_map (demux->adapter, demux->todrop);
7368             gst_byte_reader_init (&br, data + 8, demux->todrop);
7369             if (!qtdemux_parse_cenc_aux_info (demux,
7370                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7371                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7372               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7373               ret = GST_FLOW_ERROR;
7374               gst_adapter_unmap (demux->adapter);
7375               g_free (demux->cenc_aux_info_sizes);
7376               demux->cenc_aux_info_sizes = NULL;
7377               goto done;
7378             }
7379             demux->cenc_aux_info_offset = 0;
7380             g_free (demux->cenc_aux_info_sizes);
7381             demux->cenc_aux_info_sizes = NULL;
7382             gst_adapter_unmap (demux->adapter);
7383           }
7384           gst_qtdemux_drop_data (demux, demux->todrop);
7385         }
7386
7387         /* first buffer? */
7388         /* initial newsegment sent here after having added pads,
7389          * possible others in sink_event */
7390         gst_qtdemux_check_send_pending_segment (demux);
7391
7392         /* Figure out which stream this packet belongs to */
7393         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7394           stream = QTDEMUX_NTH_STREAM (demux, i);
7395           if (stream->sample_index >= stream->n_samples) {
7396             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7397             stream = NULL;
7398             continue;
7399           }
7400           GST_LOG_OBJECT (demux,
7401               "Checking track-id %u (sample_index:%d / offset:%"
7402               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7403               stream->sample_index,
7404               stream->samples[stream->sample_index].offset,
7405               stream->samples[stream->sample_index].size);
7406
7407           if (stream->samples[stream->sample_index].offset == demux->offset)
7408             break;
7409         }
7410
7411         if (G_UNLIKELY (stream == NULL))
7412           goto unknown_stream;
7413
7414         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7415
7416         if (stream->new_caps) {
7417           gst_qtdemux_configure_stream (demux, stream);
7418         }
7419
7420         /* Put data in a buffer, set timestamps, caps, ... */
7421         sample = &stream->samples[stream->sample_index];
7422
7423         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7424           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7425               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7426
7427           dts = QTSAMPLE_DTS (stream, sample);
7428           pts = QTSAMPLE_PTS (stream, sample);
7429           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7430           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7431
7432           /* check for segment end */
7433           if (G_UNLIKELY (demux->segment.stop != -1
7434                   && demux->segment.stop <= pts && stream->on_keyframe)
7435               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7436             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7437             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7438
7439             /* skip this data, stream is EOS */
7440             gst_adapter_flush (demux->adapter, demux->neededbytes);
7441             demux->offset += demux->neededbytes;
7442
7443             /* check if all streams are eos */
7444             ret = GST_FLOW_EOS;
7445             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7446               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7447                 ret = GST_FLOW_OK;
7448                 break;
7449               }
7450             }
7451           } else {
7452             GstBuffer *outbuf;
7453
7454             outbuf =
7455                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7456
7457             /* FIXME: should either be an assert or a plain check */
7458             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7459
7460             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7461                 dts, pts, duration, keyframe, dts, demux->offset);
7462           }
7463
7464           /* combine flows */
7465           GST_OBJECT_LOCK (demux);
7466           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7467           GST_OBJECT_UNLOCK (demux);
7468         } else {
7469           /* skip this data, stream is EOS */
7470           gst_adapter_flush (demux->adapter, demux->neededbytes);
7471         }
7472
7473         stream->sample_index++;
7474         stream->offset_in_sample = 0;
7475
7476         /* update current offset and figure out size of next buffer */
7477         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7478             demux->offset, demux->neededbytes);
7479         demux->offset += demux->neededbytes;
7480         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7481             demux->offset);
7482
7483
7484         if (ret == GST_FLOW_EOS) {
7485           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7486           demux->neededbytes = -1;
7487           goto eos;
7488         }
7489
7490         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7491           if (demux->fragmented) {
7492             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7493             /* there may be more to follow, only finish this atom */
7494             demux->todrop = demux->mdatleft;
7495             demux->neededbytes = demux->todrop;
7496             break;
7497           }
7498           goto eos;
7499         }
7500         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7501           goto non_ok_unlinked_flow;
7502         }
7503         break;
7504       }
7505       default:
7506         goto invalid_state;
7507     }
7508   }
7509
7510   /* when buffering movie data, at least show user something is happening */
7511   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7512       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7513     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7514         demux->neededbytes);
7515   }
7516 done:
7517
7518   return ret;
7519
7520   /* ERRORS */
7521 non_ok_unlinked_flow:
7522   {
7523     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7524         gst_flow_get_name (ret));
7525     return ret;
7526   }
7527 unknown_stream:
7528   {
7529     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7530     ret = GST_FLOW_ERROR;
7531     goto done;
7532   }
7533 eos:
7534   {
7535     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7536     ret = GST_FLOW_EOS;
7537     goto done;
7538   }
7539 invalid_state:
7540   {
7541     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7542         (NULL), ("qtdemuxer invalid state %d", demux->state));
7543     ret = GST_FLOW_ERROR;
7544     goto done;
7545   }
7546 no_moov:
7547   {
7548     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7549         (NULL), ("no 'moov' atom within the first 10 MB"));
7550     ret = GST_FLOW_ERROR;
7551     goto done;
7552   }
7553 }
7554
7555 static gboolean
7556 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7557 {
7558   GstQuery *query;
7559   gboolean pull_mode;
7560
7561   query = gst_query_new_scheduling ();
7562
7563   if (!gst_pad_peer_query (sinkpad, query)) {
7564     gst_query_unref (query);
7565     goto activate_push;
7566   }
7567
7568   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7569       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7570   gst_query_unref (query);
7571
7572   if (!pull_mode)
7573     goto activate_push;
7574
7575   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7576   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7577
7578 activate_push:
7579   {
7580     GST_DEBUG_OBJECT (sinkpad, "activating push");
7581     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7582   }
7583 }
7584
7585 static gboolean
7586 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7587     GstPadMode mode, gboolean active)
7588 {
7589   gboolean res;
7590   GstQTDemux *demux = GST_QTDEMUX (parent);
7591
7592   switch (mode) {
7593     case GST_PAD_MODE_PUSH:
7594       demux->pullbased = FALSE;
7595       res = TRUE;
7596       break;
7597     case GST_PAD_MODE_PULL:
7598       if (active) {
7599         demux->pullbased = TRUE;
7600         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7601             sinkpad, NULL);
7602       } else {
7603         res = gst_pad_stop_task (sinkpad);
7604       }
7605       break;
7606     default:
7607       res = FALSE;
7608       break;
7609   }
7610   return res;
7611 }
7612
7613 #ifdef HAVE_ZLIB
7614 static void *
7615 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7616 {
7617   guint8 *buffer;
7618   z_stream z;
7619   int ret;
7620
7621   memset (&z, 0, sizeof (z));
7622   z.zalloc = NULL;
7623   z.zfree = NULL;
7624   z.opaque = NULL;
7625
7626   if ((ret = inflateInit (&z)) != Z_OK) {
7627     GST_ERROR ("inflateInit() returned %d", ret);
7628     return NULL;
7629   }
7630
7631   z.next_in = z_buffer;
7632   z.avail_in = z_length;
7633
7634   buffer = (guint8 *) g_malloc (*length);
7635   z.avail_out = *length;
7636   z.next_out = (Bytef *) buffer;
7637   do {
7638     ret = inflate (&z, Z_NO_FLUSH);
7639     if (ret == Z_STREAM_END) {
7640       break;
7641     } else if (ret != Z_OK) {
7642       GST_WARNING ("inflate() returned %d", ret);
7643       break;
7644     }
7645
7646     *length += 4096;
7647     buffer = (guint8 *) g_realloc (buffer, *length);
7648     z.next_out = (Bytef *) (buffer + z.total_out);
7649     z.avail_out += 4096;
7650   } while (z.avail_in > 0);
7651
7652   if (ret != Z_STREAM_END) {
7653     g_free (buffer);
7654     buffer = NULL;
7655     *length = 0;
7656   } else {
7657     *length = z.total_out;
7658   }
7659
7660   inflateEnd (&z);
7661
7662   return buffer;
7663 }
7664 #endif /* HAVE_ZLIB */
7665
7666 static gboolean
7667 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7668 {
7669   GNode *cmov;
7670
7671   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7672
7673   /* counts as header data */
7674   qtdemux->header_size += length;
7675
7676   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7677   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7678
7679   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7680   if (cmov) {
7681     guint32 method;
7682     GNode *dcom;
7683     GNode *cmvd;
7684     guint32 dcom_len;
7685
7686     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7687     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7688     if (dcom == NULL || cmvd == NULL)
7689       goto invalid_compression;
7690
7691     dcom_len = QT_UINT32 (dcom->data);
7692     if (dcom_len < 12)
7693       goto invalid_compression;
7694
7695     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7696     switch (method) {
7697 #ifdef HAVE_ZLIB
7698       case FOURCC_zlib:{
7699         guint uncompressed_length;
7700         guint compressed_length;
7701         guint8 *buf;
7702         guint32 cmvd_len;
7703
7704         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7705         if (cmvd_len < 12)
7706           goto invalid_compression;
7707
7708         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7709         compressed_length = cmvd_len - 12;
7710         GST_LOG ("length = %u", uncompressed_length);
7711
7712         buf =
7713             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7714             compressed_length, &uncompressed_length);
7715
7716         if (buf) {
7717           qtdemux->moov_node_compressed = qtdemux->moov_node;
7718           qtdemux->moov_node = g_node_new (buf);
7719
7720           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7721               uncompressed_length);
7722         }
7723         break;
7724       }
7725 #endif /* HAVE_ZLIB */
7726       default:
7727         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7728             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7729         break;
7730     }
7731   }
7732   return TRUE;
7733
7734   /* ERRORS */
7735 invalid_compression:
7736   {
7737     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7738     return FALSE;
7739   }
7740 }
7741
7742 static gboolean
7743 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7744     const guint8 * end)
7745 {
7746   while (G_UNLIKELY (buf < end)) {
7747     GNode *child;
7748     guint32 len;
7749
7750     if (G_UNLIKELY (buf + 4 > end)) {
7751       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7752       break;
7753     }
7754     len = QT_UINT32 (buf);
7755     if (G_UNLIKELY (len == 0)) {
7756       GST_LOG_OBJECT (qtdemux, "empty container");
7757       break;
7758     }
7759     if (G_UNLIKELY (len < 8)) {
7760       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7761       break;
7762     }
7763     if (G_UNLIKELY (len > (end - buf))) {
7764       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7765           (gint) (end - buf));
7766       break;
7767     }
7768
7769     child = g_node_new ((guint8 *) buf);
7770     g_node_append (node, child);
7771     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7772     qtdemux_parse_node (qtdemux, child, buf, len);
7773
7774     buf += len;
7775   }
7776   return TRUE;
7777 }
7778
7779 static gboolean
7780 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7781     GNode * xdxt)
7782 {
7783   int len = QT_UINT32 (xdxt->data);
7784   guint8 *buf = xdxt->data;
7785   guint8 *end = buf + len;
7786   GstBuffer *buffer;
7787
7788   /* skip size and type */
7789   buf += 8;
7790   end -= 8;
7791
7792   while (buf < end) {
7793     gint size;
7794     guint32 type;
7795
7796     size = QT_UINT32 (buf);
7797     type = QT_FOURCC (buf + 4);
7798
7799     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7800
7801     if (buf + size > end || size <= 0)
7802       break;
7803
7804     buf += 8;
7805     size -= 8;
7806
7807     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7808         GST_FOURCC_ARGS (type));
7809
7810     switch (type) {
7811       case FOURCC_tCtH:
7812         buffer = gst_buffer_new_and_alloc (size);
7813         gst_buffer_fill (buffer, 0, buf, size);
7814         stream->buffers = g_slist_append (stream->buffers, buffer);
7815         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7816         break;
7817       case FOURCC_tCt_:
7818         buffer = gst_buffer_new_and_alloc (size);
7819         gst_buffer_fill (buffer, 0, buf, size);
7820         stream->buffers = g_slist_append (stream->buffers, buffer);
7821         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7822         break;
7823       case FOURCC_tCtC:
7824         buffer = gst_buffer_new_and_alloc (size);
7825         gst_buffer_fill (buffer, 0, buf, size);
7826         stream->buffers = g_slist_append (stream->buffers, buffer);
7827         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7828         break;
7829       default:
7830         GST_WARNING_OBJECT (qtdemux,
7831             "unknown theora cookie %" GST_FOURCC_FORMAT,
7832             GST_FOURCC_ARGS (type));
7833         break;
7834     }
7835     buf += size;
7836   }
7837   return TRUE;
7838 }
7839
7840 static gboolean
7841 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7842     guint length)
7843 {
7844   guint32 fourcc = 0;
7845   guint32 node_length = 0;
7846   const QtNodeType *type;
7847   const guint8 *end;
7848
7849   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7850
7851   if (G_UNLIKELY (length < 8))
7852     goto not_enough_data;
7853
7854   node_length = QT_UINT32 (buffer);
7855   fourcc = QT_FOURCC (buffer + 4);
7856
7857   /* ignore empty nodes */
7858   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7859     return TRUE;
7860
7861   type = qtdemux_type_get (fourcc);
7862
7863   end = buffer + length;
7864
7865   GST_LOG_OBJECT (qtdemux,
7866       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7867       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7868
7869   if (node_length > length)
7870     goto broken_atom_size;
7871
7872   if (type->flags & QT_FLAG_CONTAINER) {
7873     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7874   } else {
7875     switch (fourcc) {
7876       case FOURCC_stsd:
7877       {
7878         if (node_length < 20) {
7879           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7880           break;
7881         }
7882         GST_DEBUG_OBJECT (qtdemux,
7883             "parsing stsd (sample table, sample description) atom");
7884         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7885         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7886         break;
7887       }
7888       case FOURCC_mp4a:
7889       case FOURCC_alac:
7890       case FOURCC_fLaC:
7891       case FOURCC_aavd:
7892       {
7893         guint32 version;
7894         guint32 offset;
7895         guint min_size;
7896
7897         /* also read alac (or whatever) in stead of mp4a in the following,
7898          * since a similar layout is used in other cases as well */
7899         if (fourcc == FOURCC_mp4a)
7900           min_size = 20;
7901         else if (fourcc == FOURCC_fLaC)
7902           min_size = 86;
7903         else
7904           min_size = 40;
7905
7906         /* There are two things we might encounter here: a true mp4a atom, and
7907            an mp4a entry in an stsd atom. The latter is what we're interested
7908            in, and it looks like an atom, but isn't really one. The true mp4a
7909            atom is short, so we detect it based on length here. */
7910         if (length < min_size) {
7911           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7912               GST_FOURCC_ARGS (fourcc));
7913           break;
7914         }
7915
7916         /* 'version' here is the sound sample description version. Types 0 and
7917            1 are documented in the QTFF reference, but type 2 is not: it's
7918            described in Apple header files instead (struct SoundDescriptionV2
7919            in Movies.h) */
7920         version = QT_UINT16 (buffer + 16);
7921
7922         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7923             GST_FOURCC_ARGS (fourcc), version);
7924
7925         /* parse any esds descriptors */
7926         switch (version) {
7927           case 0:
7928             offset = 0x24;
7929             break;
7930           case 1:
7931             offset = 0x34;
7932             break;
7933           case 2:
7934             offset = 0x48;
7935             break;
7936           default:
7937             GST_WARNING_OBJECT (qtdemux,
7938                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7939                 GST_FOURCC_ARGS (fourcc), version);
7940             offset = 0;
7941             break;
7942         }
7943         if (offset)
7944           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7945         break;
7946       }
7947       case FOURCC_mp4v:
7948       case FOURCC_MP4V:
7949       case FOURCC_fmp4:
7950       case FOURCC_FMP4:
7951       case FOURCC_apcs:
7952       case FOURCC_apch:
7953       case FOURCC_apcn:
7954       case FOURCC_apco:
7955       case FOURCC_ap4h:
7956       case FOURCC_xvid:
7957       case FOURCC_XVID:
7958       case FOURCC_H264:
7959       case FOURCC_avc1:
7960       case FOURCC_avc3:
7961       case FOURCC_H265:
7962       case FOURCC_hvc1:
7963       case FOURCC_hev1:
7964       case FOURCC_dvh1:
7965       case FOURCC_dvhe:
7966       case FOURCC_mjp2:
7967       case FOURCC_encv:
7968       {
7969         guint32 version;
7970         guint32 str_len;
7971
7972         /* codec_data is contained inside these atoms, which all have
7973          * the same format. */
7974         /* video sample description size is 86 bytes without extension.
7975          * node_length have to be bigger than 86 bytes because video sample
7976          * description can include extensions such as esds, fiel, glbl, etc. */
7977         if (node_length < 86) {
7978           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7979               " sample description length too short (%u < 86)",
7980               GST_FOURCC_ARGS (fourcc), node_length);
7981           break;
7982         }
7983
7984         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7985             GST_FOURCC_ARGS (fourcc));
7986
7987         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7988          *              its data format.
7989          * revision level (2 bytes) : must be set to 0. */
7990         version = QT_UINT32 (buffer + 16);
7991         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7992
7993         /* compressor name : PASCAL string and informative purposes
7994          * first byte : the number of bytes to be displayed.
7995          *              it has to be less than 32 because it is reserved
7996          *              space of 32 bytes total including itself. */
7997         str_len = QT_UINT8 (buffer + 50);
7998         if (str_len < 32)
7999           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8000               (char *) buffer + 51);
8001         else
8002           GST_WARNING_OBJECT (qtdemux,
8003               "compressorname length too big (%u > 31)", str_len);
8004
8005         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8006             end - buffer);
8007         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8008         break;
8009       }
8010       case FOURCC_meta:
8011       {
8012         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8013
8014         /* You are reading this correctly. QTFF specifies that the
8015          * metadata atom is a short atom, whereas ISO BMFF specifies
8016          * it's a full atom. But since so many people are doing things
8017          * differently, we actually peek into the atom to see which
8018          * variant it is */
8019         if (length < 16) {
8020           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8021               GST_FOURCC_ARGS (fourcc));
8022           break;
8023         }
8024         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8025           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8026            * starts with a 'hdlr' atom */
8027           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8028         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8029           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8030            * with version/flags both set to zero */
8031           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8032         } else
8033           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8034         break;
8035       }
8036       case FOURCC_mp4s:
8037       {
8038         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8039         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8040         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8041         break;
8042       }
8043       case FOURCC_XiTh:
8044       {
8045         guint32 version;
8046         guint32 offset;
8047
8048         if (length < 16) {
8049           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8050               GST_FOURCC_ARGS (fourcc));
8051           break;
8052         }
8053
8054         version = QT_UINT32 (buffer + 12);
8055         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8056
8057         switch (version) {
8058           case 0x00000001:
8059             offset = 0x62;
8060             break;
8061           default:
8062             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8063             offset = 0;
8064             break;
8065         }
8066         if (offset) {
8067           if (length < offset) {
8068             GST_WARNING_OBJECT (qtdemux,
8069                 "skipping too small %" GST_FOURCC_FORMAT " box",
8070                 GST_FOURCC_ARGS (fourcc));
8071             break;
8072           }
8073           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8074         }
8075         break;
8076       }
8077       case FOURCC_in24:
8078       {
8079         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8080         break;
8081       }
8082       case FOURCC_uuid:
8083       {
8084         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8085         break;
8086       }
8087       case FOURCC_enca:
8088       {
8089         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8090         break;
8091       }
8092       default:
8093         if (!strcmp (type->name, "unknown"))
8094           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8095         break;
8096     }
8097   }
8098   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8099       GST_FOURCC_ARGS (fourcc));
8100   return TRUE;
8101
8102 /* ERRORS */
8103 not_enough_data:
8104   {
8105     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8106         (_("This file is corrupt and cannot be played.")),
8107         ("Not enough data for an atom header, got only %u bytes", length));
8108     return FALSE;
8109   }
8110 broken_atom_size:
8111   {
8112     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8113         (_("This file is corrupt and cannot be played.")),
8114         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8115             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8116             length));
8117     return FALSE;
8118   }
8119 }
8120
8121 static void
8122 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8123 {
8124 /* FIXME: This can only reliably work if demuxers have a
8125  * separate streaming thread per srcpad. This should be
8126  * done in a demuxer base class, which integrates parts
8127  * of multiqueue
8128  *
8129  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8130  */
8131 #if 0
8132   GstQuery *query;
8133
8134   query = gst_query_new_allocation (stream->caps, FALSE);
8135
8136   if (!gst_pad_peer_query (stream->pad, query)) {
8137     /* not a problem, just debug a little */
8138     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8139   }
8140
8141   if (stream->allocator)
8142     gst_object_unref (stream->allocator);
8143
8144   if (gst_query_get_n_allocation_params (query) > 0) {
8145     /* try the allocator */
8146     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8147         &stream->params);
8148     stream->use_allocator = TRUE;
8149   } else {
8150     stream->allocator = NULL;
8151     gst_allocation_params_init (&stream->params);
8152     stream->use_allocator = FALSE;
8153   }
8154   gst_query_unref (query);
8155 #endif
8156 }
8157
8158 static gboolean
8159 pad_query (const GValue * item, GValue * value, gpointer user_data)
8160 {
8161   GstPad *pad = g_value_get_object (item);
8162   GstQuery *query = user_data;
8163   gboolean res;
8164
8165   res = gst_pad_peer_query (pad, query);
8166
8167   if (res) {
8168     g_value_set_boolean (value, TRUE);
8169     return FALSE;
8170   }
8171
8172   GST_INFO_OBJECT (pad, "pad peer query failed");
8173   return TRUE;
8174 }
8175
8176 static gboolean
8177 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8178     GstPadDirection direction)
8179 {
8180   GstIterator *it;
8181   GstIteratorFoldFunction func = pad_query;
8182   GValue res = { 0, };
8183
8184   g_value_init (&res, G_TYPE_BOOLEAN);
8185   g_value_set_boolean (&res, FALSE);
8186
8187   /* Ask neighbor */
8188   if (direction == GST_PAD_SRC)
8189     it = gst_element_iterate_src_pads (element);
8190   else
8191     it = gst_element_iterate_sink_pads (element);
8192
8193   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8194     gst_iterator_resync (it);
8195
8196   gst_iterator_free (it);
8197
8198   return g_value_get_boolean (&res);
8199 }
8200
8201 static void
8202 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8203     QtDemuxStream * stream)
8204 {
8205   GstQuery *query;
8206   GstContext *ctxt;
8207   GstElement *element = GST_ELEMENT (qtdemux);
8208   GstStructure *st;
8209   gchar **filtered_sys_ids;
8210   GValue event_list = G_VALUE_INIT;
8211   GList *walk;
8212
8213   /* 1. Check if we already have the context. */
8214   if (qtdemux->preferred_protection_system_id != NULL) {
8215     GST_LOG_OBJECT (element,
8216         "already have the protection context, no need to request it again");
8217     return;
8218   }
8219
8220   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8221   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8222       (const gchar **) qtdemux->protection_system_ids->pdata);
8223
8224   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8225       qtdemux->protection_system_ids->len - 1);
8226   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8227       "decryptors for %u of them, running context request",
8228       qtdemux->protection_system_ids->len,
8229       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8230
8231
8232   if (stream->protection_scheme_event_queue.length) {
8233     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8234         stream->protection_scheme_event_queue.length);
8235     walk = stream->protection_scheme_event_queue.tail;
8236   } else {
8237     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8238         qtdemux->protection_event_queue.length);
8239     walk = qtdemux->protection_event_queue.tail;
8240   }
8241
8242   g_value_init (&event_list, GST_TYPE_LIST);
8243   for (; walk; walk = g_list_previous (walk)) {
8244     GValue *event_value = g_new0 (GValue, 1);
8245     g_value_init (event_value, GST_TYPE_EVENT);
8246     g_value_set_boxed (event_value, walk->data);
8247     gst_value_list_append_and_take_value (&event_list, event_value);
8248   }
8249
8250   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8251    *      check if downstream already has a context of the specific type
8252    *  2b) Query upstream as above.
8253    */
8254   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8255   st = gst_query_writable_structure (query);
8256   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8257       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8258       NULL);
8259   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8260   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8261     gst_query_parse_context (query, &ctxt);
8262     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8263     gst_element_set_context (element, ctxt);
8264   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8265     gst_query_parse_context (query, &ctxt);
8266     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8267     gst_element_set_context (element, ctxt);
8268   } else {
8269     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8270      *    the required context type and afterwards check if a
8271      *    usable context was set now as in 1). The message could
8272      *    be handled by the parent bins of the element and the
8273      *    application.
8274      */
8275     GstMessage *msg;
8276
8277     GST_INFO_OBJECT (element, "posting need context message");
8278     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8279         "drm-preferred-decryption-system-id");
8280     st = (GstStructure *) gst_message_get_structure (msg);
8281     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8282         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8283         NULL);
8284
8285     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8286     gst_element_post_message (element, msg);
8287   }
8288
8289   g_strfreev (filtered_sys_ids);
8290   g_value_unset (&event_list);
8291   gst_query_unref (query);
8292 }
8293
8294 static gboolean
8295 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8296     QtDemuxStream * stream)
8297 {
8298   GstStructure *s;
8299   const gchar *selected_system = NULL;
8300
8301   g_return_val_if_fail (qtdemux != NULL, FALSE);
8302   g_return_val_if_fail (stream != NULL, FALSE);
8303   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8304       FALSE);
8305
8306   if (stream->protection_scheme_type == FOURCC_aavd) {
8307     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8308     if (!gst_structure_has_name (s, "application/x-aavd")) {
8309       gst_structure_set (s,
8310           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8311           NULL);
8312       gst_structure_set_name (s, "application/x-aavd");
8313     }
8314     return TRUE;
8315   }
8316
8317   if (stream->protection_scheme_type != FOURCC_cenc) {
8318     GST_ERROR_OBJECT (qtdemux,
8319         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8320         GST_FOURCC_ARGS (stream->protection_scheme_type));
8321     return FALSE;
8322   }
8323
8324   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8325   if (!gst_structure_has_name (s, "application/x-cenc")) {
8326     gst_structure_set (s,
8327         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8328     gst_structure_set_name (s, "application/x-cenc");
8329   }
8330
8331   if (qtdemux->protection_system_ids == NULL) {
8332     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8333         "cenc protection system information has been found, not setting a "
8334         "protection system UUID");
8335     return TRUE;
8336   }
8337
8338   gst_qtdemux_request_protection_context (qtdemux, stream);
8339   if (qtdemux->preferred_protection_system_id != NULL) {
8340     const gchar *preferred_system_array[] =
8341         { qtdemux->preferred_protection_system_id, NULL };
8342
8343     selected_system = gst_protection_select_system (preferred_system_array);
8344
8345     if (selected_system) {
8346       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8347           qtdemux->preferred_protection_system_id);
8348     } else {
8349       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8350           "because there is no available decryptor",
8351           qtdemux->preferred_protection_system_id);
8352     }
8353   }
8354
8355   if (!selected_system) {
8356     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8357     selected_system = gst_protection_select_system ((const gchar **)
8358         qtdemux->protection_system_ids->pdata);
8359     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8360         qtdemux->protection_system_ids->len - 1);
8361   }
8362
8363   if (!selected_system) {
8364     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8365         "suitable decryptor element has been found");
8366     return FALSE;
8367   }
8368
8369   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8370       selected_system);
8371
8372   gst_structure_set (s,
8373       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8374       NULL);
8375
8376   return TRUE;
8377 }
8378
8379 static gboolean
8380 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8381 {
8382   /* fps is calculated base on the duration of the average framerate since
8383    * qt does not have a fixed framerate. */
8384   gboolean fps_available = TRUE;
8385   guint32 first_duration = 0;
8386
8387   if (stream->n_samples > 0)
8388     first_duration = stream->samples[0].duration;
8389
8390   if ((stream->n_samples == 1 && first_duration == 0)
8391       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8392     /* still frame */
8393     CUR_STREAM (stream)->fps_n = 0;
8394     CUR_STREAM (stream)->fps_d = 1;
8395   } else {
8396     if (stream->duration == 0 || stream->n_samples < 2) {
8397       CUR_STREAM (stream)->fps_n = stream->timescale;
8398       CUR_STREAM (stream)->fps_d = 1;
8399       fps_available = FALSE;
8400     } else {
8401       GstClockTime avg_duration;
8402       guint64 duration;
8403       guint32 n_samples;
8404
8405       /* duration and n_samples can be updated for fragmented format
8406        * so, framerate of fragmented format is calculated using data in a moof */
8407       if (qtdemux->fragmented && stream->n_samples_moof > 0
8408           && stream->duration_moof > 0) {
8409         n_samples = stream->n_samples_moof;
8410         duration = stream->duration_moof;
8411       } else {
8412         n_samples = stream->n_samples;
8413         duration = stream->duration;
8414       }
8415
8416       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8417       /* stream->duration is guint64, timescale, n_samples are guint32 */
8418       avg_duration =
8419           gst_util_uint64_scale_round (duration -
8420           first_duration, GST_SECOND,
8421           (guint64) (stream->timescale) * (n_samples - 1));
8422
8423       GST_LOG_OBJECT (qtdemux,
8424           "Calculating avg sample duration based on stream (or moof) duration %"
8425           G_GUINT64_FORMAT
8426           " minus first sample %u, leaving %d samples gives %"
8427           GST_TIME_FORMAT, duration, first_duration,
8428           n_samples - 1, GST_TIME_ARGS (avg_duration));
8429
8430       fps_available =
8431           gst_video_guess_framerate (avg_duration,
8432           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8433
8434       GST_DEBUG_OBJECT (qtdemux,
8435           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8436           stream->timescale, CUR_STREAM (stream)->fps_n,
8437           CUR_STREAM (stream)->fps_d);
8438     }
8439   }
8440
8441   return fps_available;
8442 }
8443
8444 static gboolean
8445 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8446 {
8447   if (stream->subtype == FOURCC_vide) {
8448     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8449
8450     if (CUR_STREAM (stream)->caps) {
8451       CUR_STREAM (stream)->caps =
8452           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8453
8454       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8455         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8456             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8457             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8458
8459       /* set framerate if calculated framerate is reliable */
8460       if (fps_available) {
8461         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8462             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8463             CUR_STREAM (stream)->fps_d, NULL);
8464       }
8465
8466       /* calculate pixel-aspect-ratio using display width and height */
8467       GST_DEBUG_OBJECT (qtdemux,
8468           "video size %dx%d, target display size %dx%d",
8469           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8470           stream->display_width, stream->display_height);
8471       /* qt file might have pasp atom */
8472       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8473         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8474             CUR_STREAM (stream)->par_h);
8475         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8476             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8477             CUR_STREAM (stream)->par_h, NULL);
8478       } else if (stream->display_width > 0 && stream->display_height > 0
8479           && CUR_STREAM (stream)->width > 0
8480           && CUR_STREAM (stream)->height > 0) {
8481         gint n, d;
8482
8483         /* calculate the pixel aspect ratio using the display and pixel w/h */
8484         n = stream->display_width * CUR_STREAM (stream)->height;
8485         d = stream->display_height * CUR_STREAM (stream)->width;
8486         if (n == d)
8487           n = d = 1;
8488         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8489         CUR_STREAM (stream)->par_w = n;
8490         CUR_STREAM (stream)->par_h = d;
8491         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8492             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8493             CUR_STREAM (stream)->par_h, NULL);
8494       }
8495
8496       if (CUR_STREAM (stream)->interlace_mode > 0) {
8497         if (CUR_STREAM (stream)->interlace_mode == 1) {
8498           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8499               G_TYPE_STRING, "progressive", NULL);
8500         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8501           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8502               G_TYPE_STRING, "interleaved", NULL);
8503           if (CUR_STREAM (stream)->field_order == 9) {
8504             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8505                 G_TYPE_STRING, "top-field-first", NULL);
8506           } else if (CUR_STREAM (stream)->field_order == 14) {
8507             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8508                 G_TYPE_STRING, "bottom-field-first", NULL);
8509           }
8510         }
8511       }
8512
8513       /* Create incomplete colorimetry here if needed */
8514       if (CUR_STREAM (stream)->colorimetry.range ||
8515           CUR_STREAM (stream)->colorimetry.matrix ||
8516           CUR_STREAM (stream)->colorimetry.transfer
8517           || CUR_STREAM (stream)->colorimetry.primaries) {
8518         gchar *colorimetry =
8519             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8520         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8521             G_TYPE_STRING, colorimetry, NULL);
8522         g_free (colorimetry);
8523       }
8524
8525       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8526         guint par_w = 1, par_h = 1;
8527
8528         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8529           par_w = CUR_STREAM (stream)->par_w;
8530           par_h = CUR_STREAM (stream)->par_h;
8531         }
8532
8533         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8534                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8535                 par_h)) {
8536           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8537         }
8538
8539         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8540             "multiview-mode", G_TYPE_STRING,
8541             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8542             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8543             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8544       }
8545     }
8546   }
8547
8548   else if (stream->subtype == FOURCC_soun) {
8549     if (CUR_STREAM (stream)->caps) {
8550       CUR_STREAM (stream)->caps =
8551           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8552       if (CUR_STREAM (stream)->rate > 0)
8553         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8554             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8555       if (CUR_STREAM (stream)->n_channels > 0)
8556         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8557             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8558       if (CUR_STREAM (stream)->n_channels > 2) {
8559         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8560          * correctly; this is just the minimum we can do - assume
8561          * we don't actually have any channel positions. */
8562         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8563             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8564       }
8565     }
8566   }
8567
8568   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8569     const GstStructure *s;
8570     QtDemuxStream *fps_stream = NULL;
8571     gboolean fps_available = FALSE;
8572
8573     /* CEA608 closed caption tracks are a bit special in that each sample
8574      * can contain CCs for multiple frames, and CCs can be omitted and have to
8575      * be inferred from the duration of the sample then.
8576      *
8577      * As such we take the framerate from the (first) video track here for
8578      * CEA608 as there must be one CC byte pair for every video frame
8579      * according to the spec.
8580      *
8581      * For CEA708 all is fine and there is one sample per frame.
8582      */
8583
8584     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8585     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8586       gint i;
8587
8588       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8589         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8590
8591         if (tmp->subtype == FOURCC_vide) {
8592           fps_stream = tmp;
8593           break;
8594         }
8595       }
8596
8597       if (fps_stream) {
8598         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8599         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8600         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8601       }
8602     } else {
8603       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8604       fps_stream = stream;
8605     }
8606
8607     CUR_STREAM (stream)->caps =
8608         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8609
8610     /* set framerate if calculated framerate is reliable */
8611     if (fps_available) {
8612       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8613           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8614           CUR_STREAM (stream)->fps_d, NULL);
8615     }
8616   }
8617
8618   if (stream->pad) {
8619     GstCaps *prev_caps = NULL;
8620
8621     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8622     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8623     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8624     gst_pad_set_active (stream->pad, TRUE);
8625
8626     gst_pad_use_fixed_caps (stream->pad);
8627
8628     if (stream->protected) {
8629       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8630         GST_ERROR_OBJECT (qtdemux,
8631             "Failed to configure protected stream caps.");
8632         return FALSE;
8633       }
8634     }
8635
8636     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8637         CUR_STREAM (stream)->caps);
8638     if (stream->new_stream) {
8639       GstEvent *event;
8640       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8641
8642       event =
8643           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8644           0);
8645       if (event) {
8646         gst_event_parse_stream_flags (event, &stream_flags);
8647         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8648           qtdemux->have_group_id = TRUE;
8649         else
8650           qtdemux->have_group_id = FALSE;
8651         gst_event_unref (event);
8652       } else if (!qtdemux->have_group_id) {
8653         qtdemux->have_group_id = TRUE;
8654         qtdemux->group_id = gst_util_group_id_next ();
8655       }
8656
8657       stream->new_stream = FALSE;
8658       event = gst_event_new_stream_start (stream->stream_id);
8659       if (qtdemux->have_group_id)
8660         gst_event_set_group_id (event, qtdemux->group_id);
8661       if (stream->disabled)
8662         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8663       if (CUR_STREAM (stream)->sparse) {
8664         stream_flags |= GST_STREAM_FLAG_SPARSE;
8665       } else {
8666         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8667       }
8668       gst_event_set_stream_flags (event, stream_flags);
8669       gst_pad_push_event (stream->pad, event);
8670     }
8671
8672     prev_caps = gst_pad_get_current_caps (stream->pad);
8673
8674     if (CUR_STREAM (stream)->caps) {
8675       if (!prev_caps
8676           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8677         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8678             CUR_STREAM (stream)->caps);
8679         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8680       } else {
8681         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8682       }
8683     } else {
8684       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8685     }
8686
8687     if (prev_caps)
8688       gst_caps_unref (prev_caps);
8689     stream->new_caps = FALSE;
8690   }
8691   return TRUE;
8692 }
8693
8694 static void
8695 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8696     QtDemuxStream * stream)
8697 {
8698   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8699     return;
8700
8701   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8702       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8703   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8704           stream->stsd_entries_length)) {
8705     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8706         (_("This file is invalid and cannot be played.")),
8707         ("New sample description id is out of bounds (%d >= %d)",
8708             stream->stsd_sample_description_id, stream->stsd_entries_length));
8709   } else {
8710     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8711     stream->new_caps = TRUE;
8712   }
8713 }
8714
8715 static gboolean
8716 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8717     QtDemuxStream * stream, GstTagList * list)
8718 {
8719   gboolean ret = TRUE;
8720
8721   if (stream->subtype == FOURCC_vide) {
8722     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8723
8724     stream->pad =
8725         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8726     g_free (name);
8727
8728     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8729       gst_object_unref (stream->pad);
8730       stream->pad = NULL;
8731       ret = FALSE;
8732       goto done;
8733     }
8734
8735     qtdemux->n_video_streams++;
8736   } else if (stream->subtype == FOURCC_soun) {
8737     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8738
8739     stream->pad =
8740         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8741     g_free (name);
8742     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8743       gst_object_unref (stream->pad);
8744       stream->pad = NULL;
8745       ret = FALSE;
8746       goto done;
8747     }
8748     qtdemux->n_audio_streams++;
8749   } else if (stream->subtype == FOURCC_strm) {
8750     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8751   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8752       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8753       || stream->subtype == FOURCC_clcp) {
8754     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8755
8756     stream->pad =
8757         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8758     g_free (name);
8759     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8760       gst_object_unref (stream->pad);
8761       stream->pad = NULL;
8762       ret = FALSE;
8763       goto done;
8764     }
8765     qtdemux->n_sub_streams++;
8766   } else if (CUR_STREAM (stream)->caps) {
8767     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8768
8769     stream->pad =
8770         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8771     g_free (name);
8772     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8773       gst_object_unref (stream->pad);
8774       stream->pad = NULL;
8775       ret = FALSE;
8776       goto done;
8777     }
8778     qtdemux->n_video_streams++;
8779   } else {
8780     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8781     goto done;
8782   }
8783
8784   if (stream->pad) {
8785     GList *l;
8786
8787     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8788         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8789     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8790     GST_OBJECT_LOCK (qtdemux);
8791     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8792     GST_OBJECT_UNLOCK (qtdemux);
8793
8794     if (stream->stream_tags)
8795       gst_tag_list_unref (stream->stream_tags);
8796     stream->stream_tags = list;
8797     list = NULL;
8798     /* global tags go on each pad anyway */
8799     stream->send_global_tags = TRUE;
8800     /* send upstream GST_EVENT_PROTECTION events that were received before
8801        this source pad was created */
8802     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8803       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8804   }
8805 done:
8806   if (list)
8807     gst_tag_list_unref (list);
8808   return ret;
8809 }
8810
8811 /* find next atom with @fourcc starting at @offset */
8812 static GstFlowReturn
8813 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8814     guint64 * length, guint32 fourcc)
8815 {
8816   GstFlowReturn ret;
8817   guint32 lfourcc;
8818   GstBuffer *buf;
8819
8820   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8821       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8822
8823   while (TRUE) {
8824     GstMapInfo map;
8825
8826     buf = NULL;
8827     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8828     if (G_UNLIKELY (ret != GST_FLOW_OK))
8829       goto locate_failed;
8830     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8831       /* likely EOF */
8832       ret = GST_FLOW_EOS;
8833       gst_buffer_unref (buf);
8834       goto locate_failed;
8835     }
8836     gst_buffer_map (buf, &map, GST_MAP_READ);
8837     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8838     gst_buffer_unmap (buf, &map);
8839     gst_buffer_unref (buf);
8840
8841     if (G_UNLIKELY (*length == 0)) {
8842       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8843       ret = GST_FLOW_ERROR;
8844       goto locate_failed;
8845     }
8846
8847     if (lfourcc == fourcc) {
8848       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
8849           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8850       break;
8851     } else {
8852       GST_LOG_OBJECT (qtdemux,
8853           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8854           GST_FOURCC_ARGS (lfourcc), *offset);
8855       if (*offset == G_MAXUINT64)
8856         goto locate_failed;
8857       *offset += *length;
8858     }
8859   }
8860
8861   return GST_FLOW_OK;
8862
8863 locate_failed:
8864   {
8865     /* might simply have had last one */
8866     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8867     return ret;
8868   }
8869 }
8870
8871 /* should only do something in pull mode */
8872 /* call with OBJECT lock */
8873 static GstFlowReturn
8874 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8875 {
8876   guint64 length, offset;
8877   GstBuffer *buf = NULL;
8878   GstFlowReturn ret = GST_FLOW_OK;
8879   GstFlowReturn res = GST_FLOW_OK;
8880   GstMapInfo map;
8881
8882   offset = qtdemux->moof_offset;
8883   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8884
8885   if (!offset) {
8886     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8887     return GST_FLOW_EOS;
8888   }
8889
8890   /* best not do pull etc with lock held */
8891   GST_OBJECT_UNLOCK (qtdemux);
8892
8893   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8894   if (ret != GST_FLOW_OK)
8895     goto flow_failed;
8896
8897   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8898   if (G_UNLIKELY (ret != GST_FLOW_OK))
8899     goto flow_failed;
8900   gst_buffer_map (buf, &map, GST_MAP_READ);
8901   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8902     gst_buffer_unmap (buf, &map);
8903     gst_buffer_unref (buf);
8904     buf = NULL;
8905     goto parse_failed;
8906   }
8907
8908   gst_buffer_unmap (buf, &map);
8909   gst_buffer_unref (buf);
8910   buf = NULL;
8911
8912   offset += length;
8913   /* look for next moof */
8914   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8915   if (G_UNLIKELY (ret != GST_FLOW_OK))
8916     goto flow_failed;
8917
8918 exit:
8919   GST_OBJECT_LOCK (qtdemux);
8920
8921   qtdemux->moof_offset = offset;
8922
8923   return res;
8924
8925 parse_failed:
8926   {
8927     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8928     offset = 0;
8929     res = GST_FLOW_ERROR;
8930     goto exit;
8931   }
8932 flow_failed:
8933   {
8934     /* maybe upstream temporarily flushing */
8935     if (ret != GST_FLOW_FLUSHING) {
8936       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8937       offset = 0;
8938     } else {
8939       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8940       /* resume at current position next time */
8941     }
8942     res = ret;
8943     goto exit;
8944   }
8945 }
8946
8947 static void
8948 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
8949 {
8950   guint i;
8951   guint32 num_chunks;
8952   gint32 stts_duration;
8953   GstByteWriter stsc, stts, stsz;
8954
8955   /* Each sample has a different size, which we don't support for merging */
8956   if (stream->sample_size == 0) {
8957     GST_DEBUG_OBJECT (qtdemux,
8958         "Not all samples have the same size, not merging");
8959     return;
8960   }
8961
8962   /* The stream has a ctts table, we don't support that */
8963   if (stream->ctts_present) {
8964     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
8965     return;
8966   }
8967
8968   /* If there's a sync sample table also ignore this stream */
8969   if (stream->stps_present || stream->stss_present) {
8970     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
8971     return;
8972   }
8973
8974   /* If chunks are considered samples already ignore this stream */
8975   if (stream->chunks_are_samples) {
8976     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
8977     return;
8978   }
8979
8980   /* Require that all samples have the same duration */
8981   if (stream->n_sample_times > 1) {
8982     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
8983     return;
8984   }
8985
8986   /* Parse the stts to get the sample duration and number of samples */
8987   gst_byte_reader_skip_unchecked (&stream->stts, 4);
8988   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8989
8990   /* Parse the number of chunks from the stco manually because the
8991    * reader is already behind that */
8992   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
8993
8994   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
8995       num_chunks);
8996
8997   /* Now parse stsc, convert chunks into single samples and generate a
8998    * new stsc, stts and stsz from this information */
8999   gst_byte_writer_init (&stsc);
9000   gst_byte_writer_init (&stts);
9001   gst_byte_writer_init (&stsz);
9002
9003   /* Note: we skip fourccs, size, version, flags and other fields of the new
9004    * atoms as the byte readers with them are already behind that position
9005    * anyway and only update the values of those inside the stream directly.
9006    */
9007   stream->n_sample_times = 0;
9008   stream->n_samples = 0;
9009   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9010     guint j;
9011     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9012
9013     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9014     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9015     sample_description_id =
9016         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9017
9018     if (i == stream->n_samples_per_chunk - 1) {
9019       /* +1 because first_chunk is 1-based */
9020       last_chunk = num_chunks + 1;
9021     } else {
9022       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9023     }
9024
9025     GST_DEBUG_OBJECT (qtdemux,
9026         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9027         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9028
9029     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9030     /* One sample in this chunk */
9031     gst_byte_writer_put_uint32_be (&stsc, 1);
9032     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9033
9034     /* For each chunk write a stts and stsz entry now */
9035     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9036     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9037     for (j = first_chunk; j < last_chunk; j++) {
9038       gst_byte_writer_put_uint32_be (&stsz,
9039           stream->sample_size * samples_per_chunk);
9040     }
9041
9042     stream->n_sample_times += 1;
9043     stream->n_samples += last_chunk - first_chunk;
9044   }
9045
9046   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9047
9048   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9049       stream->n_samples, stream->n_sample_times);
9050
9051   /* We don't have a fixed sample size anymore */
9052   stream->sample_size = 0;
9053
9054   /* Free old data for the atoms */
9055   g_free ((gpointer) stream->stsz.data);
9056   stream->stsz.data = NULL;
9057   g_free ((gpointer) stream->stsc.data);
9058   stream->stsc.data = NULL;
9059   g_free ((gpointer) stream->stts.data);
9060   stream->stts.data = NULL;
9061
9062   /* Store new data and replace byte readers */
9063   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9064   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9065   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9066   stream->stts.size = gst_byte_writer_get_size (&stts);
9067   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9068   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9069   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9070   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9071   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9072 }
9073
9074 /* initialise bytereaders for stbl sub-atoms */
9075 static gboolean
9076 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9077 {
9078   stream->stbl_index = -1;      /* no samples have yet been parsed */
9079   stream->sample_index = -1;
9080
9081   /* time-to-sample atom */
9082   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9083     goto corrupt_file;
9084
9085   /* copy atom data into a new buffer for later use */
9086   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
9087
9088   /* skip version + flags */
9089   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9090       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9091     goto corrupt_file;
9092   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9093
9094   /* make sure there's enough data */
9095   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9096     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9097     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9098         stream->n_sample_times);
9099     if (!stream->n_sample_times)
9100       goto corrupt_file;
9101   }
9102
9103   /* sync sample atom */
9104   stream->stps_present = FALSE;
9105   if ((stream->stss_present =
9106           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9107               &stream->stss) ? TRUE : FALSE) == TRUE) {
9108     /* copy atom data into a new buffer for later use */
9109     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
9110
9111     /* skip version + flags */
9112     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9113         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9114       goto corrupt_file;
9115
9116     if (stream->n_sample_syncs) {
9117       /* make sure there's enough data */
9118       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9119         goto corrupt_file;
9120     }
9121
9122     /* partial sync sample atom */
9123     if ((stream->stps_present =
9124             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9125                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9126       /* copy atom data into a new buffer for later use */
9127       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
9128
9129       /* skip version + flags */
9130       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9131           !gst_byte_reader_get_uint32_be (&stream->stps,
9132               &stream->n_sample_partial_syncs))
9133         goto corrupt_file;
9134
9135       /* if there are no entries, the stss table contains the real
9136        * sync samples */
9137       if (stream->n_sample_partial_syncs) {
9138         /* make sure there's enough data */
9139         if (!qt_atom_parser_has_chunks (&stream->stps,
9140                 stream->n_sample_partial_syncs, 4))
9141           goto corrupt_file;
9142       }
9143     }
9144   }
9145
9146   /* sample size */
9147   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9148     goto no_samples;
9149
9150   /* copy atom data into a new buffer for later use */
9151   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
9152
9153   /* skip version + flags */
9154   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9155       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9156     goto corrupt_file;
9157
9158   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9159     goto corrupt_file;
9160
9161   if (!stream->n_samples)
9162     goto no_samples;
9163
9164   /* sample-to-chunk atom */
9165   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9166     goto corrupt_file;
9167
9168   /* copy atom data into a new buffer for later use */
9169   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
9170
9171   /* skip version + flags */
9172   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9173       !gst_byte_reader_get_uint32_be (&stream->stsc,
9174           &stream->n_samples_per_chunk))
9175     goto corrupt_file;
9176
9177   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9178       stream->n_samples_per_chunk);
9179
9180   /* make sure there's enough data */
9181   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9182           12))
9183     goto corrupt_file;
9184
9185
9186   /* chunk offset */
9187   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9188     stream->co_size = sizeof (guint32);
9189   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9190           &stream->stco))
9191     stream->co_size = sizeof (guint64);
9192   else
9193     goto corrupt_file;
9194
9195   /* copy atom data into a new buffer for later use */
9196   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
9197
9198   /* skip version + flags */
9199   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9200     goto corrupt_file;
9201
9202   /* chunks_are_samples == TRUE means treat chunks as samples */
9203   stream->chunks_are_samples = stream->sample_size
9204       && !CUR_STREAM (stream)->sampled;
9205   if (stream->chunks_are_samples) {
9206     /* treat chunks as samples */
9207     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9208       goto corrupt_file;
9209   } else {
9210     /* skip number of entries */
9211     if (!gst_byte_reader_skip (&stream->stco, 4))
9212       goto corrupt_file;
9213
9214     /* make sure there are enough data in the stsz atom */
9215     if (!stream->sample_size) {
9216       /* different sizes for each sample */
9217       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9218         goto corrupt_file;
9219     }
9220   }
9221
9222   /* composition time-to-sample */
9223   if ((stream->ctts_present =
9224           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9225               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9226     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9227
9228     /* copy atom data into a new buffer for later use */
9229     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
9230
9231     /* skip version + flags */
9232     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9233         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9234             &stream->n_composition_times))
9235       goto corrupt_file;
9236
9237     /* make sure there's enough data */
9238     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9239             4 + 4))
9240       goto corrupt_file;
9241
9242     /* This is optional, if missing we iterate the ctts */
9243     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9244       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9245           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9246         g_free ((gpointer) cslg.data);
9247         goto corrupt_file;
9248       }
9249     } else {
9250       gint32 cslg_least = 0;
9251       guint num_entries, pos;
9252       gint i;
9253
9254       pos = gst_byte_reader_get_pos (&stream->ctts);
9255       num_entries = stream->n_composition_times;
9256
9257       stream->cslg_shift = 0;
9258
9259       for (i = 0; i < num_entries; i++) {
9260         gint32 offset;
9261
9262         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9263         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9264         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9265          * slightly inaccurate PTS could be more usable than corrupted one */
9266         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9267           GST_WARNING_OBJECT (qtdemux,
9268               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9269               " larger than duration %" G_GUINT64_FORMAT,
9270               offset, stream->duration);
9271
9272           stream->cslg_shift = 0;
9273           stream->ctts_present = FALSE;
9274           goto done;
9275         }
9276
9277         if (offset < cslg_least)
9278           cslg_least = offset;
9279       }
9280
9281       if (cslg_least < 0)
9282         stream->cslg_shift = ABS (cslg_least);
9283       else
9284         stream->cslg_shift = 0;
9285
9286       /* reset the reader so we can generate sample table */
9287       gst_byte_reader_set_pos (&stream->ctts, pos);
9288     }
9289   } else {
9290     /* Ensure the cslg_shift value is consistent so we can use it
9291      * unconditionally to produce TS and Segment */
9292     stream->cslg_shift = 0;
9293   }
9294
9295   /* For raw audio streams especially we might want to merge the samples
9296    * to not output one audio sample per buffer. We're doing this here
9297    * before allocating the sample tables so that from this point onwards
9298    * the number of container samples are static */
9299   if (stream->min_buffer_size > 0) {
9300     qtdemux_merge_sample_table (qtdemux, stream);
9301   }
9302
9303 done:
9304   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9305       stream->n_samples, (guint) sizeof (QtDemuxSample),
9306       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9307
9308   if (stream->n_samples >=
9309       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9310     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9311         "be larger than %uMB (broken file?)", stream->n_samples,
9312         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9313     return FALSE;
9314   }
9315
9316   g_assert (stream->samples == NULL);
9317   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9318   if (!stream->samples) {
9319     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9320         stream->n_samples);
9321     return FALSE;
9322   }
9323
9324   return TRUE;
9325
9326 corrupt_file:
9327   {
9328     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9329         (_("This file is corrupt and cannot be played.")), (NULL));
9330     return FALSE;
9331   }
9332 no_samples:
9333   {
9334     gst_qtdemux_stbl_free (stream);
9335     if (!qtdemux->fragmented) {
9336       /* not quite good */
9337       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9338       return FALSE;
9339     } else {
9340       /* may pick up samples elsewhere */
9341       return TRUE;
9342     }
9343   }
9344 }
9345
9346 /* collect samples from the next sample to be parsed up to sample @n for @stream
9347  * by reading the info from @stbl
9348  *
9349  * This code can be executed from both the streaming thread and the seeking
9350  * thread so it takes the object lock to protect itself
9351  */
9352 static gboolean
9353 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9354 {
9355   gint i, j, k;
9356   QtDemuxSample *samples, *first, *cur, *last;
9357   guint32 n_samples_per_chunk;
9358   guint32 n_samples;
9359
9360   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9361       GST_FOURCC_FORMAT ", pad %s",
9362       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9363       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9364
9365   n_samples = stream->n_samples;
9366
9367   if (n >= n_samples)
9368     goto out_of_samples;
9369
9370   GST_OBJECT_LOCK (qtdemux);
9371   if (n <= stream->stbl_index)
9372     goto already_parsed;
9373
9374   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9375
9376   if (!stream->stsz.data) {
9377     /* so we already parsed and passed all the moov samples;
9378      * onto fragmented ones */
9379     g_assert (qtdemux->fragmented);
9380     goto done;
9381   }
9382
9383   /* pointer to the sample table */
9384   samples = stream->samples;
9385
9386   /* starts from -1, moves to the next sample index to parse */
9387   stream->stbl_index++;
9388
9389   /* keep track of the first and last sample to fill */
9390   first = &samples[stream->stbl_index];
9391   last = &samples[n];
9392
9393   if (!stream->chunks_are_samples) {
9394     /* set the sample sizes */
9395     if (stream->sample_size == 0) {
9396       /* different sizes for each sample */
9397       for (cur = first; cur <= last; cur++) {
9398         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9399         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9400             (guint) (cur - samples), cur->size);
9401       }
9402     } else {
9403       /* samples have the same size */
9404       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9405       for (cur = first; cur <= last; cur++)
9406         cur->size = stream->sample_size;
9407     }
9408   }
9409
9410   n_samples_per_chunk = stream->n_samples_per_chunk;
9411   cur = first;
9412
9413   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9414     guint32 last_chunk;
9415
9416     if (stream->stsc_chunk_index >= stream->last_chunk
9417         || stream->stsc_chunk_index < stream->first_chunk) {
9418       stream->first_chunk =
9419           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9420       stream->samples_per_chunk =
9421           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9422       /* starts from 1 */
9423       stream->stsd_sample_description_id =
9424           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9425
9426       /* chunk numbers are counted from 1 it seems */
9427       if (G_UNLIKELY (stream->first_chunk == 0))
9428         goto corrupt_file;
9429
9430       --stream->first_chunk;
9431
9432       /* the last chunk of each entry is calculated by taking the first chunk
9433        * of the next entry; except if there is no next, where we fake it with
9434        * INT_MAX */
9435       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9436         stream->last_chunk = G_MAXUINT32;
9437       } else {
9438         stream->last_chunk =
9439             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9440         if (G_UNLIKELY (stream->last_chunk == 0))
9441           goto corrupt_file;
9442
9443         --stream->last_chunk;
9444       }
9445
9446       GST_LOG_OBJECT (qtdemux,
9447           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9448           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9449           stream->samples_per_chunk, stream->stsd_sample_description_id);
9450
9451       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9452         goto corrupt_file;
9453
9454       if (stream->last_chunk != G_MAXUINT32) {
9455         if (!qt_atom_parser_peek_sub (&stream->stco,
9456                 stream->first_chunk * stream->co_size,
9457                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9458                 &stream->co_chunk))
9459           goto corrupt_file;
9460
9461       } else {
9462         stream->co_chunk = stream->stco;
9463         if (!gst_byte_reader_skip (&stream->co_chunk,
9464                 stream->first_chunk * stream->co_size))
9465           goto corrupt_file;
9466       }
9467
9468       stream->stsc_chunk_index = stream->first_chunk;
9469     }
9470
9471     last_chunk = stream->last_chunk;
9472
9473     if (stream->chunks_are_samples) {
9474       cur = &samples[stream->stsc_chunk_index];
9475
9476       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9477         if (j > n) {
9478           /* save state */
9479           stream->stsc_chunk_index = j;
9480           goto done;
9481         }
9482
9483         cur->offset =
9484             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9485             stream->co_size);
9486
9487         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9488             "%" G_GUINT64_FORMAT, j, cur->offset);
9489
9490         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9491             CUR_STREAM (stream)->bytes_per_frame > 0) {
9492           cur->size =
9493               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9494               CUR_STREAM (stream)->samples_per_frame *
9495               CUR_STREAM (stream)->bytes_per_frame;
9496         } else {
9497           cur->size = stream->samples_per_chunk;
9498         }
9499
9500         GST_DEBUG_OBJECT (qtdemux,
9501             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9502             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9503                     stream->stco_sample_index)), cur->size);
9504
9505         cur->timestamp = stream->stco_sample_index;
9506         cur->duration = stream->samples_per_chunk;
9507         cur->keyframe = TRUE;
9508         cur++;
9509
9510         stream->stco_sample_index += stream->samples_per_chunk;
9511       }
9512       stream->stsc_chunk_index = j;
9513     } else {
9514       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9515         guint32 samples_per_chunk;
9516         guint64 chunk_offset;
9517
9518         if (!stream->stsc_sample_index
9519             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9520                 &stream->chunk_offset))
9521           goto corrupt_file;
9522
9523         samples_per_chunk = stream->samples_per_chunk;
9524         chunk_offset = stream->chunk_offset;
9525
9526         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9527           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9528               G_GUINT64_FORMAT " and size %d",
9529               (guint) (cur - samples), chunk_offset, cur->size);
9530
9531           cur->offset = chunk_offset;
9532           chunk_offset += cur->size;
9533           cur++;
9534
9535           if (G_UNLIKELY (cur > last)) {
9536             /* save state */
9537             stream->stsc_sample_index = k + 1;
9538             stream->chunk_offset = chunk_offset;
9539             stream->stsc_chunk_index = j;
9540             goto done2;
9541           }
9542         }
9543         stream->stsc_sample_index = 0;
9544       }
9545       stream->stsc_chunk_index = j;
9546     }
9547     stream->stsc_index++;
9548   }
9549
9550   if (stream->chunks_are_samples)
9551     goto ctts;
9552 done2:
9553   {
9554     guint32 n_sample_times;
9555
9556     n_sample_times = stream->n_sample_times;
9557     cur = first;
9558
9559     for (i = stream->stts_index; i < n_sample_times; i++) {
9560       guint32 stts_samples;
9561       gint32 stts_duration;
9562       gint64 stts_time;
9563
9564       if (stream->stts_sample_index >= stream->stts_samples
9565           || !stream->stts_sample_index) {
9566
9567         stream->stts_samples =
9568             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9569         stream->stts_duration =
9570             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9571
9572         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9573             i, stream->stts_samples, stream->stts_duration);
9574
9575         stream->stts_sample_index = 0;
9576       }
9577
9578       stts_samples = stream->stts_samples;
9579       stts_duration = stream->stts_duration;
9580       stts_time = stream->stts_time;
9581
9582       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9583         GST_DEBUG_OBJECT (qtdemux,
9584             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9585             (guint) (cur - samples), j,
9586             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9587
9588         cur->timestamp = stts_time;
9589         cur->duration = stts_duration;
9590
9591         /* avoid 32-bit wrap-around,
9592          * but still mind possible 'negative' duration */
9593         stts_time += (gint64) stts_duration;
9594         cur++;
9595
9596         if (G_UNLIKELY (cur > last)) {
9597           /* save values */
9598           stream->stts_time = stts_time;
9599           stream->stts_sample_index = j + 1;
9600           if (stream->stts_sample_index >= stream->stts_samples)
9601             stream->stts_index++;
9602           goto done3;
9603         }
9604       }
9605       stream->stts_sample_index = 0;
9606       stream->stts_time = stts_time;
9607       stream->stts_index++;
9608     }
9609     /* fill up empty timestamps with the last timestamp, this can happen when
9610      * the last samples do not decode and so we don't have timestamps for them.
9611      * We however look at the last timestamp to estimate the track length so we
9612      * need something in here. */
9613     for (; cur < last; cur++) {
9614       GST_DEBUG_OBJECT (qtdemux,
9615           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9616           (guint) (cur - samples),
9617           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9618       cur->timestamp = stream->stts_time;
9619       cur->duration = -1;
9620     }
9621   }
9622 done3:
9623   {
9624     /* sample sync, can be NULL */
9625     if (stream->stss_present == TRUE) {
9626       guint32 n_sample_syncs;
9627
9628       n_sample_syncs = stream->n_sample_syncs;
9629
9630       if (!n_sample_syncs) {
9631         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9632         stream->all_keyframe = TRUE;
9633       } else {
9634         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9635           /* note that the first sample is index 1, not 0 */
9636           guint32 index;
9637
9638           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9639
9640           if (G_LIKELY (index > 0 && index <= n_samples)) {
9641             index -= 1;
9642             samples[index].keyframe = TRUE;
9643             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9644             /* and exit if we have enough samples */
9645             if (G_UNLIKELY (index >= n)) {
9646               i++;
9647               break;
9648             }
9649           }
9650         }
9651         /* save state */
9652         stream->stss_index = i;
9653       }
9654
9655       /* stps marks partial sync frames like open GOP I-Frames */
9656       if (stream->stps_present == TRUE) {
9657         guint32 n_sample_partial_syncs;
9658
9659         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9660
9661         /* if there are no entries, the stss table contains the real
9662          * sync samples */
9663         if (n_sample_partial_syncs) {
9664           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9665             /* note that the first sample is index 1, not 0 */
9666             guint32 index;
9667
9668             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9669
9670             if (G_LIKELY (index > 0 && index <= n_samples)) {
9671               index -= 1;
9672               samples[index].keyframe = TRUE;
9673               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9674               /* and exit if we have enough samples */
9675               if (G_UNLIKELY (index >= n)) {
9676                 i++;
9677                 break;
9678               }
9679             }
9680           }
9681           /* save state */
9682           stream->stps_index = i;
9683         }
9684       }
9685     } else {
9686       /* no stss, all samples are keyframes */
9687       stream->all_keyframe = TRUE;
9688       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9689     }
9690   }
9691
9692 ctts:
9693   /* composition time to sample */
9694   if (stream->ctts_present == TRUE) {
9695     guint32 n_composition_times;
9696     guint32 ctts_count;
9697     gint32 ctts_soffset;
9698
9699     /* Fill in the pts_offsets */
9700     cur = first;
9701     n_composition_times = stream->n_composition_times;
9702
9703     for (i = stream->ctts_index; i < n_composition_times; i++) {
9704       if (stream->ctts_sample_index >= stream->ctts_count
9705           || !stream->ctts_sample_index) {
9706         stream->ctts_count =
9707             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9708         stream->ctts_soffset =
9709             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9710         stream->ctts_sample_index = 0;
9711       }
9712
9713       ctts_count = stream->ctts_count;
9714       ctts_soffset = stream->ctts_soffset;
9715
9716       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9717         cur->pts_offset = ctts_soffset;
9718         cur++;
9719
9720         if (G_UNLIKELY (cur > last)) {
9721           /* save state */
9722           stream->ctts_sample_index = j + 1;
9723           goto done;
9724         }
9725       }
9726       stream->ctts_sample_index = 0;
9727       stream->ctts_index++;
9728     }
9729   }
9730 done:
9731   stream->stbl_index = n;
9732   /* if index has been completely parsed, free data that is no-longer needed */
9733   if (n + 1 == stream->n_samples) {
9734     gst_qtdemux_stbl_free (stream);
9735     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9736     if (qtdemux->pullbased) {
9737       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9738       while (n + 1 == stream->n_samples)
9739         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9740           break;
9741     }
9742   }
9743   GST_OBJECT_UNLOCK (qtdemux);
9744
9745   return TRUE;
9746
9747   /* SUCCESS */
9748 already_parsed:
9749   {
9750     GST_LOG_OBJECT (qtdemux,
9751         "Tried to parse up to sample %u but this sample has already been parsed",
9752         n);
9753     /* if fragmented, there may be more */
9754     if (qtdemux->fragmented && n == stream->stbl_index)
9755       goto done;
9756     GST_OBJECT_UNLOCK (qtdemux);
9757     return TRUE;
9758   }
9759   /* ERRORS */
9760 out_of_samples:
9761   {
9762     GST_LOG_OBJECT (qtdemux,
9763         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9764         stream->n_samples);
9765     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9766         (_("This file is corrupt and cannot be played.")), (NULL));
9767     return FALSE;
9768   }
9769 corrupt_file:
9770   {
9771     GST_OBJECT_UNLOCK (qtdemux);
9772     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9773         (_("This file is corrupt and cannot be played.")), (NULL));
9774     return FALSE;
9775   }
9776 }
9777
9778 /* collect all segment info for @stream.
9779  */
9780 static gboolean
9781 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9782     GNode * trak)
9783 {
9784   GNode *edts;
9785   /* accept edts if they contain gaps at start and there is only
9786    * one media segment */
9787   gboolean allow_pushbased_edts = TRUE;
9788   gint media_segments_count = 0;
9789
9790   /* parse and prepare segment info from the edit list */
9791   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9792   stream->n_segments = 0;
9793   stream->segments = NULL;
9794   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9795     GNode *elst;
9796     gint n_segments;
9797     gint segment_number, entry_size;
9798     guint64 time;
9799     GstClockTime stime;
9800     const guint8 *buffer;
9801     guint8 version;
9802     guint32 size;
9803
9804     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9805     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9806       goto done;
9807
9808     buffer = elst->data;
9809
9810     size = QT_UINT32 (buffer);
9811     /* version, flags, n_segments */
9812     if (size < 16) {
9813       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9814       goto done;
9815     }
9816     version = QT_UINT8 (buffer + 8);
9817     entry_size = (version == 1) ? 20 : 12;
9818
9819     n_segments = QT_UINT32 (buffer + 12);
9820
9821     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9822       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9823       goto done;
9824     }
9825
9826     /* we might allocate a bit too much, at least allocate 1 segment */
9827     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9828
9829     /* segments always start from 0 */
9830     time = 0;
9831     stime = 0;
9832     buffer += 16;
9833     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9834       guint64 duration;
9835       guint64 media_time;
9836       gboolean empty_edit = FALSE;
9837       QtDemuxSegment *segment;
9838       guint32 rate_int;
9839       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9840
9841       if (version == 1) {
9842         media_time = QT_UINT64 (buffer + 8);
9843         duration = QT_UINT64 (buffer);
9844         if (media_time == G_MAXUINT64)
9845           empty_edit = TRUE;
9846       } else {
9847         media_time = QT_UINT32 (buffer + 4);
9848         duration = QT_UINT32 (buffer);
9849         if (media_time == G_MAXUINT32)
9850           empty_edit = TRUE;
9851       }
9852
9853       if (!empty_edit)
9854         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9855
9856       segment = &stream->segments[segment_number];
9857
9858       /* time and duration expressed in global timescale */
9859       segment->time = stime;
9860       if (duration != 0 || empty_edit) {
9861         /* edge case: empty edits with duration=zero are treated here.
9862          * (files should not have these anyway). */
9863
9864         /* add non scaled values so we don't cause roundoff errors */
9865         time += duration;
9866         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9867         segment->duration = stime - segment->time;
9868       } else {
9869         /* zero duration does not imply media_start == media_stop
9870          * but, only specify media_start. The edit ends with the track. */
9871         stime = segment->duration = GST_CLOCK_TIME_NONE;
9872         /* Don't allow more edits after this one. */
9873         n_segments = segment_number + 1;
9874       }
9875       segment->stop_time = stime;
9876
9877       segment->trak_media_start = media_time;
9878       /* media_time expressed in stream timescale */
9879       if (!empty_edit) {
9880         segment->media_start = media_start;
9881         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9882             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9883         media_segments_count++;
9884       } else {
9885         segment->media_start = GST_CLOCK_TIME_NONE;
9886         segment->media_stop = GST_CLOCK_TIME_NONE;
9887       }
9888       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9889
9890       if (rate_int <= 1) {
9891         /* 0 is not allowed, some programs write 1 instead of the floating point
9892          * value */
9893         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9894             rate_int);
9895         segment->rate = 1;
9896       } else {
9897         segment->rate = rate_int / 65536.0;
9898       }
9899
9900       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9901           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9902           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9903           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9904           segment_number, GST_TIME_ARGS (segment->time),
9905           GST_TIME_ARGS (segment->duration),
9906           GST_TIME_ARGS (segment->media_start), media_time,
9907           GST_TIME_ARGS (segment->media_stop),
9908           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9909           stream->timescale);
9910       if (segment->stop_time > qtdemux->segment.stop &&
9911           !qtdemux->upstream_format_is_time) {
9912         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9913             " extends to %" GST_TIME_FORMAT
9914             " past the end of the declared movie duration %" GST_TIME_FORMAT
9915             " movie segment will be extended", segment_number,
9916             GST_TIME_ARGS (segment->stop_time),
9917             GST_TIME_ARGS (qtdemux->segment.stop));
9918         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9919       }
9920
9921       buffer += entry_size;
9922     }
9923     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9924     stream->n_segments = n_segments;
9925     if (media_segments_count != 1)
9926       allow_pushbased_edts = FALSE;
9927   }
9928 done:
9929
9930   /* push based does not handle segments, so act accordingly here,
9931    * and warn if applicable */
9932   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9933     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9934     /* remove and use default one below, we stream like it anyway */
9935     g_free (stream->segments);
9936     stream->segments = NULL;
9937     stream->n_segments = 0;
9938   }
9939
9940   /* no segments, create one to play the complete trak */
9941   if (stream->n_segments == 0) {
9942     GstClockTime stream_duration =
9943         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9944
9945     if (stream->segments == NULL)
9946       stream->segments = g_new (QtDemuxSegment, 1);
9947
9948     /* represent unknown our way */
9949     if (stream_duration == 0)
9950       stream_duration = GST_CLOCK_TIME_NONE;
9951
9952     stream->segments[0].time = 0;
9953     stream->segments[0].stop_time = stream_duration;
9954     stream->segments[0].duration = stream_duration;
9955     stream->segments[0].media_start = 0;
9956     stream->segments[0].media_stop = stream_duration;
9957     stream->segments[0].rate = 1.0;
9958     stream->segments[0].trak_media_start = 0;
9959
9960     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9961         GST_TIME_ARGS (stream_duration));
9962     stream->n_segments = 1;
9963     stream->dummy_segment = TRUE;
9964   }
9965   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9966
9967   return TRUE;
9968 }
9969
9970 /*
9971  * Parses the stsd atom of a svq3 trak looking for
9972  * the SMI and gama atoms.
9973  */
9974 static void
9975 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9976     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9977 {
9978   const guint8 *_gamma = NULL;
9979   GstBuffer *_seqh = NULL;
9980   const guint8 *stsd_data = stsd_entry_data;
9981   guint32 length = QT_UINT32 (stsd_data);
9982   guint16 version;
9983
9984   if (length < 32) {
9985     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9986     goto end;
9987   }
9988
9989   stsd_data += 16;
9990   length -= 16;
9991   version = QT_UINT16 (stsd_data);
9992   if (version == 3) {
9993     if (length >= 70) {
9994       length -= 70;
9995       stsd_data += 70;
9996       while (length > 8) {
9997         guint32 fourcc, size;
9998         const guint8 *data;
9999         size = QT_UINT32 (stsd_data);
10000         fourcc = QT_FOURCC (stsd_data + 4);
10001         data = stsd_data + 8;
10002
10003         if (size == 0) {
10004           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10005               "svq3 atom parsing");
10006           goto end;
10007         }
10008
10009         switch (fourcc) {
10010           case FOURCC_gama:{
10011             if (size == 12) {
10012               _gamma = data;
10013             } else {
10014               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10015                   " for gama atom, expected 12", size);
10016             }
10017             break;
10018           }
10019           case FOURCC_SMI_:{
10020             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10021               guint32 seqh_size;
10022               if (_seqh != NULL) {
10023                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10024                     " found, ignoring");
10025               } else {
10026                 seqh_size = QT_UINT32 (data + 4);
10027                 if (seqh_size > 0) {
10028                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10029                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10030                 }
10031               }
10032             }
10033             break;
10034           }
10035           default:{
10036             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10037                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10038           }
10039         }
10040
10041         if (size <= length) {
10042           length -= size;
10043           stsd_data += size;
10044         }
10045       }
10046     } else {
10047       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10048     }
10049   } else {
10050     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10051         G_GUINT16_FORMAT, version);
10052     goto end;
10053   }
10054
10055 end:
10056   if (gamma) {
10057     *gamma = _gamma;
10058   }
10059   if (seqh) {
10060     *seqh = _seqh;
10061   } else if (_seqh) {
10062     gst_buffer_unref (_seqh);
10063   }
10064 }
10065
10066 static gchar *
10067 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10068 {
10069   GNode *dinf;
10070   GstByteReader dref;
10071   gchar *uri = NULL;
10072
10073   /*
10074    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10075    * atom that might contain a 'data' atom with the rtsp uri.
10076    * This case was reported in bug #597497, some info about
10077    * the hndl atom can be found in TN1195
10078    */
10079   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10080   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10081
10082   if (dinf) {
10083     guint32 dref_num_entries = 0;
10084     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10085         gst_byte_reader_skip (&dref, 4) &&
10086         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10087       gint i;
10088
10089       /* search dref entries for hndl atom */
10090       for (i = 0; i < dref_num_entries; i++) {
10091         guint32 size = 0, type;
10092         guint8 string_len = 0;
10093         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10094             qt_atom_parser_get_fourcc (&dref, &type)) {
10095           if (type == FOURCC_hndl) {
10096             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10097
10098             /* skip data reference handle bytes and the
10099              * following pascal string and some extra 4
10100              * bytes I have no idea what are */
10101             if (!gst_byte_reader_skip (&dref, 4) ||
10102                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10103                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10104               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10105               break;
10106             }
10107
10108             /* iterate over the atoms to find the data atom */
10109             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10110               guint32 atom_size;
10111               guint32 atom_type;
10112
10113               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10114                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10115                 if (atom_type == FOURCC_data) {
10116                   const guint8 *uri_aux = NULL;
10117
10118                   /* found the data atom that might contain the rtsp uri */
10119                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10120                       "hndl atom, interpreting it as an URI");
10121                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10122                           &uri_aux)) {
10123                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10124                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10125                     else
10126                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10127                           "didn't contain a rtsp address");
10128                   } else {
10129                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10130                         "atom contents");
10131                   }
10132                   break;
10133                 }
10134                 /* skipping to the next entry */
10135                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10136                   break;
10137               } else {
10138                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10139                     "atom header");
10140                 break;
10141               }
10142             }
10143             break;
10144           }
10145           /* skip to the next entry */
10146           if (!gst_byte_reader_skip (&dref, size - 8))
10147             break;
10148         } else {
10149           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10150         }
10151       }
10152       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10153     }
10154   }
10155   return uri;
10156 }
10157
10158 #define AMR_NB_ALL_MODES        0x81ff
10159 #define AMR_WB_ALL_MODES        0x83ff
10160 static guint
10161 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10162 {
10163   /* The 'damr' atom is of the form:
10164    *
10165    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10166    *    32 b       8 b          16 b           8 b                 8 b
10167    *
10168    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10169    * represents the highest mode used in the stream (and thus the maximum
10170    * bitrate), with a couple of special cases as seen below.
10171    */
10172
10173   /* Map of frame type ID -> bitrate */
10174   static const guint nb_bitrates[] = {
10175     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10176   };
10177   static const guint wb_bitrates[] = {
10178     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10179   };
10180   GstMapInfo map;
10181   gsize max_mode;
10182   guint16 mode_set;
10183
10184   gst_buffer_map (buf, &map, GST_MAP_READ);
10185
10186   if (map.size != 0x11) {
10187     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10188     goto bad_data;
10189   }
10190
10191   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10192     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10193         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10194     goto bad_data;
10195   }
10196
10197   mode_set = QT_UINT16 (map.data + 13);
10198
10199   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10200     max_mode = 7 + (wb ? 1 : 0);
10201   else
10202     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10203     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10204
10205   if (max_mode == -1) {
10206     GST_DEBUG ("No mode indication was found (mode set) = %x",
10207         (guint) mode_set);
10208     goto bad_data;
10209   }
10210
10211   gst_buffer_unmap (buf, &map);
10212   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10213
10214 bad_data:
10215   gst_buffer_unmap (buf, &map);
10216   return 0;
10217 }
10218
10219 static gboolean
10220 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10221     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10222 {
10223   /*
10224    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10225    * [0 1 2]
10226    * [3 4 5]
10227    * [6 7 8]
10228    */
10229
10230   if (gst_byte_reader_get_remaining (reader) < 36)
10231     return FALSE;
10232
10233   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10234   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10235   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10236   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10237   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10238   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10239   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10240   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10241   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10242
10243   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10244   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10245       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10246       matrix[2] & 0xFF);
10247   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10248       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10249       matrix[5] & 0xFF);
10250   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10251       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10252       matrix[8] & 0xFF);
10253
10254   return TRUE;
10255 }
10256
10257 static void
10258 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10259     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10260 {
10261
10262 /* [a b c]
10263  * [d e f]
10264  * [g h i]
10265  *
10266  * This macro will only compare value abdegh, it expects cfi to have already
10267  * been checked
10268  */
10269 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10270                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10271
10272   /* only handle the cases where the last column has standard values */
10273   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10274     const gchar *rotation_tag = NULL;
10275
10276     /* no rotation needed */
10277     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10278       /* NOP */
10279     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10280       rotation_tag = "rotate-90";
10281     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10282       rotation_tag = "rotate-180";
10283     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10284       rotation_tag = "rotate-270";
10285     } else {
10286       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10287     }
10288
10289     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10290         GST_STR_NULL (rotation_tag));
10291     if (rotation_tag != NULL) {
10292       if (*taglist == NULL)
10293         *taglist = gst_tag_list_new_empty ();
10294       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10295           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10296     }
10297   } else {
10298     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10299   }
10300 }
10301
10302 static gboolean
10303 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10304     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10305 {
10306   GNode *adrm;
10307   guint32 adrm_size;
10308   GstBuffer *adrm_buf = NULL;
10309   QtDemuxAavdEncryptionInfo *info;
10310
10311   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10312   if (G_UNLIKELY (!adrm)) {
10313     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10314     return FALSE;
10315   }
10316   adrm_size = QT_UINT32 (adrm->data);
10317   adrm_buf =
10318       gst_buffer_new_wrapped (g_memdup (adrm->data, adrm_size), adrm_size);
10319
10320   stream->protection_scheme_type = FOURCC_aavd;
10321
10322   if (!stream->protection_scheme_info)
10323     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10324
10325   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10326
10327   if (info->default_properties)
10328     gst_structure_free (info->default_properties);
10329   info->default_properties = gst_structure_new ("application/x-aavd",
10330       "encrypted", G_TYPE_BOOLEAN, TRUE,
10331       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10332   gst_buffer_unref (adrm_buf);
10333
10334   *original_fmt = FOURCC_mp4a;
10335   return TRUE;
10336 }
10337
10338 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10339  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10340  * Common Encryption (cenc), the function will also parse the tenc box (defined
10341  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10342  * (typically an enc[v|a|t|s] sample entry); the function will set
10343  * @original_fmt to the fourcc of the original unencrypted stream format.
10344  * Returns TRUE if successful; FALSE otherwise. */
10345 static gboolean
10346 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10347     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10348 {
10349   GNode *sinf;
10350   GNode *frma;
10351   GNode *schm;
10352   GNode *schi;
10353   QtDemuxCencSampleSetInfo *info;
10354   GNode *tenc;
10355   const guint8 *tenc_data;
10356
10357   g_return_val_if_fail (qtdemux != NULL, FALSE);
10358   g_return_val_if_fail (stream != NULL, FALSE);
10359   g_return_val_if_fail (container != NULL, FALSE);
10360   g_return_val_if_fail (original_fmt != NULL, FALSE);
10361
10362   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10363   if (G_UNLIKELY (!sinf)) {
10364     if (stream->protection_scheme_type == FOURCC_cenc) {
10365       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10366           "mandatory for Common Encryption");
10367       return FALSE;
10368     }
10369     return TRUE;
10370   }
10371
10372   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10373   if (G_UNLIKELY (!frma)) {
10374     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10375     return FALSE;
10376   }
10377
10378   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10379   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10380       GST_FOURCC_ARGS (*original_fmt));
10381
10382   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10383   if (!schm) {
10384     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10385     return FALSE;
10386   }
10387   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10388   stream->protection_scheme_version =
10389       QT_UINT32 ((const guint8 *) schm->data + 16);
10390
10391   GST_DEBUG_OBJECT (qtdemux,
10392       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10393       "protection_scheme_version: %#010x",
10394       GST_FOURCC_ARGS (stream->protection_scheme_type),
10395       stream->protection_scheme_version);
10396
10397   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10398   if (!schi) {
10399     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10400     return FALSE;
10401   }
10402   if (stream->protection_scheme_type != FOURCC_cenc &&
10403       stream->protection_scheme_type != FOURCC_piff) {
10404     GST_ERROR_OBJECT (qtdemux,
10405         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10406         GST_FOURCC_ARGS (stream->protection_scheme_type));
10407     return FALSE;
10408   }
10409
10410   if (G_UNLIKELY (!stream->protection_scheme_info))
10411     stream->protection_scheme_info =
10412         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10413
10414   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10415
10416   if (stream->protection_scheme_type == FOURCC_cenc) {
10417     guint32 is_encrypted;
10418     guint8 iv_size;
10419     const guint8 *default_kid;
10420
10421     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10422     if (!tenc) {
10423       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10424           "which is mandatory for Common Encryption");
10425       return FALSE;
10426     }
10427     tenc_data = (const guint8 *) tenc->data + 12;
10428     is_encrypted = QT_UINT24 (tenc_data);
10429     iv_size = QT_UINT8 (tenc_data + 3);
10430     default_kid = (tenc_data + 4);
10431     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10432         is_encrypted, iv_size, default_kid);
10433   } else if (stream->protection_scheme_type == FOURCC_piff) {
10434     GstByteReader br;
10435     static const guint8 piff_track_encryption_uuid[] = {
10436       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10437       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10438     };
10439
10440     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10441     if (!tenc) {
10442       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10443           "which is mandatory for Common Encryption");
10444       return FALSE;
10445     }
10446
10447     tenc_data = (const guint8 *) tenc->data + 8;
10448     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10449       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10450       GST_ERROR_OBJECT (qtdemux,
10451           "Unsupported track encryption box with uuid: %s", box_uuid);
10452       g_free (box_uuid);
10453       return FALSE;
10454     }
10455     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10456     gst_byte_reader_init (&br, tenc_data, 20);
10457     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10458       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10459       return FALSE;
10460     }
10461     stream->protection_scheme_type = FOURCC_cenc;
10462   }
10463
10464   return TRUE;
10465 }
10466
10467 static gint
10468 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10469     QtDemuxStream ** stream2)
10470 {
10471   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10472 }
10473
10474 static gboolean
10475 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10476     GNode * stbl)
10477 {
10478   GNode *svmi;
10479
10480   /*parse svmi header if existing */
10481   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10482   if (svmi) {
10483     guint len = QT_UINT32 ((guint8 *) svmi->data);
10484     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10485     if (!version) {
10486       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10487       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10488       guint8 frame_type, frame_layout;
10489       guint32 stereo_mono_change_count;
10490
10491       if (len < 18)
10492         return FALSE;
10493
10494       /* MPEG-A stereo video */
10495       if (qtdemux->major_brand == FOURCC_ss02)
10496         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10497
10498       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10499       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10500       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10501
10502       switch (frame_type) {
10503         case 0:
10504           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10505           break;
10506         case 1:
10507           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10508           break;
10509         case 2:
10510           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10511           break;
10512         case 3:
10513           /* mode 3 is primary/secondary view sequence, ie
10514            * left/right views in separate tracks. See section 7.2
10515            * of ISO/IEC 23000-11:2009 */
10516           /* In the future this might be supported using related
10517            * streams, like an enhancement track - if files like this
10518            * ever exist */
10519           GST_FIXME_OBJECT (qtdemux,
10520               "Implement stereo video in separate streams");
10521       }
10522
10523       if ((frame_layout & 0x1) == 0)
10524         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10525
10526       GST_LOG_OBJECT (qtdemux,
10527           "StereoVideo: composition type: %u, is_left_first: %u",
10528           frame_type, frame_layout);
10529
10530       if (stereo_mono_change_count > 1) {
10531         GST_FIXME_OBJECT (qtdemux,
10532             "Mixed-mono flags are not yet supported in qtdemux.");
10533       }
10534
10535       stream->multiview_mode = mode;
10536       stream->multiview_flags = flags;
10537     }
10538   }
10539
10540   return TRUE;
10541 }
10542
10543 /* parse the traks.
10544  * With each track we associate a new QtDemuxStream that contains all the info
10545  * about the trak.
10546  * traks that do not decode to something (like strm traks) will not have a pad.
10547  */
10548 static gboolean
10549 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10550 {
10551   GstByteReader tkhd;
10552   int offset;
10553   GNode *mdia;
10554   GNode *mdhd;
10555   GNode *hdlr;
10556   GNode *minf;
10557   GNode *stbl;
10558   GNode *stsd;
10559   GNode *mp4a;
10560   GNode *mp4v;
10561   GNode *esds;
10562   GNode *tref;
10563   GNode *udta;
10564
10565   QtDemuxStream *stream = NULL;
10566   const guint8 *stsd_data;
10567   const guint8 *stsd_entry_data;
10568   guint remaining_stsd_len;
10569   guint stsd_entry_count;
10570   guint stsd_index;
10571   guint16 lang_code;            /* quicktime lang code or packed iso code */
10572   guint32 version;
10573   guint32 tkhd_flags = 0;
10574   guint8 tkhd_version = 0;
10575   guint32 w = 0, h = 0;
10576   guint value_size, stsd_len, len;
10577   guint32 track_id;
10578   guint32 dummy;
10579
10580   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10581
10582   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10583       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10584       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10585     goto corrupt_file;
10586
10587   /* pick between 64 or 32 bits */
10588   value_size = tkhd_version == 1 ? 8 : 4;
10589   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10590       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10591     goto corrupt_file;
10592
10593   /* Check if current moov has duplicated track_id */
10594   if (qtdemux_find_stream (qtdemux, track_id))
10595     goto existing_stream;
10596
10597   stream = _create_stream (qtdemux, track_id);
10598   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10599
10600   /* need defaults for fragments */
10601   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10602
10603   if ((tkhd_flags & 1) == 0)
10604     stream->disabled = TRUE;
10605
10606   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10607       tkhd_version, tkhd_flags, stream->track_id);
10608
10609   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10610     goto corrupt_file;
10611
10612   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10613     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10614     if (qtdemux->major_brand != FOURCC_mjp2 ||
10615         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10616       goto corrupt_file;
10617   }
10618
10619   len = QT_UINT32 ((guint8 *) mdhd->data);
10620   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10621   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10622   if (version == 0x01000000) {
10623     if (len < 42)
10624       goto corrupt_file;
10625     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10626     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10627     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10628   } else {
10629     if (len < 30)
10630       goto corrupt_file;
10631     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10632     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10633     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10634   }
10635
10636   if (lang_code < 0x400) {
10637     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10638   } else if (lang_code == 0x7fff) {
10639     stream->lang_id[0] = 0;     /* unspecified */
10640   } else {
10641     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10642     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10643     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10644     stream->lang_id[3] = 0;
10645   }
10646
10647   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10648       stream->timescale);
10649   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10650       stream->duration);
10651   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10652       lang_code, stream->lang_id);
10653
10654   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10655     goto corrupt_file;
10656
10657   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10658     /* chapters track reference */
10659     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10660     if (chap) {
10661       gsize length = GST_READ_UINT32_BE (chap->data);
10662       if (qtdemux->chapters_track_id)
10663         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10664
10665       if (length >= 12) {
10666         qtdemux->chapters_track_id =
10667             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10668       }
10669     }
10670   }
10671
10672   /* fragmented files may have bogus duration in moov */
10673   if (!qtdemux->fragmented &&
10674       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10675     guint64 tdur1, tdur2;
10676
10677     /* don't overflow */
10678     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10679     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10680
10681     /* HACK:
10682      * some of those trailers, nowadays, have prologue images that are
10683      * themselves video tracks as well. I haven't really found a way to
10684      * identify those yet, except for just looking at their duration. */
10685     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10686       GST_WARNING_OBJECT (qtdemux,
10687           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10688           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10689           "found, assuming preview image or something; skipping track",
10690           stream->duration, stream->timescale, qtdemux->duration,
10691           qtdemux->timescale);
10692       gst_qtdemux_stream_unref (stream);
10693       return TRUE;
10694     }
10695   }
10696
10697   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10698     goto corrupt_file;
10699
10700   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10701       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10702
10703   len = QT_UINT32 ((guint8 *) hdlr->data);
10704   if (len >= 20)
10705     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10706   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10707       GST_FOURCC_ARGS (stream->subtype));
10708
10709   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10710     goto corrupt_file;
10711
10712   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10713     goto corrupt_file;
10714
10715   /* Parse out svmi (and later st3d/sv3d) atoms */
10716   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10717     goto corrupt_file;
10718
10719   /* parse rest of tkhd */
10720   if (stream->subtype == FOURCC_vide) {
10721     guint32 matrix[9];
10722
10723     /* version 1 uses some 64-bit ints */
10724     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10725       goto corrupt_file;
10726
10727     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10728       goto corrupt_file;
10729
10730     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10731         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10732       goto corrupt_file;
10733
10734     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10735         &stream->stream_tags);
10736   }
10737
10738   /* parse stsd */
10739   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10740     goto corrupt_file;
10741   stsd_data = (const guint8 *) stsd->data;
10742
10743   /* stsd should at least have one entry */
10744   stsd_len = QT_UINT32 (stsd_data);
10745   if (stsd_len < 24) {
10746     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10747     if (stream->subtype == FOURCC_vivo) {
10748       gst_qtdemux_stream_unref (stream);
10749       return TRUE;
10750     } else {
10751       goto corrupt_file;
10752     }
10753   }
10754
10755   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10756   /* each stsd entry must contain at least 8 bytes */
10757   if (stream->stsd_entries_length == 0
10758       || stream->stsd_entries_length > stsd_len / 8) {
10759     stream->stsd_entries_length = 0;
10760     goto corrupt_file;
10761   }
10762   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10763   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10764   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10765
10766   stsd_entry_data = stsd_data + 16;
10767   remaining_stsd_len = stsd_len - 16;
10768   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10769     guint32 fourcc;
10770     gchar *codec = NULL;
10771     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10772
10773     /* and that entry should fit within stsd */
10774     len = QT_UINT32 (stsd_entry_data);
10775     if (len > remaining_stsd_len)
10776       goto corrupt_file;
10777
10778     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10779     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10780         GST_FOURCC_ARGS (entry->fourcc));
10781     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10782
10783     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10784       goto error_encrypted;
10785
10786     if (fourcc == FOURCC_aavd) {
10787       if (stream->subtype != FOURCC_soun) {
10788         GST_ERROR_OBJECT (qtdemux,
10789             "Unexpeced stsd type 'aavd' outside 'soun' track");
10790       } else {
10791         /* encrypted audio with sound sample description v0 */
10792         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10793         stream->protected = TRUE;
10794         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
10795           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10796       }
10797     }
10798
10799     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10800       /* FIXME this looks wrong, there might be multiple children
10801        * with the same type */
10802       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10803       stream->protected = TRUE;
10804       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10805         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10806     }
10807
10808     if (stream->subtype == FOURCC_vide) {
10809       GNode *colr;
10810       GNode *fiel;
10811       GNode *pasp;
10812       gboolean gray;
10813       gint depth, palette_size, palette_count;
10814       guint32 *palette_data = NULL;
10815
10816       entry->sampled = TRUE;
10817
10818       stream->display_width = w >> 16;
10819       stream->display_height = h >> 16;
10820
10821       offset = 16;
10822       if (len < 86)             /* TODO verify */
10823         goto corrupt_file;
10824
10825       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10826       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10827       entry->fps_n = 0;         /* this is filled in later */
10828       entry->fps_d = 0;         /* this is filled in later */
10829       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10830       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10831
10832       /* if color_table_id is 0, ctab atom must follow; however some files
10833        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10834        * if color table is not present we'll correct the value */
10835       if (entry->color_table_id == 0 &&
10836           (len < 90
10837               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10838         entry->color_table_id = -1;
10839       }
10840
10841       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10842           entry->width, entry->height, entry->bits_per_sample,
10843           entry->color_table_id);
10844
10845       depth = entry->bits_per_sample;
10846
10847       /* more than 32 bits means grayscale */
10848       gray = (depth > 32);
10849       /* low 32 bits specify the depth  */
10850       depth &= 0x1F;
10851
10852       /* different number of palette entries is determined by depth. */
10853       palette_count = 0;
10854       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10855         palette_count = (1 << depth);
10856       palette_size = palette_count * 4;
10857
10858       if (entry->color_table_id) {
10859         switch (palette_count) {
10860           case 0:
10861             break;
10862           case 2:
10863             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10864             break;
10865           case 4:
10866             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10867             break;
10868           case 16:
10869             if (gray)
10870               palette_data =
10871                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10872             else
10873               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10874             break;
10875           case 256:
10876             if (gray)
10877               palette_data =
10878                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10879             else
10880               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10881             break;
10882           default:
10883             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10884                 (_("The video in this file might not play correctly.")),
10885                 ("unsupported palette depth %d", depth));
10886             break;
10887         }
10888       } else {
10889         gint i, j, start, end;
10890
10891         if (len < 94)
10892           goto corrupt_file;
10893
10894         /* read table */
10895         start = QT_UINT32 (stsd_entry_data + offset + 70);
10896         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10897         end = QT_UINT16 (stsd_entry_data + offset + 76);
10898
10899         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10900             start, end, palette_count);
10901
10902         if (end > 255)
10903           end = 255;
10904         if (start > end)
10905           start = end;
10906
10907         if (len < 94 + (end - start) * 8)
10908           goto corrupt_file;
10909
10910         /* palette is always the same size */
10911         palette_data = g_malloc0 (256 * 4);
10912         palette_size = 256 * 4;
10913
10914         for (j = 0, i = start; i <= end; j++, i++) {
10915           guint32 a, r, g, b;
10916
10917           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10918           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10919           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10920           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10921
10922           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10923               (g & 0xff00) | (b >> 8);
10924         }
10925       }
10926
10927       if (entry->caps)
10928         gst_caps_unref (entry->caps);
10929
10930       entry->caps =
10931           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10932           &codec);
10933       if (G_UNLIKELY (!entry->caps)) {
10934         g_free (palette_data);
10935         goto unknown_stream;
10936       }
10937
10938       if (codec) {
10939         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10940             GST_TAG_VIDEO_CODEC, codec, NULL);
10941         g_free (codec);
10942         codec = NULL;
10943       }
10944
10945       if (palette_data) {
10946         GstStructure *s;
10947
10948         if (entry->rgb8_palette)
10949           gst_memory_unref (entry->rgb8_palette);
10950         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10951             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10952
10953         s = gst_caps_get_structure (entry->caps, 0);
10954
10955         /* non-raw video has a palette_data property. raw video has the palette as
10956          * an extra plane that we append to the output buffers before we push
10957          * them*/
10958         if (!gst_structure_has_name (s, "video/x-raw")) {
10959           GstBuffer *palette;
10960
10961           palette = gst_buffer_new ();
10962           gst_buffer_append_memory (palette, entry->rgb8_palette);
10963           entry->rgb8_palette = NULL;
10964
10965           gst_caps_set_simple (entry->caps, "palette_data",
10966               GST_TYPE_BUFFER, palette, NULL);
10967           gst_buffer_unref (palette);
10968         }
10969       } else if (palette_count != 0) {
10970         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10971             (NULL), ("Unsupported palette depth %d", depth));
10972       }
10973
10974       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10975           QT_UINT16 (stsd_entry_data + offset + 32));
10976
10977       esds = NULL;
10978       pasp = NULL;
10979       colr = NULL;
10980       fiel = NULL;
10981       /* pick 'the' stsd child */
10982       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10983       // We should skip parsing the stsd for non-protected streams if
10984       // the entry doesn't match the fourcc, since they don't change
10985       // format. However, for protected streams we can have partial
10986       // encryption, where parts of the stream are encrypted and parts
10987       // not. For both parts of such streams, we should ensure the
10988       // esds overrides are parsed for both from the stsd.
10989       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10990         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
10991           mp4v = NULL;
10992         else if (!stream->protected)
10993           mp4v = NULL;
10994       }
10995
10996       if (mp4v) {
10997         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10998         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10999         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11000         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11001       }
11002
11003       if (pasp) {
11004         const guint8 *pasp_data = (const guint8 *) pasp->data;
11005         gint len = QT_UINT32 (pasp_data);
11006
11007         if (len == 16) {
11008           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11009           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11010         } else {
11011           CUR_STREAM (stream)->par_w = 0;
11012           CUR_STREAM (stream)->par_h = 0;
11013         }
11014       } else {
11015         CUR_STREAM (stream)->par_w = 0;
11016         CUR_STREAM (stream)->par_h = 0;
11017       }
11018
11019       if (fiel) {
11020         const guint8 *fiel_data = (const guint8 *) fiel->data;
11021         gint len = QT_UINT32 (fiel_data);
11022
11023         if (len == 10) {
11024           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11025           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11026         }
11027       }
11028
11029       if (colr) {
11030         const guint8 *colr_data = (const guint8 *) colr->data;
11031         gint len = QT_UINT32 (colr_data);
11032
11033         if (len == 19 || len == 18) {
11034           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11035
11036           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11037             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11038             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11039             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11040             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11041
11042             CUR_STREAM (stream)->colorimetry.primaries =
11043                 gst_video_color_primaries_from_iso (primaries);
11044             CUR_STREAM (stream)->colorimetry.transfer =
11045                 gst_video_transfer_function_from_iso (transfer_function);
11046             CUR_STREAM (stream)->colorimetry.matrix =
11047                 gst_video_color_matrix_from_iso (matrix);
11048             CUR_STREAM (stream)->colorimetry.range =
11049                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11050                 GST_VIDEO_COLOR_RANGE_16_235;
11051           } else {
11052             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11053           }
11054         } else {
11055           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11056         }
11057       }
11058
11059       if (esds) {
11060         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11061             stream->stream_tags);
11062       } else {
11063         switch (fourcc) {
11064           case FOURCC_H264:
11065           case FOURCC_avc1:
11066           case FOURCC_avc3:
11067           {
11068             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11069             const guint8 *avc_data = stsd_entry_data + 0x56;
11070
11071             /* find avcC */
11072             while (len >= 0x8) {
11073               gint size;
11074
11075               if (QT_UINT32 (avc_data) <= len)
11076                 size = QT_UINT32 (avc_data) - 0x8;
11077               else
11078                 size = len - 0x8;
11079
11080               if (size < 1)
11081                 /* No real data, so break out */
11082                 break;
11083
11084               switch (QT_FOURCC (avc_data + 0x4)) {
11085                 case FOURCC_avcC:
11086                 {
11087                   /* parse, if found */
11088                   GstBuffer *buf;
11089
11090                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11091
11092                   /* First 4 bytes are the length of the atom, the next 4 bytes
11093                    * are the fourcc, the next 1 byte is the version, and the
11094                    * subsequent bytes are profile_tier_level structure like data. */
11095                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11096                       avc_data + 8 + 1, size - 1);
11097                   buf = gst_buffer_new_and_alloc (size);
11098                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11099                   gst_caps_set_simple (entry->caps,
11100                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11101                   gst_buffer_unref (buf);
11102
11103                   break;
11104                 }
11105                 case FOURCC_strf:
11106                 {
11107                   GstBuffer *buf;
11108
11109                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11110
11111                   /* First 4 bytes are the length of the atom, the next 4 bytes
11112                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11113                    * next 1 byte is the version, and the
11114                    * subsequent bytes are sequence parameter set like data. */
11115
11116                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11117                   if (size > 1) {
11118                     gst_codec_utils_h264_caps_set_level_and_profile
11119                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11120
11121                     buf = gst_buffer_new_and_alloc (size);
11122                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11123                     gst_caps_set_simple (entry->caps,
11124                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11125                     gst_buffer_unref (buf);
11126                   }
11127                   break;
11128                 }
11129                 case FOURCC_btrt:
11130                 {
11131                   guint avg_bitrate, max_bitrate;
11132
11133                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11134                   if (size < 12)
11135                     break;
11136
11137                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11138                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11139
11140                   if (!max_bitrate && !avg_bitrate)
11141                     break;
11142
11143                   /* Some muxers seem to swap the average and maximum bitrates
11144                    * (I'm looking at you, YouTube), so we swap for sanity. */
11145                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11146                     guint temp = avg_bitrate;
11147
11148                     avg_bitrate = max_bitrate;
11149                     max_bitrate = temp;
11150                   }
11151
11152                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11153                     gst_tag_list_add (stream->stream_tags,
11154                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11155                         max_bitrate, NULL);
11156                   }
11157                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11158                     gst_tag_list_add (stream->stream_tags,
11159                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11160                         NULL);
11161                   }
11162
11163                   break;
11164                 }
11165
11166                 default:
11167                   break;
11168               }
11169
11170               len -= size + 8;
11171               avc_data += size + 8;
11172             }
11173
11174             break;
11175           }
11176           case FOURCC_H265:
11177           case FOURCC_hvc1:
11178           case FOURCC_hev1:
11179           case FOURCC_dvh1:
11180           case FOURCC_dvhe:
11181           {
11182             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11183             const guint8 *hevc_data = stsd_entry_data + 0x56;
11184
11185             /* find hevc */
11186             while (len >= 0x8) {
11187               gint size;
11188
11189               if (QT_UINT32 (hevc_data) <= len)
11190                 size = QT_UINT32 (hevc_data) - 0x8;
11191               else
11192                 size = len - 0x8;
11193
11194               if (size < 1)
11195                 /* No real data, so break out */
11196                 break;
11197
11198               switch (QT_FOURCC (hevc_data + 0x4)) {
11199                 case FOURCC_hvcC:
11200                 {
11201                   /* parse, if found */
11202                   GstBuffer *buf;
11203
11204                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11205
11206                   /* First 4 bytes are the length of the atom, the next 4 bytes
11207                    * are the fourcc, the next 1 byte is the version, and the
11208                    * subsequent bytes are sequence parameter set like data. */
11209                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11210                       (entry->caps, hevc_data + 8 + 1, size - 1);
11211
11212                   buf = gst_buffer_new_and_alloc (size);
11213                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11214                   gst_caps_set_simple (entry->caps,
11215                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11216                   gst_buffer_unref (buf);
11217                   break;
11218                 }
11219                 default:
11220                   break;
11221               }
11222               len -= size + 8;
11223               hevc_data += size + 8;
11224             }
11225             break;
11226           }
11227           case FOURCC_mp4v:
11228           case FOURCC_MP4V:
11229           case FOURCC_fmp4:
11230           case FOURCC_FMP4:
11231           case FOURCC_xvid:
11232           case FOURCC_XVID:
11233           {
11234             GNode *glbl;
11235
11236             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11237                 GST_FOURCC_ARGS (fourcc));
11238
11239             /* codec data might be in glbl extension atom */
11240             glbl = mp4v ?
11241                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11242             if (glbl) {
11243               guint8 *data;
11244               GstBuffer *buf;
11245               gint len;
11246
11247               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11248               data = glbl->data;
11249               len = QT_UINT32 (data);
11250               if (len > 0x8) {
11251                 len -= 0x8;
11252                 buf = gst_buffer_new_and_alloc (len);
11253                 gst_buffer_fill (buf, 0, data + 8, len);
11254                 gst_caps_set_simple (entry->caps,
11255                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11256                 gst_buffer_unref (buf);
11257               }
11258             }
11259             break;
11260           }
11261           case FOURCC_mjp2:
11262           {
11263             /* see annex I of the jpeg2000 spec */
11264             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11265             const guint8 *data;
11266             const gchar *colorspace = NULL;
11267             gint ncomp = 0;
11268             guint32 ncomp_map = 0;
11269             gint32 *comp_map = NULL;
11270             guint32 nchan_def = 0;
11271             gint32 *chan_def = NULL;
11272
11273             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11274             /* some required atoms */
11275             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11276             if (!mjp2)
11277               break;
11278             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11279             if (!jp2h)
11280               break;
11281
11282             /* number of components; redundant with info in codestream, but useful
11283                to a muxer */
11284             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11285             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11286               break;
11287             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11288
11289             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11290             if (!colr)
11291               break;
11292             GST_DEBUG_OBJECT (qtdemux, "found colr");
11293             /* extract colour space info */
11294             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11295               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11296                 case 16:
11297                   colorspace = "sRGB";
11298                   break;
11299                 case 17:
11300                   colorspace = "GRAY";
11301                   break;
11302                 case 18:
11303                   colorspace = "sYUV";
11304                   break;
11305                 default:
11306                   colorspace = NULL;
11307                   break;
11308               }
11309             }
11310             if (!colorspace)
11311               /* colr is required, and only values 16, 17, and 18 are specified,
11312                  so error if we have no colorspace */
11313               break;
11314
11315             /* extract component mapping */
11316             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11317             if (cmap) {
11318               guint32 cmap_len = 0;
11319               int i;
11320               cmap_len = QT_UINT32 (cmap->data);
11321               if (cmap_len >= 8) {
11322                 /* normal box, subtract off header */
11323                 cmap_len -= 8;
11324                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11325                 if (cmap_len % 4 == 0) {
11326                   ncomp_map = (cmap_len / 4);
11327                   comp_map = g_new0 (gint32, ncomp_map);
11328                   for (i = 0; i < ncomp_map; i++) {
11329                     guint16 cmp;
11330                     guint8 mtyp, pcol;
11331                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11332                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11333                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11334                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11335                   }
11336                 }
11337               }
11338             }
11339             /* extract channel definitions */
11340             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11341             if (cdef) {
11342               guint32 cdef_len = 0;
11343               int i;
11344               cdef_len = QT_UINT32 (cdef->data);
11345               if (cdef_len >= 10) {
11346                 /* normal box, subtract off header and len */
11347                 cdef_len -= 10;
11348                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11349                 if (cdef_len % 6 == 0) {
11350                   nchan_def = (cdef_len / 6);
11351                   chan_def = g_new0 (gint32, nchan_def);
11352                   for (i = 0; i < nchan_def; i++)
11353                     chan_def[i] = -1;
11354                   for (i = 0; i < nchan_def; i++) {
11355                     guint16 cn, typ, asoc;
11356                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11357                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11358                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11359                     if (cn < nchan_def) {
11360                       switch (typ) {
11361                         case 0:
11362                           chan_def[cn] = asoc;
11363                           break;
11364                         case 1:
11365                           chan_def[cn] = 0;     /* alpha */
11366                           break;
11367                         default:
11368                           chan_def[cn] = -typ;
11369                       }
11370                     }
11371                   }
11372                 }
11373               }
11374             }
11375
11376             gst_caps_set_simple (entry->caps,
11377                 "num-components", G_TYPE_INT, ncomp, NULL);
11378             gst_caps_set_simple (entry->caps,
11379                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11380
11381             if (comp_map) {
11382               GValue arr = { 0, };
11383               GValue elt = { 0, };
11384               int i;
11385               g_value_init (&arr, GST_TYPE_ARRAY);
11386               g_value_init (&elt, G_TYPE_INT);
11387               for (i = 0; i < ncomp_map; i++) {
11388                 g_value_set_int (&elt, comp_map[i]);
11389                 gst_value_array_append_value (&arr, &elt);
11390               }
11391               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11392                   "component-map", &arr);
11393               g_value_unset (&elt);
11394               g_value_unset (&arr);
11395               g_free (comp_map);
11396             }
11397
11398             if (chan_def) {
11399               GValue arr = { 0, };
11400               GValue elt = { 0, };
11401               int i;
11402               g_value_init (&arr, GST_TYPE_ARRAY);
11403               g_value_init (&elt, G_TYPE_INT);
11404               for (i = 0; i < nchan_def; i++) {
11405                 g_value_set_int (&elt, chan_def[i]);
11406                 gst_value_array_append_value (&arr, &elt);
11407               }
11408               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11409                   "channel-definitions", &arr);
11410               g_value_unset (&elt);
11411               g_value_unset (&arr);
11412               g_free (chan_def);
11413             }
11414
11415             /* some optional atoms */
11416             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11417             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11418
11419             /* indicate possible fields in caps */
11420             if (field) {
11421               data = (guint8 *) field->data + 8;
11422               if (*data != 1)
11423                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11424                     (gint) * data, NULL);
11425             }
11426             /* add codec_data if provided */
11427             if (prefix) {
11428               GstBuffer *buf;
11429               gint len;
11430
11431               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11432               data = prefix->data;
11433               len = QT_UINT32 (data);
11434               if (len > 0x8) {
11435                 len -= 0x8;
11436                 buf = gst_buffer_new_and_alloc (len);
11437                 gst_buffer_fill (buf, 0, data + 8, len);
11438                 gst_caps_set_simple (entry->caps,
11439                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11440                 gst_buffer_unref (buf);
11441               }
11442             }
11443             break;
11444           }
11445           case FOURCC_SVQ3:
11446           case FOURCC_VP31:
11447           {
11448             GstBuffer *buf;
11449             GstBuffer *seqh = NULL;
11450             const guint8 *gamma_data = NULL;
11451             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11452
11453             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11454                 &seqh);
11455             if (gamma_data) {
11456               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11457                   QT_FP32 (gamma_data), NULL);
11458             }
11459             if (seqh) {
11460               /* sorry for the bad name, but we don't know what this is, other
11461                * than its own fourcc */
11462               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11463                   NULL);
11464               gst_buffer_unref (seqh);
11465             }
11466
11467             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11468             buf = gst_buffer_new_and_alloc (len);
11469             gst_buffer_fill (buf, 0, stsd_data, len);
11470             gst_caps_set_simple (entry->caps,
11471                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11472             gst_buffer_unref (buf);
11473             break;
11474           }
11475           case FOURCC_jpeg:
11476           {
11477             /* https://developer.apple.com/standards/qtff-2001.pdf,
11478              * page 92, "Video Sample Description", under table 3.1 */
11479             GstByteReader br;
11480
11481             const gint compressor_offset =
11482                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11483             const gint min_size = compressor_offset + 32 + 2 + 2;
11484             GNode *jpeg;
11485             guint32 len;
11486             guint16 color_table_id = 0;
11487             gboolean ok;
11488
11489             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11490
11491             /* recover information on interlaced/progressive */
11492             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11493             if (!jpeg)
11494               break;
11495
11496             len = QT_UINT32 (jpeg->data);
11497             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11498                 min_size);
11499             if (len >= min_size) {
11500               gst_byte_reader_init (&br, jpeg->data, len);
11501
11502               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11503               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11504               if (color_table_id != 0) {
11505                 /* the spec says there can be concatenated chunks in the data, and we want
11506                  * to find one called field. Walk through them. */
11507                 gint offset = min_size;
11508                 while (offset + 8 < len) {
11509                   guint32 size = 0, tag;
11510                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11511                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11512                   if (!ok || size < 8) {
11513                     GST_WARNING_OBJECT (qtdemux,
11514                         "Failed to walk optional chunk list");
11515                     break;
11516                   }
11517                   GST_DEBUG_OBJECT (qtdemux,
11518                       "Found optional %4.4s chunk, size %u",
11519                       (const char *) &tag, size);
11520                   if (tag == FOURCC_fiel) {
11521                     guint8 n_fields = 0, ordering = 0;
11522                     gst_byte_reader_get_uint8 (&br, &n_fields);
11523                     gst_byte_reader_get_uint8 (&br, &ordering);
11524                     if (n_fields == 1 || n_fields == 2) {
11525                       GST_DEBUG_OBJECT (qtdemux,
11526                           "Found fiel tag with %u fields, ordering %u",
11527                           n_fields, ordering);
11528                       if (n_fields == 2)
11529                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11530                             "interlace-mode", G_TYPE_STRING, "interleaved",
11531                             NULL);
11532                     } else {
11533                       GST_WARNING_OBJECT (qtdemux,
11534                           "Found fiel tag with invalid fields (%u)", n_fields);
11535                     }
11536                   }
11537                   offset += size;
11538                 }
11539               } else {
11540                 GST_DEBUG_OBJECT (qtdemux,
11541                     "Color table ID is 0, not trying to get interlacedness");
11542               }
11543             } else {
11544               GST_WARNING_OBJECT (qtdemux,
11545                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11546             }
11547
11548             break;
11549           }
11550           case FOURCC_rle_:
11551           case FOURCC_WRLE:
11552           {
11553             gst_caps_set_simple (entry->caps,
11554                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11555                 NULL);
11556             break;
11557           }
11558           case FOURCC_XiTh:
11559           {
11560             GNode *xith, *xdxt;
11561
11562             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11563             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11564             if (!xith)
11565               break;
11566
11567             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11568             if (!xdxt)
11569               break;
11570
11571             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11572             /* collect the headers and store them in a stream list so that we can
11573              * send them out first */
11574             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11575             break;
11576           }
11577           case FOURCC_ovc1:
11578           {
11579             GNode *ovc1;
11580             guint8 *ovc1_data;
11581             guint ovc1_len;
11582             GstBuffer *buf;
11583
11584             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11585             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11586             if (!ovc1)
11587               break;
11588             ovc1_data = ovc1->data;
11589             ovc1_len = QT_UINT32 (ovc1_data);
11590             if (ovc1_len <= 198) {
11591               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11592               break;
11593             }
11594             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11595             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11596             gst_caps_set_simple (entry->caps,
11597                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11598             gst_buffer_unref (buf);
11599             break;
11600           }
11601           case FOURCC_vc_1:
11602           {
11603             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11604             const guint8 *vc1_data = stsd_entry_data + 0x56;
11605
11606             /* find dvc1 */
11607             while (len >= 8) {
11608               gint size;
11609
11610               if (QT_UINT32 (vc1_data) <= len)
11611                 size = QT_UINT32 (vc1_data) - 8;
11612               else
11613                 size = len - 8;
11614
11615               if (size < 1)
11616                 /* No real data, so break out */
11617                 break;
11618
11619               switch (QT_FOURCC (vc1_data + 0x4)) {
11620                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11621                 {
11622                   GstBuffer *buf;
11623
11624                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11625                   buf = gst_buffer_new_and_alloc (size);
11626                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11627                   gst_caps_set_simple (entry->caps,
11628                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11629                   gst_buffer_unref (buf);
11630                   break;
11631                 }
11632                 default:
11633                   break;
11634               }
11635               len -= size + 8;
11636               vc1_data += size + 8;
11637             }
11638             break;
11639           }
11640           case FOURCC_av01:
11641           {
11642             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11643             const guint8 *av1_data = stsd_entry_data + 0x56;
11644
11645             /* find av1C */
11646             while (len >= 0x8) {
11647               gint size;
11648
11649               if (QT_UINT32 (av1_data) <= len)
11650                 size = QT_UINT32 (av1_data) - 0x8;
11651               else
11652                 size = len - 0x8;
11653
11654               if (size < 1)
11655                 /* No real data, so break out */
11656                 break;
11657
11658               switch (QT_FOURCC (av1_data + 0x4)) {
11659                 case FOURCC_av1C:
11660                 {
11661                   /* parse, if found */
11662                   GstBuffer *buf;
11663                   guint8 pres_delay_field;
11664
11665                   GST_DEBUG_OBJECT (qtdemux,
11666                       "found av1C codec_data in stsd of size %d", size);
11667
11668                   /* not enough data, just ignore and hope for the best */
11669                   if (size < 5)
11670                     break;
11671
11672                   /* Content is:
11673                    * 4 bytes: atom length
11674                    * 4 bytes: fourcc
11675                    * 1 byte: version
11676                    * 3 bytes: flags
11677                    * 3 bits: reserved
11678                    * 1 bits:  initial_presentation_delay_present
11679                    * 4 bits: initial_presentation_delay (if present else reserved
11680                    * rest: OBUs.
11681                    */
11682
11683                   if (av1_data[9] != 0) {
11684                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11685                     break;
11686                   }
11687
11688                   /* We skip initial_presentation_delay* for now */
11689                   pres_delay_field = *(av1_data + 12);
11690                   if (pres_delay_field & (1 << 5)) {
11691                     gst_caps_set_simple (entry->caps,
11692                         "presentation-delay", G_TYPE_INT,
11693                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11694                   }
11695                   if (size > 5) {
11696                     buf = gst_buffer_new_and_alloc (size - 5);
11697                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11698                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11699                     gst_caps_set_simple (entry->caps,
11700                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11701                     gst_buffer_unref (buf);
11702                   }
11703                   break;
11704                 }
11705                 default:
11706                   break;
11707               }
11708
11709               len -= size + 8;
11710               av1_data += size + 8;
11711             }
11712
11713             break;
11714           }
11715
11716             /* TODO: Need to parse vpcC for VP8 codec too.
11717              * Note that VPCodecConfigurationBox (vpcC) is defined for
11718              * vp08, vp09, and vp10 fourcc. */
11719           case FOURCC_vp09:
11720           {
11721             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11722             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11723
11724             /* find vpcC */
11725             while (len >= 0x8) {
11726               gint size;
11727
11728               if (QT_UINT32 (vpcc_data) <= len)
11729                 size = QT_UINT32 (vpcc_data) - 0x8;
11730               else
11731                 size = len - 0x8;
11732
11733               if (size < 1)
11734                 /* No real data, so break out */
11735                 break;
11736
11737               switch (QT_FOURCC (vpcc_data + 0x4)) {
11738                 case FOURCC_vpcC:
11739                 {
11740                   const gchar *profile_str = NULL;
11741                   const gchar *chroma_format_str = NULL;
11742                   guint8 profile;
11743                   guint8 bitdepth;
11744                   guint8 chroma_format;
11745                   GstVideoColorimetry cinfo;
11746
11747                   /* parse, if found */
11748                   GST_DEBUG_OBJECT (qtdemux,
11749                       "found vp codec_data in stsd of size %d", size);
11750
11751                   /* the meaning of "size" is length of the atom body, excluding
11752                    * atom length and fourcc fields */
11753                   if (size < 12)
11754                     break;
11755
11756                   /* Content is:
11757                    * 4 bytes: atom length
11758                    * 4 bytes: fourcc
11759                    * 1 byte: version
11760                    * 3 bytes: flags
11761                    * 1 byte: profile
11762                    * 1 byte: level
11763                    * 4 bits: bitDepth
11764                    * 3 bits: chromaSubsampling
11765                    * 1 bit: videoFullRangeFlag
11766                    * 1 byte: colourPrimaries
11767                    * 1 byte: transferCharacteristics
11768                    * 1 byte: matrixCoefficients
11769                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11770                    * rest: codecIntializationData (not used for vp8 and vp9)
11771                    */
11772
11773                   if (vpcc_data[8] != 1) {
11774                     GST_WARNING_OBJECT (qtdemux,
11775                         "unknown vpcC version %d", vpcc_data[8]);
11776                     break;
11777                   }
11778
11779                   profile = vpcc_data[12];
11780                   switch (profile) {
11781                     case 0:
11782                       profile_str = "0";
11783                       break;
11784                     case 1:
11785                       profile_str = "1";
11786                       break;
11787                     case 2:
11788                       profile_str = "2";
11789                       break;
11790                     case 3:
11791                       profile_str = "3";
11792                       break;
11793                     default:
11794                       break;
11795                   }
11796
11797                   if (profile_str) {
11798                     gst_caps_set_simple (entry->caps,
11799                         "profile", G_TYPE_STRING, profile_str, NULL);
11800                   }
11801
11802                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11803                    * but webm spec define various ones. Add level to caps
11804                    * if we really need it then */
11805
11806                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11807                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11808                     gst_caps_set_simple (entry->caps,
11809                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11810                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11811                   }
11812
11813                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11814                   switch (chroma_format) {
11815                     case 0:
11816                     case 1:
11817                       chroma_format_str = "4:2:0";
11818                       break;
11819                     case 2:
11820                       chroma_format_str = "4:2:2";
11821                       break;
11822                     case 3:
11823                       chroma_format_str = "4:4:4";
11824                       break;
11825                     default:
11826                       break;
11827                   }
11828
11829                   if (chroma_format_str) {
11830                     gst_caps_set_simple (entry->caps,
11831                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11832                         NULL);
11833                   }
11834
11835                   if ((vpcc_data[14] & 0x1) != 0)
11836                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
11837                   else
11838                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
11839                   cinfo.primaries =
11840                       gst_video_color_primaries_from_iso (vpcc_data[15]);
11841                   cinfo.transfer =
11842                       gst_video_transfer_function_from_iso (vpcc_data[16]);
11843                   cinfo.matrix =
11844                       gst_video_color_matrix_from_iso (vpcc_data[17]);
11845
11846                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
11847                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
11848                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
11849                     /* set this only if all values are known, otherwise this
11850                      * might overwrite valid ones parsed from other color box */
11851                     CUR_STREAM (stream)->colorimetry = cinfo;
11852                   }
11853                   break;
11854                 }
11855                 default:
11856                   break;
11857               }
11858
11859               len -= size + 8;
11860               vpcc_data += size + 8;
11861             }
11862
11863             break;
11864           }
11865           default:
11866             break;
11867         }
11868       }
11869
11870       GST_INFO_OBJECT (qtdemux,
11871           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11872           GST_FOURCC_ARGS (fourcc), entry->caps);
11873
11874     } else if (stream->subtype == FOURCC_soun) {
11875       GNode *wave;
11876       int version, samplesize;
11877       guint16 compression_id;
11878       gboolean amrwb = FALSE;
11879
11880       offset = 16;
11881       /* sample description entry (16) + sound sample description v0 (20) */
11882       if (len < 36)
11883         goto corrupt_file;
11884
11885       version = QT_UINT32 (stsd_entry_data + offset);
11886       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11887       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11888       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11889       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11890
11891       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11892       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11893           QT_UINT32 (stsd_entry_data + offset + 4));
11894       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11895       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11896       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11897       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11898           QT_UINT16 (stsd_entry_data + offset + 14));
11899       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11900
11901       if (compression_id == 0xfffe)
11902         entry->sampled = TRUE;
11903
11904       /* first assume uncompressed audio */
11905       entry->bytes_per_sample = samplesize / 8;
11906       entry->samples_per_frame = entry->n_channels;
11907       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11908       entry->samples_per_packet = entry->samples_per_frame;
11909       entry->bytes_per_packet = entry->bytes_per_sample;
11910
11911       offset = 36;
11912
11913       if (version == 0x00010000) {
11914         /* sample description entry (16) + sound sample description v1 (20+16) */
11915         if (len < 52)
11916           goto corrupt_file;
11917
11918         /* take information from here over the normal sample description */
11919         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11920         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11921         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11922         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11923
11924         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
11925         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11926             entry->samples_per_packet);
11927         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11928             entry->bytes_per_packet);
11929         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11930             entry->bytes_per_frame);
11931         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11932             entry->bytes_per_sample);
11933
11934         if (!entry->sampled && entry->bytes_per_packet) {
11935           entry->samples_per_frame = (entry->bytes_per_frame /
11936               entry->bytes_per_packet) * entry->samples_per_packet;
11937           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11938               entry->samples_per_frame);
11939         }
11940       } else if (version == 0x00020000) {
11941         /* sample description entry (16) + sound sample description v2 (56) */
11942         if (len < 72)
11943           goto corrupt_file;
11944
11945         /* take information from here over the normal sample description */
11946         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
11947         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11948         entry->samples_per_frame = entry->n_channels;
11949         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
11950         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
11951         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
11952         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
11953
11954         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11955         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11956         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11957         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11958             entry->bytes_per_sample * 8);
11959         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11960             QT_UINT32 (stsd_entry_data + offset + 24));
11961         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11962             entry->bytes_per_packet);
11963         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11964             entry->samples_per_packet);
11965       } else if (version != 0x00000) {
11966         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11967             version);
11968       }
11969
11970       switch (fourcc) {
11971           /* Yes, these have to be hard-coded */
11972         case FOURCC_MAC6:
11973         {
11974           entry->samples_per_packet = 6;
11975           entry->bytes_per_packet = 1;
11976           entry->bytes_per_frame = 1 * entry->n_channels;
11977           entry->bytes_per_sample = 1;
11978           entry->samples_per_frame = 6 * entry->n_channels;
11979           break;
11980         }
11981         case FOURCC_MAC3:
11982         {
11983           entry->samples_per_packet = 3;
11984           entry->bytes_per_packet = 1;
11985           entry->bytes_per_frame = 1 * entry->n_channels;
11986           entry->bytes_per_sample = 1;
11987           entry->samples_per_frame = 3 * entry->n_channels;
11988           break;
11989         }
11990         case FOURCC_ima4:
11991         {
11992           entry->samples_per_packet = 64;
11993           entry->bytes_per_packet = 34;
11994           entry->bytes_per_frame = 34 * entry->n_channels;
11995           entry->bytes_per_sample = 2;
11996           entry->samples_per_frame = 64 * entry->n_channels;
11997           break;
11998         }
11999         case FOURCC_ulaw:
12000         case FOURCC_alaw:
12001         {
12002           entry->samples_per_packet = 1;
12003           entry->bytes_per_packet = 1;
12004           entry->bytes_per_frame = 1 * entry->n_channels;
12005           entry->bytes_per_sample = 1;
12006           entry->samples_per_frame = 1 * entry->n_channels;
12007           break;
12008         }
12009         case FOURCC_agsm:
12010         {
12011           entry->samples_per_packet = 160;
12012           entry->bytes_per_packet = 33;
12013           entry->bytes_per_frame = 33 * entry->n_channels;
12014           entry->bytes_per_sample = 2;
12015           entry->samples_per_frame = 160 * entry->n_channels;
12016           break;
12017         }
12018           /* fix up any invalid header information from above */
12019         case FOURCC_twos:
12020         case FOURCC_sowt:
12021         case FOURCC_raw_:
12022         case FOURCC_lpcm:
12023           /* Sometimes these are set to 0 in the sound sample descriptions so
12024            * let's try to infer useful values from the other information we
12025            * have available */
12026           if (entry->bytes_per_sample == 0)
12027             entry->bytes_per_sample =
12028                 entry->bytes_per_frame / entry->n_channels;
12029           if (entry->bytes_per_sample == 0)
12030             entry->bytes_per_sample = samplesize / 8;
12031
12032           if (entry->bytes_per_frame == 0)
12033             entry->bytes_per_frame =
12034                 entry->bytes_per_sample * entry->n_channels;
12035
12036           if (entry->bytes_per_packet == 0)
12037             entry->bytes_per_packet = entry->bytes_per_sample;
12038
12039           if (entry->samples_per_frame == 0)
12040             entry->samples_per_frame = entry->n_channels;
12041
12042           if (entry->samples_per_packet == 0)
12043             entry->samples_per_packet = entry->samples_per_frame;
12044
12045           break;
12046         case FOURCC_in24:
12047         case FOURCC_in32:
12048         case FOURCC_fl32:
12049         case FOURCC_fl64:
12050         case FOURCC_s16l:{
12051           switch (fourcc) {
12052             case FOURCC_in24:
12053               entry->bytes_per_sample = 3;
12054               break;
12055             case FOURCC_in32:
12056             case FOURCC_fl32:
12057               entry->bytes_per_sample = 4;
12058               break;
12059             case FOURCC_fl64:
12060               entry->bytes_per_sample = 8;
12061               break;
12062             case FOURCC_s16l:
12063               entry->bytes_per_sample = 2;
12064               break;
12065             default:
12066               g_assert_not_reached ();
12067               break;
12068           }
12069           entry->samples_per_frame = entry->n_channels;
12070           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12071           entry->samples_per_packet = entry->samples_per_frame;
12072           entry->bytes_per_packet = entry->bytes_per_sample;
12073           break;
12074         }
12075         default:
12076           break;
12077       }
12078
12079       if (entry->caps)
12080         gst_caps_unref (entry->caps);
12081
12082       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12083           stsd_entry_data + 32, len - 16, &codec);
12084
12085       switch (fourcc) {
12086         case FOURCC_in24:
12087         case FOURCC_in32:
12088         case FOURCC_fl32:
12089         case FOURCC_fl64:
12090         {
12091           GNode *enda;
12092           GNode *fmt;
12093
12094           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12095
12096           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12097           if (!enda) {
12098             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12099             if (wave)
12100               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12101           }
12102           if (enda) {
12103             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12104             const gchar *format_str;
12105
12106             switch (fourcc) {
12107               case FOURCC_in24:
12108                 format_str = (enda_value) ? "S24LE" : "S24BE";
12109                 break;
12110               case FOURCC_in32:
12111                 format_str = (enda_value) ? "S32LE" : "S32BE";
12112                 break;
12113               case FOURCC_fl32:
12114                 format_str = (enda_value) ? "F32LE" : "F32BE";
12115                 break;
12116               case FOURCC_fl64:
12117                 format_str = (enda_value) ? "F64LE" : "F64BE";
12118                 break;
12119               default:
12120                 g_assert_not_reached ();
12121                 break;
12122             }
12123             gst_caps_set_simple (entry->caps,
12124                 "format", G_TYPE_STRING, format_str, NULL);
12125           }
12126           break;
12127         }
12128         case FOURCC_owma:
12129         {
12130           const guint8 *owma_data;
12131           const gchar *codec_name = NULL;
12132           guint owma_len;
12133           GstBuffer *buf;
12134           gint version = 1;
12135           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12136           /* FIXME this should also be gst_riff_strf_auds,
12137            * but the latter one is actually missing bits-per-sample :( */
12138           typedef struct
12139           {
12140             gint16 wFormatTag;
12141             gint16 nChannels;
12142             gint32 nSamplesPerSec;
12143             gint32 nAvgBytesPerSec;
12144             gint16 nBlockAlign;
12145             gint16 wBitsPerSample;
12146             gint16 cbSize;
12147           } WAVEFORMATEX;
12148           WAVEFORMATEX *wfex;
12149
12150           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12151           owma_data = stsd_entry_data;
12152           owma_len = QT_UINT32 (owma_data);
12153           if (owma_len <= 54) {
12154             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12155             break;
12156           }
12157           wfex = (WAVEFORMATEX *) (owma_data + 36);
12158           buf = gst_buffer_new_and_alloc (owma_len - 54);
12159           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12160           if (wfex->wFormatTag == 0x0161) {
12161             codec_name = "Windows Media Audio";
12162             version = 2;
12163           } else if (wfex->wFormatTag == 0x0162) {
12164             codec_name = "Windows Media Audio 9 Pro";
12165             version = 3;
12166           } else if (wfex->wFormatTag == 0x0163) {
12167             codec_name = "Windows Media Audio 9 Lossless";
12168             /* is that correct? gstffmpegcodecmap.c is missing it, but
12169              * fluendo codec seems to support it */
12170             version = 4;
12171           }
12172
12173           gst_caps_set_simple (entry->caps,
12174               "codec_data", GST_TYPE_BUFFER, buf,
12175               "wmaversion", G_TYPE_INT, version,
12176               "block_align", G_TYPE_INT,
12177               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12178               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12179               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12180               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12181           gst_buffer_unref (buf);
12182
12183           if (codec_name) {
12184             g_free (codec);
12185             codec = g_strdup (codec_name);
12186           }
12187           break;
12188         }
12189         case FOURCC_wma_:
12190         {
12191           gint len = QT_UINT32 (stsd_entry_data) - offset;
12192           const guint8 *wfex_data = stsd_entry_data + offset;
12193           const gchar *codec_name = NULL;
12194           gint version = 1;
12195           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12196           /* FIXME this should also be gst_riff_strf_auds,
12197            * but the latter one is actually missing bits-per-sample :( */
12198           typedef struct
12199           {
12200             gint16 wFormatTag;
12201             gint16 nChannels;
12202             gint32 nSamplesPerSec;
12203             gint32 nAvgBytesPerSec;
12204             gint16 nBlockAlign;
12205             gint16 wBitsPerSample;
12206             gint16 cbSize;
12207           } WAVEFORMATEX;
12208           WAVEFORMATEX wfex;
12209
12210           /* FIXME: unify with similar wavformatex parsing code above */
12211           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12212
12213           /* find wfex */
12214           while (len >= 8) {
12215             gint size;
12216
12217             if (QT_UINT32 (wfex_data) <= len)
12218               size = QT_UINT32 (wfex_data) - 8;
12219             else
12220               size = len - 8;
12221
12222             if (size < 1)
12223               /* No real data, so break out */
12224               break;
12225
12226             switch (QT_FOURCC (wfex_data + 4)) {
12227               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12228               {
12229                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12230
12231                 if (size < 8 + 18)
12232                   break;
12233
12234                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12235                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12236                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12237                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12238                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12239                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12240                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12241
12242                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12243                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12244                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12245                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12246                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12247                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12248
12249                 if (wfex.wFormatTag == 0x0161) {
12250                   codec_name = "Windows Media Audio";
12251                   version = 2;
12252                 } else if (wfex.wFormatTag == 0x0162) {
12253                   codec_name = "Windows Media Audio 9 Pro";
12254                   version = 3;
12255                 } else if (wfex.wFormatTag == 0x0163) {
12256                   codec_name = "Windows Media Audio 9 Lossless";
12257                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12258                    * fluendo codec seems to support it */
12259                   version = 4;
12260                 }
12261
12262                 gst_caps_set_simple (entry->caps,
12263                     "wmaversion", G_TYPE_INT, version,
12264                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12265                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12266                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12267                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12268
12269                 if (size > wfex.cbSize) {
12270                   GstBuffer *buf;
12271
12272                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12273                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12274                       size - wfex.cbSize);
12275                   gst_caps_set_simple (entry->caps,
12276                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12277                   gst_buffer_unref (buf);
12278                 } else {
12279                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12280                 }
12281
12282                 if (codec_name) {
12283                   g_free (codec);
12284                   codec = g_strdup (codec_name);
12285                 }
12286                 break;
12287               }
12288               default:
12289                 break;
12290             }
12291             len -= size + 8;
12292             wfex_data += size + 8;
12293           }
12294           break;
12295         }
12296         case FOURCC_opus:
12297         {
12298           const guint8 *opus_data;
12299           guint8 *channel_mapping = NULL;
12300           guint32 rate;
12301           guint8 channels;
12302           guint8 channel_mapping_family;
12303           guint8 stream_count;
12304           guint8 coupled_count;
12305           guint8 i;
12306
12307           opus_data = stsd_entry_data;
12308
12309           channels = GST_READ_UINT8 (opus_data + 45);
12310           rate = GST_READ_UINT32_LE (opus_data + 48);
12311           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12312           stream_count = GST_READ_UINT8 (opus_data + 55);
12313           coupled_count = GST_READ_UINT8 (opus_data + 56);
12314
12315           if (channels > 0) {
12316             channel_mapping = g_malloc (channels * sizeof (guint8));
12317             for (i = 0; i < channels; i++)
12318               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12319           }
12320
12321           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12322               channel_mapping_family, stream_count, coupled_count,
12323               channel_mapping);
12324           break;
12325         }
12326         default:
12327           break;
12328       }
12329
12330       if (codec) {
12331         GstStructure *s;
12332         gint bitrate = 0;
12333
12334         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12335             GST_TAG_AUDIO_CODEC, codec, NULL);
12336         g_free (codec);
12337         codec = NULL;
12338
12339         /* some bitrate info may have ended up in caps */
12340         s = gst_caps_get_structure (entry->caps, 0);
12341         gst_structure_get_int (s, "bitrate", &bitrate);
12342         if (bitrate > 0)
12343           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12344               GST_TAG_BITRATE, bitrate, NULL);
12345       }
12346
12347       esds = NULL;
12348       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12349       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12350         if (stream->protected) {
12351           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12352             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12353           }
12354           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12355             mp4a = NULL;
12356           }
12357         } else {
12358           mp4a = NULL;
12359         }
12360       }
12361
12362       wave = NULL;
12363       if (mp4a) {
12364         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12365         if (wave)
12366           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12367         if (!esds)
12368           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12369       }
12370
12371
12372       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12373          16 bits is a byte-swapped wave-style codec identifier,
12374          and we can find a WAVE header internally to a 'wave' atom here.
12375          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12376          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12377          is big-endian).
12378        */
12379       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12380         if (len < offset + 20) {
12381           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12382         } else {
12383           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12384           const guint8 *data = stsd_entry_data + offset + 16;
12385           GNode *wavenode;
12386           GNode *waveheadernode;
12387
12388           wavenode = g_node_new ((guint8 *) data);
12389           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12390             const guint8 *waveheader;
12391             guint32 headerlen;
12392
12393             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12394             if (waveheadernode) {
12395               waveheader = (const guint8 *) waveheadernode->data;
12396               headerlen = QT_UINT32 (waveheader);
12397
12398               if (headerlen > 8) {
12399                 gst_riff_strf_auds *header = NULL;
12400                 GstBuffer *headerbuf;
12401                 GstBuffer *extra;
12402
12403                 waveheader += 8;
12404                 headerlen -= 8;
12405
12406                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12407                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12408
12409                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12410                         headerbuf, &header, &extra)) {
12411                   gst_caps_unref (entry->caps);
12412                   /* FIXME: Need to do something with the channel reorder map */
12413                   entry->caps =
12414                       gst_riff_create_audio_caps (header->format, NULL, header,
12415                       extra, NULL, NULL, NULL);
12416
12417                   if (extra)
12418                     gst_buffer_unref (extra);
12419                   g_free (header);
12420                 }
12421               }
12422             } else
12423               GST_DEBUG ("Didn't find waveheadernode for this codec");
12424           }
12425           g_node_destroy (wavenode);
12426         }
12427       } else if (esds) {
12428         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12429             stream->stream_tags);
12430       } else {
12431         switch (fourcc) {
12432 #if 0
12433             /* FIXME: what is in the chunk? */
12434           case FOURCC_QDMC:
12435           {
12436             gint len = QT_UINT32 (stsd_data);
12437
12438             /* seems to be always = 116 = 0x74 */
12439             break;
12440           }
12441 #endif
12442           case FOURCC_QDM2:
12443           {
12444             gint len = QT_UINT32 (stsd_entry_data);
12445
12446             if (len > 0x3C) {
12447               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12448
12449               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12450               gst_caps_set_simple (entry->caps,
12451                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12452               gst_buffer_unref (buf);
12453             }
12454             gst_caps_set_simple (entry->caps,
12455                 "samplesize", G_TYPE_INT, samplesize, NULL);
12456             break;
12457           }
12458           case FOURCC_alac:
12459           {
12460             GNode *alac, *wave = NULL;
12461
12462             /* apparently, m4a has this atom appended directly in the stsd entry,
12463              * while mov has it in a wave atom */
12464             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12465             if (alac) {
12466               /* alac now refers to stsd entry atom */
12467               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12468               if (wave)
12469                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12470               else
12471                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12472             }
12473             if (alac) {
12474               const guint8 *alac_data = alac->data;
12475               gint len = QT_UINT32 (alac->data);
12476               GstBuffer *buf;
12477
12478               if (len < 36) {
12479                 GST_DEBUG_OBJECT (qtdemux,
12480                     "discarding alac atom with unexpected len %d", len);
12481               } else {
12482                 /* codec-data contains alac atom size and prefix,
12483                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12484                 buf = gst_buffer_new_and_alloc (len);
12485                 gst_buffer_fill (buf, 0, alac->data, len);
12486                 gst_caps_set_simple (entry->caps,
12487                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12488                 gst_buffer_unref (buf);
12489
12490                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12491                 entry->n_channels = QT_UINT8 (alac_data + 21);
12492                 entry->rate = QT_UINT32 (alac_data + 32);
12493                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12494               }
12495             }
12496             gst_caps_set_simple (entry->caps,
12497                 "samplesize", G_TYPE_INT, samplesize, NULL);
12498             break;
12499           }
12500           case FOURCC_fLaC:
12501           {
12502             /* The codingname of the sample entry is 'fLaC' */
12503             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12504
12505             if (flac) {
12506               /* The 'dfLa' box is added to the sample entry to convey
12507                  initializing information for the decoder. */
12508               const GNode *dfla =
12509                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12510
12511               if (dfla) {
12512                 const guint32 len = QT_UINT32 (dfla->data);
12513
12514                 /* Must contain at least dfLa box header (12),
12515                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12516                 if (len < 50) {
12517                   GST_DEBUG_OBJECT (qtdemux,
12518                       "discarding dfla atom with unexpected len %d", len);
12519                 } else {
12520                   /* skip dfLa header to get the METADATA_BLOCKs */
12521                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12522                   const guint32 metadata_blocks_len = len - 12;
12523
12524                   gchar *stream_marker = g_strdup ("fLaC");
12525                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12526                       strlen (stream_marker));
12527
12528                   guint32 index = 0;
12529                   guint32 remainder = 0;
12530                   guint32 block_size = 0;
12531                   gboolean is_last = FALSE;
12532
12533                   GValue array = G_VALUE_INIT;
12534                   GValue value = G_VALUE_INIT;
12535
12536                   g_value_init (&array, GST_TYPE_ARRAY);
12537                   g_value_init (&value, GST_TYPE_BUFFER);
12538
12539                   gst_value_set_buffer (&value, block);
12540                   gst_value_array_append_value (&array, &value);
12541                   g_value_reset (&value);
12542
12543                   gst_buffer_unref (block);
12544
12545                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12546                    * of data, and we haven't already finished parsing */
12547                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12548                     remainder = metadata_blocks_len - index;
12549
12550                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12551                     block_size = 4 +
12552                         (metadata_blocks[index + 1] << 16) +
12553                         (metadata_blocks[index + 2] << 8) +
12554                         metadata_blocks[index + 3];
12555
12556                     /* be careful not to read off end of box */
12557                     if (block_size > remainder) {
12558                       break;
12559                     }
12560
12561                     is_last = metadata_blocks[index] >> 7;
12562
12563                     block = gst_buffer_new_and_alloc (block_size);
12564
12565                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12566                         block_size);
12567
12568                     gst_value_set_buffer (&value, block);
12569                     gst_value_array_append_value (&array, &value);
12570                     g_value_reset (&value);
12571
12572                     gst_buffer_unref (block);
12573
12574                     index += block_size;
12575                   }
12576
12577                   /* only append the metadata if we successfully read all of it */
12578                   if (is_last) {
12579                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12580                             (stream)->caps, 0), "streamheader", &array);
12581                   } else {
12582                     GST_WARNING_OBJECT (qtdemux,
12583                         "discarding all METADATA_BLOCKs due to invalid "
12584                         "block_size %d at idx %d, rem %d", block_size, index,
12585                         remainder);
12586                   }
12587
12588                   g_value_unset (&value);
12589                   g_value_unset (&array);
12590
12591                   /* The sample rate obtained from the stsd may not be accurate
12592                    * since it cannot represent rates greater than 65535Hz, so
12593                    * override that value with the sample rate from the
12594                    * METADATA_BLOCK_STREAMINFO block */
12595                   CUR_STREAM (stream)->rate =
12596                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12597                 }
12598               }
12599             }
12600             break;
12601           }
12602           case FOURCC_sawb:
12603             /* Fallthrough! */
12604             amrwb = TRUE;
12605           case FOURCC_samr:
12606           {
12607             gint len = QT_UINT32 (stsd_entry_data);
12608
12609             if (len > 0x24) {
12610               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12611               guint bitrate;
12612
12613               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12614
12615               /* If we have enough data, let's try to get the 'damr' atom. See
12616                * the 3GPP container spec (26.244) for more details. */
12617               if ((len - 0x34) > 8 &&
12618                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12619                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12620                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12621               }
12622
12623               gst_caps_set_simple (entry->caps,
12624                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12625               gst_buffer_unref (buf);
12626             }
12627             break;
12628           }
12629           case FOURCC_mp4a:
12630           {
12631             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12632             gint len = QT_UINT32 (stsd_entry_data);
12633
12634             if (len >= 34) {
12635               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12636
12637               if (sound_version == 1) {
12638                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12639                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12640                 guint8 codec_data[2];
12641                 GstBuffer *buf;
12642                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12643
12644                 gint sample_rate_index =
12645                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12646
12647                 /* build AAC codec data */
12648                 codec_data[0] = profile << 3;
12649                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12650                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12651                 codec_data[1] |= (channels & 0xF) << 3;
12652
12653                 buf = gst_buffer_new_and_alloc (2);
12654                 gst_buffer_fill (buf, 0, codec_data, 2);
12655                 gst_caps_set_simple (entry->caps,
12656                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12657                 gst_buffer_unref (buf);
12658               }
12659             }
12660             break;
12661           }
12662           case FOURCC_lpcm:
12663           case FOURCC_in24:
12664           case FOURCC_in32:
12665           case FOURCC_fl32:
12666           case FOURCC_fl64:
12667           case FOURCC_s16l:
12668             /* Fully handled elsewhere */
12669             break;
12670           default:
12671             GST_INFO_OBJECT (qtdemux,
12672                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12673             break;
12674         }
12675       }
12676       GST_INFO_OBJECT (qtdemux,
12677           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12678           GST_FOURCC_ARGS (fourcc), entry->caps);
12679
12680     } else if (stream->subtype == FOURCC_strm) {
12681       if (fourcc == FOURCC_rtsp) {
12682         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12683       } else {
12684         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12685             GST_FOURCC_ARGS (fourcc));
12686         goto unknown_stream;
12687       }
12688       entry->sampled = TRUE;
12689     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12690         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12691         || stream->subtype == FOURCC_clcp) {
12692
12693       entry->sampled = TRUE;
12694       entry->sparse = TRUE;
12695
12696       entry->caps =
12697           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12698           &codec);
12699       if (codec) {
12700         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12701             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12702         g_free (codec);
12703         codec = NULL;
12704       }
12705
12706       /* hunt for sort-of codec data */
12707       switch (fourcc) {
12708         case FOURCC_mp4s:
12709         {
12710           GNode *mp4s = NULL;
12711           GNode *esds = NULL;
12712
12713           /* look for palette in a stsd->mp4s->esds sub-atom */
12714           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12715           if (mp4s)
12716             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12717           if (esds == NULL) {
12718             /* Invalid STSD */
12719             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12720             break;
12721           }
12722
12723           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12724               stream->stream_tags);
12725           break;
12726         }
12727         default:
12728           GST_INFO_OBJECT (qtdemux,
12729               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12730           break;
12731       }
12732       GST_INFO_OBJECT (qtdemux,
12733           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12734           GST_FOURCC_ARGS (fourcc), entry->caps);
12735     } else {
12736       /* everything in 1 sample */
12737       entry->sampled = TRUE;
12738
12739       entry->caps =
12740           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12741           &codec);
12742
12743       if (entry->caps == NULL)
12744         goto unknown_stream;
12745
12746       if (codec) {
12747         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12748             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12749         g_free (codec);
12750         codec = NULL;
12751       }
12752     }
12753
12754     /* promote to sampled format */
12755     if (entry->fourcc == FOURCC_samr) {
12756       /* force mono 8000 Hz for AMR */
12757       entry->sampled = TRUE;
12758       entry->n_channels = 1;
12759       entry->rate = 8000;
12760     } else if (entry->fourcc == FOURCC_sawb) {
12761       /* force mono 16000 Hz for AMR-WB */
12762       entry->sampled = TRUE;
12763       entry->n_channels = 1;
12764       entry->rate = 16000;
12765     } else if (entry->fourcc == FOURCC_mp4a) {
12766       entry->sampled = TRUE;
12767     }
12768
12769
12770     stsd_entry_data += len;
12771     remaining_stsd_len -= len;
12772
12773   }
12774
12775   /* collect sample information */
12776   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12777     goto samples_failed;
12778
12779   if (qtdemux->fragmented) {
12780     guint64 offset;
12781
12782     /* need all moov samples as basis; probably not many if any at all */
12783     /* prevent moof parsing taking of at this time */
12784     offset = qtdemux->moof_offset;
12785     qtdemux->moof_offset = 0;
12786     if (stream->n_samples &&
12787         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12788       qtdemux->moof_offset = offset;
12789       goto samples_failed;
12790     }
12791     qtdemux->moof_offset = offset;
12792     /* movie duration more reliable in this case (e.g. mehd) */
12793     if (qtdemux->segment.duration &&
12794         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12795       stream->duration =
12796           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12797   }
12798
12799   /* configure segments */
12800   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12801     goto segments_failed;
12802
12803   /* add some language tag, if useful */
12804   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12805       strcmp (stream->lang_id, "und")) {
12806     const gchar *lang_code;
12807
12808     /* convert ISO 639-2 code to ISO 639-1 */
12809     lang_code = gst_tag_get_language_code (stream->lang_id);
12810     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12811         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12812   }
12813
12814   /* Check for UDTA tags */
12815   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12816     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12817   }
12818
12819   /* Insert and sort new stream in track-id order.
12820    * This will help in comparing old/new streams during stream update check */
12821   g_ptr_array_add (qtdemux->active_streams, stream);
12822   g_ptr_array_sort (qtdemux->active_streams,
12823       (GCompareFunc) qtdemux_track_id_compare_func);
12824   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12825       QTDEMUX_N_STREAMS (qtdemux));
12826
12827   return TRUE;
12828
12829 /* ERRORS */
12830 corrupt_file:
12831   {
12832     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12833         (_("This file is corrupt and cannot be played.")), (NULL));
12834     if (stream)
12835       gst_qtdemux_stream_unref (stream);
12836     return FALSE;
12837   }
12838 error_encrypted:
12839   {
12840     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12841     gst_qtdemux_stream_unref (stream);
12842     return FALSE;
12843   }
12844 samples_failed:
12845 segments_failed:
12846   {
12847     /* we posted an error already */
12848     /* free stbl sub-atoms */
12849     gst_qtdemux_stbl_free (stream);
12850     gst_qtdemux_stream_unref (stream);
12851     return FALSE;
12852   }
12853 existing_stream:
12854   {
12855     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12856         track_id);
12857     return TRUE;
12858   }
12859 unknown_stream:
12860   {
12861     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12862         GST_FOURCC_ARGS (stream->subtype));
12863     gst_qtdemux_stream_unref (stream);
12864     return TRUE;
12865   }
12866 }
12867
12868 /* If we can estimate the overall bitrate, and don't have information about the
12869  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12870  * the overall bitrate minus the sum of the bitrates of all other streams. This
12871  * should be useful for the common case where we have one audio and one video
12872  * stream and can estimate the bitrate of one, but not the other. */
12873 static void
12874 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12875 {
12876   QtDemuxStream *stream = NULL;
12877   gint64 size, sys_bitrate, sum_bitrate = 0;
12878   GstClockTime duration;
12879   guint bitrate;
12880   gint i;
12881
12882   if (qtdemux->fragmented)
12883     return;
12884
12885   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12886
12887   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12888       || size <= 0) {
12889     GST_DEBUG_OBJECT (qtdemux,
12890         "Size in bytes of the stream not known - bailing");
12891     return;
12892   }
12893
12894   /* Subtract the header size */
12895   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12896       size, qtdemux->header_size);
12897
12898   if (size < qtdemux->header_size)
12899     return;
12900
12901   size = size - qtdemux->header_size;
12902
12903   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12904     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12905     return;
12906   }
12907
12908   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12909     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12910     switch (str->subtype) {
12911       case FOURCC_soun:
12912       case FOURCC_vide:
12913         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12914             CUR_STREAM (str)->caps);
12915         /* retrieve bitrate, prefer avg then max */
12916         bitrate = 0;
12917         if (str->stream_tags) {
12918           if (gst_tag_list_get_uint (str->stream_tags,
12919                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12920             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12921           if (gst_tag_list_get_uint (str->stream_tags,
12922                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12923             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12924           if (gst_tag_list_get_uint (str->stream_tags,
12925                   GST_TAG_BITRATE, &bitrate))
12926             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12927         }
12928         if (bitrate)
12929           sum_bitrate += bitrate;
12930         else {
12931           if (stream) {
12932             GST_DEBUG_OBJECT (qtdemux,
12933                 ">1 stream with unknown bitrate - bailing");
12934             return;
12935           } else
12936             stream = str;
12937         }
12938
12939       default:
12940         /* For other subtypes, we assume no significant impact on bitrate */
12941         break;
12942     }
12943   }
12944
12945   if (!stream) {
12946     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12947     return;
12948   }
12949
12950   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12951
12952   if (sys_bitrate < sum_bitrate) {
12953     /* This can happen, since sum_bitrate might be derived from maximum
12954      * bitrates and not average bitrates */
12955     GST_DEBUG_OBJECT (qtdemux,
12956         "System bitrate less than sum bitrate - bailing");
12957     return;
12958   }
12959
12960   bitrate = sys_bitrate - sum_bitrate;
12961   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12962       ", Stream bitrate = %u", sys_bitrate, bitrate);
12963
12964   if (!stream->stream_tags)
12965     stream->stream_tags = gst_tag_list_new_empty ();
12966   else
12967     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12968
12969   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12970       GST_TAG_BITRATE, bitrate, NULL);
12971 }
12972
12973 static GstFlowReturn
12974 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12975 {
12976   GstFlowReturn ret = GST_FLOW_OK;
12977   gint i;
12978
12979   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
12980
12981   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12982     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12983     guint32 sample_num = 0;
12984
12985     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12986         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12987
12988     if (qtdemux->fragmented && qtdemux->pullbased) {
12989       /* need all moov samples first */
12990       GST_OBJECT_LOCK (qtdemux);
12991       while (stream->n_samples == 0)
12992         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12993           break;
12994       GST_OBJECT_UNLOCK (qtdemux);
12995     } else {
12996       /* discard any stray moof */
12997       qtdemux->moof_offset = 0;
12998     }
12999
13000     /* prepare braking */
13001     if (ret != GST_FLOW_ERROR)
13002       ret = GST_FLOW_OK;
13003
13004     /* in pull mode, we should have parsed some sample info by now;
13005      * and quite some code will not handle no samples.
13006      * in push mode, we'll just have to deal with it */
13007     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13008       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13009       g_ptr_array_remove_index (qtdemux->active_streams, i);
13010       i--;
13011       continue;
13012     } else if (stream->track_id == qtdemux->chapters_track_id &&
13013         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13014       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13015          so that it doesn't look like a subtitle track */
13016       g_ptr_array_remove_index (qtdemux->active_streams, i);
13017       i--;
13018       continue;
13019     }
13020
13021     /* parse the initial sample for use in setting the frame rate cap */
13022     while (sample_num == 0 && sample_num < stream->n_samples) {
13023       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13024         break;
13025       ++sample_num;
13026     }
13027   }
13028
13029   return ret;
13030 }
13031
13032 static gboolean
13033 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13034 {
13035   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13036 }
13037
13038 static gboolean
13039 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13040 {
13041   gint i;
13042
13043   /* Different length, updated */
13044   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13045     return TRUE;
13046
13047   /* streams in list are sorted in track-id order */
13048   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13049     /* Different stream-id, updated */
13050     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13051             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13052       return TRUE;
13053   }
13054
13055   return FALSE;
13056 }
13057
13058 static gboolean
13059 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13060     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13061 {
13062   /* Connect old stream's srcpad to new stream */
13063   newstream->pad = oldstream->pad;
13064   oldstream->pad = NULL;
13065
13066   /* unset new_stream to prevent stream-start event */
13067   newstream->new_stream = FALSE;
13068
13069   return gst_qtdemux_configure_stream (qtdemux, newstream);
13070 }
13071
13072 static gboolean
13073 qtdemux_update_streams (GstQTDemux * qtdemux)
13074 {
13075   gint i;
13076   g_assert (qtdemux->streams_aware);
13077
13078   /* At below, figure out which stream in active_streams has identical stream-id
13079    * with that of in old_streams. If there is matching stream-id,
13080    * corresponding newstream will not be exposed again,
13081    * but demux will reuse srcpad of matched old stream
13082    *
13083    * active_streams : newly created streams from the latest moov
13084    * old_streams : existing streams (belong to previous moov)
13085    */
13086
13087   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13088     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13089     QtDemuxStream *oldstream = NULL;
13090     guint target;
13091
13092     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13093         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13094
13095     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13096             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13097       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13098
13099       /* null pad stream cannot be reused */
13100       if (oldstream->pad == NULL)
13101         oldstream = NULL;
13102     }
13103
13104     if (oldstream) {
13105       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13106
13107       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13108         return FALSE;
13109
13110       /* we don't need to preserve order of old streams */
13111       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13112     } else {
13113       GstTagList *list;
13114
13115       /* now we have all info and can expose */
13116       list = stream->stream_tags;
13117       stream->stream_tags = NULL;
13118       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13119         return FALSE;
13120     }
13121   }
13122
13123   return TRUE;
13124 }
13125
13126 /* Must be called with expose lock */
13127 static GstFlowReturn
13128 qtdemux_expose_streams (GstQTDemux * qtdemux)
13129 {
13130   gint i;
13131
13132   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13133
13134   if (!qtdemux_is_streams_update (qtdemux)) {
13135     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13136     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13137       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13138       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13139       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13140         return GST_FLOW_ERROR;
13141     }
13142
13143     g_ptr_array_set_size (qtdemux->old_streams, 0);
13144     qtdemux->need_segment = TRUE;
13145
13146     return GST_FLOW_OK;
13147   }
13148
13149   if (qtdemux->streams_aware) {
13150     if (!qtdemux_update_streams (qtdemux))
13151       return GST_FLOW_ERROR;
13152   } else {
13153     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13154       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13155       GstTagList *list;
13156
13157       /* now we have all info and can expose */
13158       list = stream->stream_tags;
13159       stream->stream_tags = NULL;
13160       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13161         return GST_FLOW_ERROR;
13162
13163     }
13164   }
13165
13166   gst_qtdemux_guess_bitrate (qtdemux);
13167
13168   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13169
13170   /* If we have still old_streams, it's no more used stream */
13171   for (i = 0; i < qtdemux->old_streams->len; i++) {
13172     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13173
13174     if (stream->pad) {
13175       GstEvent *event;
13176
13177       event = gst_event_new_eos ();
13178       if (qtdemux->segment_seqnum)
13179         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13180
13181       gst_pad_push_event (stream->pad, event);
13182     }
13183   }
13184
13185   g_ptr_array_set_size (qtdemux->old_streams, 0);
13186
13187   /* check if we should post a redirect in case there is a single trak
13188    * and it is a redirecting trak */
13189   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13190       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13191     GstMessage *m;
13192
13193     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13194         "an external content");
13195     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13196         gst_structure_new ("redirect",
13197             "new-location", G_TYPE_STRING,
13198             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13199     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13200     g_free (qtdemux->redirect_location);
13201     qtdemux->redirect_location =
13202         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13203   }
13204
13205   g_ptr_array_foreach (qtdemux->active_streams,
13206       (GFunc) qtdemux_do_allocation, qtdemux);
13207
13208   qtdemux->need_segment = TRUE;
13209
13210   qtdemux->exposed = TRUE;
13211   return GST_FLOW_OK;
13212 }
13213
13214 typedef struct
13215 {
13216   GstStructure *structure;      /* helper for sort function */
13217   gchar *location;
13218   guint min_req_bitrate;
13219   guint min_req_qt_version;
13220 } GstQtReference;
13221
13222 static gint
13223 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13224 {
13225   GstQtReference *ref_a = (GstQtReference *) a;
13226   GstQtReference *ref_b = (GstQtReference *) b;
13227
13228   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13229     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13230
13231   /* known bitrates go before unknown; higher bitrates go first */
13232   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13233 }
13234
13235 /* sort the redirects and post a message for the application.
13236  */
13237 static void
13238 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13239 {
13240   GstQtReference *best;
13241   GstStructure *s;
13242   GstMessage *msg;
13243   GValue list_val = { 0, };
13244   GList *l;
13245
13246   g_assert (references != NULL);
13247
13248   references = g_list_sort (references, qtdemux_redirects_sort_func);
13249
13250   best = (GstQtReference *) references->data;
13251
13252   g_value_init (&list_val, GST_TYPE_LIST);
13253
13254   for (l = references; l != NULL; l = l->next) {
13255     GstQtReference *ref = (GstQtReference *) l->data;
13256     GValue struct_val = { 0, };
13257
13258     ref->structure = gst_structure_new ("redirect",
13259         "new-location", G_TYPE_STRING, ref->location, NULL);
13260
13261     if (ref->min_req_bitrate > 0) {
13262       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13263           ref->min_req_bitrate, NULL);
13264     }
13265
13266     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13267     g_value_set_boxed (&struct_val, ref->structure);
13268     gst_value_list_append_value (&list_val, &struct_val);
13269     g_value_unset (&struct_val);
13270     /* don't free anything here yet, since we need best->structure below */
13271   }
13272
13273   g_assert (best != NULL);
13274   s = gst_structure_copy (best->structure);
13275
13276   if (g_list_length (references) > 1) {
13277     gst_structure_set_value (s, "locations", &list_val);
13278   }
13279
13280   g_value_unset (&list_val);
13281
13282   for (l = references; l != NULL; l = l->next) {
13283     GstQtReference *ref = (GstQtReference *) l->data;
13284
13285     gst_structure_free (ref->structure);
13286     g_free (ref->location);
13287     g_free (ref);
13288   }
13289   g_list_free (references);
13290
13291   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13292   g_free (qtdemux->redirect_location);
13293   qtdemux->redirect_location =
13294       g_strdup (gst_structure_get_string (s, "new-location"));
13295   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13296   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13297 }
13298
13299 /* look for redirect nodes, collect all redirect information and
13300  * process it.
13301  */
13302 static gboolean
13303 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13304 {
13305   GNode *rmra, *rmda, *rdrf;
13306
13307   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13308   if (rmra) {
13309     GList *redirects = NULL;
13310
13311     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13312     while (rmda) {
13313       GstQtReference ref = { NULL, NULL, 0, 0 };
13314       GNode *rmdr, *rmvc;
13315
13316       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13317         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13318         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13319             ref.min_req_bitrate);
13320       }
13321
13322       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13323         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13324         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13325
13326 #ifndef GST_DISABLE_GST_DEBUG
13327         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13328 #endif
13329         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13330
13331         GST_LOG_OBJECT (qtdemux,
13332             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13333             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13334             bitmask, check_type);
13335         if (package == FOURCC_qtim && check_type == 0) {
13336           ref.min_req_qt_version = version;
13337         }
13338       }
13339
13340       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13341       if (rdrf) {
13342         guint32 ref_type;
13343         guint8 *ref_data;
13344         guint ref_len;
13345
13346         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13347         if (ref_len > 20) {
13348           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13349           ref_data = (guint8 *) rdrf->data + 20;
13350           if (ref_type == FOURCC_alis) {
13351             guint record_len, record_version, fn_len;
13352
13353             if (ref_len > 70) {
13354               /* MacOSX alias record, google for alias-layout.txt */
13355               record_len = QT_UINT16 (ref_data + 4);
13356               record_version = QT_UINT16 (ref_data + 4 + 2);
13357               fn_len = QT_UINT8 (ref_data + 50);
13358               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13359                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13360               }
13361             } else {
13362               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13363                   ref_len);
13364             }
13365           } else if (ref_type == FOURCC_url_) {
13366             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13367           } else {
13368             GST_DEBUG_OBJECT (qtdemux,
13369                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13370                 GST_FOURCC_ARGS (ref_type));
13371           }
13372           if (ref.location != NULL) {
13373             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13374             redirects =
13375                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13376           } else {
13377             GST_WARNING_OBJECT (qtdemux,
13378                 "Failed to extract redirect location from rdrf atom");
13379           }
13380         } else {
13381           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13382         }
13383       }
13384
13385       /* look for others */
13386       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13387     }
13388
13389     if (redirects != NULL) {
13390       qtdemux_process_redirects (qtdemux, redirects);
13391     }
13392   }
13393   return TRUE;
13394 }
13395
13396 static GstTagList *
13397 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13398 {
13399   const gchar *fmt;
13400
13401   if (tags == NULL) {
13402     tags = gst_tag_list_new_empty ();
13403     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13404   }
13405
13406   if (qtdemux->major_brand == FOURCC_mjp2)
13407     fmt = "Motion JPEG 2000";
13408   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13409     fmt = "3GP";
13410   else if (qtdemux->major_brand == FOURCC_qt__)
13411     fmt = "Quicktime";
13412   else if (qtdemux->fragmented)
13413     fmt = "ISO fMP4";
13414   else
13415     fmt = "ISO MP4/M4A";
13416
13417   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13418       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13419
13420   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13421       fmt, NULL);
13422
13423   return tags;
13424 }
13425
13426 /* we have read the complete moov node now.
13427  * This function parses all of the relevant info, creates the traks and
13428  * prepares all data structures for playback
13429  */
13430 static gboolean
13431 qtdemux_parse_tree (GstQTDemux * qtdemux)
13432 {
13433   GNode *mvhd;
13434   GNode *trak;
13435   GNode *udta;
13436   GNode *mvex;
13437   GNode *pssh;
13438   guint64 creation_time;
13439   GstDateTime *datetime = NULL;
13440   gint version;
13441
13442   /* make sure we have a usable taglist */
13443   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13444
13445   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13446   if (mvhd == NULL) {
13447     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13448     return qtdemux_parse_redirects (qtdemux);
13449   }
13450
13451   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13452   if (version == 1) {
13453     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13454     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13455     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13456   } else if (version == 0) {
13457     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13458     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13459     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13460   } else {
13461     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13462     return FALSE;
13463   }
13464
13465   /* Moving qt creation time (secs since 1904) to unix time */
13466   if (creation_time != 0) {
13467     /* Try to use epoch first as it should be faster and more commonly found */
13468     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13469       gint64 now_s;
13470
13471       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13472       /* some data cleansing sanity */
13473       now_s = g_get_real_time () / G_USEC_PER_SEC;
13474       if (now_s + 24 * 3600 < creation_time) {
13475         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13476       } else {
13477         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13478       }
13479     } else {
13480       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13481       GDateTime *dt, *dt_local;
13482
13483       dt = g_date_time_add_seconds (base_dt, creation_time);
13484       dt_local = g_date_time_to_local (dt);
13485       datetime = gst_date_time_new_from_g_date_time (dt_local);
13486
13487       g_date_time_unref (base_dt);
13488       g_date_time_unref (dt);
13489     }
13490   }
13491   if (datetime) {
13492     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13493     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13494         datetime, NULL);
13495     gst_date_time_unref (datetime);
13496   }
13497
13498   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13499   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13500
13501   /* check for fragmented file and get some (default) data */
13502   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13503   if (mvex) {
13504     GNode *mehd;
13505     GstByteReader mehd_data;
13506
13507     /* let track parsing or anyone know weird stuff might happen ... */
13508     qtdemux->fragmented = TRUE;
13509
13510     /* compensate for total duration */
13511     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13512     if (mehd)
13513       qtdemux_parse_mehd (qtdemux, &mehd_data);
13514   }
13515
13516   /* Update the movie segment duration, unless it was directly given to us
13517    * by upstream. Otherwise let it as is, as we don't want to mangle the
13518    * duration provided by upstream that may come e.g. from a MPD file. */
13519   if (!qtdemux->upstream_format_is_time) {
13520     GstClockTime duration;
13521     /* set duration in the segment info */
13522     gst_qtdemux_get_duration (qtdemux, &duration);
13523     qtdemux->segment.duration = duration;
13524     /* also do not exceed duration; stop is set that way post seek anyway,
13525      * and segment activation falls back to duration,
13526      * whereas loop only checks stop, so let's align this here as well */
13527     qtdemux->segment.stop = duration;
13528   }
13529
13530   /* parse all traks */
13531   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13532   while (trak) {
13533     qtdemux_parse_trak (qtdemux, trak);
13534     /* iterate all siblings */
13535     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13536   }
13537
13538   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13539
13540   /* find tags */
13541   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13542   if (udta) {
13543     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13544   } else {
13545     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13546   }
13547
13548   /* maybe also some tags in meta box */
13549   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13550   if (udta) {
13551     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13552     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13553   } else {
13554     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13555   }
13556
13557   /* parse any protection system info */
13558   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13559   while (pssh) {
13560     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13561     qtdemux_parse_pssh (qtdemux, pssh);
13562     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13563   }
13564
13565   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13566
13567   return TRUE;
13568 }
13569
13570 /* taken from ffmpeg */
13571 static int
13572 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13573 {
13574   int count = 4;
13575   int len = 0;
13576
13577   while (count--) {
13578     int c;
13579
13580     if (ptr >= end)
13581       return -1;
13582
13583     c = *ptr++;
13584     len = (len << 7) | (c & 0x7f);
13585     if (!(c & 0x80))
13586       break;
13587   }
13588   *end_out = ptr;
13589   return len;
13590 }
13591
13592 static GList *
13593 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13594     gsize codec_data_size)
13595 {
13596   GList *list = NULL;
13597   guint8 *p = codec_data;
13598   gint i, offset, num_packets;
13599   guint *length, last;
13600
13601   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13602
13603   if (codec_data == NULL || codec_data_size == 0)
13604     goto error;
13605
13606   /* start of the stream and vorbis audio or theora video, need to
13607    * send the codec_priv data as first three packets */
13608   num_packets = p[0] + 1;
13609   GST_DEBUG_OBJECT (qtdemux,
13610       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13611       (guint) num_packets, codec_data_size);
13612
13613   /* Let's put some limits, Don't think there even is a xiph codec
13614    * with more than 3-4 headers */
13615   if (G_UNLIKELY (num_packets > 16)) {
13616     GST_WARNING_OBJECT (qtdemux,
13617         "Unlikely number of xiph headers, most likely not valid");
13618     goto error;
13619   }
13620
13621   length = g_alloca (num_packets * sizeof (guint));
13622   last = 0;
13623   offset = 1;
13624
13625   /* first packets, read length values */
13626   for (i = 0; i < num_packets - 1; i++) {
13627     length[i] = 0;
13628     while (offset < codec_data_size) {
13629       length[i] += p[offset];
13630       if (p[offset++] != 0xff)
13631         break;
13632     }
13633     last += length[i];
13634   }
13635   if (offset + last > codec_data_size)
13636     goto error;
13637
13638   /* last packet is the remaining size */
13639   length[i] = codec_data_size - offset - last;
13640
13641   for (i = 0; i < num_packets; i++) {
13642     GstBuffer *hdr;
13643
13644     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13645
13646     if (offset + length[i] > codec_data_size)
13647       goto error;
13648
13649     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13650     list = g_list_append (list, hdr);
13651
13652     offset += length[i];
13653   }
13654
13655   return list;
13656
13657   /* ERRORS */
13658 error:
13659   {
13660     if (list != NULL)
13661       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13662     return NULL;
13663   }
13664
13665 }
13666
13667 /* this can change the codec originally present in @list */
13668 static void
13669 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13670     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13671 {
13672   int len = QT_UINT32 (esds->data);
13673   guint8 *ptr = esds->data;
13674   guint8 *end = ptr + len;
13675   int tag;
13676   guint8 *data_ptr = NULL;
13677   int data_len = 0;
13678   guint8 object_type_id = 0;
13679   guint8 stream_type = 0;
13680   const char *codec_name = NULL;
13681   GstCaps *caps = NULL;
13682
13683   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13684   ptr += 8;
13685   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13686   ptr += 4;
13687   while (ptr + 1 < end) {
13688     tag = QT_UINT8 (ptr);
13689     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13690     ptr++;
13691     len = read_descr_size (ptr, end, &ptr);
13692     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13693
13694     /* Check the stated amount of data is available for reading */
13695     if (len < 0 || ptr + len > end)
13696       break;
13697
13698     switch (tag) {
13699       case ES_DESCRIPTOR_TAG:
13700         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13701         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13702         ptr += 3;
13703         break;
13704       case DECODER_CONFIG_DESC_TAG:{
13705         guint max_bitrate, avg_bitrate;
13706
13707         object_type_id = QT_UINT8 (ptr);
13708         stream_type = QT_UINT8 (ptr + 1) >> 2;
13709         max_bitrate = QT_UINT32 (ptr + 5);
13710         avg_bitrate = QT_UINT32 (ptr + 9);
13711         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13712         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13713         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13714         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13715         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13716         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13717           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13718               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13719         }
13720         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13721           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13722               avg_bitrate, NULL);
13723         }
13724         ptr += 13;
13725         break;
13726       }
13727       case DECODER_SPECIFIC_INFO_TAG:
13728         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13729         if (object_type_id == 0xe0 && len == 0x40) {
13730           guint8 *data;
13731           GstStructure *s;
13732           guint32 clut[16];
13733           gint i;
13734
13735           GST_DEBUG_OBJECT (qtdemux,
13736               "Have VOBSUB palette. Creating palette event");
13737           /* move to decConfigDescr data and read palette */
13738           data = ptr;
13739           for (i = 0; i < 16; i++) {
13740             clut[i] = QT_UINT32 (data);
13741             data += 4;
13742           }
13743
13744           s = gst_structure_new ("application/x-gst-dvd", "event",
13745               G_TYPE_STRING, "dvd-spu-clut-change",
13746               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13747               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13748               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13749               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13750               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13751               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13752               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13753               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13754               NULL);
13755
13756           /* store event and trigger custom processing */
13757           stream->pending_event =
13758               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13759         } else {
13760           /* Generic codec_data handler puts it on the caps */
13761           data_ptr = ptr;
13762           data_len = len;
13763         }
13764
13765         ptr += len;
13766         break;
13767       case SL_CONFIG_DESC_TAG:
13768         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13769         ptr += 1;
13770         break;
13771       default:
13772         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13773             tag);
13774         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13775         ptr += len;
13776         break;
13777     }
13778   }
13779
13780   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13781    * in use, and should also be used to override some other parameters for some
13782    * codecs. */
13783   switch (object_type_id) {
13784     case 0x20:                 /* MPEG-4 */
13785       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13786        * profile_and_level_indication */
13787       if (data_ptr != NULL && data_len >= 5 &&
13788           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13789         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13790             data_ptr + 4, data_len - 4);
13791       }
13792       break;                    /* Nothing special needed here */
13793     case 0x21:                 /* H.264 */
13794       codec_name = "H.264 / AVC";
13795       caps = gst_caps_new_simple ("video/x-h264",
13796           "stream-format", G_TYPE_STRING, "avc",
13797           "alignment", G_TYPE_STRING, "au", NULL);
13798       break;
13799     case 0x40:                 /* AAC (any) */
13800     case 0x66:                 /* AAC Main */
13801     case 0x67:                 /* AAC LC */
13802     case 0x68:                 /* AAC SSR */
13803       /* Override channels and rate based on the codec_data, as it's often
13804        * wrong. */
13805       /* Only do so for basic setup without HE-AAC extension */
13806       if (data_ptr && data_len == 2) {
13807         guint channels, rate;
13808
13809         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13810         if (channels > 0)
13811           entry->n_channels = channels;
13812
13813         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13814         if (rate > 0)
13815           entry->rate = rate;
13816       }
13817
13818       /* Set level and profile if possible */
13819       if (data_ptr != NULL && data_len >= 2) {
13820         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13821             data_ptr, data_len);
13822       } else {
13823         const gchar *profile_str = NULL;
13824         GstBuffer *buffer;
13825         GstMapInfo map;
13826         guint8 *codec_data;
13827         gint rate_idx, profile;
13828
13829         /* No codec_data, let's invent something.
13830          * FIXME: This is wrong for SBR! */
13831
13832         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13833
13834         buffer = gst_buffer_new_and_alloc (2);
13835         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13836         codec_data = map.data;
13837
13838         rate_idx =
13839             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13840             (stream)->rate);
13841
13842         switch (object_type_id) {
13843           case 0x66:
13844             profile_str = "main";
13845             profile = 0;
13846             break;
13847           case 0x67:
13848             profile_str = "lc";
13849             profile = 1;
13850             break;
13851           case 0x68:
13852             profile_str = "ssr";
13853             profile = 2;
13854             break;
13855           default:
13856             profile = 3;
13857             break;
13858         }
13859
13860         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13861         codec_data[1] =
13862             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13863
13864         gst_buffer_unmap (buffer, &map);
13865         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13866             GST_TYPE_BUFFER, buffer, NULL);
13867         gst_buffer_unref (buffer);
13868
13869         if (profile_str) {
13870           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13871               G_TYPE_STRING, profile_str, NULL);
13872         }
13873       }
13874       break;
13875     case 0x60:                 /* MPEG-2, various profiles */
13876     case 0x61:
13877     case 0x62:
13878     case 0x63:
13879     case 0x64:
13880     case 0x65:
13881       codec_name = "MPEG-2 video";
13882       caps = gst_caps_new_simple ("video/mpeg",
13883           "mpegversion", G_TYPE_INT, 2,
13884           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13885       break;
13886     case 0x69:                 /* MPEG-2 BC audio */
13887     case 0x6B:                 /* MPEG-1 audio */
13888       caps = gst_caps_new_simple ("audio/mpeg",
13889           "mpegversion", G_TYPE_INT, 1, NULL);
13890       codec_name = "MPEG-1 audio";
13891       break;
13892     case 0x6A:                 /* MPEG-1 */
13893       codec_name = "MPEG-1 video";
13894       caps = gst_caps_new_simple ("video/mpeg",
13895           "mpegversion", G_TYPE_INT, 1,
13896           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13897       break;
13898     case 0x6C:                 /* MJPEG */
13899       caps =
13900           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13901           NULL);
13902       codec_name = "Motion-JPEG";
13903       break;
13904     case 0x6D:                 /* PNG */
13905       caps =
13906           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13907           NULL);
13908       codec_name = "PNG still images";
13909       break;
13910     case 0x6E:                 /* JPEG2000 */
13911       codec_name = "JPEG-2000";
13912       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13913       break;
13914     case 0xA4:                 /* Dirac */
13915       codec_name = "Dirac";
13916       caps = gst_caps_new_empty_simple ("video/x-dirac");
13917       break;
13918     case 0xA5:                 /* AC3 */
13919       codec_name = "AC-3 audio";
13920       caps = gst_caps_new_simple ("audio/x-ac3",
13921           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13922       break;
13923     case 0xA9:                 /* AC3 */
13924       codec_name = "DTS audio";
13925       caps = gst_caps_new_simple ("audio/x-dts",
13926           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13927       break;
13928     case 0xDD:
13929       if (stream_type == 0x05 && data_ptr) {
13930         GList *headers =
13931             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
13932         if (headers) {
13933           GList *tmp;
13934           GValue arr_val = G_VALUE_INIT;
13935           GValue buf_val = G_VALUE_INIT;
13936           GstStructure *s;
13937
13938           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
13939           codec_name = "Vorbis";
13940           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
13941           g_value_init (&arr_val, GST_TYPE_ARRAY);
13942           g_value_init (&buf_val, GST_TYPE_BUFFER);
13943           for (tmp = headers; tmp; tmp = tmp->next) {
13944             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
13945             gst_value_array_append_value (&arr_val, &buf_val);
13946           }
13947           s = gst_caps_get_structure (caps, 0);
13948           gst_structure_take_value (s, "streamheader", &arr_val);
13949           g_value_unset (&buf_val);
13950           g_list_free (headers);
13951
13952           data_ptr = NULL;
13953           data_len = 0;
13954         }
13955       }
13956       break;
13957     case 0xE1:                 /* QCELP */
13958       /* QCELP, the codec_data is a riff tag (little endian) with
13959        * 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). */
13960       caps = gst_caps_new_empty_simple ("audio/qcelp");
13961       codec_name = "QCELP";
13962       break;
13963     default:
13964       break;
13965   }
13966
13967   /* If we have a replacement caps, then change our caps for this stream */
13968   if (caps) {
13969     gst_caps_unref (entry->caps);
13970     entry->caps = caps;
13971   }
13972
13973   if (codec_name && list)
13974     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13975         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13976
13977   /* Add the codec_data attribute to caps, if we have it */
13978   if (data_ptr) {
13979     GstBuffer *buffer;
13980
13981     buffer = gst_buffer_new_and_alloc (data_len);
13982     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13983
13984     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13985     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13986
13987     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13988         buffer, NULL);
13989     gst_buffer_unref (buffer);
13990   }
13991
13992 }
13993
13994 static inline GstCaps *
13995 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13996 {
13997   GstCaps *caps;
13998   guint i;
13999   char *s, fourstr[5];
14000
14001   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14002   for (i = 0; i < 4; i++) {
14003     if (!g_ascii_isalnum (fourstr[i]))
14004       fourstr[i] = '_';
14005   }
14006   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14007   caps = gst_caps_new_empty_simple (s);
14008   g_free (s);
14009   return caps;
14010 }
14011
14012 #define _codec(name) \
14013   do { \
14014     if (codec_name) { \
14015       *codec_name = g_strdup (name); \
14016     } \
14017   } while (0)
14018
14019 static GstCaps *
14020 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14021     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14022     const guint8 * stsd_entry_data, gchar ** codec_name)
14023 {
14024   GstCaps *caps = NULL;
14025   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14026
14027   switch (fourcc) {
14028     case FOURCC_png:
14029       _codec ("PNG still images");
14030       caps = gst_caps_new_empty_simple ("image/png");
14031       break;
14032     case FOURCC_jpeg:
14033       _codec ("JPEG still images");
14034       caps =
14035           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14036           NULL);
14037       break;
14038     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14039     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14040     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14041     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14042       _codec ("Motion-JPEG");
14043       caps =
14044           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14045           NULL);
14046       break;
14047     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14048       _codec ("Motion-JPEG format B");
14049       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14050       break;
14051     case FOURCC_mjp2:
14052       _codec ("JPEG-2000");
14053       /* override to what it should be according to spec, avoid palette_data */
14054       entry->bits_per_sample = 24;
14055       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14056       break;
14057     case FOURCC_SVQ3:
14058       _codec ("Sorensen video v.3");
14059       caps = gst_caps_new_simple ("video/x-svq",
14060           "svqversion", G_TYPE_INT, 3, NULL);
14061       break;
14062     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14063     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14064       _codec ("Sorensen video v.1");
14065       caps = gst_caps_new_simple ("video/x-svq",
14066           "svqversion", G_TYPE_INT, 1, NULL);
14067       break;
14068     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14069       caps = gst_caps_new_empty_simple ("video/x-raw");
14070       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14071       _codec ("Windows Raw RGB");
14072       stream->alignment = 32;
14073       break;
14074     case FOURCC_raw_:
14075     {
14076       guint16 bps;
14077
14078       bps = QT_UINT16 (stsd_entry_data + 82);
14079       switch (bps) {
14080         case 15:
14081           format = GST_VIDEO_FORMAT_RGB15;
14082           break;
14083         case 16:
14084           format = GST_VIDEO_FORMAT_RGB16;
14085           break;
14086         case 24:
14087           format = GST_VIDEO_FORMAT_RGB;
14088           break;
14089         case 32:
14090           format = GST_VIDEO_FORMAT_ARGB;
14091           break;
14092         default:
14093           /* unknown */
14094           break;
14095       }
14096       break;
14097     }
14098     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14099       format = GST_VIDEO_FORMAT_I420;
14100       break;
14101     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14102     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14103       format = GST_VIDEO_FORMAT_I420;
14104       break;
14105     case FOURCC_2vuy:
14106     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14107       format = GST_VIDEO_FORMAT_UYVY;
14108       break;
14109     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14110       format = GST_VIDEO_FORMAT_v308;
14111       break;
14112     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14113       format = GST_VIDEO_FORMAT_v216;
14114       break;
14115     case FOURCC_v210:
14116       format = GST_VIDEO_FORMAT_v210;
14117       break;
14118     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14119       format = GST_VIDEO_FORMAT_r210;
14120       break;
14121       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14122          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14123          format = GST_VIDEO_FORMAT_v410;
14124          break;
14125        */
14126       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14127        * but different order than AYUV
14128        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14129        format = GST_VIDEO_FORMAT_v408;
14130        break;
14131        */
14132     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14133     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14134       _codec ("MPEG-1 video");
14135       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14136           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14137       break;
14138     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14139     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14140     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14141     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14142     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14143     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14144     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14145     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14146     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14147     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14148     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14149     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14150     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14151     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14152     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14153     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14154     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14155     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14156     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14157     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14158     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14159     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14160     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14161     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14162     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14163     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14164     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14165     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14166     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14167     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14168     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14169     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14170     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14171     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14172     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14173     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14174     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14175     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14176     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14177     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14178     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14179     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14180     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14181     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14182     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14183     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14184     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14185       _codec ("MPEG-2 video");
14186       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14187           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14188       break;
14189     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14190       _codec ("GIF still images");
14191       caps = gst_caps_new_empty_simple ("image/gif");
14192       break;
14193     case FOURCC_h263:
14194     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14195     case FOURCC_s263:
14196     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14197       _codec ("H.263");
14198       /* ffmpeg uses the height/width props, don't know why */
14199       caps = gst_caps_new_simple ("video/x-h263",
14200           "variant", G_TYPE_STRING, "itu", NULL);
14201       break;
14202     case FOURCC_mp4v:
14203     case FOURCC_MP4V:
14204       _codec ("MPEG-4 video");
14205       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14206           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14207       break;
14208     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14209     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14210       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14211       caps = gst_caps_new_simple ("video/x-msmpeg",
14212           "msmpegversion", G_TYPE_INT, 43, NULL);
14213       break;
14214     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14215       _codec ("DivX 3");
14216       caps = gst_caps_new_simple ("video/x-divx",
14217           "divxversion", G_TYPE_INT, 3, NULL);
14218       break;
14219     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14220     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14221       _codec ("DivX 4");
14222       caps = gst_caps_new_simple ("video/x-divx",
14223           "divxversion", G_TYPE_INT, 4, NULL);
14224       break;
14225     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14226       _codec ("DivX 5");
14227       caps = gst_caps_new_simple ("video/x-divx",
14228           "divxversion", G_TYPE_INT, 5, NULL);
14229       break;
14230
14231     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14232       _codec ("FFV1");
14233       caps = gst_caps_new_simple ("video/x-ffv",
14234           "ffvversion", G_TYPE_INT, 1, NULL);
14235       break;
14236
14237     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14238     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14239     case FOURCC_XVID:
14240     case FOURCC_xvid:
14241     case FOURCC_FMP4:
14242     case FOURCC_fmp4:
14243     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14244       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14245           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14246       _codec ("MPEG-4");
14247       break;
14248
14249     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14250       _codec ("Cinepak");
14251       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14252       break;
14253     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14254       _codec ("Apple QuickDraw");
14255       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14256       break;
14257     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14258       _codec ("Apple video");
14259       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14260       break;
14261     case FOURCC_H264:
14262     case FOURCC_avc1:
14263     case FOURCC_dva1:
14264       _codec ("H.264 / AVC");
14265       caps = gst_caps_new_simple ("video/x-h264",
14266           "stream-format", G_TYPE_STRING, "avc",
14267           "alignment", G_TYPE_STRING, "au", NULL);
14268       break;
14269     case FOURCC_avc3:
14270     case FOURCC_dvav:
14271       _codec ("H.264 / AVC");
14272       caps = gst_caps_new_simple ("video/x-h264",
14273           "stream-format", G_TYPE_STRING, "avc3",
14274           "alignment", G_TYPE_STRING, "au", NULL);
14275       break;
14276     case FOURCC_H265:
14277     case FOURCC_hvc1:
14278     case FOURCC_dvh1:
14279       _codec ("H.265 / HEVC");
14280       caps = gst_caps_new_simple ("video/x-h265",
14281           "stream-format", G_TYPE_STRING, "hvc1",
14282           "alignment", G_TYPE_STRING, "au", NULL);
14283       break;
14284     case FOURCC_hev1:
14285     case FOURCC_dvhe:
14286       _codec ("H.265 / HEVC");
14287       caps = gst_caps_new_simple ("video/x-h265",
14288           "stream-format", G_TYPE_STRING, "hev1",
14289           "alignment", G_TYPE_STRING, "au", NULL);
14290       break;
14291     case FOURCC_rle_:
14292       _codec ("Run-length encoding");
14293       caps = gst_caps_new_simple ("video/x-rle",
14294           "layout", G_TYPE_STRING, "quicktime", NULL);
14295       break;
14296     case FOURCC_WRLE:
14297       _codec ("Run-length encoding");
14298       caps = gst_caps_new_simple ("video/x-rle",
14299           "layout", G_TYPE_STRING, "microsoft", NULL);
14300       break;
14301     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14302     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14303       _codec ("Indeo Video 3");
14304       caps = gst_caps_new_simple ("video/x-indeo",
14305           "indeoversion", G_TYPE_INT, 3, NULL);
14306       break;
14307     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14308     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14309       _codec ("Intel Video 4");
14310       caps = gst_caps_new_simple ("video/x-indeo",
14311           "indeoversion", G_TYPE_INT, 4, NULL);
14312       break;
14313     case FOURCC_dvcp:
14314     case FOURCC_dvc_:
14315     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14316     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14317     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14318     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14319     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14320     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14321       _codec ("DV Video");
14322       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14323           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14324       break;
14325     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14326     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14327       _codec ("DVCPro50 Video");
14328       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14329           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14330       break;
14331     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14332     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14333       _codec ("DVCProHD Video");
14334       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14335           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14336       break;
14337     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14338       _codec ("Apple Graphics (SMC)");
14339       caps = gst_caps_new_empty_simple ("video/x-smc");
14340       break;
14341     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14342       _codec ("VP3");
14343       caps = gst_caps_new_empty_simple ("video/x-vp3");
14344       break;
14345     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14346       _codec ("VP6 Flash");
14347       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14348       break;
14349     case FOURCC_XiTh:
14350       _codec ("Theora");
14351       caps = gst_caps_new_empty_simple ("video/x-theora");
14352       /* theora uses one byte of padding in the data stream because it does not
14353        * allow 0 sized packets while theora does */
14354       entry->padding = 1;
14355       break;
14356     case FOURCC_drac:
14357       _codec ("Dirac");
14358       caps = gst_caps_new_empty_simple ("video/x-dirac");
14359       break;
14360     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14361       _codec ("TIFF still images");
14362       caps = gst_caps_new_empty_simple ("image/tiff");
14363       break;
14364     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14365       _codec ("Apple Intermediate Codec");
14366       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14367       break;
14368     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14369       _codec ("AVID DNxHD");
14370       caps = gst_caps_from_string ("video/x-dnxhd");
14371       break;
14372     case FOURCC_VP80:
14373     case FOURCC_vp08:
14374       _codec ("On2 VP8");
14375       caps = gst_caps_from_string ("video/x-vp8");
14376       break;
14377     case FOURCC_vp09:
14378       _codec ("Google VP9");
14379       caps = gst_caps_from_string ("video/x-vp9");
14380       break;
14381     case FOURCC_apcs:
14382       _codec ("Apple ProRes LT");
14383       caps =
14384           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14385           NULL);
14386       break;
14387     case FOURCC_apch:
14388       _codec ("Apple ProRes HQ");
14389       caps =
14390           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14391           NULL);
14392       break;
14393     case FOURCC_apcn:
14394       _codec ("Apple ProRes");
14395       caps =
14396           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14397           "standard", NULL);
14398       break;
14399     case FOURCC_apco:
14400       _codec ("Apple ProRes Proxy");
14401       caps =
14402           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14403           "proxy", NULL);
14404       break;
14405     case FOURCC_ap4h:
14406       _codec ("Apple ProRes 4444");
14407       caps =
14408           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14409           "4444", NULL);
14410       break;
14411     case FOURCC_ap4x:
14412       _codec ("Apple ProRes 4444 XQ");
14413       caps =
14414           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14415           "4444xq", NULL);
14416       break;
14417     case FOURCC_cfhd:
14418       _codec ("GoPro CineForm");
14419       caps = gst_caps_from_string ("video/x-cineform");
14420       break;
14421     case FOURCC_vc_1:
14422     case FOURCC_ovc1:
14423       _codec ("VC-1");
14424       caps = gst_caps_new_simple ("video/x-wmv",
14425           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14426       break;
14427     case FOURCC_av01:
14428       _codec ("AV1");
14429       caps = gst_caps_new_empty_simple ("video/x-av1");
14430       break;
14431     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14432     default:
14433     {
14434       caps = _get_unknown_codec_name ("video", fourcc);
14435       break;
14436     }
14437   }
14438
14439   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14440     GstVideoInfo info;
14441
14442     gst_video_info_init (&info);
14443     gst_video_info_set_format (&info, format, entry->width, entry->height);
14444
14445     caps = gst_video_info_to_caps (&info);
14446     *codec_name = gst_pb_utils_get_codec_description (caps);
14447
14448     /* enable clipping for raw video streams */
14449     stream->need_clip = TRUE;
14450     stream->alignment = 32;
14451   }
14452
14453   return caps;
14454 }
14455
14456 static guint
14457 round_up_pow2 (guint n)
14458 {
14459   n = n - 1;
14460   n = n | (n >> 1);
14461   n = n | (n >> 2);
14462   n = n | (n >> 4);
14463   n = n | (n >> 8);
14464   n = n | (n >> 16);
14465   return n + 1;
14466 }
14467
14468 static GstCaps *
14469 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14470     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14471     int len, gchar ** codec_name)
14472 {
14473   GstCaps *caps;
14474   const GstStructure *s;
14475   const gchar *name;
14476   gint endian = 0;
14477   GstAudioFormat format = 0;
14478   gint depth;
14479
14480   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14481
14482   depth = entry->bytes_per_packet * 8;
14483
14484   switch (fourcc) {
14485     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14486     case FOURCC_raw_:
14487       /* 8-bit audio is unsigned */
14488       if (depth == 8)
14489         format = GST_AUDIO_FORMAT_U8;
14490       /* otherwise it's signed and big-endian just like 'twos' */
14491     case FOURCC_twos:
14492       endian = G_BIG_ENDIAN;
14493       /* fall-through */
14494     case FOURCC_sowt:
14495     {
14496       gchar *str;
14497
14498       if (!endian)
14499         endian = G_LITTLE_ENDIAN;
14500
14501       if (!format)
14502         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14503
14504       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14505       _codec (str);
14506       g_free (str);
14507
14508       caps = gst_caps_new_simple ("audio/x-raw",
14509           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14510           "layout", G_TYPE_STRING, "interleaved", NULL);
14511       stream->alignment = GST_ROUND_UP_8 (depth);
14512       stream->alignment = round_up_pow2 (stream->alignment);
14513       break;
14514     }
14515     case FOURCC_fl64:
14516       _codec ("Raw 64-bit floating-point audio");
14517       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14518        * endian later */
14519       caps = gst_caps_new_simple ("audio/x-raw",
14520           "format", G_TYPE_STRING, "F64BE",
14521           "layout", G_TYPE_STRING, "interleaved", NULL);
14522       stream->alignment = 8;
14523       break;
14524     case FOURCC_fl32:
14525       _codec ("Raw 32-bit floating-point audio");
14526       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14527        * endian later */
14528       caps = gst_caps_new_simple ("audio/x-raw",
14529           "format", G_TYPE_STRING, "F32BE",
14530           "layout", G_TYPE_STRING, "interleaved", NULL);
14531       stream->alignment = 4;
14532       break;
14533     case FOURCC_in24:
14534       _codec ("Raw 24-bit PCM audio");
14535       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14536        * endian later */
14537       caps = gst_caps_new_simple ("audio/x-raw",
14538           "format", G_TYPE_STRING, "S24BE",
14539           "layout", G_TYPE_STRING, "interleaved", NULL);
14540       stream->alignment = 4;
14541       break;
14542     case FOURCC_in32:
14543       _codec ("Raw 32-bit PCM audio");
14544       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14545        * endian later */
14546       caps = gst_caps_new_simple ("audio/x-raw",
14547           "format", G_TYPE_STRING, "S32BE",
14548           "layout", G_TYPE_STRING, "interleaved", NULL);
14549       stream->alignment = 4;
14550       break;
14551     case FOURCC_s16l:
14552       _codec ("Raw 16-bit PCM audio");
14553       caps = gst_caps_new_simple ("audio/x-raw",
14554           "format", G_TYPE_STRING, "S16LE",
14555           "layout", G_TYPE_STRING, "interleaved", NULL);
14556       stream->alignment = 2;
14557       break;
14558     case FOURCC_ulaw:
14559       _codec ("Mu-law audio");
14560       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14561       break;
14562     case FOURCC_alaw:
14563       _codec ("A-law audio");
14564       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14565       break;
14566     case 0x0200736d:
14567     case 0x6d730002:
14568       _codec ("Microsoft ADPCM");
14569       /* Microsoft ADPCM-ACM code 2 */
14570       caps = gst_caps_new_simple ("audio/x-adpcm",
14571           "layout", G_TYPE_STRING, "microsoft", NULL);
14572       break;
14573     case 0x1100736d:
14574     case 0x6d730011:
14575       _codec ("DVI/IMA ADPCM");
14576       caps = gst_caps_new_simple ("audio/x-adpcm",
14577           "layout", G_TYPE_STRING, "dvi", NULL);
14578       break;
14579     case 0x1700736d:
14580     case 0x6d730017:
14581       _codec ("DVI/Intel IMA ADPCM");
14582       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14583       caps = gst_caps_new_simple ("audio/x-adpcm",
14584           "layout", G_TYPE_STRING, "quicktime", NULL);
14585       break;
14586     case 0x5500736d:
14587     case 0x6d730055:
14588       /* MPEG layer 3, CBR only (pre QT4.1) */
14589     case FOURCC__mp3:
14590     case FOURCC_mp3_:
14591       _codec ("MPEG-1 layer 3");
14592       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14593       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14594           "mpegversion", G_TYPE_INT, 1, NULL);
14595       break;
14596     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14597       _codec ("MPEG-1 layer 2");
14598       /* MPEG layer 2 */
14599       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14600           "mpegversion", G_TYPE_INT, 1, NULL);
14601       break;
14602     case 0x20736d:
14603     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14604       _codec ("EAC-3 audio");
14605       caps = gst_caps_new_simple ("audio/x-eac3",
14606           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14607       entry->sampled = TRUE;
14608       break;
14609     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14610     case FOURCC_ac_3:
14611       _codec ("AC-3 audio");
14612       caps = gst_caps_new_simple ("audio/x-ac3",
14613           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14614       entry->sampled = TRUE;
14615       break;
14616     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14617     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14618       _codec ("DTS audio");
14619       caps = gst_caps_new_simple ("audio/x-dts",
14620           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14621       entry->sampled = TRUE;
14622       break;
14623     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14624     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14625       _codec ("DTS-HD audio");
14626       caps = gst_caps_new_simple ("audio/x-dts",
14627           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14628       entry->sampled = TRUE;
14629       break;
14630     case FOURCC_MAC3:
14631       _codec ("MACE-3");
14632       caps = gst_caps_new_simple ("audio/x-mace",
14633           "maceversion", G_TYPE_INT, 3, NULL);
14634       break;
14635     case FOURCC_MAC6:
14636       _codec ("MACE-6");
14637       caps = gst_caps_new_simple ("audio/x-mace",
14638           "maceversion", G_TYPE_INT, 6, NULL);
14639       break;
14640     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14641       /* ogg/vorbis */
14642       caps = gst_caps_new_empty_simple ("application/ogg");
14643       break;
14644     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14645       _codec ("DV audio");
14646       caps = gst_caps_new_empty_simple ("audio/x-dv");
14647       break;
14648     case FOURCC_mp4a:
14649       _codec ("MPEG-4 AAC audio");
14650       caps = gst_caps_new_simple ("audio/mpeg",
14651           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14652           "stream-format", G_TYPE_STRING, "raw", NULL);
14653       break;
14654     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14655       _codec ("QDesign Music");
14656       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14657       break;
14658     case FOURCC_QDM2:
14659       _codec ("QDesign Music v.2");
14660       /* FIXME: QDesign music version 2 (no constant) */
14661       if (FALSE && data) {
14662         caps = gst_caps_new_simple ("audio/x-qdm2",
14663             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14664             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14665             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14666       } else {
14667         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14668       }
14669       break;
14670     case FOURCC_agsm:
14671       _codec ("GSM audio");
14672       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14673       break;
14674     case FOURCC_samr:
14675       _codec ("AMR audio");
14676       caps = gst_caps_new_empty_simple ("audio/AMR");
14677       break;
14678     case FOURCC_sawb:
14679       _codec ("AMR-WB audio");
14680       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14681       break;
14682     case FOURCC_ima4:
14683       _codec ("Quicktime IMA ADPCM");
14684       caps = gst_caps_new_simple ("audio/x-adpcm",
14685           "layout", G_TYPE_STRING, "quicktime", NULL);
14686       break;
14687     case FOURCC_alac:
14688       _codec ("Apple lossless audio");
14689       caps = gst_caps_new_empty_simple ("audio/x-alac");
14690       break;
14691     case FOURCC_fLaC:
14692       _codec ("Free Lossless Audio Codec");
14693       caps = gst_caps_new_simple ("audio/x-flac",
14694           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14695       break;
14696     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14697       _codec ("QualComm PureVoice");
14698       caps = gst_caps_from_string ("audio/qcelp");
14699       break;
14700     case FOURCC_wma_:
14701     case FOURCC_owma:
14702       _codec ("WMA");
14703       caps = gst_caps_new_empty_simple ("audio/x-wma");
14704       break;
14705     case FOURCC_opus:
14706       _codec ("Opus");
14707       caps = gst_caps_new_empty_simple ("audio/x-opus");
14708       break;
14709     case FOURCC_lpcm:
14710     {
14711       guint32 flags = 0;
14712       guint32 depth = 0;
14713       guint32 width = 0;
14714       GstAudioFormat format;
14715       enum
14716       {
14717         FLAG_IS_FLOAT = 0x1,
14718         FLAG_IS_BIG_ENDIAN = 0x2,
14719         FLAG_IS_SIGNED = 0x4,
14720         FLAG_IS_PACKED = 0x8,
14721         FLAG_IS_ALIGNED_HIGH = 0x10,
14722         FLAG_IS_NON_INTERLEAVED = 0x20
14723       };
14724       _codec ("Raw LPCM audio");
14725
14726       if (data && len >= 36) {
14727         depth = QT_UINT32 (data + 24);
14728         flags = QT_UINT32 (data + 28);
14729         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14730       }
14731       if ((flags & FLAG_IS_FLOAT) == 0) {
14732         if (depth == 0)
14733           depth = 16;
14734         if (width == 0)
14735           width = 16;
14736         if ((flags & FLAG_IS_ALIGNED_HIGH))
14737           depth = width;
14738
14739         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14740             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14741             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14742         caps = gst_caps_new_simple ("audio/x-raw",
14743             "format", G_TYPE_STRING,
14744             format !=
14745             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14746             "UNKNOWN", "layout", G_TYPE_STRING,
14747             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14748             "interleaved", NULL);
14749         stream->alignment = GST_ROUND_UP_8 (depth);
14750         stream->alignment = round_up_pow2 (stream->alignment);
14751       } else {
14752         if (width == 0)
14753           width = 32;
14754         if (width == 64) {
14755           if (flags & FLAG_IS_BIG_ENDIAN)
14756             format = GST_AUDIO_FORMAT_F64BE;
14757           else
14758             format = GST_AUDIO_FORMAT_F64LE;
14759         } else {
14760           if (flags & FLAG_IS_BIG_ENDIAN)
14761             format = GST_AUDIO_FORMAT_F32BE;
14762           else
14763             format = GST_AUDIO_FORMAT_F32LE;
14764         }
14765         caps = gst_caps_new_simple ("audio/x-raw",
14766             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14767             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14768             "non-interleaved" : "interleaved", NULL);
14769         stream->alignment = width / 8;
14770       }
14771       break;
14772     }
14773     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14774     {
14775       _codec ("AC4");
14776       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14777       break;
14778     }
14779     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14780       /* ? */
14781     default:
14782     {
14783       caps = _get_unknown_codec_name ("audio", fourcc);
14784       break;
14785     }
14786   }
14787
14788   if (caps) {
14789     GstCaps *templ_caps =
14790         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14791     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14792     gst_caps_unref (caps);
14793     gst_caps_unref (templ_caps);
14794     caps = intersection;
14795   }
14796
14797   /* enable clipping for raw audio streams */
14798   s = gst_caps_get_structure (caps, 0);
14799   name = gst_structure_get_name (s);
14800   if (g_str_has_prefix (name, "audio/x-raw")) {
14801     stream->need_clip = TRUE;
14802     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14803     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14804     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
14805         stream->max_buffer_size);
14806   }
14807   return caps;
14808 }
14809
14810 static GstCaps *
14811 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14812     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14813     const guint8 * stsd_entry_data, gchar ** codec_name)
14814 {
14815   GstCaps *caps;
14816
14817   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14818
14819   switch (fourcc) {
14820     case FOURCC_mp4s:
14821       _codec ("DVD subtitle");
14822       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14823       stream->need_process = TRUE;
14824       break;
14825     case FOURCC_text:
14826       _codec ("Quicktime timed text");
14827       goto text;
14828     case FOURCC_tx3g:
14829       _codec ("3GPP timed text");
14830     text:
14831       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14832           "utf8", NULL);
14833       /* actual text piece needs to be extracted */
14834       stream->need_process = TRUE;
14835       break;
14836     case FOURCC_stpp:
14837       _codec ("XML subtitles");
14838       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14839       break;
14840     case FOURCC_c608:
14841       _codec ("CEA 608 Closed Caption");
14842       caps =
14843           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14844           G_TYPE_STRING, "s334-1a", NULL);
14845       stream->need_process = TRUE;
14846       stream->need_split = TRUE;
14847       break;
14848     case FOURCC_c708:
14849       _codec ("CEA 708 Closed Caption");
14850       caps =
14851           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
14852           G_TYPE_STRING, "cdp", NULL);
14853       stream->need_process = TRUE;
14854       break;
14855
14856     default:
14857     {
14858       caps = _get_unknown_codec_name ("text", fourcc);
14859       break;
14860     }
14861   }
14862   return caps;
14863 }
14864
14865 static GstCaps *
14866 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14867     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14868     const guint8 * stsd_entry_data, gchar ** codec_name)
14869 {
14870   GstCaps *caps;
14871
14872   switch (fourcc) {
14873     case FOURCC_m1v:
14874       _codec ("MPEG 1 video");
14875       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14876           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14877       break;
14878     default:
14879       caps = NULL;
14880       break;
14881   }
14882   return caps;
14883 }
14884
14885 static void
14886 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14887     const gchar * system_id)
14888 {
14889   gint i;
14890
14891   if (!qtdemux->protection_system_ids)
14892     qtdemux->protection_system_ids =
14893         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14894   /* Check whether we already have an entry for this system ID. */
14895   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14896     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14897     if (g_ascii_strcasecmp (system_id, id) == 0) {
14898       return;
14899     }
14900   }
14901   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14902   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14903           -1));
14904 }