e77eacbfdaa0ec15b95afbfeb2f397ecc2a99aa7
[platform/upstream/gst-plugins-good.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  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
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  * </refsect2>
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/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.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
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include <math.h>
76 #include <gst/math-compat.h>
77
78 #ifdef HAVE_ZLIB
79 # include <zlib.h>
80 #endif
81
82 /* max. size considered 'sane' for non-mdat atoms */
83 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
84
85 /* if the sample index is larger than this, something is likely wrong */
86 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
87
88 /* For converting qt creation times to unix epoch times */
89 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
90 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
91 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
92     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
93
94 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
95
96 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
97
98 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
99
100 #define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
101   ? (QtDemuxStream *)(demux)->active_streams->data : NULL)
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103
104 GST_DEBUG_CATEGORY (qtdemux_debug);
105 #define GST_CAT_DEFAULT qtdemux_debug
106
107 typedef struct _QtDemuxSegment QtDemuxSegment;
108 typedef struct _QtDemuxSample QtDemuxSample;
109
110 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
111
112 struct _QtDemuxSample
113 {
114   guint32 size;
115   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
116   guint64 offset;
117   guint64 timestamp;            /* DTS In mov time */
118   guint32 duration;             /* In mov time */
119   gboolean keyframe;            /* TRUE when this packet is a keyframe */
120 };
121
122 /* Macros for converting to/from timescale */
123 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
124 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
125
126 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
127 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
128
129 /* timestamp is the DTS */
130 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
131 /* timestamp + offset + cslg_shift is the outgoing PTS */
132 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
133 /* timestamp + offset is the PTS used for internal seek calcuations */
134 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
135 /* timestamp + duration - dts is the duration */
136 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
137
138 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
139
140 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
141 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
142     GST_TRACE("Locking from thread %p", g_thread_self()); \
143     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
144     GST_TRACE("Locked from thread %p", g_thread_self()); \
145  } G_STMT_END
146
147 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
148     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
149     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
150  } G_STMT_END
151
152 /*
153  * Quicktime has tracks and segments. A track is a continuous piece of
154  * multimedia content. The track is not always played from start to finish but
155  * instead, pieces of the track are 'cut out' and played in sequence. This is
156  * what the segments do.
157  *
158  * Inside the track we have keyframes (K) and delta frames. The track has its
159  * own timing, which starts from 0 and extends to end. The position in the track
160  * is called the media_time.
161  *
162  * The segments now describe the pieces that should be played from this track
163  * and are basically tuples of media_time/duration/rate entries. We can have
164  * multiple segments and they are all played after one another. An example:
165  *
166  * segment 1: media_time: 1 second, duration: 1 second, rate 1
167  * segment 2: media_time: 3 second, duration: 2 second, rate 2
168  *
169  * To correctly play back this track, one must play: 1 second of media starting
170  * from media_time 1 followed by 2 seconds of media starting from media_time 3
171  * at a rate of 2.
172  *
173  * Each of the segments will be played at a specific time, the first segment at
174  * time 0, the second one after the duration of the first one, etc.. Note that
175  * the time in resulting playback is not identical to the media_time of the
176  * track anymore.
177  *
178  * Visually, assuming the track has 4 second of media_time:
179  *
180  *                (a)                   (b)          (c)              (d)
181  *         .-----------------------------------------------------------.
182  * track:  | K.....K.........K........K.......K.......K...........K... |
183  *         '-----------------------------------------------------------'
184  *         0              1              2              3              4
185  *           .------------^              ^   .----------^              ^
186  *          /              .-------------'  /       .------------------'
187  *         /              /          .-----'       /
188  *         .--------------.         .--------------.
189  *         | segment 1    |         | segment 2    |
190  *         '--------------'         '--------------'
191  *
192  * The challenge here is to cut out the right pieces of the track for each of
193  * the playback segments. This fortunately can easily be done with the SEGMENT
194  * events of GStreamer.
195  *
196  * For playback of segment 1, we need to provide the decoder with the keyframe
197  * (a), in the above figure, but we must instruct it only to output the decoded
198  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
199  * position set to the time of the segment: 0.
200  *
201  * We then proceed to push data from keyframe (a) to frame (b). The decoder
202  * decodes but clips all before media_time 1.
203  *
204  * After finishing a segment, we push out a new SEGMENT event with the clipping
205  * boundaries of the new data.
206  *
207  * This is a good usecase for the GStreamer accumulated SEGMENT events.
208  */
209
210 struct _QtDemuxSegment
211 {
212   /* global time and duration, all gst time */
213   GstClockTime time;
214   GstClockTime stop_time;
215   GstClockTime duration;
216   /* media time of trak, all gst time */
217   GstClockTime media_start;
218   GstClockTime media_stop;
219   gdouble rate;
220   /* Media start time in trak timescale units */
221   guint32 trak_media_start;
222 };
223
224 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
225
226 /* Used with fragmented MP4 files (mfra atom) */
227 typedef struct
228 {
229   GstClockTime ts;
230   guint64 moof_offset;
231 } QtDemuxRandomAccessEntry;
232
233 typedef struct _QtDemuxStreamStsdEntry
234 {
235   GstCaps *caps;
236   guint32 fourcc;
237   gboolean sparse;
238
239   /* video info */
240   gint width;
241   gint height;
242   gint par_w;
243   gint par_h;
244   /* Numerator/denominator framerate */
245   gint fps_n;
246   gint fps_d;
247   GstVideoColorimetry colorimetry;
248   guint16 bits_per_sample;
249   guint16 color_table_id;
250   GstMemory *rgb8_palette;
251   guint interlace_mode;
252   guint field_order;
253
254   /* audio info */
255   gdouble rate;
256   gint n_channels;
257   guint samples_per_packet;
258   guint samples_per_frame;
259   guint bytes_per_packet;
260   guint bytes_per_sample;
261   guint bytes_per_frame;
262   guint compression;
263
264   /* if we use chunks or samples */
265   gboolean sampled;
266   guint padding;
267
268 } QtDemuxStreamStsdEntry;
269
270 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
271
272 struct _QtDemuxStream
273 {
274   GstPad *pad;
275
276   GstQTDemux *demux;
277   gchar *stream_id;
278
279   QtDemuxStreamStsdEntry *stsd_entries;
280   guint stsd_entries_length;
281   guint cur_stsd_entry_index;
282
283   /* stream type */
284   guint32 subtype;
285
286   gboolean new_caps;            /* If TRUE, caps need to be generated (by
287                                  * calling _configure_stream()) This happens
288                                  * for MSS and fragmented streams */
289
290   gboolean new_stream;          /* signals that a stream_start is required */
291   gboolean on_keyframe;         /* if this stream last pushed buffer was a
292                                  * keyframe. This is important to identify
293                                  * where to stop pushing buffers after a
294                                  * segment stop time */
295
296   /* if the stream has a redirect URI in its headers, we store it here */
297   gchar *redirect_uri;
298
299   /* track id */
300   guint track_id;
301
302   /* duration/scale */
303   guint64 duration;             /* in timescale units */
304   guint32 timescale;
305
306   /* language */
307   gchar lang_id[4];             /* ISO 639-2T language code */
308
309   /* our samples */
310   guint32 n_samples;
311   QtDemuxSample *samples;
312   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
313   guint32 n_samples_moof;       /* sample count in a moof */
314   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
315                                  * the framerate of fragmented format stream */
316   guint64 duration_last_moof;
317
318   guint32 offset_in_sample;     /* Offset in the current sample, used for
319                                  * streams which have got exceedingly big
320                                  * sample size (such as 24s of raw audio).
321                                  * Only used when max_buffer_size is non-NULL */
322   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
323                                  * Currently only set for raw audio streams*/
324
325   /* video info */
326   /* aspect ratio */
327   gint display_width;
328   gint display_height;
329
330   /* allocation */
331   gboolean use_allocator;
332   GstAllocator *allocator;
333   GstAllocationParams params;
334
335   gsize alignment;
336
337   /* when a discontinuity is pending */
338   gboolean discont;
339
340   /* list of buffers to push first */
341   GSList *buffers;
342
343   /* if we need to clip this buffer. This is only needed for uncompressed
344    * data */
345   gboolean need_clip;
346
347   /* buffer needs some custom processing, e.g. subtitles */
348   gboolean need_process;
349
350   /* current position */
351   guint32 segment_index;
352   guint32 sample_index;
353   GstClockTime time_position;   /* in gst time */
354   guint64 accumulated_base;
355
356   /* the Gst segment we are processing out, used for clipping */
357   GstSegment segment;
358
359   /* quicktime segments */
360   guint32 n_segments;
361   QtDemuxSegment *segments;
362   gboolean dummy_segment;
363   guint32 from_sample;
364   guint32 to_sample;
365
366   gboolean sent_eos;
367   GstTagList *stream_tags;
368   gboolean send_global_tags;
369
370   GstEvent *pending_event;
371
372   GstByteReader stco;
373   GstByteReader stsz;
374   GstByteReader stsc;
375   GstByteReader stts;
376   GstByteReader stss;
377   GstByteReader stps;
378   GstByteReader ctts;
379
380   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
381   gint64 stbl_index;
382   /* stco */
383   guint co_size;
384   GstByteReader co_chunk;
385   guint32 first_chunk;
386   guint32 current_chunk;
387   guint32 last_chunk;
388   guint32 samples_per_chunk;
389   guint32 stsd_sample_description_id;
390   guint32 stco_sample_index;
391   /* stsz */
392   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
393   /* stsc */
394   guint32 stsc_index;
395   guint32 n_samples_per_chunk;
396   guint32 stsc_chunk_index;
397   guint32 stsc_sample_index;
398   guint64 chunk_offset;
399   /* stts */
400   guint32 stts_index;
401   guint32 stts_samples;
402   guint32 n_sample_times;
403   guint32 stts_sample_index;
404   guint64 stts_time;
405   guint32 stts_duration;
406   /* stss */
407   gboolean stss_present;
408   guint32 n_sample_syncs;
409   guint32 stss_index;
410   /* stps */
411   gboolean stps_present;
412   guint32 n_sample_partial_syncs;
413   guint32 stps_index;
414   QtDemuxRandomAccessEntry *ra_entries;
415   guint n_ra_entries;
416
417   const QtDemuxRandomAccessEntry *pending_seek;
418
419   /* ctts */
420   gboolean ctts_present;
421   guint32 n_composition_times;
422   guint32 ctts_index;
423   guint32 ctts_sample_index;
424   guint32 ctts_count;
425   gint32 ctts_soffset;
426
427   /* cslg */
428   guint32 cslg_shift;
429
430   /* fragmented */
431   gboolean parsed_trex;
432   guint32 def_sample_description_index; /* index is 1-based */
433   guint32 def_sample_duration;
434   guint32 def_sample_size;
435   guint32 def_sample_flags;
436
437   gboolean disabled;
438
439   /* stereoscopic video streams */
440   GstVideoMultiviewMode multiview_mode;
441   GstVideoMultiviewFlags multiview_flags;
442
443   /* protected streams */
444   gboolean protected;
445   guint32 protection_scheme_type;
446   guint32 protection_scheme_version;
447   gpointer protection_scheme_info;      /* specific to the protection scheme */
448   GQueue protection_scheme_event_queue;
449 };
450
451 /* Contains properties and cryptographic info for a set of samples from a
452  * track protected using Common Encryption (cenc) */
453 struct _QtDemuxCencSampleSetInfo
454 {
455   GstStructure *default_properties;
456
457   /* @crypto_info holds one GstStructure per sample */
458   GPtrArray *crypto_info;
459 };
460
461 static const gchar *
462 qt_demux_state_string (enum QtDemuxState state)
463 {
464   switch (state) {
465     case QTDEMUX_STATE_INITIAL:
466       return "<INITIAL>";
467     case QTDEMUX_STATE_HEADER:
468       return "<HEADER>";
469     case QTDEMUX_STATE_MOVIE:
470       return "<MOVIE>";
471     case QTDEMUX_STATE_BUFFER_MDAT:
472       return "<BUFFER_MDAT>";
473     default:
474       return "<UNKNOWN>";
475   }
476 }
477
478 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
479 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
480     guint32 fourcc, GstByteReader * parser);
481 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
482 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
483     guint32 fourcc, GstByteReader * parser);
484
485 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
486
487 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
488
489 static GstStaticPadTemplate gst_qtdemux_sink_template =
490     GST_STATIC_PAD_TEMPLATE ("sink",
491     GST_PAD_SINK,
492     GST_PAD_ALWAYS,
493     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
494         "application/x-3gp")
495     );
496
497 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
498 GST_STATIC_PAD_TEMPLATE ("video_%u",
499     GST_PAD_SRC,
500     GST_PAD_SOMETIMES,
501     GST_STATIC_CAPS_ANY);
502
503 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
504 GST_STATIC_PAD_TEMPLATE ("audio_%u",
505     GST_PAD_SRC,
506     GST_PAD_SOMETIMES,
507     GST_STATIC_CAPS_ANY);
508
509 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
510 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
511     GST_PAD_SRC,
512     GST_PAD_SOMETIMES,
513     GST_STATIC_CAPS_ANY);
514
515 #define gst_qtdemux_parent_class parent_class
516 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
517
518 static void gst_qtdemux_dispose (GObject * object);
519
520 static guint32
521 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
522     GstClockTime media_time);
523 static guint32
524 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
525     QtDemuxStream * str, gint64 media_offset);
526
527 #if 0
528 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
529 static GstIndex *gst_qtdemux_get_index (GstElement * element);
530 #endif
531 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
532     GstStateChange transition);
533 static void gst_qtdemux_set_context (GstElement * element,
534     GstContext * context);
535 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
536 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
537     GstObject * parent, GstPadMode mode, gboolean active);
538
539 static void gst_qtdemux_loop (GstPad * pad);
540 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
541     GstBuffer * inbuf);
542 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
543     GstEvent * event);
544 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
545 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
546     QtDemuxStream * stream);
547 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
548     QtDemuxStream * stream);
549 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
550     gboolean force);
551
552 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
553     const guint8 * buffer, guint length);
554 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
555     const guint8 * buffer, guint length);
556 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
557 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
558     GNode * udta);
559
560 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
561     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
562     GstTagList * list);
563 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
564     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
565     const guint8 * stsd_entry_data, gchar ** codec_name);
566 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
567     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
568     const guint8 * data, int len, gchar ** codec_name);
569 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
570     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
571     gchar ** codec_name);
572 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
573     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
574     const guint8 * stsd_entry_data, gchar ** codec_name);
575
576 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
577     QtDemuxStream * stream, guint32 n);
578 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
579 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
580 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
581 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
582     QtDemuxStream * stream);
583 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
584 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
585     QtDemuxStream * stream);
586 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
587     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
588 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
589     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
590     GstClockTime * _start, GstClockTime * _stop);
591 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
592     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
593
594 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
595 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
596
597 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
598
599 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
600     QtDemuxStream * stream, guint sample_index);
601 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
602     const gchar * id);
603 static void qtdemux_gst_structure_free (GstStructure * gststructure);
604 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
605
606 static void
607 gst_qtdemux_class_init (GstQTDemuxClass * klass)
608 {
609   GObjectClass *gobject_class;
610   GstElementClass *gstelement_class;
611
612   gobject_class = (GObjectClass *) klass;
613   gstelement_class = (GstElementClass *) klass;
614
615   parent_class = g_type_class_peek_parent (klass);
616
617   gobject_class->dispose = gst_qtdemux_dispose;
618
619   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
620 #if 0
621   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
622   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
623 #endif
624   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
625
626   gst_tag_register_musicbrainz_tags ();
627
628   gst_element_class_add_static_pad_template (gstelement_class,
629       &gst_qtdemux_sink_template);
630   gst_element_class_add_static_pad_template (gstelement_class,
631       &gst_qtdemux_videosrc_template);
632   gst_element_class_add_static_pad_template (gstelement_class,
633       &gst_qtdemux_audiosrc_template);
634   gst_element_class_add_static_pad_template (gstelement_class,
635       &gst_qtdemux_subsrc_template);
636   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
637       "Codec/Demuxer",
638       "Demultiplex a QuickTime file into audio and video streams",
639       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
640
641   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
642   gst_riff_init ();
643 }
644
645 static void
646 gst_qtdemux_init (GstQTDemux * qtdemux)
647 {
648   qtdemux->sinkpad =
649       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
650   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
651   gst_pad_set_activatemode_function (qtdemux->sinkpad,
652       qtdemux_sink_activate_mode);
653   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
654   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
655   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
656
657   qtdemux->adapter = gst_adapter_new ();
658   g_queue_init (&qtdemux->protection_event_queue);
659   qtdemux->flowcombiner = gst_flow_combiner_new ();
660   g_mutex_init (&qtdemux->expose_lock);
661
662   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
663
664   gst_qtdemux_reset (qtdemux, TRUE);
665 }
666
667 static void
668 gst_qtdemux_dispose (GObject * object)
669 {
670   GstQTDemux *qtdemux = GST_QTDEMUX (object);
671
672   if (qtdemux->adapter) {
673     g_object_unref (G_OBJECT (qtdemux->adapter));
674     qtdemux->adapter = NULL;
675   }
676   gst_tag_list_unref (qtdemux->tag_list);
677   gst_flow_combiner_free (qtdemux->flowcombiner);
678   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
679       NULL);
680   g_queue_clear (&qtdemux->protection_event_queue);
681
682   g_free (qtdemux->cenc_aux_info_sizes);
683   qtdemux->cenc_aux_info_sizes = NULL;
684   g_mutex_clear (&qtdemux->expose_lock);
685
686   G_OBJECT_CLASS (parent_class)->dispose (object);
687 }
688
689 static void
690 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
691 {
692   if (qtdemux->posted_redirect) {
693     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
694         (_("This file contains no playable streams.")),
695         ("no known streams found, a redirect message has been posted"));
696   } else {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found"));
700   }
701 }
702
703 static GstBuffer *
704 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
705 {
706   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
707       mem, size, 0, size, mem, free_func);
708 }
709
710 static GstFlowReturn
711 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
712     GstBuffer ** buf)
713 {
714   GstFlowReturn flow;
715   GstMapInfo map;
716   gsize bsize;
717
718   if (G_UNLIKELY (size == 0)) {
719     GstFlowReturn ret;
720     GstBuffer *tmp = NULL;
721
722     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
723     if (ret != GST_FLOW_OK)
724       return ret;
725
726     gst_buffer_map (tmp, &map, GST_MAP_READ);
727     size = QT_UINT32 (map.data);
728     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
729
730     gst_buffer_unmap (tmp, &map);
731     gst_buffer_unref (tmp);
732   }
733
734   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
735   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
736     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
737       /* we're pulling header but already got most interesting bits,
738        * so never mind the rest (e.g. tags) (that much) */
739       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
740           size);
741       return GST_FLOW_EOS;
742     } else {
743       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
744           (_("This file is invalid and cannot be played.")),
745           ("atom has bogus size %" G_GUINT64_FORMAT, size));
746       return GST_FLOW_ERROR;
747     }
748   }
749
750   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
751
752   if (G_UNLIKELY (flow != GST_FLOW_OK))
753     return flow;
754
755   bsize = gst_buffer_get_size (*buf);
756   /* Catch short reads - we don't want any partial atoms */
757   if (G_UNLIKELY (bsize < size)) {
758     GST_WARNING_OBJECT (qtdemux,
759         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
760     gst_buffer_unref (*buf);
761     *buf = NULL;
762     return GST_FLOW_EOS;
763   }
764
765   return flow;
766 }
767
768 #if 1
769 static gboolean
770 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
771     GstFormat src_format, gint64 src_value, GstFormat dest_format,
772     gint64 * dest_value)
773 {
774   gboolean res = TRUE;
775   QtDemuxStream *stream = gst_pad_get_element_private (pad);
776   gint32 index;
777
778   if (stream->subtype != FOURCC_vide) {
779     res = FALSE;
780     goto done;
781   }
782
783   switch (src_format) {
784     case GST_FORMAT_TIME:
785       switch (dest_format) {
786         case GST_FORMAT_BYTES:{
787           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
788           if (-1 == index) {
789             res = FALSE;
790             goto done;
791           }
792
793           *dest_value = stream->samples[index].offset;
794
795           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
796               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
797               GST_TIME_ARGS (src_value), *dest_value);
798           break;
799         }
800         default:
801           res = FALSE;
802           break;
803       }
804       break;
805     case GST_FORMAT_BYTES:
806       switch (dest_format) {
807         case GST_FORMAT_TIME:{
808           index =
809               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
810               stream, src_value);
811
812           if (-1 == index) {
813             res = FALSE;
814             goto done;
815           }
816
817           *dest_value =
818               QTSTREAMTIME_TO_GSTTIME (stream,
819               stream->samples[index].timestamp);
820           GST_DEBUG_OBJECT (qtdemux,
821               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
822               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
823           break;
824         }
825         default:
826           res = FALSE;
827           break;
828       }
829       break;
830     default:
831       res = FALSE;
832       break;
833   }
834
835 done:
836   return res;
837 }
838 #endif
839
840 static gboolean
841 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
842 {
843   gboolean res = FALSE;
844
845   *duration = GST_CLOCK_TIME_NONE;
846
847   if (qtdemux->duration != 0 &&
848       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
849     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
850     res = TRUE;
851   } else {
852     *duration = GST_CLOCK_TIME_NONE;
853   }
854
855   return res;
856 }
857
858 static gboolean
859 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
860     GstQuery * query)
861 {
862   gboolean res = FALSE;
863   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
864
865   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
866
867   switch (GST_QUERY_TYPE (query)) {
868     case GST_QUERY_POSITION:{
869       GstFormat fmt;
870
871       gst_query_parse_position (query, &fmt, NULL);
872       if (fmt == GST_FORMAT_TIME
873           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
874         gst_query_set_position (query, GST_FORMAT_TIME,
875             qtdemux->segment.position);
876         res = TRUE;
877       }
878     }
879       break;
880     case GST_QUERY_DURATION:{
881       GstFormat fmt;
882
883       gst_query_parse_duration (query, &fmt, NULL);
884       if (fmt == GST_FORMAT_TIME) {
885         /* First try to query upstream */
886         res = gst_pad_query_default (pad, parent, query);
887         if (!res) {
888           GstClockTime duration;
889           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
890             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
891             res = TRUE;
892           }
893         }
894       }
895       break;
896     }
897     case GST_QUERY_CONVERT:{
898       GstFormat src_fmt, dest_fmt;
899       gint64 src_value, dest_value = 0;
900
901       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
902
903       res = gst_qtdemux_src_convert (qtdemux, pad,
904           src_fmt, src_value, dest_fmt, &dest_value);
905       if (res)
906         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
907
908       break;
909     }
910     case GST_QUERY_FORMATS:
911       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
912       res = TRUE;
913       break;
914     case GST_QUERY_SEEKING:{
915       GstFormat fmt;
916       gboolean seekable;
917
918       /* try upstream first */
919       res = gst_pad_query_default (pad, parent, query);
920
921       if (!res) {
922         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
923         if (fmt == GST_FORMAT_TIME) {
924           GstClockTime duration;
925
926           gst_qtdemux_get_duration (qtdemux, &duration);
927           seekable = TRUE;
928           if (!qtdemux->pullbased) {
929             GstQuery *q;
930
931             /* we might be able with help from upstream */
932             seekable = FALSE;
933             q = gst_query_new_seeking (GST_FORMAT_BYTES);
934             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
935               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
936               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
937             }
938             gst_query_unref (q);
939           }
940           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
941           res = TRUE;
942         }
943       }
944       break;
945     }
946     case GST_QUERY_SEGMENT:
947     {
948       GstFormat format;
949       gint64 start, stop;
950
951       format = qtdemux->segment.format;
952
953       start =
954           gst_segment_to_stream_time (&qtdemux->segment, format,
955           qtdemux->segment.start);
956       if ((stop = qtdemux->segment.stop) == -1)
957         stop = qtdemux->segment.duration;
958       else
959         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
960
961       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
962       res = TRUE;
963       break;
964     }
965     default:
966       res = gst_pad_query_default (pad, parent, query);
967       break;
968   }
969
970   return res;
971 }
972
973 static void
974 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
975 {
976   if (G_LIKELY (stream->pad)) {
977     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
978         GST_DEBUG_PAD_NAME (stream->pad));
979
980     if (!gst_tag_list_is_empty (stream->stream_tags)) {
981       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
982           stream->stream_tags);
983       gst_pad_push_event (stream->pad,
984           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
985     }
986
987     if (G_UNLIKELY (stream->send_global_tags)) {
988       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
989           qtdemux->tag_list);
990       gst_pad_push_event (stream->pad,
991           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
992       stream->send_global_tags = FALSE;
993     }
994   }
995 }
996
997 /* push event on all source pads; takes ownership of the event */
998 static void
999 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1000 {
1001   gboolean has_valid_stream = FALSE;
1002   GstEventType etype = GST_EVENT_TYPE (event);
1003   GList *iter;
1004
1005   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1006       GST_EVENT_TYPE_NAME (event));
1007
1008   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1009     GstPad *pad;
1010     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1011     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1012
1013     if ((pad = stream->pad)) {
1014       has_valid_stream = TRUE;
1015
1016       if (etype == GST_EVENT_EOS) {
1017         /* let's not send twice */
1018         if (stream->sent_eos)
1019           continue;
1020         stream->sent_eos = TRUE;
1021       }
1022
1023       gst_pad_push_event (pad, gst_event_ref (event));
1024     }
1025   }
1026
1027   gst_event_unref (event);
1028
1029   /* if it is EOS and there are no pads, post an error */
1030   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1031     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1032   }
1033 }
1034
1035 typedef struct
1036 {
1037   guint64 media_time;
1038 } FindData;
1039
1040 static gint
1041 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1042 {
1043   if ((gint64) s1->timestamp > *media_time)
1044     return 1;
1045   if ((gint64) s1->timestamp == *media_time)
1046     return 0;
1047
1048   return -1;
1049 }
1050
1051 /* find the index of the sample that includes the data for @media_time using a
1052  * binary search.  Only to be called in optimized cases of linear search below.
1053  *
1054  * Returns the index of the sample with the corresponding *DTS*.
1055  */
1056 static guint32
1057 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1058     guint64 media_time)
1059 {
1060   QtDemuxSample *result;
1061   guint32 index;
1062
1063   /* convert media_time to mov format */
1064   media_time =
1065       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1066
1067   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1068       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1069       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1070
1071   if (G_LIKELY (result))
1072     index = result - str->samples;
1073   else
1074     index = 0;
1075
1076   return index;
1077 }
1078
1079
1080
1081 /* find the index of the sample that includes the data for @media_offset using a
1082  * linear search
1083  *
1084  * Returns the index of the sample.
1085  */
1086 static guint32
1087 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1088     QtDemuxStream * str, gint64 media_offset)
1089 {
1090   QtDemuxSample *result = str->samples;
1091   guint32 index = 0;
1092
1093   if (result == NULL || str->n_samples == 0)
1094     return -1;
1095
1096   if (media_offset == result->offset)
1097     return index;
1098
1099   result++;
1100   while (index < str->n_samples - 1) {
1101     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1102       goto parse_failed;
1103
1104     if (media_offset < result->offset)
1105       break;
1106
1107     index++;
1108     result++;
1109   }
1110   return index;
1111
1112   /* ERRORS */
1113 parse_failed:
1114   {
1115     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1116     return -1;
1117   }
1118 }
1119
1120 /* find the index of the sample that includes the data for @media_time using a
1121  * linear search, and keeping in mind that not all samples may have been parsed
1122  * yet.  If possible, it will delegate to binary search.
1123  *
1124  * Returns the index of the sample.
1125  */
1126 static guint32
1127 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1128     GstClockTime media_time)
1129 {
1130   guint32 index = 0;
1131   guint64 mov_time;
1132   QtDemuxSample *sample;
1133
1134   /* convert media_time to mov format */
1135   mov_time =
1136       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1137
1138   sample = str->samples;
1139   if (mov_time == sample->timestamp + sample->pts_offset)
1140     return index;
1141
1142   /* use faster search if requested time in already parsed range */
1143   sample = str->samples + str->stbl_index;
1144   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1145     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1146     sample = str->samples + index;
1147   } else {
1148     while (index < str->n_samples - 1) {
1149       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1150         goto parse_failed;
1151
1152       sample = str->samples + index + 1;
1153       if (mov_time < sample->timestamp) {
1154         sample = str->samples + index;
1155         break;
1156       }
1157
1158       index++;
1159     }
1160   }
1161
1162   /* sample->timestamp is now <= media_time, need to find the corresponding
1163    * PTS now by looking backwards */
1164   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1165     index--;
1166     sample = str->samples + index;
1167   }
1168
1169   return index;
1170
1171   /* ERRORS */
1172 parse_failed:
1173   {
1174     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1175     return -1;
1176   }
1177 }
1178
1179 /* find the index of the keyframe needed to decode the sample at @index
1180  * of stream @str, or of a subsequent keyframe (depending on @next)
1181  *
1182  * Returns the index of the keyframe.
1183  */
1184 static guint32
1185 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1186     guint32 index, gboolean next)
1187 {
1188   guint32 new_index = index;
1189
1190   if (index >= str->n_samples) {
1191     new_index = str->n_samples;
1192     goto beach;
1193   }
1194
1195   /* all keyframes, return index */
1196   if (str->all_keyframe) {
1197     new_index = index;
1198     goto beach;
1199   }
1200
1201   /* else search until we have a keyframe */
1202   while (new_index < str->n_samples) {
1203     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1204       goto parse_failed;
1205
1206     if (str->samples[new_index].keyframe)
1207       break;
1208
1209     if (new_index == 0)
1210       break;
1211
1212     if (next)
1213       new_index++;
1214     else
1215       new_index--;
1216   }
1217
1218   if (new_index == str->n_samples) {
1219     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1220     new_index = -1;
1221   }
1222
1223 beach:
1224   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1225       "gave %u", next ? "after" : "before", index, new_index);
1226
1227   return new_index;
1228
1229   /* ERRORS */
1230 parse_failed:
1231   {
1232     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1233     return -1;
1234   }
1235 }
1236
1237 /* find the segment for @time_position for @stream
1238  *
1239  * Returns the index of the segment containing @time_position.
1240  * Returns the last segment and sets the @eos variable to TRUE
1241  * if the time is beyond the end. @eos may be NULL
1242  */
1243 static guint32
1244 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1245     GstClockTime time_position)
1246 {
1247   gint i;
1248   guint32 seg_idx;
1249
1250   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1251       GST_TIME_ARGS (time_position));
1252
1253   seg_idx = -1;
1254   for (i = 0; i < stream->n_segments; i++) {
1255     QtDemuxSegment *segment = &stream->segments[i];
1256
1257     GST_LOG_OBJECT (stream->pad,
1258         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1259         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1260
1261     /* For the last segment we include stop_time in the last segment */
1262     if (i < stream->n_segments - 1) {
1263       if (segment->time <= time_position && time_position < segment->stop_time) {
1264         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1265         seg_idx = i;
1266         break;
1267       }
1268     } else {
1269       /* Last segment always matches */
1270       seg_idx = i;
1271       break;
1272     }
1273   }
1274   return seg_idx;
1275 }
1276
1277 /* move the stream @str to the sample position @index.
1278  *
1279  * Updates @str->sample_index and marks discontinuity if needed.
1280  */
1281 static void
1282 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1283     guint32 index)
1284 {
1285   /* no change needed */
1286   if (index == str->sample_index)
1287     return;
1288
1289   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1290       str->n_samples);
1291
1292   /* position changed, we have a discont */
1293   str->sample_index = index;
1294   str->offset_in_sample = 0;
1295   /* Each time we move in the stream we store the position where we are
1296    * starting from */
1297   str->from_sample = index;
1298   str->discont = TRUE;
1299 }
1300
1301 static void
1302 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1303     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1304 {
1305   guint64 min_offset;
1306   gint64 min_byte_offset = -1;
1307   GList *iter;
1308
1309   min_offset = desired_time;
1310
1311   /* for each stream, find the index of the sample in the segment
1312    * and move back to the previous keyframe. */
1313   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1314     QtDemuxStream *str;
1315     guint32 index, kindex;
1316     guint32 seg_idx;
1317     GstClockTime media_start;
1318     GstClockTime media_time;
1319     GstClockTime seg_time;
1320     QtDemuxSegment *seg;
1321     gboolean empty_segment = FALSE;
1322
1323     str = QTDEMUX_STREAM (iter->data);
1324
1325     if (CUR_STREAM (str)->sparse && !use_sparse)
1326       continue;
1327
1328     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1329     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1330
1331     /* get segment and time in the segment */
1332     seg = &str->segments[seg_idx];
1333     seg_time = (desired_time - seg->time) * seg->rate;
1334
1335     while (QTSEGMENT_IS_EMPTY (seg)) {
1336       seg_time = 0;
1337       empty_segment = TRUE;
1338       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1339           seg_idx);
1340       seg_idx++;
1341       if (seg_idx == str->n_segments)
1342         break;
1343       seg = &str->segments[seg_idx];
1344     }
1345
1346     if (seg_idx == str->n_segments) {
1347       /* FIXME track shouldn't have the last segment as empty, but if it
1348        * happens we better handle it */
1349       continue;
1350     }
1351
1352     /* get the media time in the segment */
1353     media_start = seg->media_start + seg_time;
1354
1355     /* get the index of the sample with media time */
1356     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1357     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1358         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1359         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1360         empty_segment);
1361
1362     /* shift to next frame if we are looking for next keyframe */
1363     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1364         && index < str->stbl_index)
1365       index++;
1366
1367     if (!empty_segment) {
1368       /* find previous keyframe */
1369       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1370
1371       /* we will settle for one before if none found after */
1372       if (next && kindex == -1)
1373         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1374
1375       /* if the keyframe is at a different position, we need to update the
1376        * requested seek time */
1377       if (index != kindex) {
1378         index = kindex;
1379
1380         /* get timestamp of keyframe */
1381         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1382         GST_DEBUG_OBJECT (qtdemux,
1383             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1384             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1385             str->samples[kindex].offset);
1386
1387         /* keyframes in the segment get a chance to change the
1388          * desired_offset. keyframes out of the segment are
1389          * ignored. */
1390         if (media_time >= seg->media_start) {
1391           GstClockTime seg_time;
1392
1393           /* this keyframe is inside the segment, convert back to
1394            * segment time */
1395           seg_time = (media_time - seg->media_start) + seg->time;
1396           if ((!next && (seg_time < min_offset)) ||
1397               (next && (seg_time > min_offset)))
1398             min_offset = seg_time;
1399         }
1400       }
1401     }
1402
1403     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1404       min_byte_offset = str->samples[index].offset;
1405   }
1406
1407   if (key_time)
1408     *key_time = min_offset;
1409   if (key_offset)
1410     *key_offset = min_byte_offset;
1411 }
1412
1413 static gboolean
1414 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1415     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1416 {
1417   gboolean res;
1418
1419   g_return_val_if_fail (format != NULL, FALSE);
1420   g_return_val_if_fail (cur != NULL, FALSE);
1421   g_return_val_if_fail (stop != NULL, FALSE);
1422
1423   if (*format == GST_FORMAT_TIME)
1424     return TRUE;
1425
1426   res = TRUE;
1427   if (cur_type != GST_SEEK_TYPE_NONE)
1428     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1429   if (res && stop_type != GST_SEEK_TYPE_NONE)
1430     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1431
1432   if (res)
1433     *format = GST_FORMAT_TIME;
1434
1435   return res;
1436 }
1437
1438 /* perform seek in push based mode:
1439    find BYTE position to move to based on time and delegate to upstream
1440 */
1441 static gboolean
1442 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1443 {
1444   gdouble rate;
1445   GstFormat format;
1446   GstSeekFlags flags;
1447   GstSeekType cur_type, stop_type;
1448   gint64 cur, stop, key_cur;
1449   gboolean res;
1450   gint64 byte_cur;
1451   gint64 original_stop;
1452   guint32 seqnum;
1453
1454   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1455
1456   gst_event_parse_seek (event, &rate, &format, &flags,
1457       &cur_type, &cur, &stop_type, &stop);
1458   seqnum = gst_event_get_seqnum (event);
1459
1460   /* only forward streaming and seeking is possible */
1461   if (rate <= 0)
1462     goto unsupported_seek;
1463
1464   /* convert to TIME if needed and possible */
1465   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1466           stop_type, &stop))
1467     goto no_format;
1468
1469   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1470    * the original stop position to use when upstream pushes the new segment
1471    * for this seek */
1472   original_stop = stop;
1473   stop = -1;
1474
1475   /* find reasonable corresponding BYTE position,
1476    * also try to mind about keyframes, since we can not go back a bit for them
1477    * later on */
1478   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1479    * mostly just work, but let's not yet boldly go there  ... */
1480   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1481
1482   if (byte_cur == -1)
1483     goto abort_seek;
1484
1485   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1486       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1487       stop);
1488
1489   GST_OBJECT_LOCK (qtdemux);
1490   qtdemux->seek_offset = byte_cur;
1491   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1492     qtdemux->push_seek_start = cur;
1493   } else {
1494     qtdemux->push_seek_start = key_cur;
1495   }
1496
1497   if (stop_type == GST_SEEK_TYPE_NONE) {
1498     qtdemux->push_seek_stop = qtdemux->segment.stop;
1499   } else {
1500     qtdemux->push_seek_stop = original_stop;
1501   }
1502   GST_OBJECT_UNLOCK (qtdemux);
1503
1504   qtdemux->segment_seqnum = seqnum;
1505   /* BYTE seek event */
1506   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1507       stop_type, stop);
1508   gst_event_set_seqnum (event, seqnum);
1509   res = gst_pad_push_event (qtdemux->sinkpad, event);
1510
1511   return res;
1512
1513   /* ERRORS */
1514 abort_seek:
1515   {
1516     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1517         "seek aborted.");
1518     return FALSE;
1519   }
1520 unsupported_seek:
1521   {
1522     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1523     return FALSE;
1524   }
1525 no_format:
1526   {
1527     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1528     return FALSE;
1529   }
1530 }
1531
1532 /* perform the seek.
1533  *
1534  * We set all segment_indexes in the streams to unknown and
1535  * adjust the time_position to the desired position. this is enough
1536  * to trigger a segment switch in the streaming thread to start
1537  * streaming from the desired position.
1538  *
1539  * Keyframe seeking is a little more complicated when dealing with
1540  * segments. Ideally we want to move to the previous keyframe in
1541  * the segment but there might not be a keyframe in the segment. In
1542  * fact, none of the segments could contain a keyframe. We take a
1543  * practical approach: seek to the previous keyframe in the segment,
1544  * if there is none, seek to the beginning of the segment.
1545  *
1546  * Called with STREAM_LOCK
1547  */
1548 static gboolean
1549 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1550     guint32 seqnum, GstSeekFlags flags)
1551 {
1552   gint64 desired_offset;
1553   GList *iter;
1554
1555   desired_offset = segment->position;
1556
1557   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1558       GST_TIME_ARGS (desired_offset));
1559
1560   /* may not have enough fragmented info to do this adjustment,
1561    * and we can't scan (and probably should not) at this time with
1562    * possibly flushing upstream */
1563   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1564     gint64 min_offset;
1565     gboolean next, before, after;
1566
1567     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1568     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1569     next = after && !before;
1570     if (segment->rate < 0)
1571       next = !next;
1572
1573     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1574         NULL);
1575     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1576         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1577     desired_offset = min_offset;
1578   }
1579
1580   /* and set all streams to the final position */
1581   gst_flow_combiner_reset (qtdemux->flowcombiner);
1582   qtdemux->segment_seqnum = seqnum;
1583   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1584     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1585
1586     stream->time_position = desired_offset;
1587     stream->accumulated_base = 0;
1588     stream->sample_index = -1;
1589     stream->offset_in_sample = 0;
1590     stream->segment_index = -1;
1591     stream->sent_eos = FALSE;
1592
1593     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1594       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1595   }
1596   segment->position = desired_offset;
1597   segment->time = desired_offset;
1598   if (segment->rate >= 0) {
1599     segment->start = desired_offset;
1600
1601     /* we stop at the end */
1602     if (segment->stop == -1)
1603       segment->stop = segment->duration;
1604   } else {
1605     segment->stop = desired_offset;
1606   }
1607
1608   if (qtdemux->fragmented)
1609     qtdemux->fragmented_seek_pending = TRUE;
1610
1611   return TRUE;
1612 }
1613
1614 /* do a seek in pull based mode */
1615 static gboolean
1616 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1617 {
1618   gdouble rate;
1619   GstFormat format;
1620   GstSeekFlags flags;
1621   GstSeekType cur_type, stop_type;
1622   gint64 cur, stop;
1623   gboolean flush;
1624   gboolean update;
1625   GstSegment seeksegment;
1626   guint32 seqnum = GST_SEQNUM_INVALID;
1627   GstEvent *flush_event;
1628   gboolean ret;
1629
1630   if (event) {
1631     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1632
1633     gst_event_parse_seek (event, &rate, &format, &flags,
1634         &cur_type, &cur, &stop_type, &stop);
1635     seqnum = gst_event_get_seqnum (event);
1636
1637     /* we have to have a format as the segment format. Try to convert
1638      * if not. */
1639     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1640             stop_type, &stop))
1641       goto no_format;
1642
1643     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1644   } else {
1645     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1646     flags = 0;
1647   }
1648
1649   flush = flags & GST_SEEK_FLAG_FLUSH;
1650
1651   /* stop streaming, either by flushing or by pausing the task */
1652   if (flush) {
1653     flush_event = gst_event_new_flush_start ();
1654     if (seqnum != GST_SEQNUM_INVALID)
1655       gst_event_set_seqnum (flush_event, seqnum);
1656     /* unlock upstream pull_range */
1657     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1658     /* make sure out loop function exits */
1659     gst_qtdemux_push_event (qtdemux, flush_event);
1660   } else {
1661     /* non flushing seek, pause the task */
1662     gst_pad_pause_task (qtdemux->sinkpad);
1663   }
1664
1665   /* wait for streaming to finish */
1666   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1667
1668   /* copy segment, we need this because we still need the old
1669    * segment when we close the current segment. */
1670   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1671
1672   if (event) {
1673     /* configure the segment with the seek variables */
1674     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1675     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1676             cur_type, cur, stop_type, stop, &update)) {
1677       ret = FALSE;
1678       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1679     } else {
1680       /* now do the seek */
1681       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1682     }
1683   } else {
1684     /* now do the seek */
1685     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1686   }
1687
1688   /* prepare for streaming again */
1689   if (flush) {
1690     flush_event = gst_event_new_flush_stop (TRUE);
1691     if (seqnum != GST_SEQNUM_INVALID)
1692       gst_event_set_seqnum (flush_event, seqnum);
1693
1694     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1695     gst_qtdemux_push_event (qtdemux, flush_event);
1696   }
1697
1698   /* commit the new segment */
1699   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1700
1701   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1702     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1703         qtdemux->segment.format, qtdemux->segment.position);
1704     if (seqnum != GST_SEQNUM_INVALID)
1705       gst_message_set_seqnum (msg, seqnum);
1706     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1707   }
1708
1709   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1710   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1711       qtdemux->sinkpad, NULL);
1712
1713   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1714
1715   return ret;
1716
1717   /* ERRORS */
1718 no_format:
1719   {
1720     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1721     return FALSE;
1722   }
1723 }
1724
1725 static gboolean
1726 qtdemux_ensure_index (GstQTDemux * qtdemux)
1727 {
1728   GList *iter;
1729
1730   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1731
1732   /* Build complete index */
1733   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1734     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1735
1736     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1737       GST_LOG_OBJECT (qtdemux,
1738           "Building complete index of track-id %u for seeking failed!",
1739           stream->track_id);
1740       return FALSE;
1741     }
1742   }
1743
1744   return TRUE;
1745 }
1746
1747 static gboolean
1748 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1749     GstEvent * event)
1750 {
1751   gboolean res = TRUE;
1752   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1753
1754   switch (GST_EVENT_TYPE (event)) {
1755     case GST_EVENT_SEEK:
1756     {
1757 #ifndef GST_DISABLE_GST_DEBUG
1758       GstClockTime ts = gst_util_get_timestamp ();
1759 #endif
1760       guint32 seqnum = gst_event_get_seqnum (event);
1761
1762       qtdemux->received_seek = TRUE;
1763
1764       if (seqnum == qtdemux->segment_seqnum) {
1765         GST_LOG_OBJECT (pad,
1766             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1767         gst_event_unref (event);
1768         return TRUE;
1769       }
1770
1771       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1772         /* seek should be handled by upstream, we might need to re-download fragments */
1773         GST_DEBUG_OBJECT (qtdemux,
1774             "let upstream handle seek for fragmented playback");
1775         goto upstream;
1776       }
1777
1778       /* Build complete index for seeking;
1779        * if not a fragmented file at least */
1780       if (!qtdemux->fragmented)
1781         if (!qtdemux_ensure_index (qtdemux))
1782           goto index_failed;
1783 #ifndef GST_DISABLE_GST_DEBUG
1784       ts = gst_util_get_timestamp () - ts;
1785       GST_INFO_OBJECT (qtdemux,
1786           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1787 #endif
1788     }
1789       if (qtdemux->pullbased) {
1790         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1791       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1792         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1793         res = TRUE;
1794       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1795           && !qtdemux->fragmented) {
1796         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1797       } else {
1798         GST_DEBUG_OBJECT (qtdemux,
1799             "ignoring seek in push mode in current state");
1800         res = FALSE;
1801       }
1802       gst_event_unref (event);
1803       break;
1804     default:
1805     upstream:
1806       res = gst_pad_event_default (pad, parent, event);
1807       break;
1808   }
1809
1810 done:
1811   return res;
1812
1813   /* ERRORS */
1814 index_failed:
1815   {
1816     GST_ERROR_OBJECT (qtdemux, "Index failed");
1817     gst_event_unref (event);
1818     res = FALSE;
1819     goto done;
1820   }
1821 }
1822
1823 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1824  *
1825  * If @fw is false, the coding order is explored backwards.
1826  *
1827  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1828  * sample is found for that track.
1829  *
1830  * The stream and sample index of the sample with the minimum offset in the direction explored
1831  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1832  *
1833  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1834  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1835  * @_stream and @_index. */
1836 static void
1837 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1838     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1839 {
1840   gint i, index;
1841   gint64 time, min_time;
1842   QtDemuxStream *stream;
1843   GList *iter;
1844
1845   min_time = -1;
1846   stream = NULL;
1847   index = -1;
1848
1849   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1850     QtDemuxStream *str;
1851     gint inc;
1852     gboolean set_sample;
1853
1854     str = QTDEMUX_STREAM (iter->data);
1855     set_sample = !set;
1856
1857     if (fw) {
1858       i = 0;
1859       inc = 1;
1860     } else {
1861       i = str->n_samples - 1;
1862       inc = -1;
1863     }
1864
1865     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1866       if (str->samples[i].size == 0)
1867         continue;
1868
1869       if (fw && (str->samples[i].offset < byte_pos))
1870         continue;
1871
1872       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1873         continue;
1874
1875       /* move stream to first available sample */
1876       if (set) {
1877         gst_qtdemux_move_stream (qtdemux, str, i);
1878         set_sample = TRUE;
1879       }
1880
1881       /* avoid index from sparse streams since they might be far away */
1882       if (!CUR_STREAM (str)->sparse) {
1883         /* determine min/max time */
1884         time = QTSAMPLE_PTS (str, &str->samples[i]);
1885         if (min_time == -1 || (!fw && time > min_time) ||
1886             (fw && time < min_time)) {
1887           min_time = time;
1888         }
1889
1890         /* determine stream with leading sample, to get its position */
1891         if (!stream ||
1892             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1893             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1894           stream = str;
1895           index = i;
1896         }
1897       }
1898       break;
1899     }
1900
1901     /* no sample for this stream, mark eos */
1902     if (!set_sample)
1903       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1904   }
1905
1906   if (_time)
1907     *_time = min_time;
1908   if (_stream)
1909     *_stream = stream;
1910   if (_index)
1911     *_index = index;
1912 }
1913
1914 /* Copied from mpegtsbase code */
1915 /* FIXME: replace this function when we add new util function for stream-id creation */
1916 static gchar *
1917 _get_upstream_id (GstQTDemux * demux)
1918 {
1919   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1920
1921   if (!upstream_id) {
1922     /* Try to create one from the upstream URI, else use a randome number */
1923     GstQuery *query;
1924     gchar *uri = NULL;
1925
1926     /* Try to generate one from the URI query and
1927      * if it fails take a random number instead */
1928     query = gst_query_new_uri ();
1929     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1930       gst_query_parse_uri (query, &uri);
1931     }
1932
1933     if (uri) {
1934       GChecksum *cs;
1935
1936       /* And then generate an SHA256 sum of the URI */
1937       cs = g_checksum_new (G_CHECKSUM_SHA256);
1938       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1939       g_free (uri);
1940       upstream_id = g_strdup (g_checksum_get_string (cs));
1941       g_checksum_free (cs);
1942     } else {
1943       /* Just get some random number if the URI query fails */
1944       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1945           "implementing a deterministic way of creating a stream-id");
1946       upstream_id =
1947           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1948           g_random_int (), g_random_int ());
1949     }
1950
1951     gst_query_unref (query);
1952   }
1953   return upstream_id;
1954 }
1955
1956 static QtDemuxStream *
1957 _create_stream (GstQTDemux * demux, guint32 track_id)
1958 {
1959   QtDemuxStream *stream;
1960   gchar *upstream_id;
1961
1962   stream = g_new0 (QtDemuxStream, 1);
1963   stream->demux = demux;
1964   stream->track_id = track_id;
1965   upstream_id = _get_upstream_id (demux);
1966   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1967   g_free (upstream_id);
1968   /* new streams always need a discont */
1969   stream->discont = TRUE;
1970   /* we enable clipping for raw audio/video streams */
1971   stream->need_clip = FALSE;
1972   stream->need_process = FALSE;
1973   stream->segment_index = -1;
1974   stream->time_position = 0;
1975   stream->sample_index = -1;
1976   stream->offset_in_sample = 0;
1977   stream->new_stream = TRUE;
1978   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1979   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1980   stream->protected = FALSE;
1981   stream->protection_scheme_type = 0;
1982   stream->protection_scheme_version = 0;
1983   stream->protection_scheme_info = NULL;
1984   stream->n_samples_moof = 0;
1985   stream->duration_moof = 0;
1986   stream->duration_last_moof = 0;
1987   stream->alignment = 1;
1988   stream->stream_tags = gst_tag_list_new_empty ();
1989   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1990   g_queue_init (&stream->protection_scheme_event_queue);
1991   return stream;
1992 }
1993
1994 static gboolean
1995 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1996 {
1997   GstStructure *structure;
1998   const gchar *variant;
1999   const GstCaps *mediacaps = NULL;
2000
2001   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2002
2003   structure = gst_caps_get_structure (caps, 0);
2004   variant = gst_structure_get_string (structure, "variant");
2005
2006   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2007     QtDemuxStream *stream;
2008     const GValue *value;
2009
2010     demux->fragmented = TRUE;
2011     demux->mss_mode = TRUE;
2012
2013     if (demux->n_streams > 1) {
2014       /* can't do this, we can only renegotiate for another mss format */
2015       return FALSE;
2016     }
2017
2018     value = gst_structure_get_value (structure, "media-caps");
2019     /* create stream */
2020     if (value) {
2021       const GValue *timescale_v;
2022
2023       /* TODO update when stream changes during playback */
2024
2025       if (demux->n_streams == 0) {
2026         stream = _create_stream (demux, 1);
2027         demux->active_streams = g_list_append (demux->active_streams, stream);
2028         demux->n_streams = 1;
2029         /* mss has no stsd/stsd entry, use id 0 as default */
2030         stream->stsd_entries_length = 1;
2031         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2032         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2033       } else {
2034         stream = QTDEMUX_FIRST_STREAM (demux);
2035       }
2036
2037       timescale_v = gst_structure_get_value (structure, "timescale");
2038       if (timescale_v) {
2039         stream->timescale = g_value_get_uint64 (timescale_v);
2040       } else {
2041         /* default mss timescale */
2042         stream->timescale = 10000000;
2043       }
2044       demux->timescale = stream->timescale;
2045
2046       mediacaps = gst_value_get_caps (value);
2047       if (!CUR_STREAM (stream)->caps
2048           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2049         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2050             mediacaps);
2051         stream->new_caps = TRUE;
2052       }
2053       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2054       structure = gst_caps_get_structure (mediacaps, 0);
2055       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2056         stream->subtype = FOURCC_vide;
2057
2058         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2059         gst_structure_get_int (structure, "height",
2060             &CUR_STREAM (stream)->height);
2061         gst_structure_get_fraction (structure, "framerate",
2062             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2063       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2064         gint rate = 0;
2065         stream->subtype = FOURCC_soun;
2066         gst_structure_get_int (structure, "channels",
2067             &CUR_STREAM (stream)->n_channels);
2068         gst_structure_get_int (structure, "rate", &rate);
2069         CUR_STREAM (stream)->rate = rate;
2070       }
2071     }
2072     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2073   } else {
2074     demux->mss_mode = FALSE;
2075   }
2076
2077   return TRUE;
2078 }
2079
2080 static void
2081 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2082 {
2083   GList *iter;
2084
2085   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2086   gst_pad_stop_task (qtdemux->sinkpad);
2087
2088   if (hard || qtdemux->upstream_format_is_time) {
2089     qtdemux->state = QTDEMUX_STATE_INITIAL;
2090     qtdemux->neededbytes = 16;
2091     qtdemux->todrop = 0;
2092     qtdemux->pullbased = FALSE;
2093     qtdemux->posted_redirect = FALSE;
2094     qtdemux->first_mdat = -1;
2095     qtdemux->header_size = 0;
2096     qtdemux->mdatoffset = -1;
2097     qtdemux->restoredata_offset = -1;
2098     if (qtdemux->mdatbuffer)
2099       gst_buffer_unref (qtdemux->mdatbuffer);
2100     if (qtdemux->restoredata_buffer)
2101       gst_buffer_unref (qtdemux->restoredata_buffer);
2102     qtdemux->mdatbuffer = NULL;
2103     qtdemux->restoredata_buffer = NULL;
2104     qtdemux->mdatleft = 0;
2105     qtdemux->mdatsize = 0;
2106     if (qtdemux->comp_brands)
2107       gst_buffer_unref (qtdemux->comp_brands);
2108     qtdemux->comp_brands = NULL;
2109     qtdemux->last_moov_offset = -1;
2110     if (qtdemux->moov_node_compressed) {
2111       g_node_destroy (qtdemux->moov_node_compressed);
2112       if (qtdemux->moov_node)
2113         g_free (qtdemux->moov_node->data);
2114     }
2115     qtdemux->moov_node_compressed = NULL;
2116     if (qtdemux->moov_node)
2117       g_node_destroy (qtdemux->moov_node);
2118     qtdemux->moov_node = NULL;
2119     if (qtdemux->tag_list)
2120       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2121     qtdemux->tag_list = gst_tag_list_new_empty ();
2122     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2123 #if 0
2124     if (qtdemux->element_index)
2125       gst_object_unref (qtdemux->element_index);
2126     qtdemux->element_index = NULL;
2127 #endif
2128     qtdemux->major_brand = 0;
2129     qtdemux->upstream_format_is_time = FALSE;
2130     qtdemux->upstream_seekable = FALSE;
2131     qtdemux->upstream_size = 0;
2132
2133     qtdemux->fragment_start = -1;
2134     qtdemux->fragment_start_offset = -1;
2135     qtdemux->duration = 0;
2136     qtdemux->moof_offset = 0;
2137     qtdemux->chapters_track_id = 0;
2138     qtdemux->have_group_id = FALSE;
2139     qtdemux->group_id = G_MAXUINT;
2140
2141     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2142         NULL);
2143     g_queue_clear (&qtdemux->protection_event_queue);
2144
2145     qtdemux->received_seek = FALSE;
2146     qtdemux->first_moof_already_parsed = FALSE;
2147   }
2148   qtdemux->offset = 0;
2149   gst_adapter_clear (qtdemux->adapter);
2150   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2151   qtdemux->need_segment = TRUE;
2152
2153   if (hard) {
2154     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2155     g_list_free_full (qtdemux->active_streams,
2156         (GDestroyNotify) gst_qtdemux_stream_free);
2157     g_list_free_full (qtdemux->old_streams,
2158         (GDestroyNotify) gst_qtdemux_stream_free);
2159     qtdemux->active_streams = NULL;
2160     qtdemux->old_streams = NULL;
2161     qtdemux->n_streams = 0;
2162     qtdemux->n_video_streams = 0;
2163     qtdemux->n_audio_streams = 0;
2164     qtdemux->n_sub_streams = 0;
2165     qtdemux->exposed = FALSE;
2166     qtdemux->fragmented = FALSE;
2167     qtdemux->mss_mode = FALSE;
2168     gst_caps_replace (&qtdemux->media_caps, NULL);
2169     qtdemux->timescale = 0;
2170     qtdemux->got_moov = FALSE;
2171     qtdemux->cenc_aux_info_offset = 0;
2172     qtdemux->cenc_aux_info_sizes = NULL;
2173     qtdemux->cenc_aux_sample_count = 0;
2174     if (qtdemux->protection_system_ids) {
2175       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2176       qtdemux->protection_system_ids = NULL;
2177     }
2178     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2179         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2180         GST_BIN_FLAG_STREAMS_AWARE);
2181
2182     if (qtdemux->preferred_protection_system_id) {
2183       g_free (qtdemux->preferred_protection_system_id);
2184       qtdemux->preferred_protection_system_id = NULL;
2185     }
2186   } else if (qtdemux->mss_mode) {
2187     gst_flow_combiner_reset (qtdemux->flowcombiner);
2188     g_list_foreach (qtdemux->active_streams,
2189         (GFunc) gst_qtdemux_stream_clear, NULL);
2190   } else {
2191     gst_flow_combiner_reset (qtdemux->flowcombiner);
2192     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2193       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2194       stream->sent_eos = FALSE;
2195       stream->time_position = 0;
2196       stream->accumulated_base = 0;
2197     }
2198   }
2199 }
2200
2201
2202 /* Maps the @segment to the qt edts internal segments and pushes
2203  * the correspnding segment event.
2204  *
2205  * If it ends up being at a empty segment, a gap will be pushed and the next
2206  * edts segment will be activated in sequence.
2207  *
2208  * To be used in push-mode only */
2209 static void
2210 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2211 {
2212   gint i;
2213   GList *iter;
2214
2215   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2216     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2217
2218     stream->time_position = segment->start;
2219
2220     /* in push mode we should be guaranteed that we will have empty segments
2221      * at the beginning and then one segment after, other scenarios are not
2222      * supported and are discarded when parsing the edts */
2223     for (i = 0; i < stream->n_segments; i++) {
2224       if (stream->segments[i].stop_time > segment->start) {
2225         /* push the empty segment and move to the next one */
2226         gst_qtdemux_activate_segment (qtdemux, stream, i,
2227             stream->time_position);
2228         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2229           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2230               stream->time_position);
2231
2232           /* accumulate previous segments */
2233           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2234             stream->accumulated_base +=
2235                 (stream->segment.stop -
2236                 stream->segment.start) / ABS (stream->segment.rate);
2237           continue;
2238         }
2239
2240         g_assert (i == stream->n_segments - 1);
2241       }
2242     }
2243   }
2244 }
2245
2246 static gboolean
2247 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2248     GstEvent * event)
2249 {
2250   GstQTDemux *demux = GST_QTDEMUX (parent);
2251   gboolean res = TRUE;
2252
2253   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2254
2255   switch (GST_EVENT_TYPE (event)) {
2256     case GST_EVENT_SEGMENT:
2257     {
2258       gint64 offset = 0;
2259       QtDemuxStream *stream;
2260       gint idx;
2261       GstSegment segment;
2262
2263       /* some debug output */
2264       gst_event_copy_segment (event, &segment);
2265       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2266           &segment);
2267
2268       if (segment.format == GST_FORMAT_TIME) {
2269         demux->upstream_format_is_time = TRUE;
2270         demux->segment_seqnum = gst_event_get_seqnum (event);
2271       } else {
2272         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2273             "not in time format");
2274
2275         /* chain will send initial newsegment after pads have been added */
2276         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2277           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2278           goto exit;
2279         }
2280       }
2281
2282       /* check if this matches a time seek we received previously
2283        * FIXME for backwards compatibility reasons we use the
2284        * seek_offset here to compare. In the future we might want to
2285        * change this to use the seqnum as it uniquely should identify
2286        * the segment that corresponds to the seek. */
2287       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2288           ", received segment offset %" G_GINT64_FORMAT,
2289           demux->seek_offset, segment.start);
2290       if (segment.format == GST_FORMAT_BYTES
2291           && demux->seek_offset == segment.start) {
2292         GST_OBJECT_LOCK (demux);
2293         offset = segment.start;
2294
2295         segment.format = GST_FORMAT_TIME;
2296         segment.start = demux->push_seek_start;
2297         segment.stop = demux->push_seek_stop;
2298         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2299             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2300             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2301         GST_OBJECT_UNLOCK (demux);
2302       }
2303
2304       /* we only expect a BYTE segment, e.g. following a seek */
2305       if (segment.format == GST_FORMAT_BYTES) {
2306         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2307           offset = segment.start;
2308
2309           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2310               NULL, (gint64 *) & segment.start);
2311           if ((gint64) segment.start < 0)
2312             segment.start = 0;
2313         }
2314         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2315           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2316               NULL, (gint64 *) & segment.stop);
2317           /* keyframe seeking should already arrange for start >= stop,
2318            * but make sure in other rare cases */
2319           segment.stop = MAX (segment.stop, segment.start);
2320         }
2321       } else if (segment.format == GST_FORMAT_TIME) {
2322         /* push all data on the adapter before starting this
2323          * new segment */
2324         gst_qtdemux_process_adapter (demux, TRUE);
2325       } else {
2326         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2327         goto exit;
2328       }
2329
2330       /* We shouldn't modify upstream driven TIME FORMAT segment */
2331       if (!demux->upstream_format_is_time) {
2332         /* accept upstream's notion of segment and distribute along */
2333         segment.format = GST_FORMAT_TIME;
2334         segment.position = segment.time = segment.start;
2335         segment.duration = demux->segment.duration;
2336         segment.base = gst_segment_to_running_time (&demux->segment,
2337             GST_FORMAT_TIME, demux->segment.position);
2338       }
2339
2340       gst_segment_copy_into (&segment, &demux->segment);
2341       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2342
2343       /* map segment to internal qt segments and push on each stream */
2344       if (demux->n_streams) {
2345         demux->need_segment = TRUE;
2346         gst_qtdemux_check_send_pending_segment (demux);
2347       }
2348
2349       /* clear leftover in current segment, if any */
2350       gst_adapter_clear (demux->adapter);
2351
2352       /* set up streaming thread */
2353       demux->offset = offset;
2354       if (demux->upstream_format_is_time) {
2355         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2356             "set values to restart reading from a new atom");
2357         demux->neededbytes = 16;
2358         demux->todrop = 0;
2359       } else {
2360         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2361             NULL);
2362         if (stream) {
2363           demux->todrop = stream->samples[idx].offset - offset;
2364           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2365         } else {
2366           /* set up for EOS */
2367           demux->neededbytes = -1;
2368           demux->todrop = 0;
2369         }
2370       }
2371     exit:
2372       gst_event_unref (event);
2373       res = TRUE;
2374       goto drop;
2375     }
2376     case GST_EVENT_FLUSH_START:
2377     {
2378       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2379         gst_event_unref (event);
2380         goto drop;
2381       }
2382       QTDEMUX_EXPOSE_LOCK (demux);
2383       res = gst_pad_event_default (demux->sinkpad, parent, event);
2384       QTDEMUX_EXPOSE_UNLOCK (demux);
2385       goto drop;
2386     }
2387     case GST_EVENT_FLUSH_STOP:
2388     {
2389       guint64 dur;
2390
2391       dur = demux->segment.duration;
2392       gst_qtdemux_reset (demux, FALSE);
2393       demux->segment.duration = dur;
2394
2395       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2396         gst_event_unref (event);
2397         goto drop;
2398       }
2399       break;
2400     }
2401     case GST_EVENT_EOS:
2402       /* If we are in push mode, and get an EOS before we've seen any streams,
2403        * then error out - we have nowhere to send the EOS */
2404       if (!demux->pullbased) {
2405         GList *iter;
2406         gboolean has_valid_stream = FALSE;
2407         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2408           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2409             has_valid_stream = TRUE;
2410             break;
2411           }
2412         }
2413         if (!has_valid_stream)
2414           gst_qtdemux_post_no_playable_stream_error (demux);
2415         else {
2416           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2417               (guint) gst_adapter_available (demux->adapter));
2418           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2419             res = FALSE;
2420           }
2421         }
2422       }
2423       break;
2424     case GST_EVENT_CAPS:{
2425       GstCaps *caps = NULL;
2426
2427       gst_event_parse_caps (event, &caps);
2428       gst_qtdemux_setcaps (demux, caps);
2429       res = TRUE;
2430       gst_event_unref (event);
2431       goto drop;
2432     }
2433     case GST_EVENT_PROTECTION:
2434     {
2435       const gchar *system_id = NULL;
2436
2437       gst_event_parse_protection (event, &system_id, NULL, NULL);
2438       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2439           system_id);
2440       gst_qtdemux_append_protection_system_id (demux, system_id);
2441       /* save the event for later, for source pads that have not been created */
2442       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2443       /* send it to all pads that already exist */
2444       gst_qtdemux_push_event (demux, event);
2445       res = TRUE;
2446       goto drop;
2447     }
2448     case GST_EVENT_STREAM_START:
2449     {
2450       res = TRUE;
2451       gst_event_unref (event);
2452
2453       /* Drain all the buffers */
2454       gst_qtdemux_process_adapter (demux, TRUE);
2455       gst_qtdemux_reset (demux, FALSE);
2456       /* We expect new moov box after new stream-start event */
2457       demux->old_streams =
2458           g_list_concat (demux->old_streams, demux->active_streams);
2459       demux->active_streams = NULL;
2460
2461       goto drop;
2462     }
2463     default:
2464       break;
2465   }
2466
2467   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2468
2469 drop:
2470   return res;
2471 }
2472
2473 #if 0
2474 static void
2475 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2476 {
2477   GstQTDemux *demux = GST_QTDEMUX (element);
2478
2479   GST_OBJECT_LOCK (demux);
2480   if (demux->element_index)
2481     gst_object_unref (demux->element_index);
2482   if (index) {
2483     demux->element_index = gst_object_ref (index);
2484   } else {
2485     demux->element_index = NULL;
2486   }
2487   GST_OBJECT_UNLOCK (demux);
2488   /* object lock might be taken again */
2489   if (index)
2490     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2491   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2492       demux->element_index, demux->index_id);
2493 }
2494
2495 static GstIndex *
2496 gst_qtdemux_get_index (GstElement * element)
2497 {
2498   GstIndex *result = NULL;
2499   GstQTDemux *demux = GST_QTDEMUX (element);
2500
2501   GST_OBJECT_LOCK (demux);
2502   if (demux->element_index)
2503     result = gst_object_ref (demux->element_index);
2504   GST_OBJECT_UNLOCK (demux);
2505
2506   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2507
2508   return result;
2509 }
2510 #endif
2511
2512 static void
2513 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2514 {
2515   g_free ((gpointer) stream->stco.data);
2516   stream->stco.data = NULL;
2517   g_free ((gpointer) stream->stsz.data);
2518   stream->stsz.data = NULL;
2519   g_free ((gpointer) stream->stsc.data);
2520   stream->stsc.data = NULL;
2521   g_free ((gpointer) stream->stts.data);
2522   stream->stts.data = NULL;
2523   g_free ((gpointer) stream->stss.data);
2524   stream->stss.data = NULL;
2525   g_free ((gpointer) stream->stps.data);
2526   stream->stps.data = NULL;
2527   g_free ((gpointer) stream->ctts.data);
2528   stream->ctts.data = NULL;
2529 }
2530
2531 static void
2532 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2533 {
2534   g_free (stream->segments);
2535   stream->segments = NULL;
2536   stream->segment_index = -1;
2537   stream->accumulated_base = 0;
2538 }
2539
2540 static void
2541 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2542 {
2543   g_free (stream->samples);
2544   stream->samples = NULL;
2545   gst_qtdemux_stbl_free (stream);
2546
2547   /* fragments */
2548   g_free (stream->ra_entries);
2549   stream->ra_entries = NULL;
2550   stream->n_ra_entries = 0;
2551
2552   stream->sample_index = -1;
2553   stream->stbl_index = -1;
2554   stream->n_samples = 0;
2555   stream->time_position = 0;
2556
2557   stream->n_samples_moof = 0;
2558   stream->duration_moof = 0;
2559   stream->duration_last_moof = 0;
2560 }
2561
2562 static void
2563 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2564 {
2565   gint i;
2566   if (stream->allocator)
2567     gst_object_unref (stream->allocator);
2568   while (stream->buffers) {
2569     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2570     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2571   }
2572   for (i = 0; i < stream->stsd_entries_length; i++) {
2573     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2574     if (entry->rgb8_palette) {
2575       gst_memory_unref (entry->rgb8_palette);
2576       entry->rgb8_palette = NULL;
2577     }
2578     entry->sparse = FALSE;
2579   }
2580
2581   if (stream->stream_tags)
2582     gst_tag_list_unref (stream->stream_tags);
2583
2584   stream->stream_tags = gst_tag_list_new_empty ();
2585   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2586   g_free (stream->redirect_uri);
2587   stream->redirect_uri = NULL;
2588   stream->sent_eos = FALSE;
2589   stream->protected = FALSE;
2590   if (stream->protection_scheme_info) {
2591     if (stream->protection_scheme_type == FOURCC_cenc) {
2592       QtDemuxCencSampleSetInfo *info =
2593           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2594       if (info->default_properties)
2595         gst_structure_free (info->default_properties);
2596       if (info->crypto_info)
2597         g_ptr_array_free (info->crypto_info, TRUE);
2598     }
2599     g_free (stream->protection_scheme_info);
2600     stream->protection_scheme_info = NULL;
2601   }
2602   stream->protection_scheme_type = 0;
2603   stream->protection_scheme_version = 0;
2604   g_queue_foreach (&stream->protection_scheme_event_queue,
2605       (GFunc) gst_event_unref, NULL);
2606   g_queue_clear (&stream->protection_scheme_event_queue);
2607   gst_qtdemux_stream_flush_segments_data (stream);
2608   gst_qtdemux_stream_flush_samples_data (stream);
2609 }
2610
2611 static void
2612 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2613 {
2614   gint i;
2615   gst_qtdemux_stream_clear (stream);
2616   for (i = 0; i < stream->stsd_entries_length; i++) {
2617     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2618     if (entry->caps) {
2619       gst_caps_unref (entry->caps);
2620       entry->caps = NULL;
2621     }
2622   }
2623   g_free (stream->stsd_entries);
2624   stream->stsd_entries = NULL;
2625   stream->stsd_entries_length = 0;
2626 }
2627
2628
2629 static void
2630 gst_qtdemux_stream_free (QtDemuxStream * stream)
2631 {
2632   gst_qtdemux_stream_reset (stream);
2633   gst_tag_list_unref (stream->stream_tags);
2634   if (stream->pad) {
2635     GstQTDemux *demux = stream->demux;
2636     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2637     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2638   }
2639   g_free (stream->stream_id);
2640   g_free (stream);
2641 }
2642
2643 static void
2644 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2645 {
2646   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2647   gst_qtdemux_stream_free (stream);
2648   qtdemux->n_streams--;
2649 }
2650
2651 static GstStateChangeReturn
2652 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2653 {
2654   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2655   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2656
2657   switch (transition) {
2658     case GST_STATE_CHANGE_READY_TO_PAUSED:
2659       gst_qtdemux_reset (qtdemux, TRUE);
2660       break;
2661     default:
2662       break;
2663   }
2664
2665   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2666
2667   switch (transition) {
2668     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2669       gst_qtdemux_reset (qtdemux, TRUE);
2670       break;
2671     }
2672     default:
2673       break;
2674   }
2675
2676   return result;
2677 }
2678
2679 static void
2680 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2681 {
2682   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2683
2684   g_return_if_fail (GST_IS_CONTEXT (context));
2685
2686   if (gst_context_has_context_type (context,
2687           "drm-preferred-decryption-system-id")) {
2688     const GstStructure *s;
2689
2690     s = gst_context_get_structure (context);
2691     g_free (qtdemux->preferred_protection_system_id);
2692     qtdemux->preferred_protection_system_id =
2693         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2694     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2695         qtdemux->preferred_protection_system_id);
2696   }
2697
2698   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2699 }
2700
2701 static void
2702 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2703 {
2704   /* counts as header data */
2705   qtdemux->header_size += length;
2706
2707   /* only consider at least a sufficiently complete ftyp atom */
2708   if (length >= 20) {
2709     GstBuffer *buf;
2710
2711     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2712     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2713         GST_FOURCC_ARGS (qtdemux->major_brand));
2714     if (qtdemux->comp_brands)
2715       gst_buffer_unref (qtdemux->comp_brands);
2716     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2717     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2718   }
2719 }
2720
2721 static void
2722 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2723     GstTagList * xmptaglist)
2724 {
2725   /* Strip out bogus fields */
2726   if (xmptaglist) {
2727     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2728       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2729       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2730     } else {
2731       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2732     }
2733
2734     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2735
2736     /* prioritize native tags using _KEEP mode */
2737     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2738     gst_tag_list_unref (xmptaglist);
2739   }
2740 }
2741
2742 static void
2743 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2744     guint offset)
2745 {
2746   GstByteReader br;
2747   guint8 version;
2748   guint32 flags = 0;
2749   guint i;
2750   guint8 iv_size = 8;
2751   QtDemuxStream *stream;
2752   GstStructure *structure;
2753   QtDemuxCencSampleSetInfo *ss_info = NULL;
2754   const gchar *system_id;
2755   gboolean uses_sub_sample_encryption = FALSE;
2756   guint32 sample_count;
2757
2758   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2759   if (!stream)
2760     return;
2761
2762   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2763   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2764     GST_WARNING_OBJECT (qtdemux,
2765         "Attempting PIFF box parsing on an unencrypted stream.");
2766     return;
2767   }
2768
2769   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2770       G_TYPE_STRING, &system_id, NULL);
2771   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2772
2773   stream->protected = TRUE;
2774   stream->protection_scheme_type = FOURCC_cenc;
2775
2776   if (!stream->protection_scheme_info)
2777     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2778
2779   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2780
2781   if (ss_info->default_properties)
2782     gst_structure_free (ss_info->default_properties);
2783
2784   ss_info->default_properties =
2785       gst_structure_new ("application/x-cenc",
2786       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2787
2788   if (ss_info->crypto_info) {
2789     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2790     g_ptr_array_free (ss_info->crypto_info, TRUE);
2791     ss_info->crypto_info = NULL;
2792   }
2793
2794   /* skip UUID */
2795   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2796
2797   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2798     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2799     return;
2800   }
2801
2802   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2803     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2804     return;
2805   }
2806
2807   if ((flags & 0x000001)) {
2808     guint32 algorithm_id = 0;
2809     const guint8 *kid;
2810     GstBuffer *kid_buf;
2811     gboolean is_encrypted = TRUE;
2812
2813     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2814       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2815       return;
2816     }
2817
2818     algorithm_id >>= 8;
2819     if (algorithm_id == 0) {
2820       is_encrypted = FALSE;
2821     } else if (algorithm_id == 1) {
2822       /* FIXME: maybe store this in properties? */
2823       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2824     } else if (algorithm_id == 2) {
2825       /* FIXME: maybe store this in properties? */
2826       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2827     }
2828
2829     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2830       return;
2831
2832     if (!gst_byte_reader_get_data (&br, 16, &kid))
2833       return;
2834
2835     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2836     gst_buffer_fill (kid_buf, 0, kid, 16);
2837     if (ss_info->default_properties)
2838       gst_structure_free (ss_info->default_properties);
2839     ss_info->default_properties =
2840         gst_structure_new ("application/x-cenc",
2841         "iv_size", G_TYPE_UINT, iv_size,
2842         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2843         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2844     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2845         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2846     gst_buffer_unref (kid_buf);
2847   } else if ((flags & 0x000002)) {
2848     uses_sub_sample_encryption = TRUE;
2849   }
2850
2851   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2852     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2853     return;
2854   }
2855
2856   ss_info->crypto_info =
2857       g_ptr_array_new_full (sample_count,
2858       (GDestroyNotify) qtdemux_gst_structure_free);
2859
2860   for (i = 0; i < sample_count; ++i) {
2861     GstStructure *properties;
2862     guint8 *data;
2863     GstBuffer *buf;
2864
2865     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2866     if (properties == NULL) {
2867       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2868       qtdemux->cenc_aux_sample_count = i;
2869       return;
2870     }
2871
2872     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2873       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2874       gst_structure_free (properties);
2875       qtdemux->cenc_aux_sample_count = i;
2876       return;
2877     }
2878     buf = gst_buffer_new_wrapped (data, iv_size);
2879     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2880     gst_buffer_unref (buf);
2881
2882     if (uses_sub_sample_encryption) {
2883       guint16 n_subsamples;
2884
2885       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2886           || n_subsamples == 0) {
2887         GST_ERROR_OBJECT (qtdemux,
2888             "failed to get subsample count for sample %u", i);
2889         gst_structure_free (properties);
2890         qtdemux->cenc_aux_sample_count = i;
2891         return;
2892       }
2893       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2894       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2895         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2896             i);
2897         gst_structure_free (properties);
2898         qtdemux->cenc_aux_sample_count = i;
2899         return;
2900       }
2901       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2902       gst_structure_set (properties,
2903           "subsample_count", G_TYPE_UINT, n_subsamples,
2904           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2905       gst_buffer_unref (buf);
2906     } else {
2907       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2908     }
2909
2910     g_ptr_array_add (ss_info->crypto_info, properties);
2911   }
2912
2913   qtdemux->cenc_aux_sample_count = sample_count;
2914 }
2915
2916 static void
2917 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2918 {
2919   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2920     0x97, 0xA9, 0x42, 0xE8,
2921     0x9C, 0x71, 0x99, 0x94,
2922     0x91, 0xE3, 0xAF, 0xAC
2923   };
2924   static const guint8 playready_uuid[] = {
2925     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2926     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2927   };
2928
2929   static const guint8 piff_sample_encryption_uuid[] = {
2930     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2931     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2932   };
2933
2934   guint offset;
2935
2936   /* counts as header data */
2937   qtdemux->header_size += length;
2938
2939   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2940
2941   if (length <= offset + 16) {
2942     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2943     return;
2944   }
2945
2946   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2947     GstBuffer *buf;
2948     GstTagList *taglist;
2949
2950     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2951         length - offset - 16, NULL);
2952     taglist = gst_tag_list_from_xmp_buffer (buf);
2953     gst_buffer_unref (buf);
2954
2955     /* make sure we have a usable taglist */
2956     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2957
2958     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2959
2960   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2961     int len;
2962     const gunichar2 *s_utf16;
2963     char *contents;
2964
2965     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2966     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2967     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2968     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2969
2970     g_free (contents);
2971
2972     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2973         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2974         (NULL));
2975   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2976     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2977   } else {
2978     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2979         GST_READ_UINT32_LE (buffer + offset),
2980         GST_READ_UINT32_LE (buffer + offset + 4),
2981         GST_READ_UINT32_LE (buffer + offset + 8),
2982         GST_READ_UINT32_LE (buffer + offset + 12));
2983   }
2984 }
2985
2986 static void
2987 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2988 {
2989   GstSidxParser sidx_parser;
2990   GstIsoffParserResult res;
2991   guint consumed;
2992
2993   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2994
2995   res =
2996       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2997       &consumed);
2998   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2999   if (res == GST_ISOFF_QT_PARSER_DONE) {
3000     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3001   }
3002   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3003 }
3004
3005 /* caller verifies at least 8 bytes in buf */
3006 static void
3007 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3008     guint64 * plength, guint32 * pfourcc)
3009 {
3010   guint64 length;
3011   guint32 fourcc;
3012
3013   length = QT_UINT32 (data);
3014   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3015   fourcc = QT_FOURCC (data + 4);
3016   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3017
3018   if (length == 0) {
3019     length = G_MAXUINT64;
3020   } else if (length == 1 && size >= 16) {
3021     /* this means we have an extended size, which is the 64 bit value of
3022      * the next 8 bytes */
3023     length = QT_UINT64 (data + 8);
3024     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3025   }
3026
3027   if (plength)
3028     *plength = length;
3029   if (pfourcc)
3030     *pfourcc = fourcc;
3031 }
3032
3033 static gboolean
3034 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3035 {
3036   guint32 version = 0;
3037   GstClockTime duration = 0;
3038
3039   if (!gst_byte_reader_get_uint32_be (br, &version))
3040     goto failed;
3041
3042   version >>= 24;
3043   if (version == 1) {
3044     if (!gst_byte_reader_get_uint64_be (br, &duration))
3045       goto failed;
3046   } else {
3047     guint32 dur = 0;
3048
3049     if (!gst_byte_reader_get_uint32_be (br, &dur))
3050       goto failed;
3051     duration = dur;
3052   }
3053
3054   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3055   qtdemux->duration = duration;
3056
3057   return TRUE;
3058
3059 failed:
3060   {
3061     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3062     return FALSE;
3063   }
3064 }
3065
3066 static gboolean
3067 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3068     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3069 {
3070   if (!stream->parsed_trex && qtdemux->moov_node) {
3071     GNode *mvex, *trex;
3072     GstByteReader trex_data;
3073
3074     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3075     if (mvex) {
3076       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3077           &trex_data);
3078       while (trex) {
3079         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3080
3081         /* skip version/flags */
3082         if (!gst_byte_reader_skip (&trex_data, 4))
3083           goto next;
3084         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3085           goto next;
3086         if (id != stream->track_id)
3087           goto next;
3088         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3089           goto next;
3090         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3091           goto next;
3092         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3093           goto next;
3094         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3095           goto next;
3096
3097         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3098             "duration %d,  size %d, flags 0x%x", stream->track_id,
3099             dur, size, flags);
3100
3101         stream->parsed_trex = TRUE;
3102         stream->def_sample_description_index = sdi;
3103         stream->def_sample_duration = dur;
3104         stream->def_sample_size = size;
3105         stream->def_sample_flags = flags;
3106
3107       next:
3108         /* iterate all siblings */
3109         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3110             &trex_data);
3111       }
3112     }
3113   }
3114
3115   *ds_duration = stream->def_sample_duration;
3116   *ds_size = stream->def_sample_size;
3117   *ds_flags = stream->def_sample_flags;
3118
3119   /* even then, above values are better than random ... */
3120   if (G_UNLIKELY (!stream->parsed_trex)) {
3121     GST_WARNING_OBJECT (qtdemux,
3122         "failed to find fragment defaults for stream %d", stream->track_id);
3123     return FALSE;
3124   }
3125
3126   return TRUE;
3127 }
3128
3129 /* This method should be called whenever a more accurate duration might
3130  * have been found. It will update all relevant variables if/where needed
3131  */
3132 static void
3133 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3134 {
3135   guint i;
3136   guint64 movdur;
3137   GstClockTime prevdur;
3138   GList *iter;
3139
3140   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3141
3142   if (movdur > qtdemux->duration) {
3143     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3144     GST_DEBUG_OBJECT (qtdemux,
3145         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3146         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3147     qtdemux->duration = movdur;
3148     GST_DEBUG_OBJECT (qtdemux,
3149         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3150         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3151         GST_TIME_ARGS (qtdemux->segment.stop));
3152     if (qtdemux->segment.duration == prevdur) {
3153       /* If the current segment has duration/stop identical to previous duration
3154        * update them also (because they were set at that point in time with
3155        * the wrong duration */
3156       /* We convert the value *from* the timescale version to avoid rounding errors */
3157       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3158       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3159       qtdemux->segment.duration = fixeddur;
3160       qtdemux->segment.stop = fixeddur;
3161     }
3162   }
3163   for (iter = qtdemux->active_streams, i = 0; iter;
3164       iter = g_list_next (iter), i++) {
3165     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3166
3167     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3168     if (movdur > stream->duration) {
3169       GST_DEBUG_OBJECT (qtdemux,
3170           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3171           GST_TIME_ARGS (duration));
3172       stream->duration = movdur;
3173       /* internal duration tracking state has been updated above, so */
3174       /* preserve an open-ended dummy segment rather than repeatedly updating
3175        * it and spamming downstream accordingly with segment events */
3176       if (stream->dummy_segment &&
3177           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3178         /* Update all dummy values to new duration */
3179         stream->segments[0].stop_time = duration;
3180         stream->segments[0].duration = duration;
3181         stream->segments[0].media_stop = duration;
3182
3183         /* let downstream know we possibly have a new stop time */
3184         if (stream->segment_index != -1) {
3185           GstClockTime pos;
3186
3187           if (qtdemux->segment.rate >= 0) {
3188             pos = stream->segment.start;
3189           } else {
3190             pos = stream->segment.stop;
3191           }
3192
3193           gst_qtdemux_stream_update_segment (qtdemux, stream,
3194               stream->segment_index, pos, NULL, NULL);
3195         }
3196       }
3197     }
3198   }
3199 }
3200
3201 static gboolean
3202 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3203     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3204     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3205     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3206     gboolean has_tfdt)
3207 {
3208   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3209   guint64 timestamp;
3210   gint32 data_offset = 0;
3211   guint32 flags = 0, first_flags = 0, samples_count = 0;
3212   gint i;
3213   guint8 *data;
3214   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3215   QtDemuxSample *sample;
3216   gboolean ismv = FALSE;
3217   gint64 initial_offset;
3218
3219   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3220       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3221       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3222       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3223
3224   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3225     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3226     return TRUE;
3227   }
3228
3229   /* presence of stss or not can't really tell us much,
3230    * and flags and so on tend to be marginally reliable in these files */
3231   if (stream->subtype == FOURCC_soun) {
3232     GST_DEBUG_OBJECT (qtdemux,
3233         "sound track in fragmented file; marking all keyframes");
3234     stream->all_keyframe = TRUE;
3235   }
3236
3237   if (!gst_byte_reader_skip (trun, 1) ||
3238       !gst_byte_reader_get_uint24_be (trun, &flags))
3239     goto fail;
3240
3241   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3242     goto fail;
3243
3244   if (flags & TR_DATA_OFFSET) {
3245     /* note this is really signed */
3246     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3247       goto fail;
3248     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3249     /* default base offset = first byte of moof */
3250     if (*base_offset == -1) {
3251       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3252       *base_offset = moof_offset;
3253     }
3254     *running_offset = *base_offset + data_offset;
3255   } else {
3256     /* if no offset at all, that would mean data starts at moof start,
3257      * which is a bit wrong and is ismv crappy way, so compensate
3258      * assuming data is in mdat following moof */
3259     if (*base_offset == -1) {
3260       *base_offset = moof_offset + moof_length + 8;
3261       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3262       ismv = TRUE;
3263     }
3264     if (*running_offset == -1)
3265       *running_offset = *base_offset;
3266   }
3267
3268   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3269       *running_offset);
3270   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3271       data_offset, flags, samples_count);
3272
3273   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3274     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3275       GST_DEBUG_OBJECT (qtdemux,
3276           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3277       flags ^= TR_FIRST_SAMPLE_FLAGS;
3278     } else {
3279       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3280         goto fail;
3281       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3282     }
3283   }
3284
3285   /* FIXME ? spec says other bits should also be checked to determine
3286    * entry size (and prefix size for that matter) */
3287   entry_size = 0;
3288   dur_offset = size_offset = 0;
3289   if (flags & TR_SAMPLE_DURATION) {
3290     GST_LOG_OBJECT (qtdemux, "entry duration present");
3291     dur_offset = entry_size;
3292     entry_size += 4;
3293   }
3294   if (flags & TR_SAMPLE_SIZE) {
3295     GST_LOG_OBJECT (qtdemux, "entry size present");
3296     size_offset = entry_size;
3297     entry_size += 4;
3298   }
3299   if (flags & TR_SAMPLE_FLAGS) {
3300     GST_LOG_OBJECT (qtdemux, "entry flags present");
3301     flags_offset = entry_size;
3302     entry_size += 4;
3303   }
3304   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3305     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3306     ct_offset = entry_size;
3307     entry_size += 4;
3308   }
3309
3310   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3311     goto fail;
3312   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3313
3314   if (stream->n_samples + samples_count >=
3315       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3316     goto index_too_big;
3317
3318   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3319       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3320       (stream->n_samples + samples_count) *
3321       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3322
3323   /* create a new array of samples if it's the first sample parsed */
3324   if (stream->n_samples == 0) {
3325     g_assert (stream->samples == NULL);
3326     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3327     /* or try to reallocate it with space enough to insert the new samples */
3328   } else
3329     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3330         stream->n_samples + samples_count);
3331   if (stream->samples == NULL)
3332     goto out_of_memory;
3333
3334   if (qtdemux->fragment_start != -1) {
3335     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3336     qtdemux->fragment_start = -1;
3337   } else {
3338     if (stream->n_samples == 0) {
3339       if (decode_ts > 0) {
3340         timestamp = decode_ts;
3341       } else if (stream->pending_seek != NULL) {
3342         /* if we don't have a timestamp from a tfdt box, we'll use the one
3343          * from the mfra seek table */
3344         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3345             GST_TIME_ARGS (stream->pending_seek->ts));
3346
3347         /* FIXME: this is not fully correct, the timestamp refers to the random
3348          * access sample refered to in the tfra entry, which may not necessarily
3349          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3350         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3351       } else {
3352         timestamp = 0;
3353       }
3354
3355       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3356       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3357           GST_TIME_ARGS (gst_ts));
3358     } else {
3359       /* subsequent fragments extend stream */
3360       timestamp =
3361           stream->samples[stream->n_samples - 1].timestamp +
3362           stream->samples[stream->n_samples - 1].duration;
3363
3364       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3365        * difference (1 sec.) between decode_ts and timestamp, prefer the
3366        * former */
3367       if (has_tfdt && !qtdemux->upstream_format_is_time
3368           && ABSDIFF (decode_ts, timestamp) >
3369           MAX (stream->duration_last_moof / 2,
3370               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3371         GST_INFO_OBJECT (qtdemux,
3372             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3373             ") are significantly different (more than %" GST_TIME_FORMAT
3374             "), using decode_ts",
3375             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3376             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3377             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3378                     MAX (stream->duration_last_moof / 2,
3379                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3380         timestamp = decode_ts;
3381       }
3382
3383       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3384       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3385           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3386     }
3387   }
3388
3389   initial_offset = *running_offset;
3390
3391   sample = stream->samples + stream->n_samples;
3392   for (i = 0; i < samples_count; i++) {
3393     guint32 dur, size, sflags, ct;
3394
3395     /* first read sample data */
3396     if (flags & TR_SAMPLE_DURATION) {
3397       dur = QT_UINT32 (data + dur_offset);
3398     } else {
3399       dur = d_sample_duration;
3400     }
3401     if (flags & TR_SAMPLE_SIZE) {
3402       size = QT_UINT32 (data + size_offset);
3403     } else {
3404       size = d_sample_size;
3405     }
3406     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3407       if (i == 0) {
3408         sflags = first_flags;
3409       } else {
3410         sflags = d_sample_flags;
3411       }
3412     } else if (flags & TR_SAMPLE_FLAGS) {
3413       sflags = QT_UINT32 (data + flags_offset);
3414     } else {
3415       sflags = d_sample_flags;
3416     }
3417     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3418       ct = QT_UINT32 (data + ct_offset);
3419     } else {
3420       ct = 0;
3421     }
3422     data += entry_size;
3423
3424     /* fill the sample information */
3425     sample->offset = *running_offset;
3426     sample->pts_offset = ct;
3427     sample->size = size;
3428     sample->timestamp = timestamp;
3429     sample->duration = dur;
3430     /* sample-is-difference-sample */
3431     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3432      * now idea how it relates to bitfield other than massive LE/BE confusion */
3433     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3434     *running_offset += size;
3435     timestamp += dur;
3436     stream->duration_moof += dur;
3437     sample++;
3438   }
3439
3440   /* Update total duration if needed */
3441   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3442
3443   /* Pre-emptively figure out size of mdat based on trun information.
3444    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3445    * size, else we will still be able to use this when dealing with gap'ed
3446    * input */
3447   qtdemux->mdatleft = *running_offset - initial_offset;
3448   qtdemux->mdatoffset = initial_offset;
3449   qtdemux->mdatsize = qtdemux->mdatleft;
3450
3451   stream->n_samples += samples_count;
3452   stream->n_samples_moof += samples_count;
3453
3454   if (stream->pending_seek != NULL)
3455     stream->pending_seek = NULL;
3456
3457   return TRUE;
3458
3459 fail:
3460   {
3461     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3462     return FALSE;
3463   }
3464 out_of_memory:
3465   {
3466     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3467         stream->n_samples);
3468     return FALSE;
3469   }
3470 index_too_big:
3471   {
3472     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3473         "be larger than %uMB (broken file?)", stream->n_samples,
3474         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3475     return FALSE;
3476   }
3477 }
3478
3479 /* find stream with @id */
3480 static inline QtDemuxStream *
3481 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3482 {
3483   QtDemuxStream *stream;
3484   GList *iter;
3485
3486   /* check */
3487   if (G_UNLIKELY (!id)) {
3488     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3489     return NULL;
3490   }
3491
3492   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3493     stream = QTDEMUX_STREAM (iter->data);
3494     if (stream->track_id == id)
3495       return stream;
3496   }
3497   if (qtdemux->mss_mode) {
3498     /* mss should have only 1 stream anyway */
3499     return QTDEMUX_FIRST_STREAM (qtdemux);
3500   }
3501
3502   return NULL;
3503 }
3504
3505 static gboolean
3506 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3507     guint32 * fragment_number)
3508 {
3509   if (!gst_byte_reader_skip (mfhd, 4))
3510     goto fail;
3511   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3512     goto fail;
3513   return TRUE;
3514 fail:
3515   {
3516     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3517     return FALSE;
3518   }
3519 }
3520
3521 static gboolean
3522 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3523     QtDemuxStream ** stream, guint32 * default_sample_duration,
3524     guint32 * default_sample_size, guint32 * default_sample_flags,
3525     gint64 * base_offset)
3526 {
3527   guint32 flags = 0;
3528   guint32 track_id = 0;
3529
3530   if (!gst_byte_reader_skip (tfhd, 1) ||
3531       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3532     goto invalid_track;
3533
3534   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3535     goto invalid_track;
3536
3537   *stream = qtdemux_find_stream (qtdemux, track_id);
3538   if (G_UNLIKELY (!*stream))
3539     goto unknown_stream;
3540
3541   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3542     *base_offset = qtdemux->moof_offset;
3543
3544   if (flags & TF_BASE_DATA_OFFSET)
3545     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3546       goto invalid_track;
3547
3548   /* obtain stream defaults */
3549   qtdemux_parse_trex (qtdemux, *stream,
3550       default_sample_duration, default_sample_size, default_sample_flags);
3551
3552   (*stream)->stsd_sample_description_id =
3553       (*stream)->def_sample_description_index - 1;
3554
3555   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3556     guint32 sample_description_index;
3557     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3558       goto invalid_track;
3559     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3560   }
3561
3562   if (qtdemux->mss_mode) {
3563     /* mss has no stsd entry */
3564     (*stream)->stsd_sample_description_id = 0;
3565   }
3566
3567   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3568     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3569       goto invalid_track;
3570
3571   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3572     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3573       goto invalid_track;
3574
3575   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3576     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3577       goto invalid_track;
3578
3579   return TRUE;
3580
3581 invalid_track:
3582   {
3583     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3584     return FALSE;
3585   }
3586 unknown_stream:
3587   {
3588     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3589     return TRUE;
3590   }
3591 }
3592
3593 static gboolean
3594 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3595     guint64 * decode_time)
3596 {
3597   guint32 version = 0;
3598
3599   if (!gst_byte_reader_get_uint32_be (br, &version))
3600     return FALSE;
3601
3602   version >>= 24;
3603   if (version == 1) {
3604     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3605       goto failed;
3606   } else {
3607     guint32 dec_time = 0;
3608     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3609       goto failed;
3610     *decode_time = dec_time;
3611   }
3612
3613   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3614       *decode_time);
3615
3616   return TRUE;
3617
3618 failed:
3619   {
3620     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3621     return FALSE;
3622   }
3623 }
3624
3625 /* Returns a pointer to a GstStructure containing the properties of
3626  * the stream sample identified by @sample_index. The caller must unref
3627  * the returned object after use. Returns NULL if unsuccessful. */
3628 static GstStructure *
3629 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3630     QtDemuxStream * stream, guint sample_index)
3631 {
3632   QtDemuxCencSampleSetInfo *info = NULL;
3633
3634   g_return_val_if_fail (stream != NULL, NULL);
3635   g_return_val_if_fail (stream->protected, NULL);
3636   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3637
3638   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3639
3640   /* Currently, cenc properties for groups of samples are not supported, so
3641    * simply return a copy of the default sample properties */
3642   return gst_structure_copy (info->default_properties);
3643 }
3644
3645 /* Parses the sizes of sample auxiliary information contained within a stream,
3646  * as given in a saiz box. Returns array of sample_count guint8 size values,
3647  * or NULL on failure */
3648 static guint8 *
3649 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3650     GstByteReader * br, guint32 * sample_count)
3651 {
3652   guint32 flags = 0;
3653   guint8 *info_sizes;
3654   guint8 default_info_size;
3655
3656   g_return_val_if_fail (qtdemux != NULL, NULL);
3657   g_return_val_if_fail (stream != NULL, NULL);
3658   g_return_val_if_fail (br != NULL, NULL);
3659   g_return_val_if_fail (sample_count != NULL, NULL);
3660
3661   if (!gst_byte_reader_get_uint32_be (br, &flags))
3662     return NULL;
3663
3664   if (flags & 0x1) {
3665     /* aux_info_type and aux_info_type_parameter are ignored */
3666     if (!gst_byte_reader_skip (br, 8))
3667       return NULL;
3668   }
3669
3670   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3671     return NULL;
3672   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3673
3674   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3675     return NULL;
3676   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3677
3678
3679   if (default_info_size == 0) {
3680     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3681       return NULL;
3682     }
3683   } else {
3684     info_sizes = g_new (guint8, *sample_count);
3685     memset (info_sizes, default_info_size, *sample_count);
3686   }
3687
3688   return info_sizes;
3689 }
3690
3691 /* Parses the offset of sample auxiliary information contained within a stream,
3692  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3693 static gboolean
3694 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3695     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3696     guint64 * offset)
3697 {
3698   guint8 version = 0;
3699   guint32 flags = 0;
3700   guint32 aux_info_type = 0;
3701   guint32 aux_info_type_parameter = 0;
3702   guint32 entry_count;
3703   guint32 off_32;
3704   guint64 off_64;
3705   const guint8 *aux_info_type_data = NULL;
3706
3707   g_return_val_if_fail (qtdemux != NULL, FALSE);
3708   g_return_val_if_fail (stream != NULL, FALSE);
3709   g_return_val_if_fail (br != NULL, FALSE);
3710   g_return_val_if_fail (offset != NULL, FALSE);
3711
3712   if (!gst_byte_reader_get_uint8 (br, &version))
3713     return FALSE;
3714
3715   if (!gst_byte_reader_get_uint24_be (br, &flags))
3716     return FALSE;
3717
3718   if (flags & 0x1) {
3719
3720     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3721       return FALSE;
3722     aux_info_type = QT_FOURCC (aux_info_type_data);
3723
3724     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3725       return FALSE;
3726   } else if (stream->protected) {
3727     aux_info_type = stream->protection_scheme_type;
3728   } else {
3729     aux_info_type = CUR_STREAM (stream)->fourcc;
3730   }
3731
3732   if (info_type)
3733     *info_type = aux_info_type;
3734   if (info_type_parameter)
3735     *info_type_parameter = aux_info_type_parameter;
3736
3737   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3738       "aux_info_type_parameter:  %#06x",
3739       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3740
3741   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3742     return FALSE;
3743
3744   if (entry_count != 1) {
3745     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3746     return FALSE;
3747   }
3748
3749   if (version == 0) {
3750     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3751       return FALSE;
3752     *offset = (guint64) off_32;
3753   } else {
3754     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3755       return FALSE;
3756     *offset = off_64;
3757   }
3758
3759   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3760   return TRUE;
3761 }
3762
3763 static void
3764 qtdemux_gst_structure_free (GstStructure * gststructure)
3765 {
3766   if (gststructure) {
3767     gst_structure_free (gststructure);
3768   }
3769 }
3770
3771 /* Parses auxiliary information relating to samples protected using Common
3772  * Encryption (cenc); the format of this information is defined in
3773  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3774 static gboolean
3775 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3776     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3777 {
3778   QtDemuxCencSampleSetInfo *ss_info = NULL;
3779   guint8 size;
3780   gint i;
3781   GPtrArray *old_crypto_info = NULL;
3782   guint old_entries = 0;
3783
3784   g_return_val_if_fail (qtdemux != NULL, FALSE);
3785   g_return_val_if_fail (stream != NULL, FALSE);
3786   g_return_val_if_fail (br != NULL, FALSE);
3787   g_return_val_if_fail (stream->protected, FALSE);
3788   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3789
3790   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3791
3792   if (ss_info->crypto_info) {
3793     old_crypto_info = ss_info->crypto_info;
3794     /* Count number of non-null entries remaining at the tail end */
3795     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3796       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3797         break;
3798       old_entries++;
3799     }
3800   }
3801
3802   ss_info->crypto_info =
3803       g_ptr_array_new_full (sample_count + old_entries,
3804       (GDestroyNotify) qtdemux_gst_structure_free);
3805
3806   /* We preserve old entries because we parse the next moof in advance
3807    * of consuming all samples from the previous moof, and otherwise
3808    * we'd discard the corresponding crypto info for the samples
3809    * from the previous fragment. */
3810   if (old_entries) {
3811     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3812         old_entries);
3813     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3814       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3815               i));
3816       g_ptr_array_index (old_crypto_info, i) = NULL;
3817     }
3818   }
3819
3820   if (old_crypto_info) {
3821     /* Everything now belongs to the new array */
3822     g_ptr_array_free (old_crypto_info, TRUE);
3823   }
3824
3825   for (i = 0; i < sample_count; ++i) {
3826     GstStructure *properties;
3827     guint16 n_subsamples = 0;
3828     guint8 *data;
3829     guint iv_size;
3830     GstBuffer *buf;
3831
3832     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3833     if (properties == NULL) {
3834       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3835       return FALSE;
3836     }
3837     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3838       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3839       gst_structure_free (properties);
3840       return FALSE;
3841     }
3842     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3843       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3844       gst_structure_free (properties);
3845       return FALSE;
3846     }
3847     buf = gst_buffer_new_wrapped (data, iv_size);
3848     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3849     gst_buffer_unref (buf);
3850     size = info_sizes[i];
3851     if (size > iv_size) {
3852       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3853           || !(n_subsamples > 0)) {
3854         gst_structure_free (properties);
3855         GST_ERROR_OBJECT (qtdemux,
3856             "failed to get subsample count for sample %u", i);
3857         return FALSE;
3858       }
3859       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3860       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3861         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3862             i);
3863         gst_structure_free (properties);
3864         return FALSE;
3865       }
3866       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3867       if (!buf) {
3868         gst_structure_free (properties);
3869         return FALSE;
3870       }
3871       gst_structure_set (properties,
3872           "subsample_count", G_TYPE_UINT, n_subsamples,
3873           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3874       gst_buffer_unref (buf);
3875     } else {
3876       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3877     }
3878     g_ptr_array_add (ss_info->crypto_info, properties);
3879   }
3880   return TRUE;
3881 }
3882
3883 /* Converts a UUID in raw byte form to a string representation, as defined in
3884  * RFC 4122. The caller takes ownership of the returned string and is
3885  * responsible for freeing it after use. */
3886 static gchar *
3887 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3888 {
3889   const guint8 *uuid = (const guint8 *) uuid_bytes;
3890
3891   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3892       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3893       uuid[0], uuid[1], uuid[2], uuid[3],
3894       uuid[4], uuid[5], uuid[6], uuid[7],
3895       uuid[8], uuid[9], uuid[10], uuid[11],
3896       uuid[12], uuid[13], uuid[14], uuid[15]);
3897 }
3898
3899 /* Parses a Protection System Specific Header box (pssh), as defined in the
3900  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3901  * information needed by a specific content protection system in order to
3902  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3903  * otherwise. */
3904 static gboolean
3905 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3906 {
3907   gchar *sysid_string;
3908   guint32 pssh_size = QT_UINT32 (node->data);
3909   GstBuffer *pssh = NULL;
3910   GstEvent *event = NULL;
3911   guint32 parent_box_type;
3912   GList *iter;
3913
3914   if (G_UNLIKELY (pssh_size < 32U)) {
3915     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3916     return FALSE;
3917   }
3918
3919   sysid_string =
3920       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3921
3922   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3923
3924   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3925   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3926       gst_buffer_get_size (pssh));
3927
3928   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3929
3930   /* Push an event containing the pssh box onto the queues of all streams. */
3931   event = gst_event_new_protection (sysid_string, pssh,
3932       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3933   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3934     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3935     GST_TRACE_OBJECT (qtdemux,
3936         "adding protection event for stream %s and system %s",
3937         stream->stream_id, sysid_string);
3938     g_queue_push_tail (&stream->protection_scheme_event_queue,
3939         gst_event_ref (event));
3940   }
3941   g_free (sysid_string);
3942   gst_event_unref (event);
3943   gst_buffer_unref (pssh);
3944   return TRUE;
3945 }
3946
3947 static gboolean
3948 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3949     guint64 moof_offset, QtDemuxStream * stream)
3950 {
3951   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3952   GNode *uuid_node;
3953   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3954   GNode *saiz_node, *saio_node, *pssh_node;
3955   GstByteReader saiz_data, saio_data;
3956   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3957   gint64 base_offset, running_offset;
3958   guint32 frag_num;
3959   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3960
3961   /* NOTE @stream ignored */
3962
3963   moof_node = g_node_new ((guint8 *) buffer);
3964   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3965   qtdemux_node_dump (qtdemux, moof_node);
3966
3967   /* Get fragment number from mfhd and check it's valid */
3968   mfhd_node =
3969       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3970   if (mfhd_node == NULL)
3971     goto missing_mfhd;
3972   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3973     goto fail;
3974   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3975
3976   /* unknown base_offset to start with */
3977   base_offset = running_offset = -1;
3978   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3979   while (traf_node) {
3980     guint64 decode_time = 0;
3981
3982     /* Fragment Header node */
3983     tfhd_node =
3984         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3985         &tfhd_data);
3986     if (!tfhd_node)
3987       goto missing_tfhd;
3988     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3989             &ds_size, &ds_flags, &base_offset))
3990       goto missing_tfhd;
3991
3992     /* The following code assumes at most a single set of sample auxiliary
3993      * data in the fragment (consisting of a saiz box and a corresponding saio
3994      * box); in theory, however, there could be multiple sets of sample
3995      * auxiliary data in a fragment. */
3996     saiz_node =
3997         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3998         &saiz_data);
3999     if (saiz_node) {
4000       guint32 info_type = 0;
4001       guint64 offset = 0;
4002       guint32 info_type_parameter = 0;
4003
4004       g_free (qtdemux->cenc_aux_info_sizes);
4005
4006       qtdemux->cenc_aux_info_sizes =
4007           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4008           &qtdemux->cenc_aux_sample_count);
4009       if (qtdemux->cenc_aux_info_sizes == NULL) {
4010         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4011         goto fail;
4012       }
4013       saio_node =
4014           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4015           &saio_data);
4016       if (!saio_node) {
4017         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4018         g_free (qtdemux->cenc_aux_info_sizes);
4019         qtdemux->cenc_aux_info_sizes = NULL;
4020         goto fail;
4021       }
4022
4023       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4024                   &info_type, &info_type_parameter, &offset))) {
4025         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4026         g_free (qtdemux->cenc_aux_info_sizes);
4027         qtdemux->cenc_aux_info_sizes = NULL;
4028         goto fail;
4029       }
4030       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4031         offset += (guint64) (base_offset - qtdemux->moof_offset);
4032       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4033         GstByteReader br;
4034         if (offset > length) {
4035           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4036           qtdemux->cenc_aux_info_offset = offset;
4037         } else {
4038           gst_byte_reader_init (&br, buffer + offset, length - offset);
4039           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4040                   qtdemux->cenc_aux_info_sizes,
4041                   qtdemux->cenc_aux_sample_count)) {
4042             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4043             g_free (qtdemux->cenc_aux_info_sizes);
4044             qtdemux->cenc_aux_info_sizes = NULL;
4045             goto fail;
4046           }
4047         }
4048       }
4049     }
4050
4051     tfdt_node =
4052         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4053         &tfdt_data);
4054     if (tfdt_node) {
4055       /* We'll use decode_time to interpolate timestamps
4056        * in case the input timestamps are missing */
4057       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4058
4059       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4060           " (%" GST_TIME_FORMAT ")", decode_time,
4061           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4062                   decode_time) : GST_CLOCK_TIME_NONE));
4063
4064       /* Discard the fragment buffer timestamp info to avoid using it.
4065        * Rely on tfdt instead as it is more accurate than the timestamp
4066        * that is fetched from a manifest/playlist and is usually
4067        * less accurate. */
4068       qtdemux->fragment_start = -1;
4069     }
4070
4071     if (G_UNLIKELY (!stream)) {
4072       /* we lost track of offset, we'll need to regain it,
4073        * but can delay complaining until later or avoid doing so altogether */
4074       base_offset = -2;
4075       goto next;
4076     }
4077     if (G_UNLIKELY (base_offset < -1))
4078       goto lost_offset;
4079
4080     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4081
4082     if (!qtdemux->pullbased) {
4083       /* Sample tables can grow enough to be problematic if the system memory
4084        * is very low (e.g. embedded devices) and the videos very long
4085        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4086        * Fortunately, we can easily discard them for each new fragment when
4087        * we know qtdemux will not receive seeks outside of the current fragment.
4088        * adaptivedemux honors this assumption.
4089        * This optimization is also useful for applications that use qtdemux as
4090        * a push-based simple demuxer, like Media Source Extensions. */
4091       gst_qtdemux_stream_flush_samples_data (stream);
4092     }
4093
4094     /* initialise moof sample data */
4095     stream->n_samples_moof = 0;
4096     stream->duration_last_moof = stream->duration_moof;
4097     stream->duration_moof = 0;
4098
4099     /* Track Run node */
4100     trun_node =
4101         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4102         &trun_data);
4103     while (trun_node) {
4104       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4105           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4106           &running_offset, decode_time, (tfdt_node != NULL));
4107       /* iterate all siblings */
4108       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4109           &trun_data);
4110     }
4111
4112     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4113     if (uuid_node) {
4114       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4115       guint32 box_length = QT_UINT32 (uuid_buffer);
4116
4117       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4118     }
4119
4120     /* if no new base_offset provided for next traf,
4121      * base is end of current traf */
4122     base_offset = running_offset;
4123     running_offset = -1;
4124
4125     if (stream->n_samples_moof && stream->duration_moof)
4126       stream->new_caps = TRUE;
4127
4128   next:
4129     /* iterate all siblings */
4130     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4131   }
4132
4133   /* parse any protection system info */
4134   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4135   while (pssh_node) {
4136     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4137     qtdemux_parse_pssh (qtdemux, pssh_node);
4138     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4139   }
4140
4141   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4142       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4143       && min_dts != 0) {
4144     /* Unless the user has explictly requested another seek, perform an
4145      * internal seek to the time specified in the tfdt.
4146      *
4147      * This way if the user opens a file where the first tfdt is 1 hour
4148      * into the presentation, they will not have to wait 1 hour for run
4149      * time to catch up and actual playback to start. */
4150     GList *iter;
4151
4152     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4153         "performing an internal seek to %" GST_TIME_FORMAT,
4154         GST_TIME_ARGS (min_dts));
4155
4156     qtdemux->segment.start = min_dts;
4157     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4158
4159     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4160       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
4161       stream->time_position = min_dts;
4162     }
4163
4164     /* Before this code was run a segment was already sent when the moov was
4165      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4166      * be emitted after a moov, and we can emit a second segment anyway for
4167      * special cases like this. */
4168     qtdemux->need_segment = TRUE;
4169   }
4170
4171   qtdemux->first_moof_already_parsed = TRUE;
4172
4173   g_node_destroy (moof_node);
4174   return TRUE;
4175
4176 missing_tfhd:
4177   {
4178     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4179     goto fail;
4180   }
4181 missing_mfhd:
4182   {
4183     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4184     goto fail;
4185   }
4186 lost_offset:
4187   {
4188     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4189     goto fail;
4190   }
4191 fail:
4192   {
4193     g_node_destroy (moof_node);
4194     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4195         (_("This file is corrupt and cannot be played.")), (NULL));
4196     return FALSE;
4197   }
4198 }
4199
4200 #if 0
4201 /* might be used if some day we actually use mfra & co
4202  * for random access to fragments,
4203  * but that will require quite some modifications and much less relying
4204  * on a sample array */
4205 #endif
4206
4207 static gboolean
4208 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4209 {
4210   QtDemuxStream *stream;
4211   guint32 ver_flags, track_id, len, num_entries, i;
4212   guint value_size, traf_size, trun_size, sample_size;
4213   guint64 time = 0, moof_offset = 0;
4214 #if 0
4215   GstBuffer *buf = NULL;
4216   GstFlowReturn ret;
4217 #endif
4218   GstByteReader tfra;
4219
4220   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4221
4222   if (!gst_byte_reader_skip (&tfra, 8))
4223     return FALSE;
4224
4225   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4226     return FALSE;
4227
4228   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4229       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4230       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4231     return FALSE;
4232
4233   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4234
4235   stream = qtdemux_find_stream (qtdemux, track_id);
4236   if (stream == NULL)
4237     goto unknown_trackid;
4238
4239   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4240   sample_size = (len & 3) + 1;
4241   trun_size = ((len & 12) >> 2) + 1;
4242   traf_size = ((len & 48) >> 4) + 1;
4243
4244   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4245       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4246
4247   if (num_entries == 0)
4248     goto no_samples;
4249
4250   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4251           value_size + value_size + traf_size + trun_size + sample_size))
4252     goto corrupt_file;
4253
4254   g_free (stream->ra_entries);
4255   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4256   stream->n_ra_entries = num_entries;
4257
4258   for (i = 0; i < num_entries; i++) {
4259     qt_atom_parser_get_offset (&tfra, value_size, &time);
4260     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4261     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4262     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4263     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4264
4265     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4266
4267     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4268         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4269
4270     stream->ra_entries[i].ts = time;
4271     stream->ra_entries[i].moof_offset = moof_offset;
4272
4273     /* don't want to go through the entire file and read all moofs at startup */
4274 #if 0
4275     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4276     if (ret != GST_FLOW_OK)
4277       goto corrupt_file;
4278     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4279         moof_offset, stream);
4280     gst_buffer_unref (buf);
4281 #endif
4282   }
4283
4284   check_update_duration (qtdemux, time);
4285
4286   return TRUE;
4287
4288 /* ERRORS */
4289 unknown_trackid:
4290   {
4291     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4292     return FALSE;
4293   }
4294 corrupt_file:
4295   {
4296     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4297     return FALSE;
4298   }
4299 no_samples:
4300   {
4301     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4302     return FALSE;
4303   }
4304 }
4305
4306 static gboolean
4307 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4308 {
4309   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4310   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4311   GstBuffer *mfro = NULL, *mfra = NULL;
4312   GstFlowReturn flow;
4313   gboolean ret = FALSE;
4314   GNode *mfra_node, *tfra_node;
4315   guint64 mfra_offset = 0;
4316   guint32 fourcc, mfra_size;
4317   gint64 len;
4318
4319   /* query upstream size in bytes */
4320   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4321     goto size_query_failed;
4322
4323   /* mfro box should be at the very end of the file */
4324   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4325   if (flow != GST_FLOW_OK)
4326     goto exit;
4327
4328   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4329
4330   fourcc = QT_FOURCC (mfro_map.data + 4);
4331   if (fourcc != FOURCC_mfro)
4332     goto exit;
4333
4334   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4335   if (mfro_map.size < 16)
4336     goto invalid_mfro_size;
4337
4338   mfra_size = QT_UINT32 (mfro_map.data + 12);
4339   if (mfra_size >= len)
4340     goto invalid_mfra_size;
4341
4342   mfra_offset = len - mfra_size;
4343
4344   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4345       mfra_offset, mfra_size);
4346
4347   /* now get and parse mfra box */
4348   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4349   if (flow != GST_FLOW_OK)
4350     goto broken_file;
4351
4352   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4353
4354   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4355   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4356
4357   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4358
4359   while (tfra_node) {
4360     qtdemux_parse_tfra (qtdemux, tfra_node);
4361     /* iterate all siblings */
4362     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4363   }
4364   g_node_destroy (mfra_node);
4365
4366   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4367   ret = TRUE;
4368
4369 exit:
4370
4371   if (mfro) {
4372     if (mfro_map.memory != NULL)
4373       gst_buffer_unmap (mfro, &mfro_map);
4374     gst_buffer_unref (mfro);
4375   }
4376   if (mfra) {
4377     if (mfra_map.memory != NULL)
4378       gst_buffer_unmap (mfra, &mfra_map);
4379     gst_buffer_unref (mfra);
4380   }
4381   return ret;
4382
4383 /* ERRORS */
4384 size_query_failed:
4385   {
4386     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4387     goto exit;
4388   }
4389 invalid_mfro_size:
4390   {
4391     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4392     goto exit;
4393   }
4394 invalid_mfra_size:
4395   {
4396     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4397     goto exit;
4398   }
4399 broken_file:
4400   {
4401     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4402     goto exit;
4403   }
4404 }
4405
4406 static guint64
4407 add_offset (guint64 offset, guint64 advance)
4408 {
4409   /* Avoid 64-bit overflow by clamping */
4410   if (offset > G_MAXUINT64 - advance)
4411     return G_MAXUINT64;
4412   return offset + advance;
4413 }
4414
4415 static GstFlowReturn
4416 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4417 {
4418   guint64 length = 0;
4419   guint32 fourcc = 0;
4420   GstBuffer *buf = NULL;
4421   GstFlowReturn ret = GST_FLOW_OK;
4422   guint64 cur_offset = qtdemux->offset;
4423   GstMapInfo map;
4424
4425   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4426   if (G_UNLIKELY (ret != GST_FLOW_OK))
4427     goto beach;
4428   gst_buffer_map (buf, &map, GST_MAP_READ);
4429   if (G_LIKELY (map.size >= 8))
4430     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4431   gst_buffer_unmap (buf, &map);
4432   gst_buffer_unref (buf);
4433
4434   /* maybe we already got most we needed, so only consider this eof */
4435   if (G_UNLIKELY (length == 0)) {
4436     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4437         (_("Invalid atom size.")),
4438         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4439             GST_FOURCC_ARGS (fourcc)));
4440     ret = GST_FLOW_EOS;
4441     goto beach;
4442   }
4443
4444   switch (fourcc) {
4445     case FOURCC_moof:
4446       /* record for later parsing when needed */
4447       if (!qtdemux->moof_offset) {
4448         qtdemux->moof_offset = qtdemux->offset;
4449       }
4450       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4451         /* FIXME */
4452       } else {
4453         qtdemux->offset += length;      /* skip moof and keep going */
4454       }
4455       if (qtdemux->got_moov) {
4456         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4457         ret = GST_FLOW_EOS;
4458         goto beach;
4459       }
4460       break;
4461     case FOURCC_mdat:
4462     case FOURCC_free:
4463     case FOURCC_skip:
4464     case FOURCC_wide:
4465     case FOURCC_PICT:
4466     case FOURCC_pnot:
4467     {
4468       GST_LOG_OBJECT (qtdemux,
4469           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4470           GST_FOURCC_ARGS (fourcc), cur_offset);
4471       qtdemux->offset = add_offset (qtdemux->offset, length);
4472       break;
4473     }
4474     case FOURCC_moov:
4475     {
4476       GstBuffer *moov = NULL;
4477
4478       if (qtdemux->got_moov) {
4479         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4480         qtdemux->offset = add_offset (qtdemux->offset, length);
4481         goto beach;
4482       }
4483
4484       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4485       if (ret != GST_FLOW_OK)
4486         goto beach;
4487       gst_buffer_map (moov, &map, GST_MAP_READ);
4488
4489       if (length != map.size) {
4490         /* Some files have a 'moov' atom at the end of the file which contains
4491          * a terminal 'free' atom where the body of the atom is missing.
4492          * Check for, and permit, this special case.
4493          */
4494         if (map.size >= 8) {
4495           guint8 *final_data = map.data + (map.size - 8);
4496           guint32 final_length = QT_UINT32 (final_data);
4497           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4498
4499           if (final_fourcc == FOURCC_free
4500               && map.size + final_length - 8 == length) {
4501             /* Ok, we've found that special case. Allocate a new buffer with
4502              * that free atom actually present. */
4503             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4504             gst_buffer_fill (newmoov, 0, map.data, map.size);
4505             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4506             gst_buffer_unmap (moov, &map);
4507             gst_buffer_unref (moov);
4508             moov = newmoov;
4509             gst_buffer_map (moov, &map, GST_MAP_READ);
4510           }
4511         }
4512       }
4513
4514       if (length != map.size) {
4515         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4516             (_("This file is incomplete and cannot be played.")),
4517             ("We got less than expected (received %" G_GSIZE_FORMAT
4518                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4519                 (guint) length, cur_offset));
4520         gst_buffer_unmap (moov, &map);
4521         gst_buffer_unref (moov);
4522         ret = GST_FLOW_ERROR;
4523         goto beach;
4524       }
4525       qtdemux->offset += length;
4526
4527       qtdemux_parse_moov (qtdemux, map.data, length);
4528       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4529
4530       qtdemux_parse_tree (qtdemux);
4531       if (qtdemux->moov_node_compressed) {
4532         g_node_destroy (qtdemux->moov_node_compressed);
4533         g_free (qtdemux->moov_node->data);
4534       }
4535       qtdemux->moov_node_compressed = NULL;
4536       g_node_destroy (qtdemux->moov_node);
4537       qtdemux->moov_node = NULL;
4538       gst_buffer_unmap (moov, &map);
4539       gst_buffer_unref (moov);
4540       qtdemux->got_moov = TRUE;
4541
4542       break;
4543     }
4544     case FOURCC_ftyp:
4545     {
4546       GstBuffer *ftyp = NULL;
4547
4548       /* extract major brand; might come in handy for ISO vs QT issues */
4549       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4550       if (ret != GST_FLOW_OK)
4551         goto beach;
4552       qtdemux->offset += length;
4553       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4554       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4555       gst_buffer_unmap (ftyp, &map);
4556       gst_buffer_unref (ftyp);
4557       break;
4558     }
4559     case FOURCC_uuid:
4560     {
4561       GstBuffer *uuid = NULL;
4562
4563       /* uuid are extension atoms */
4564       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4565       if (ret != GST_FLOW_OK)
4566         goto beach;
4567       qtdemux->offset += length;
4568       gst_buffer_map (uuid, &map, GST_MAP_READ);
4569       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4570       gst_buffer_unmap (uuid, &map);
4571       gst_buffer_unref (uuid);
4572       break;
4573     }
4574     case FOURCC_sidx:
4575     {
4576       GstBuffer *sidx = NULL;
4577       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4578       if (ret != GST_FLOW_OK)
4579         goto beach;
4580       qtdemux->offset += length;
4581       gst_buffer_map (sidx, &map, GST_MAP_READ);
4582       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4583       gst_buffer_unmap (sidx, &map);
4584       gst_buffer_unref (sidx);
4585       break;
4586     }
4587     default:
4588     {
4589       GstBuffer *unknown = NULL;
4590
4591       GST_LOG_OBJECT (qtdemux,
4592           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4593           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4594           cur_offset);
4595       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4596       if (ret != GST_FLOW_OK)
4597         goto beach;
4598       gst_buffer_map (unknown, &map, GST_MAP_READ);
4599       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4600       gst_buffer_unmap (unknown, &map);
4601       gst_buffer_unref (unknown);
4602       qtdemux->offset += length;
4603       break;
4604     }
4605   }
4606
4607 beach:
4608   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4609     /* digested all data, show what we have */
4610     qtdemux_prepare_streams (qtdemux);
4611     QTDEMUX_EXPOSE_LOCK (qtdemux);
4612     ret = qtdemux_expose_streams (qtdemux);
4613     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4614
4615     qtdemux->state = QTDEMUX_STATE_MOVIE;
4616     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4617         qtdemux->state);
4618     return ret;
4619   }
4620   return ret;
4621 }
4622
4623 /* Seeks to the previous keyframe of the indexed stream and
4624  * aligns other streams with respect to the keyframe timestamp
4625  * of indexed stream. Only called in case of Reverse Playback
4626  */
4627 static GstFlowReturn
4628 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4629 {
4630   guint32 seg_idx = 0, k_index = 0;
4631   guint32 ref_seg_idx, ref_k_index;
4632   GstClockTime k_pos = 0, last_stop = 0;
4633   QtDemuxSegment *seg = NULL;
4634   QtDemuxStream *ref_str = NULL;
4635   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4636   guint64 target_ts;
4637   GList *iter;
4638
4639   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4640    * and finally align all the other streams on that timestamp with their
4641    * respective keyframes */
4642   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4643     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4644
4645     /* No candidate yet, take the first stream */
4646     if (!ref_str) {
4647       ref_str = str;
4648       continue;
4649     }
4650
4651     /* So that stream has a segment, we prefer video streams */
4652     if (str->subtype == FOURCC_vide) {
4653       ref_str = str;
4654       break;
4655     }
4656   }
4657
4658   if (G_UNLIKELY (!ref_str)) {
4659     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4660     goto eos;
4661   }
4662
4663   if (G_UNLIKELY (!ref_str->from_sample)) {
4664     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4665     goto eos;
4666   }
4667
4668   /* So that stream has been playing from from_sample to to_sample. We will
4669    * get the timestamp of the previous sample and search for a keyframe before
4670    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4671   if (ref_str->subtype == FOURCC_vide) {
4672     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4673         ref_str->from_sample - 1, FALSE);
4674   } else {
4675     if (ref_str->from_sample >= 10)
4676       k_index = ref_str->from_sample - 10;
4677     else
4678       k_index = 0;
4679   }
4680
4681   target_ts =
4682       ref_str->samples[k_index].timestamp +
4683       ref_str->samples[k_index].pts_offset;
4684
4685   /* get current segment for that stream */
4686   seg = &ref_str->segments[ref_str->segment_index];
4687   /* Use segment start in original timescale for comparisons */
4688   seg_media_start_mov = seg->trak_media_start;
4689
4690   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4691       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4692       k_index, target_ts, seg_media_start_mov,
4693       GST_TIME_ARGS (seg->media_start));
4694
4695   /* Crawl back through segments to find the one containing this I frame */
4696   while (target_ts < seg_media_start_mov) {
4697     GST_DEBUG_OBJECT (qtdemux,
4698         "keyframe position (sample %u) is out of segment %u " " target %"
4699         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4700         ref_str->segment_index, target_ts, seg_media_start_mov);
4701
4702     if (G_UNLIKELY (!ref_str->segment_index)) {
4703       /* Reached first segment, let's consider it's EOS */
4704       goto eos;
4705     }
4706     ref_str->segment_index--;
4707     seg = &ref_str->segments[ref_str->segment_index];
4708     /* Use segment start in original timescale for comparisons */
4709     seg_media_start_mov = seg->trak_media_start;
4710   }
4711   /* Calculate time position of the keyframe and where we should stop */
4712   k_pos =
4713       QTSTREAMTIME_TO_GSTTIME (ref_str,
4714       target_ts - seg->trak_media_start) + seg->time;
4715   last_stop =
4716       QTSTREAMTIME_TO_GSTTIME (ref_str,
4717       ref_str->samples[ref_str->from_sample].timestamp -
4718       seg->trak_media_start) + seg->time;
4719
4720   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4721       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4722       k_index, GST_TIME_ARGS (k_pos));
4723
4724   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4725   qtdemux->segment.position = last_stop;
4726   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4727       GST_TIME_ARGS (last_stop));
4728
4729   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4730     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4731     goto eos;
4732   }
4733
4734   ref_seg_idx = ref_str->segment_index;
4735   ref_k_index = k_index;
4736
4737   /* Align them all on this */
4738   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4739     guint32 index = 0;
4740     GstClockTime seg_time = 0;
4741     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4742
4743     /* aligning reference stream again might lead to backing up to yet another
4744      * keyframe (due to timestamp rounding issues),
4745      * potentially putting more load on downstream; so let's try to avoid */
4746     if (str == ref_str) {
4747       seg_idx = ref_seg_idx;
4748       seg = &str->segments[seg_idx];
4749       k_index = ref_k_index;
4750       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4751           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4752     } else {
4753       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4754       GST_DEBUG_OBJECT (qtdemux,
4755           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4756           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4757
4758       /* get segment and time in the segment */
4759       seg = &str->segments[seg_idx];
4760       seg_time = k_pos - seg->time;
4761
4762       /* get the media time in the segment.
4763        * No adjustment for empty "filler" segments */
4764       if (seg->media_start != GST_CLOCK_TIME_NONE)
4765         seg_time += seg->media_start;
4766
4767       /* get the index of the sample with media time */
4768       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4769       GST_DEBUG_OBJECT (qtdemux,
4770           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4771           GST_TIME_ARGS (seg_time), index);
4772
4773       /* find previous keyframe */
4774       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4775     }
4776
4777     /* Remember until where we want to go */
4778     str->to_sample = str->from_sample - 1;
4779     /* Define our time position */
4780     target_ts =
4781         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4782     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4783     if (seg->media_start != GST_CLOCK_TIME_NONE)
4784       str->time_position -= seg->media_start;
4785
4786     /* Now seek back in time */
4787     gst_qtdemux_move_stream (qtdemux, str, k_index);
4788     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4789         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4790         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4791   }
4792
4793   return GST_FLOW_OK;
4794
4795 eos:
4796   return GST_FLOW_EOS;
4797 }
4798
4799 /*
4800  * Gets the current qt segment start, stop and position for the
4801  * given time offset. This is used in update_segment()
4802  */
4803 static void
4804 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4805     QtDemuxStream * stream, GstClockTime offset,
4806     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4807 {
4808   GstClockTime seg_time;
4809   GstClockTime start, stop, time;
4810   QtDemuxSegment *segment;
4811
4812   segment = &stream->segments[stream->segment_index];
4813
4814   /* get time in this segment */
4815   seg_time = (offset - segment->time) * segment->rate;
4816
4817   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4818       GST_TIME_ARGS (seg_time));
4819
4820   if (G_UNLIKELY (seg_time > segment->duration)) {
4821     GST_LOG_OBJECT (stream->pad,
4822         "seg_time > segment->duration %" GST_TIME_FORMAT,
4823         GST_TIME_ARGS (segment->duration));
4824     seg_time = segment->duration;
4825   }
4826
4827   /* qtdemux->segment.stop is in outside-time-realm, whereas
4828    * segment->media_stop is in track-time-realm.
4829    *
4830    * In order to compare the two, we need to bring segment.stop
4831    * into the track-time-realm
4832    *
4833    * FIXME - does this comment still hold? Don't see any conversion here */
4834
4835   stop = qtdemux->segment.stop;
4836   if (stop == GST_CLOCK_TIME_NONE)
4837     stop = qtdemux->segment.duration;
4838   if (stop == GST_CLOCK_TIME_NONE)
4839     stop = segment->media_stop;
4840   else
4841     stop =
4842         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4843
4844   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4845     start = segment->time + seg_time;
4846     time = offset;
4847     stop = start - seg_time + segment->duration;
4848   } else if (qtdemux->segment.rate >= 0) {
4849     start = MIN (segment->media_start + seg_time, stop);
4850     time = offset;
4851   } else {
4852     if (segment->media_start >= qtdemux->segment.start) {
4853       time = segment->time;
4854     } else {
4855       time = segment->time + (qtdemux->segment.start - segment->media_start);
4856     }
4857
4858     start = MAX (segment->media_start, qtdemux->segment.start);
4859     stop = MIN (segment->media_start + seg_time, stop);
4860   }
4861
4862   *_start = start;
4863   *_stop = stop;
4864   *_time = time;
4865 }
4866
4867 /*
4868  * Updates the qt segment used for the stream and pushes a new segment event
4869  * downstream on this stream's pad.
4870  */
4871 static gboolean
4872 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4873     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4874     GstClockTime * _stop)
4875 {
4876   QtDemuxSegment *segment;
4877   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4878   gdouble rate;
4879   GstEvent *event;
4880
4881   /* update the current segment */
4882   stream->segment_index = seg_idx;
4883
4884   /* get the segment */
4885   segment = &stream->segments[seg_idx];
4886
4887   if (G_UNLIKELY (offset < segment->time)) {
4888     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4889         GST_TIME_ARGS (segment->time));
4890     return FALSE;
4891   }
4892
4893   /* segment lies beyond total indicated duration */
4894   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4895           segment->time > qtdemux->segment.duration)) {
4896     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4897         " < segment->time %" GST_TIME_FORMAT,
4898         GST_TIME_ARGS (qtdemux->segment.duration),
4899         GST_TIME_ARGS (segment->time));
4900     return FALSE;
4901   }
4902
4903   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4904       &start, &stop, &time);
4905
4906   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4907       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4908       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4909
4910   /* combine global rate with that of the segment */
4911   rate = segment->rate * qtdemux->segment.rate;
4912
4913   /* Copy flags from main segment */
4914   stream->segment.flags = qtdemux->segment.flags;
4915
4916   /* update the segment values used for clipping */
4917   stream->segment.offset = qtdemux->segment.offset;
4918   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4919   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4920   stream->segment.rate = rate;
4921   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4922       stream->cslg_shift);
4923   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4924       stream->cslg_shift);
4925   stream->segment.time = time;
4926   stream->segment.position = stream->segment.start;
4927
4928   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4929       &stream->segment);
4930
4931   /* now prepare and send the segment */
4932   if (stream->pad) {
4933     event = gst_event_new_segment (&stream->segment);
4934     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4935       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4936     }
4937     gst_pad_push_event (stream->pad, event);
4938     /* assume we can send more data now */
4939     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4940     /* clear to send tags on this pad now */
4941     gst_qtdemux_push_tags (qtdemux, stream);
4942   }
4943
4944   if (_start)
4945     *_start = start;
4946   if (_stop)
4947     *_stop = stop;
4948
4949   return TRUE;
4950 }
4951
4952 /* activate the given segment number @seg_idx of @stream at time @offset.
4953  * @offset is an absolute global position over all the segments.
4954  *
4955  * This will push out a NEWSEGMENT event with the right values and
4956  * position the stream index to the first decodable sample before
4957  * @offset.
4958  */
4959 static gboolean
4960 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4961     guint32 seg_idx, GstClockTime offset)
4962 {
4963   QtDemuxSegment *segment;
4964   guint32 index, kf_index;
4965   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4966
4967   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4968       seg_idx, GST_TIME_ARGS (offset));
4969
4970   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4971           &start, &stop))
4972     return FALSE;
4973
4974   segment = &stream->segments[stream->segment_index];
4975
4976   /* in the fragmented case, we pick a fragment that starts before our
4977    * desired position and rely on downstream to wait for a keyframe
4978    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4979    * tfra entries tells us which trun/sample the key unit is in, but we don't
4980    * make use of this additional information at the moment) */
4981   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4982     stream->to_sample = G_MAXUINT32;
4983     return TRUE;
4984   } else {
4985     /* well, it will be taken care of below */
4986     qtdemux->fragmented_seek_pending = FALSE;
4987     /* FIXME ideally the do_fragmented_seek can be done right here,
4988      * rather than at loop level
4989      * (which might even allow handling edit lists in a fragmented file) */
4990   }
4991
4992   /* We don't need to look for a sample in push-based */
4993   if (!qtdemux->pullbased)
4994     return TRUE;
4995
4996   /* and move to the keyframe before the indicated media time of the
4997    * segment */
4998   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4999     if (qtdemux->segment.rate >= 0) {
5000       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5001       stream->to_sample = G_MAXUINT32;
5002       GST_DEBUG_OBJECT (stream->pad,
5003           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5004           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5005           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5006     } else {
5007       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5008       stream->to_sample = index;
5009       GST_DEBUG_OBJECT (stream->pad,
5010           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5011           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5012           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5013     }
5014   } else {
5015     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5016         "this is an empty segment");
5017     return TRUE;
5018   }
5019
5020   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5021    * encountered an error and printed a message so we return appropriately */
5022   if (index == -1)
5023     return FALSE;
5024
5025   /* we're at the right spot */
5026   if (index == stream->sample_index) {
5027     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5028     return TRUE;
5029   }
5030
5031   /* find keyframe of the target index */
5032   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5033
5034 /* *INDENT-OFF* */
5035 /* indent does stupid stuff with stream->samples[].timestamp */
5036
5037   /* if we move forwards, we don't have to go back to the previous
5038    * keyframe since we already sent that. We can also just jump to
5039    * the keyframe right before the target index if there is one. */
5040   if (index > stream->sample_index) {
5041     /* moving forwards check if we move past a keyframe */
5042     if (kf_index > stream->sample_index) {
5043       GST_DEBUG_OBJECT (stream->pad,
5044            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5045            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5046            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5047       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5048     } else {
5049       GST_DEBUG_OBJECT (stream->pad,
5050           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5051           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5052           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5053     }
5054   } else {
5055     GST_DEBUG_OBJECT (stream->pad,
5056         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5057         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5058         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5059     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5060   }
5061
5062 /* *INDENT-ON* */
5063
5064   return TRUE;
5065 }
5066
5067 /* prepare to get the current sample of @stream, getting essential values.
5068  *
5069  * This function will also prepare and send the segment when needed.
5070  *
5071  * Return FALSE if the stream is EOS.
5072  *
5073  * PULL-BASED
5074  */
5075 static gboolean
5076 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5077     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5078     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5079     gboolean * keyframe)
5080 {
5081   QtDemuxSample *sample;
5082   GstClockTime time_position;
5083   guint32 seg_idx;
5084
5085   g_return_val_if_fail (stream != NULL, FALSE);
5086
5087   time_position = stream->time_position;
5088   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5089     goto eos;
5090
5091   seg_idx = stream->segment_index;
5092   if (G_UNLIKELY (seg_idx == -1)) {
5093     /* find segment corresponding to time_position if we are looking
5094      * for a segment. */
5095     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5096   }
5097
5098   /* different segment, activate it, sample_index will be set. */
5099   if (G_UNLIKELY (stream->segment_index != seg_idx))
5100     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5101
5102   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5103                   segment_index]))) {
5104     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5105
5106     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5107         " prepare empty sample");
5108
5109     *empty = TRUE;
5110     *pts = *dts = time_position;
5111     *duration = seg->duration - (time_position - seg->time);
5112
5113     return TRUE;
5114   }
5115
5116   *empty = FALSE;
5117
5118   if (stream->sample_index == -1)
5119     stream->sample_index = 0;
5120
5121   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5122       stream->sample_index, stream->n_samples);
5123
5124   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5125     if (!qtdemux->fragmented)
5126       goto eos;
5127
5128     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5129     do {
5130       GstFlowReturn flow;
5131
5132       GST_OBJECT_LOCK (qtdemux);
5133       flow = qtdemux_add_fragmented_samples (qtdemux);
5134       GST_OBJECT_UNLOCK (qtdemux);
5135
5136       if (flow != GST_FLOW_OK)
5137         goto eos;
5138     }
5139     while (stream->sample_index >= stream->n_samples);
5140   }
5141
5142   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5143     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5144         stream->sample_index);
5145     return FALSE;
5146   }
5147
5148   /* now get the info for the sample we're at */
5149   sample = &stream->samples[stream->sample_index];
5150
5151   *dts = QTSAMPLE_DTS (stream, sample);
5152   *pts = QTSAMPLE_PTS (stream, sample);
5153   *offset = sample->offset;
5154   *size = sample->size;
5155   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5156   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5157
5158   return TRUE;
5159
5160   /* special cases */
5161 eos:
5162   {
5163     stream->time_position = GST_CLOCK_TIME_NONE;
5164     return FALSE;
5165   }
5166 }
5167
5168 /* move to the next sample in @stream.
5169  *
5170  * Moves to the next segment when needed.
5171  */
5172 static void
5173 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5174 {
5175   QtDemuxSample *sample;
5176   QtDemuxSegment *segment;
5177
5178   /* get current segment */
5179   segment = &stream->segments[stream->segment_index];
5180
5181   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5182     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5183     goto next_segment;
5184   }
5185
5186   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5187     /* Mark the stream as EOS */
5188     GST_DEBUG_OBJECT (qtdemux,
5189         "reached max allowed sample %u, mark EOS", stream->to_sample);
5190     stream->time_position = GST_CLOCK_TIME_NONE;
5191     return;
5192   }
5193
5194   /* move to next sample */
5195   stream->sample_index++;
5196   stream->offset_in_sample = 0;
5197
5198   /* reached the last sample, we need the next segment */
5199   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5200     goto next_segment;
5201
5202   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5203     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5204         stream->sample_index);
5205     return;
5206   }
5207
5208   /* get next sample */
5209   sample = &stream->samples[stream->sample_index];
5210
5211   /* see if we are past the segment */
5212   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5213     goto next_segment;
5214
5215   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5216     /* inside the segment, update time_position, looks very familiar to
5217      * GStreamer segments, doesn't it? */
5218     stream->time_position =
5219         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5220   } else {
5221     /* not yet in segment, time does not yet increment. This means
5222      * that we are still prerolling keyframes to the decoder so it can
5223      * decode the first sample of the segment. */
5224     stream->time_position = segment->time;
5225   }
5226   return;
5227
5228   /* move to the next segment */
5229 next_segment:
5230   {
5231     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5232
5233     if (stream->segment_index == stream->n_segments - 1) {
5234       /* are we at the end of the last segment, we're EOS */
5235       stream->time_position = GST_CLOCK_TIME_NONE;
5236     } else {
5237       /* else we're only at the end of the current segment */
5238       stream->time_position = segment->stop_time;
5239     }
5240     /* make sure we select a new segment */
5241
5242     /* accumulate previous segments */
5243     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5244       stream->accumulated_base +=
5245           (stream->segment.stop -
5246           stream->segment.start) / ABS (stream->segment.rate);
5247
5248     stream->segment_index = -1;
5249   }
5250 }
5251
5252 static void
5253 gst_qtdemux_sync_streams (GstQTDemux * demux)
5254 {
5255   GList *iter;
5256
5257   if (demux->n_streams <= 1)
5258     return;
5259
5260   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5261     QtDemuxStream *stream;
5262     GstClockTime end_time;
5263
5264     stream = QTDEMUX_STREAM (iter->data);
5265
5266     if (!stream->pad)
5267       continue;
5268
5269     /* TODO advance time on subtitle streams here, if any some day */
5270
5271     /* some clips/trailers may have unbalanced streams at the end,
5272      * so send EOS on shorter stream to prevent stalling others */
5273
5274     /* do not mess with EOS if SEGMENT seeking */
5275     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5276       continue;
5277
5278     if (demux->pullbased) {
5279       /* loop mode is sample time based */
5280       if (!STREAM_IS_EOS (stream))
5281         continue;
5282     } else {
5283       /* push mode is byte position based */
5284       if (stream->n_samples &&
5285           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5286         continue;
5287     }
5288
5289     if (stream->sent_eos)
5290       continue;
5291
5292     /* only act if some gap */
5293     end_time = stream->segments[stream->n_segments - 1].stop_time;
5294     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5295         ", stream end: %" GST_TIME_FORMAT,
5296         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5297     if (GST_CLOCK_TIME_IS_VALID (end_time)
5298         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5299       GstEvent *event;
5300
5301       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5302           GST_PAD_NAME (stream->pad));
5303       stream->sent_eos = TRUE;
5304       event = gst_event_new_eos ();
5305       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5306         gst_event_set_seqnum (event, demux->segment_seqnum);
5307       gst_pad_push_event (stream->pad, event);
5308     }
5309   }
5310 }
5311
5312 /* EOS and NOT_LINKED need to be combined. This means that we return:
5313  *
5314  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5315  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5316  */
5317 static GstFlowReturn
5318 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5319     GstFlowReturn ret)
5320 {
5321   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5322
5323   if (stream->pad)
5324     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5325         ret);
5326   else
5327     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5328
5329   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5330   return ret;
5331 }
5332
5333 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5334  * completely clipped
5335  *
5336  * Should be used only with raw buffers */
5337 static GstBuffer *
5338 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5339     GstBuffer * buf)
5340 {
5341   guint64 start, stop, cstart, cstop, diff;
5342   GstClockTime pts, duration;
5343   gsize size, osize;
5344   gint num_rate, denom_rate;
5345   gint frame_size;
5346   gboolean clip_data;
5347   guint offset;
5348
5349   osize = size = gst_buffer_get_size (buf);
5350   offset = 0;
5351
5352   /* depending on the type, setup the clip parameters */
5353   if (stream->subtype == FOURCC_soun) {
5354     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5355     num_rate = GST_SECOND;
5356     denom_rate = (gint) CUR_STREAM (stream)->rate;
5357     clip_data = TRUE;
5358   } else if (stream->subtype == FOURCC_vide) {
5359     frame_size = size;
5360     num_rate = CUR_STREAM (stream)->fps_n;
5361     denom_rate = CUR_STREAM (stream)->fps_d;
5362     clip_data = FALSE;
5363   } else
5364     goto wrong_type;
5365
5366   if (frame_size <= 0)
5367     goto bad_frame_size;
5368
5369   /* we can only clip if we have a valid pts */
5370   pts = GST_BUFFER_PTS (buf);
5371   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5372     goto no_pts;
5373
5374   duration = GST_BUFFER_DURATION (buf);
5375
5376   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5377     duration =
5378         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5379   }
5380
5381   start = pts;
5382   stop = start + duration;
5383
5384   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5385               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5386     goto clipped;
5387
5388   /* see if some clipping happened */
5389   diff = cstart - start;
5390   if (diff > 0) {
5391     pts += diff;
5392     duration -= diff;
5393
5394     if (clip_data) {
5395       /* bring clipped time to samples and to bytes */
5396       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5397       diff *= frame_size;
5398
5399       GST_DEBUG_OBJECT (qtdemux,
5400           "clipping start to %" GST_TIME_FORMAT " %"
5401           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5402
5403       offset = diff;
5404       size -= diff;
5405     }
5406   }
5407   diff = stop - cstop;
5408   if (diff > 0) {
5409     duration -= diff;
5410
5411     if (clip_data) {
5412       /* bring clipped time to samples and then to bytes */
5413       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5414       diff *= frame_size;
5415       GST_DEBUG_OBJECT (qtdemux,
5416           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5417           " bytes", GST_TIME_ARGS (cstop), diff);
5418       size -= diff;
5419     }
5420   }
5421
5422   if (offset != 0 || size != osize)
5423     gst_buffer_resize (buf, offset, size);
5424
5425   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5426   GST_BUFFER_PTS (buf) = pts;
5427   GST_BUFFER_DURATION (buf) = duration;
5428
5429   return buf;
5430
5431   /* dropped buffer */
5432 wrong_type:
5433   {
5434     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5435     return buf;
5436   }
5437 bad_frame_size:
5438   {
5439     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5440     return buf;
5441   }
5442 no_pts:
5443   {
5444     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5445     return buf;
5446   }
5447 clipped:
5448   {
5449     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5450     gst_buffer_unref (buf);
5451     return NULL;
5452   }
5453 }
5454
5455 static GstBuffer *
5456 gst_qtdemux_align_buffer (GstQTDemux * demux,
5457     GstBuffer * buffer, gsize alignment)
5458 {
5459   GstMapInfo map;
5460
5461   gst_buffer_map (buffer, &map, GST_MAP_READ);
5462
5463   if (map.size < sizeof (guintptr)) {
5464     gst_buffer_unmap (buffer, &map);
5465     return buffer;
5466   }
5467
5468   if (((guintptr) map.data) & (alignment - 1)) {
5469     GstBuffer *new_buffer;
5470     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5471
5472     new_buffer = gst_buffer_new_allocate (NULL,
5473         gst_buffer_get_size (buffer), &params);
5474
5475     /* Copy data "by hand", so ensure alignment is kept: */
5476     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5477
5478     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5479     GST_DEBUG_OBJECT (demux,
5480         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5481         alignment);
5482
5483     gst_buffer_unmap (buffer, &map);
5484     gst_buffer_unref (buffer);
5485
5486     return new_buffer;
5487   }
5488
5489   gst_buffer_unmap (buffer, &map);
5490   return buffer;
5491 }
5492
5493 static guint8 *
5494 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5495     gsize * res)
5496 {
5497   guint8 *storage;
5498   gsize i;
5499
5500   /* We are converting from pairs to triplets */
5501   *res = ccpair_size / 2 * 3;
5502   storage = g_malloc (*res);
5503   for (i = 0; i * 2 < ccpair_size; i += 1) {
5504     if (field == 1)
5505       storage[i * 3] = 0xfc;
5506     else
5507       storage[i * 3] = 0xfd;
5508     storage[i * 3 + 1] = ccpair[i * 2];
5509     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5510   }
5511
5512   return storage;
5513 }
5514
5515 static guint8 *
5516 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5517     gsize * cclen)
5518 {
5519   guint8 *res = NULL;
5520   guint32 atom_length, fourcc;
5521   QtDemuxStreamStsdEntry *stsd_entry;
5522
5523   GST_MEMDUMP ("caption atom", data, size);
5524
5525   /* There might be multiple atoms */
5526
5527   *cclen = 0;
5528   if (size < 8)
5529     goto invalid_cdat;
5530   atom_length = QT_UINT32 (data);
5531   fourcc = QT_FOURCC (data + 4);
5532   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5533     goto invalid_cdat;
5534
5535   GST_DEBUG_OBJECT (stream->pad, "here");
5536
5537   /* Check if we have somethig compatible */
5538   stsd_entry = CUR_STREAM (stream);
5539   switch (stsd_entry->fourcc) {
5540     case FOURCC_c608:{
5541       guint8 *cdat = NULL, *cdt2 = NULL;
5542       gsize cdat_size = 0, cdt2_size = 0;
5543       /* Should be cdat or cdt2 */
5544       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5545         GST_WARNING_OBJECT (stream->pad,
5546             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5547             GST_FOURCC_ARGS (fourcc));
5548         goto invalid_cdat;
5549       }
5550
5551       /* Convert to cc_data triplet */
5552       if (fourcc == FOURCC_cdat)
5553         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5554       else
5555         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5556       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5557           size, atom_length);
5558
5559       /* Check for another atom ? */
5560       if (size > atom_length + 8) {
5561         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5562         if (size >= atom_length + new_atom_length) {
5563           fourcc = QT_FOURCC (data + atom_length + 4);
5564           if (fourcc == FOURCC_cdat) {
5565             if (cdat == NULL)
5566               cdat =
5567                   convert_to_ccdata (data + atom_length + 8,
5568                   new_atom_length - 8, 1, &cdat_size);
5569             else
5570               GST_WARNING_OBJECT (stream->pad,
5571                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5572           } else {
5573             if (cdt2 == NULL)
5574               cdt2 =
5575                   convert_to_ccdata (data + atom_length + 8,
5576                   new_atom_length - 8, 2, &cdt2_size);
5577             else
5578               GST_WARNING_OBJECT (stream->pad,
5579                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5580           }
5581         }
5582       }
5583
5584       *cclen = cdat_size + cdt2_size;
5585       res = g_malloc (*cclen);
5586       if (cdat_size)
5587         memcpy (res, cdat, cdat_size);
5588       if (cdt2_size)
5589         memcpy (res + cdat_size, cdt2, cdt2_size);
5590       g_free (cdat);
5591       g_free (cdt2);
5592     }
5593       break;
5594     case FOURCC_c708:
5595       if (fourcc != FOURCC_ccdp) {
5596         GST_WARNING_OBJECT (stream->pad,
5597             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5598             GST_FOURCC_ARGS (fourcc));
5599         goto invalid_cdat;
5600       }
5601       *cclen = atom_length - 8;
5602       res = g_memdup (data + 8, *cclen);
5603       break;
5604     default:
5605       /* Keep this here in case other closed caption formats are added */
5606       g_assert_not_reached ();
5607       break;
5608   }
5609
5610   GST_MEMDUMP ("Output", res, *cclen);
5611   return res;
5612
5613   /* Errors */
5614 invalid_cdat:
5615   GST_WARNING ("[cdat] atom is too small or invalid");
5616   return NULL;
5617 }
5618
5619 /* the input buffer metadata must be writable,
5620  * but time/duration etc not yet set and need not be preserved */
5621 static GstBuffer *
5622 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5623     GstBuffer * buf)
5624 {
5625   GstMapInfo map;
5626   guint nsize = 0;
5627   gchar *str;
5628
5629   /* not many cases for now */
5630   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5631     /* send a one time dvd clut event */
5632     if (stream->pending_event && stream->pad)
5633       gst_pad_push_event (stream->pad, stream->pending_event);
5634     stream->pending_event = NULL;
5635   }
5636
5637   if (G_UNLIKELY (stream->subtype != FOURCC_text
5638           && stream->subtype != FOURCC_sbtl &&
5639           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5640     return buf;
5641   }
5642
5643   gst_buffer_map (buf, &map, GST_MAP_READ);
5644
5645   /* empty buffer is sent to terminate previous subtitle */
5646   if (map.size <= 2) {
5647     gst_buffer_unmap (buf, &map);
5648     gst_buffer_unref (buf);
5649     return NULL;
5650   }
5651   if (stream->subtype == FOURCC_subp) {
5652     /* That's all the processing needed for subpictures */
5653     gst_buffer_unmap (buf, &map);
5654     return buf;
5655   }
5656
5657   if (stream->subtype == FOURCC_clcp) {
5658     guint8 *cc;
5659     gsize cclen = 0;
5660     /* For closed caption, we need to extract the information from the
5661      * [cdat],[cdt2] or [ccdp] atom */
5662     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5663     gst_buffer_unmap (buf, &map);
5664     gst_buffer_unref (buf);
5665     if (cc) {
5666       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5667     } else {
5668       /* Conversion failed or there's nothing */
5669       buf = NULL;
5670     }
5671     return buf;
5672   }
5673
5674   nsize = GST_READ_UINT16_BE (map.data);
5675   nsize = MIN (nsize, map.size - 2);
5676
5677   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5678       nsize, map.size);
5679
5680   /* takes care of UTF-8 validation or UTF-16 recognition,
5681    * no other encoding expected */
5682   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5683   gst_buffer_unmap (buf, &map);
5684   if (str) {
5685     gst_buffer_unref (buf);
5686     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5687   } else {
5688     /* this should not really happen unless the subtitle is corrupted */
5689     gst_buffer_unref (buf);
5690     buf = NULL;
5691   }
5692
5693   /* FIXME ? convert optional subsequent style info to markup */
5694
5695   return buf;
5696 }
5697
5698 /* Sets a buffer's attributes properly and pushes it downstream.
5699  * Also checks for additional actions and custom processing that may
5700  * need to be done first.
5701  */
5702 static GstFlowReturn
5703 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5704     QtDemuxStream * stream, GstBuffer * buf,
5705     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5706     gboolean keyframe, GstClockTime position, guint64 byte_position)
5707 {
5708   GstFlowReturn ret = GST_FLOW_OK;
5709
5710   /* offset the timestamps according to the edit list */
5711
5712   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5713     gchar *url;
5714     GstMapInfo map;
5715
5716     gst_buffer_map (buf, &map, GST_MAP_READ);
5717     url = g_strndup ((gchar *) map.data, map.size);
5718     gst_buffer_unmap (buf, &map);
5719     if (url != NULL && strlen (url) != 0) {
5720       /* we have RTSP redirect now */
5721       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5722           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5723               gst_structure_new ("redirect",
5724                   "new-location", G_TYPE_STRING, url, NULL)));
5725       qtdemux->posted_redirect = TRUE;
5726     } else {
5727       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5728           "posting");
5729     }
5730     g_free (url);
5731   }
5732
5733   /* position reporting */
5734   if (qtdemux->segment.rate >= 0) {
5735     qtdemux->segment.position = position;
5736     gst_qtdemux_sync_streams (qtdemux);
5737   }
5738
5739   if (G_UNLIKELY (!stream->pad)) {
5740     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5741     gst_buffer_unref (buf);
5742     goto exit;
5743   }
5744
5745   /* send out pending buffers */
5746   while (stream->buffers) {
5747     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5748
5749     if (G_UNLIKELY (stream->discont)) {
5750       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5751       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5752       stream->discont = FALSE;
5753     } else {
5754       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5755     }
5756
5757     if (stream->alignment > 1)
5758       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5759     gst_pad_push (stream->pad, buffer);
5760
5761     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5762   }
5763
5764   /* we're going to modify the metadata */
5765   buf = gst_buffer_make_writable (buf);
5766
5767   if (G_UNLIKELY (stream->need_process))
5768     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5769
5770   if (!buf) {
5771     goto exit;
5772   }
5773
5774   GST_BUFFER_DTS (buf) = dts;
5775   GST_BUFFER_PTS (buf) = pts;
5776   GST_BUFFER_DURATION (buf) = duration;
5777   GST_BUFFER_OFFSET (buf) = -1;
5778   GST_BUFFER_OFFSET_END (buf) = -1;
5779
5780   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5781     gst_buffer_append_memory (buf,
5782         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5783
5784   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5785     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5786   }
5787 #if 0
5788   if (G_UNLIKELY (qtdemux->element_index)) {
5789     GstClockTime stream_time;
5790
5791     stream_time =
5792         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5793         timestamp);
5794     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5795       GST_LOG_OBJECT (qtdemux,
5796           "adding association %" GST_TIME_FORMAT "-> %"
5797           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5798       gst_index_add_association (qtdemux->element_index,
5799           qtdemux->index_id,
5800           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5801           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5802           GST_FORMAT_BYTES, byte_position, NULL);
5803     }
5804   }
5805 #endif
5806
5807   if (stream->need_clip)
5808     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5809
5810   if (G_UNLIKELY (buf == NULL))
5811     goto exit;
5812
5813   if (G_UNLIKELY (stream->discont)) {
5814     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5815     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5816     stream->discont = FALSE;
5817   } else {
5818     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5819   }
5820
5821   if (!keyframe) {
5822     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5823     stream->on_keyframe = FALSE;
5824   } else {
5825     stream->on_keyframe = TRUE;
5826   }
5827
5828
5829   GST_LOG_OBJECT (qtdemux,
5830       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5831       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5832       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5833       GST_PAD_NAME (stream->pad));
5834
5835   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5836     GstStructure *crypto_info;
5837     QtDemuxCencSampleSetInfo *info =
5838         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5839     gint index;
5840     GstEvent *event;
5841
5842     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5843       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5844           GST_PTR_FORMAT, event);
5845       gst_pad_push_event (stream->pad, event);
5846     }
5847
5848     if (info->crypto_info == NULL) {
5849       GST_DEBUG_OBJECT (qtdemux,
5850           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5851     } else {
5852       /* The end of the crypto_info array matches our n_samples position,
5853        * so count backward from there */
5854       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5855       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5856         /* steal structure from array */
5857         crypto_info = g_ptr_array_index (info->crypto_info, index);
5858         g_ptr_array_index (info->crypto_info, index) = NULL;
5859         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5860             info->crypto_info->len);
5861         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5862           GST_ERROR_OBJECT (qtdemux,
5863               "failed to attach cenc metadata to buffer");
5864       } else {
5865         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5866             index, stream->sample_index);
5867       }
5868     }
5869   }
5870
5871   if (stream->alignment > 1)
5872     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5873
5874   ret = gst_pad_push (stream->pad, buf);
5875
5876   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5877     /* mark position in stream, we'll need this to know when to send GAP event */
5878     stream->segment.position = pts + duration;
5879   }
5880
5881 exit:
5882   return ret;
5883 }
5884
5885 static const QtDemuxRandomAccessEntry *
5886 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5887     GstClockTime pos, gboolean after)
5888 {
5889   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5890   guint n_entries = stream->n_ra_entries;
5891   guint i;
5892
5893   /* we assume the table is sorted */
5894   for (i = 0; i < n_entries; ++i) {
5895     if (entries[i].ts > pos)
5896       break;
5897   }
5898
5899   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5900    * probably okay to assume that the index lists the very first fragment */
5901   if (i == 0)
5902     return &entries[0];
5903
5904   if (after)
5905     return &entries[i];
5906   else
5907     return &entries[i - 1];
5908 }
5909
5910 static gboolean
5911 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5912 {
5913   const QtDemuxRandomAccessEntry *best_entry = NULL;
5914   GList *iter;
5915
5916   GST_OBJECT_LOCK (qtdemux);
5917
5918   g_assert (qtdemux->n_streams > 0);
5919
5920   /* first see if we can determine where to go to using mfra,
5921    * before we start clearing things */
5922   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5923     const QtDemuxRandomAccessEntry *entry;
5924     QtDemuxStream *stream;
5925     gboolean is_audio_or_video;
5926
5927     stream = QTDEMUX_STREAM (iter->data);
5928
5929     if (stream->ra_entries == NULL)
5930       continue;
5931
5932     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5933       is_audio_or_video = TRUE;
5934     else
5935       is_audio_or_video = FALSE;
5936
5937     entry =
5938         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5939         stream->time_position, !is_audio_or_video);
5940
5941     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5942         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5943
5944     stream->pending_seek = entry;
5945
5946     /* decide position to jump to just based on audio/video tracks, not subs */
5947     if (!is_audio_or_video)
5948       continue;
5949
5950     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5951       best_entry = entry;
5952   }
5953
5954   /* no luck, will handle seek otherwise */
5955   if (best_entry == NULL) {
5956     GST_OBJECT_UNLOCK (qtdemux);
5957     return FALSE;
5958   }
5959
5960   /* ok, now we can prepare for processing as of located moof */
5961   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5962     QtDemuxStream *stream;
5963
5964     stream = QTDEMUX_STREAM (iter->data);
5965
5966     g_free (stream->samples);
5967     stream->samples = NULL;
5968     stream->n_samples = 0;
5969     stream->stbl_index = -1;    /* no samples have yet been parsed */
5970     stream->sample_index = -1;
5971
5972     if (stream->protection_scheme_info) {
5973       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5974       if (stream->protection_scheme_type == FOURCC_cenc) {
5975         QtDemuxCencSampleSetInfo *info =
5976             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5977         if (info->crypto_info) {
5978           g_ptr_array_free (info->crypto_info, TRUE);
5979           info->crypto_info = NULL;
5980         }
5981       }
5982     }
5983   }
5984
5985   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5986       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5987       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
5988       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5989
5990   qtdemux->moof_offset = best_entry->moof_offset;
5991
5992   qtdemux_add_fragmented_samples (qtdemux);
5993
5994   GST_OBJECT_UNLOCK (qtdemux);
5995   return TRUE;
5996 }
5997
5998 static GstFlowReturn
5999 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6000 {
6001   GstFlowReturn ret = GST_FLOW_OK;
6002   GstBuffer *buf = NULL;
6003   QtDemuxStream *stream, *target_stream = NULL;
6004   GstClockTime min_time;
6005   guint64 offset = 0;
6006   GstClockTime dts = GST_CLOCK_TIME_NONE;
6007   GstClockTime pts = GST_CLOCK_TIME_NONE;
6008   GstClockTime duration = 0;
6009   gboolean keyframe = FALSE;
6010   guint sample_size = 0;
6011   gboolean empty = 0;
6012   guint size;
6013   GList *iter;
6014
6015   if (qtdemux->fragmented_seek_pending) {
6016     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6017     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6018       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6019       qtdemux->fragmented_seek_pending = FALSE;
6020     } else {
6021       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6022     }
6023   }
6024
6025   /* Figure out the next stream sample to output, min_time is expressed in
6026    * global time and runs over the edit list segments. */
6027   min_time = G_MAXUINT64;
6028   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6029     GstClockTime position;
6030
6031     stream = QTDEMUX_STREAM (iter->data);
6032     position = stream->time_position;
6033
6034     /* position of -1 is EOS */
6035     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6036       min_time = position;
6037       target_stream = stream;
6038     }
6039   }
6040   /* all are EOS */
6041   if (G_UNLIKELY (target_stream == NULL)) {
6042     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6043     goto eos;
6044   }
6045
6046   /* check for segment end */
6047   if (G_UNLIKELY (qtdemux->segment.stop != -1
6048           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6049               || (qtdemux->segment.rate < 0
6050                   && qtdemux->segment.start > min_time))
6051           && target_stream->on_keyframe)) {
6052     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6053     target_stream->time_position = GST_CLOCK_TIME_NONE;
6054     goto eos_stream;
6055   }
6056
6057   /* gap events for subtitle streams */
6058   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6059     stream = QTDEMUX_STREAM (iter->data);
6060     if (stream->pad && (stream->subtype == FOURCC_subp
6061             || stream->subtype == FOURCC_text
6062             || stream->subtype == FOURCC_sbtl)) {
6063       /* send one second gap events until the stream catches up */
6064       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6065       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6066           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6067           stream->segment.position + GST_SECOND < min_time) {
6068         GstEvent *gap =
6069             gst_event_new_gap (stream->segment.position, GST_SECOND);
6070         gst_pad_push_event (stream->pad, gap);
6071         stream->segment.position += GST_SECOND;
6072       }
6073     }
6074   }
6075
6076   stream = target_stream;
6077   /* fetch info for the current sample of this stream */
6078   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6079               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6080     goto eos_stream;
6081
6082   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6083   if (stream->new_caps) {
6084     gst_qtdemux_configure_stream (qtdemux, stream);
6085     qtdemux_do_allocation (qtdemux, stream);
6086   }
6087
6088   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6089   if (G_UNLIKELY (qtdemux->
6090           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6091     if (stream->subtype == FOURCC_vide && !keyframe) {
6092       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6093           stream->track_id);
6094       goto next;
6095     }
6096   }
6097
6098   GST_DEBUG_OBJECT (qtdemux,
6099       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6100       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6101       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6102       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6103       GST_TIME_ARGS (duration));
6104
6105   if (G_UNLIKELY (empty)) {
6106     /* empty segment, push a gap if there's a second or more
6107      * difference and move to the next one */
6108     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6109       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6110     stream->segment.position = pts + duration;
6111     goto next;
6112   }
6113
6114   /* hmm, empty sample, skip and move to next sample */
6115   if (G_UNLIKELY (sample_size <= 0))
6116     goto next;
6117
6118   /* last pushed sample was out of boundary, goto next sample */
6119   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6120     goto next;
6121
6122   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6123     size = sample_size;
6124   } else {
6125     GST_DEBUG_OBJECT (qtdemux,
6126         "size %d larger than stream max_buffer_size %d, trimming",
6127         sample_size, stream->max_buffer_size);
6128     size =
6129         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6130   }
6131
6132   if (qtdemux->cenc_aux_info_offset > 0) {
6133     GstMapInfo map;
6134     GstByteReader br;
6135     GstBuffer *aux_info = NULL;
6136
6137     /* pull the data stored before the sample */
6138     ret =
6139         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6140         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6141     if (G_UNLIKELY (ret != GST_FLOW_OK))
6142       goto beach;
6143     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6144     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6145     gst_byte_reader_init (&br, map.data + 8, map.size);
6146     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6147             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6148       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6149       gst_buffer_unmap (aux_info, &map);
6150       gst_buffer_unref (aux_info);
6151       ret = GST_FLOW_ERROR;
6152       goto beach;
6153     }
6154     gst_buffer_unmap (aux_info, &map);
6155     gst_buffer_unref (aux_info);
6156   }
6157
6158   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6159       offset);
6160
6161   if (stream->use_allocator) {
6162     /* if we have a per-stream allocator, use it */
6163     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6164   }
6165
6166   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6167       size, &buf);
6168   if (G_UNLIKELY (ret != GST_FLOW_OK))
6169     goto beach;
6170
6171   if (size != sample_size) {
6172     pts += gst_util_uint64_scale_int (GST_SECOND,
6173         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6174         stream->timescale);
6175     dts +=
6176         gst_util_uint64_scale_int (GST_SECOND,
6177         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6178         stream->timescale);
6179     duration =
6180         gst_util_uint64_scale_int (GST_SECOND,
6181         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6182   }
6183
6184   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6185       dts, pts, duration, keyframe, min_time, offset);
6186
6187   if (size != sample_size) {
6188     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6189     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6190
6191     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6192         sample->timestamp +
6193         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6194     if (time_position >= segment->media_start) {
6195       /* inside the segment, update time_position, looks very familiar to
6196        * GStreamer segments, doesn't it? */
6197       stream->time_position = (time_position - segment->media_start) +
6198           segment->time;
6199     } else {
6200       /* not yet in segment, time does not yet increment. This means
6201        * that we are still prerolling keyframes to the decoder so it can
6202        * decode the first sample of the segment. */
6203       stream->time_position = segment->time;
6204     }
6205   }
6206
6207   /* combine flows */
6208   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6209   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6210    * we have no more data for the pad to push */
6211   if (ret == GST_FLOW_EOS)
6212     ret = GST_FLOW_OK;
6213
6214   stream->offset_in_sample += size;
6215   if (stream->offset_in_sample >= sample_size) {
6216     gst_qtdemux_advance_sample (qtdemux, stream);
6217   }
6218   goto beach;
6219
6220 next:
6221   gst_qtdemux_advance_sample (qtdemux, stream);
6222
6223 beach:
6224   return ret;
6225
6226   /* special cases */
6227 eos:
6228   {
6229     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6230     ret = GST_FLOW_EOS;
6231     goto beach;
6232   }
6233 eos_stream:
6234   {
6235     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6236     /* EOS will be raised if all are EOS */
6237     ret = GST_FLOW_OK;
6238     goto beach;
6239   }
6240 }
6241
6242 static void
6243 gst_qtdemux_loop (GstPad * pad)
6244 {
6245   GstQTDemux *qtdemux;
6246   guint64 cur_offset;
6247   GstFlowReturn ret;
6248
6249   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6250
6251   cur_offset = qtdemux->offset;
6252   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6253       cur_offset, qt_demux_state_string (qtdemux->state));
6254
6255   switch (qtdemux->state) {
6256     case QTDEMUX_STATE_INITIAL:
6257     case QTDEMUX_STATE_HEADER:
6258       ret = gst_qtdemux_loop_state_header (qtdemux);
6259       break;
6260     case QTDEMUX_STATE_MOVIE:
6261       ret = gst_qtdemux_loop_state_movie (qtdemux);
6262       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6263         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6264       }
6265       break;
6266     default:
6267       /* ouch */
6268       goto invalid_state;
6269   }
6270
6271   /* if something went wrong, pause */
6272   if (ret != GST_FLOW_OK)
6273     goto pause;
6274
6275 done:
6276   gst_object_unref (qtdemux);
6277   return;
6278
6279   /* ERRORS */
6280 invalid_state:
6281   {
6282     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6283         (NULL), ("streaming stopped, invalid state"));
6284     gst_pad_pause_task (pad);
6285     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6286     goto done;
6287   }
6288 pause:
6289   {
6290     const gchar *reason = gst_flow_get_name (ret);
6291
6292     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6293
6294     gst_pad_pause_task (pad);
6295
6296     /* fatal errors need special actions */
6297     /* check EOS */
6298     if (ret == GST_FLOW_EOS) {
6299       if (qtdemux->n_streams == 0) {
6300         /* we have no streams, post an error */
6301         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6302       }
6303       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6304         gint64 stop;
6305
6306         if ((stop = qtdemux->segment.stop) == -1)
6307           stop = qtdemux->segment.duration;
6308
6309         if (qtdemux->segment.rate >= 0) {
6310           GstMessage *message;
6311           GstEvent *event;
6312
6313           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6314           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6315               GST_FORMAT_TIME, stop);
6316           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6317           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6318             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6319             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6320           }
6321           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6322           gst_qtdemux_push_event (qtdemux, event);
6323         } else {
6324           GstMessage *message;
6325           GstEvent *event;
6326
6327           /*  For Reverse Playback */
6328           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6329           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6330               GST_FORMAT_TIME, qtdemux->segment.start);
6331           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6332               qtdemux->segment.start);
6333           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6334             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6335             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6336           }
6337           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6338           gst_qtdemux_push_event (qtdemux, event);
6339         }
6340       } else {
6341         GstEvent *event;
6342
6343         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6344         event = gst_event_new_eos ();
6345         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6346           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6347         gst_qtdemux_push_event (qtdemux, event);
6348       }
6349     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6350       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6351       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6352     }
6353     goto done;
6354   }
6355 }
6356
6357 /*
6358  * has_next_entry
6359  *
6360  * Returns if there are samples to be played.
6361  */
6362 static gboolean
6363 has_next_entry (GstQTDemux * demux)
6364 {
6365   QtDemuxStream *stream;
6366   GList *iter;
6367
6368   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6369
6370   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6371     stream = QTDEMUX_STREAM (iter->data);
6372
6373     if (stream->sample_index == -1) {
6374       stream->sample_index = 0;
6375       stream->offset_in_sample = 0;
6376     }
6377
6378     if (stream->sample_index >= stream->n_samples) {
6379       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6380       continue;
6381     }
6382     GST_DEBUG_OBJECT (demux, "Found a sample");
6383     return TRUE;
6384   }
6385
6386   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6387   return FALSE;
6388 }
6389
6390 /*
6391  * next_entry_size
6392  *
6393  * Returns the size of the first entry at the current offset.
6394  * If -1, there are none (which means EOS or empty file).
6395  */
6396 static guint64
6397 next_entry_size (GstQTDemux * demux)
6398 {
6399   QtDemuxStream *stream, *target_stream = NULL;
6400   guint64 smalloffs = (guint64) - 1;
6401   QtDemuxSample *sample;
6402   GList *iter;
6403
6404   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6405       demux->offset);
6406
6407   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6408     stream = QTDEMUX_STREAM (iter->data);
6409
6410     if (stream->sample_index == -1) {
6411       stream->sample_index = 0;
6412       stream->offset_in_sample = 0;
6413     }
6414
6415     if (stream->sample_index >= stream->n_samples) {
6416       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6417       continue;
6418     }
6419
6420     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6421       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6422           stream->sample_index);
6423       return -1;
6424     }
6425
6426     sample = &stream->samples[stream->sample_index];
6427
6428     GST_LOG_OBJECT (demux,
6429         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6430         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6431         stream->sample_index, sample->offset, sample->size);
6432
6433     if (((smalloffs == -1)
6434             || (sample->offset < smalloffs)) && (sample->size)) {
6435       smalloffs = sample->offset;
6436       target_stream = stream;
6437     }
6438   }
6439
6440   if (!target_stream)
6441     return -1;
6442
6443   GST_LOG_OBJECT (demux,
6444       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6445       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6446
6447   stream = target_stream;
6448   sample = &stream->samples[stream->sample_index];
6449
6450   if (sample->offset >= demux->offset) {
6451     demux->todrop = sample->offset - demux->offset;
6452     return sample->size + demux->todrop;
6453   }
6454
6455   GST_DEBUG_OBJECT (demux,
6456       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6457   return -1;
6458 }
6459
6460 static void
6461 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6462 {
6463   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6464
6465   gst_element_post_message (GST_ELEMENT_CAST (demux),
6466       gst_message_new_element (GST_OBJECT_CAST (demux),
6467           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6468 }
6469
6470 static gboolean
6471 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6472 {
6473   GstEvent *event;
6474   gboolean res = 0;
6475
6476   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6477
6478   event =
6479       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6480       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6481       GST_SEEK_TYPE_NONE, -1);
6482
6483   /* store seqnum to drop flush events, they don't need to reach downstream */
6484   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6485   res = gst_pad_push_event (demux->sinkpad, event);
6486   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6487
6488   return res;
6489 }
6490
6491 /* check for seekable upstream, above and beyond a mere query */
6492 static void
6493 gst_qtdemux_check_seekability (GstQTDemux * demux)
6494 {
6495   GstQuery *query;
6496   gboolean seekable = FALSE;
6497   gint64 start = -1, stop = -1;
6498
6499   if (demux->upstream_size)
6500     return;
6501
6502   if (demux->upstream_format_is_time)
6503     return;
6504
6505   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6506   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6507     GST_DEBUG_OBJECT (demux, "seeking query failed");
6508     goto done;
6509   }
6510
6511   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6512
6513   /* try harder to query upstream size if we didn't get it the first time */
6514   if (seekable && stop == -1) {
6515     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6516     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6517   }
6518
6519   /* if upstream doesn't know the size, it's likely that it's not seekable in
6520    * practice even if it technically may be seekable */
6521   if (seekable && (start != 0 || stop <= start)) {
6522     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6523     seekable = FALSE;
6524   }
6525
6526 done:
6527   gst_query_unref (query);
6528
6529   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6530       G_GUINT64_FORMAT ")", seekable, start, stop);
6531   demux->upstream_seekable = seekable;
6532   demux->upstream_size = seekable ? stop : -1;
6533 }
6534
6535 static void
6536 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6537 {
6538   g_return_if_fail (bytes <= demux->todrop);
6539
6540   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6541   gst_adapter_flush (demux->adapter, bytes);
6542   demux->neededbytes -= bytes;
6543   demux->offset += bytes;
6544   demux->todrop -= bytes;
6545 }
6546
6547 /* PUSH-MODE only: Send a segment, if not done already. */
6548 static void
6549 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6550 {
6551   if (G_UNLIKELY (demux->need_segment)) {
6552     gint i;
6553     GList *iter;
6554
6555     if (!demux->upstream_format_is_time) {
6556       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6557     } else {
6558       GstEvent *segment_event;
6559       segment_event = gst_event_new_segment (&demux->segment);
6560       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6561         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6562       gst_qtdemux_push_event (demux, segment_event);
6563     }
6564
6565     demux->need_segment = FALSE;
6566
6567     /* clear to send tags on all streams */
6568     for (iter = demux->active_streams, i = 0; iter;
6569         iter = g_list_next (iter), i++) {
6570       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6571       gst_qtdemux_push_tags (demux, stream);
6572       if (CUR_STREAM (stream)->sparse) {
6573         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6574         gst_pad_push_event (stream->pad,
6575             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6576       }
6577     }
6578   }
6579 }
6580
6581 /* Used for push mode only. */
6582 static void
6583 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6584     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6585 {
6586   GstClockTime ts, dur;
6587
6588   ts = pos;
6589   dur =
6590       stream->segments[segment_index].duration - (pos -
6591       stream->segments[segment_index].time);
6592   stream->time_position += dur;
6593
6594   /* Only gaps with a duration of at least one second are propagated.
6595    * Same workaround as in pull mode.
6596    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6597   if (dur >= GST_SECOND) {
6598     GstEvent *gap;
6599     gap = gst_event_new_gap (ts, dur);
6600
6601     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6602         "segment: %" GST_PTR_FORMAT, gap);
6603     gst_pad_push_event (stream->pad, gap);
6604   }
6605 }
6606
6607 static GstFlowReturn
6608 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6609 {
6610   GstQTDemux *demux;
6611
6612   demux = GST_QTDEMUX (parent);
6613
6614   GST_DEBUG_OBJECT (demux,
6615       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6616       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6617       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6618       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6619       gst_buffer_get_size (inbuf), demux->offset);
6620
6621   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6622     gboolean is_gap_input = FALSE;
6623     GList *iter;
6624
6625     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6626
6627     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6628       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6629     }
6630
6631     /* Check if we can land back on our feet in the case where upstream is
6632      * handling the seeking/pushing of samples with gaps in between (like
6633      * in the case of trick-mode DASH for example) */
6634     if (demux->upstream_format_is_time
6635         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6636       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6637         guint32 res;
6638         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6639         GST_LOG_OBJECT (demux,
6640             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6641             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6642         res =
6643             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6644             stream, GST_BUFFER_OFFSET (inbuf));
6645         if (res != -1) {
6646           QtDemuxSample *sample = &stream->samples[res];
6647           GST_LOG_OBJECT (demux,
6648               "Checking if sample %d from track-id %u is valid (offset:%"
6649               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6650               stream->track_id, sample->offset, sample->size);
6651           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6652             GST_LOG_OBJECT (demux,
6653                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6654                 res);
6655             is_gap_input = TRUE;
6656             /* We can go back to standard playback mode */
6657             demux->state = QTDEMUX_STATE_MOVIE;
6658             /* Remember which sample this stream is at */
6659             stream->sample_index = res;
6660             /* Finally update all push-based values to the expected values */
6661             demux->neededbytes = stream->samples[res].size;
6662             demux->offset = GST_BUFFER_OFFSET (inbuf);
6663             demux->mdatleft =
6664                 demux->mdatsize - demux->offset + demux->mdatoffset;
6665             demux->todrop = 0;
6666           }
6667         }
6668       }
6669       if (!is_gap_input) {
6670         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6671         /* Reset state if it's a real discont */
6672         demux->neededbytes = 16;
6673         demux->state = QTDEMUX_STATE_INITIAL;
6674         demux->offset = GST_BUFFER_OFFSET (inbuf);
6675         gst_adapter_clear (demux->adapter);
6676       }
6677     }
6678     /* Reverse fragmented playback, need to flush all we have before
6679      * consuming a new fragment.
6680      * The samples array have the timestamps calculated by accumulating the
6681      * durations but this won't work for reverse playback of fragments as
6682      * the timestamps of a subsequent fragment should be smaller than the
6683      * previously received one. */
6684     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6685       gst_qtdemux_process_adapter (demux, TRUE);
6686       g_list_foreach (demux->active_streams,
6687           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6688     }
6689   }
6690
6691   gst_adapter_push (demux->adapter, inbuf);
6692
6693   GST_DEBUG_OBJECT (demux,
6694       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6695       demux->neededbytes, gst_adapter_available (demux->adapter));
6696
6697   return gst_qtdemux_process_adapter (demux, FALSE);
6698 }
6699
6700 static GstFlowReturn
6701 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6702 {
6703   GstFlowReturn ret = GST_FLOW_OK;
6704
6705   /* we never really mean to buffer that much */
6706   if (demux->neededbytes == -1) {
6707     goto eos;
6708   }
6709
6710   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6711       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6712
6713 #ifndef GST_DISABLE_GST_DEBUG
6714     {
6715       guint64 discont_offset, distance_from_discont;
6716
6717       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6718       distance_from_discont =
6719           gst_adapter_distance_from_discont (demux->adapter);
6720
6721       GST_DEBUG_OBJECT (demux,
6722           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6723           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6724           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6725           demux->offset, discont_offset, distance_from_discont);
6726     }
6727 #endif
6728
6729     switch (demux->state) {
6730       case QTDEMUX_STATE_INITIAL:{
6731         const guint8 *data;
6732         guint32 fourcc;
6733         guint64 size;
6734
6735         gst_qtdemux_check_seekability (demux);
6736
6737         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6738
6739         /* get fourcc/length, set neededbytes */
6740         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6741             &size, &fourcc);
6742         gst_adapter_unmap (demux->adapter);
6743         data = NULL;
6744         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6745             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6746         if (size == 0) {
6747           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6748               (_("This file is invalid and cannot be played.")),
6749               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6750                   GST_FOURCC_ARGS (fourcc)));
6751           ret = GST_FLOW_ERROR;
6752           break;
6753         }
6754         if (fourcc == FOURCC_mdat) {
6755           gint next_entry = next_entry_size (demux);
6756           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6757             /* we have the headers, start playback */
6758             demux->state = QTDEMUX_STATE_MOVIE;
6759             demux->neededbytes = next_entry;
6760             demux->mdatleft = size;
6761             demux->mdatsize = demux->mdatleft;
6762           } else {
6763             /* no headers yet, try to get them */
6764             guint bs;
6765             gboolean res;
6766             guint64 old, target;
6767
6768           buffer_data:
6769             old = demux->offset;
6770             target = old + size;
6771
6772             /* try to jump over the atom with a seek */
6773             /* only bother if it seems worth doing so,
6774              * and avoids possible upstream/server problems */
6775             if (demux->upstream_seekable &&
6776                 demux->upstream_size > 4 * (1 << 20)) {
6777               res = qtdemux_seek_offset (demux, target);
6778             } else {
6779               GST_DEBUG_OBJECT (demux, "skipping seek");
6780               res = FALSE;
6781             }
6782
6783             if (res) {
6784               GST_DEBUG_OBJECT (demux, "seek success");
6785               /* remember the offset fo the first mdat so we can seek back to it
6786                * after we have the headers */
6787               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6788                 demux->first_mdat = old;
6789                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6790                     demux->first_mdat);
6791               }
6792               /* seek worked, continue reading */
6793               demux->offset = target;
6794               demux->neededbytes = 16;
6795               demux->state = QTDEMUX_STATE_INITIAL;
6796             } else {
6797               /* seek failed, need to buffer */
6798               demux->offset = old;
6799               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6800               /* there may be multiple mdat (or alike) buffers */
6801               /* sanity check */
6802               if (demux->mdatbuffer)
6803                 bs = gst_buffer_get_size (demux->mdatbuffer);
6804               else
6805                 bs = 0;
6806               if (size + bs > 10 * (1 << 20))
6807                 goto no_moov;
6808               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6809               demux->neededbytes = size;
6810               if (!demux->mdatbuffer)
6811                 demux->mdatoffset = demux->offset;
6812             }
6813           }
6814         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6815           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6816               (_("This file is invalid and cannot be played.")),
6817               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6818                   GST_FOURCC_ARGS (fourcc), size));
6819           ret = GST_FLOW_ERROR;
6820           break;
6821         } else {
6822           /* this means we already started buffering and still no moov header,
6823            * let's continue buffering everything till we get moov */
6824           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6825                   || fourcc == FOURCC_moof))
6826             goto buffer_data;
6827           demux->neededbytes = size;
6828           demux->state = QTDEMUX_STATE_HEADER;
6829         }
6830         break;
6831       }
6832       case QTDEMUX_STATE_HEADER:{
6833         const guint8 *data;
6834         guint32 fourcc;
6835
6836         GST_DEBUG_OBJECT (demux, "In header");
6837
6838         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6839
6840         /* parse the header */
6841         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6842             &fourcc);
6843         if (fourcc == FOURCC_moov) {
6844           /* in usual fragmented setup we could try to scan for more
6845            * and end up at the the moov (after mdat) again */
6846           if (demux->got_moov && demux->n_streams > 0 &&
6847               (!demux->fragmented
6848                   || demux->last_moov_offset == demux->offset)) {
6849             GST_DEBUG_OBJECT (demux,
6850                 "Skipping moov atom as we have (this) one already");
6851           } else {
6852             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6853
6854             if (demux->got_moov && demux->fragmented) {
6855               GST_DEBUG_OBJECT (demux,
6856                   "Got a second moov, clean up data from old one");
6857               if (demux->moov_node_compressed) {
6858                 g_node_destroy (demux->moov_node_compressed);
6859                 if (demux->moov_node)
6860                   g_free (demux->moov_node->data);
6861               }
6862               demux->moov_node_compressed = NULL;
6863               if (demux->moov_node)
6864                 g_node_destroy (demux->moov_node);
6865               demux->moov_node = NULL;
6866             }
6867
6868             demux->last_moov_offset = demux->offset;
6869
6870             /* Update streams with new moov */
6871             demux->old_streams =
6872                 g_list_concat (demux->old_streams, demux->active_streams);
6873             demux->active_streams = NULL;
6874
6875             qtdemux_parse_moov (demux, data, demux->neededbytes);
6876             qtdemux_node_dump (demux, demux->moov_node);
6877             qtdemux_parse_tree (demux);
6878             qtdemux_prepare_streams (demux);
6879             QTDEMUX_EXPOSE_LOCK (demux);
6880             qtdemux_expose_streams (demux);
6881             QTDEMUX_EXPOSE_UNLOCK (demux);
6882
6883             demux->got_moov = TRUE;
6884
6885             gst_qtdemux_check_send_pending_segment (demux);
6886
6887             if (demux->moov_node_compressed) {
6888               g_node_destroy (demux->moov_node_compressed);
6889               g_free (demux->moov_node->data);
6890             }
6891             demux->moov_node_compressed = NULL;
6892             g_node_destroy (demux->moov_node);
6893             demux->moov_node = NULL;
6894             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6895           }
6896         } else if (fourcc == FOURCC_moof) {
6897           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6898             guint64 dist = 0;
6899             GstClockTime prev_pts;
6900             guint64 prev_offset;
6901             guint64 adapter_discont_offset, adapter_discont_dist;
6902
6903             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6904
6905             /*
6906              * The timestamp of the moof buffer is relevant as some scenarios
6907              * won't have the initial timestamp in the atoms. Whenever a new
6908              * buffer has started, we get that buffer's PTS and use it as a base
6909              * timestamp for the trun entries.
6910              *
6911              * To keep track of the current buffer timestamp and starting point
6912              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6913              * from the beggining of the buffer, with the distance and demux->offset
6914              * we know if it is still the same buffer or not.
6915              */
6916             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6917             prev_offset = demux->offset - dist;
6918             if (demux->fragment_start_offset == -1
6919                 || prev_offset > demux->fragment_start_offset) {
6920               demux->fragment_start_offset = prev_offset;
6921               demux->fragment_start = prev_pts;
6922               GST_DEBUG_OBJECT (demux,
6923                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6924                   GST_TIME_FORMAT, demux->fragment_start_offset,
6925                   GST_TIME_ARGS (demux->fragment_start));
6926             }
6927
6928             /* We can't use prev_offset() here because this would require
6929              * upstream to set consistent and correct offsets on all buffers
6930              * since the discont. Nothing ever did that in the past and we
6931              * would break backwards compatibility here then.
6932              * Instead take the offset we had at the last discont and count
6933              * the bytes from there. This works with old code as there would
6934              * be no discont between moov and moof, and also works with
6935              * adaptivedemux which correctly sets offset and will set the
6936              * DISCONT flag accordingly when needed.
6937              *
6938              * We also only do this for upstream TIME segments as otherwise
6939              * there are potential backwards compatibility problems with
6940              * seeking in PUSH mode and upstream providing inconsistent
6941              * timestamps. */
6942             adapter_discont_offset =
6943                 gst_adapter_offset_at_discont (demux->adapter);
6944             adapter_discont_dist =
6945                 gst_adapter_distance_from_discont (demux->adapter);
6946
6947             GST_DEBUG_OBJECT (demux,
6948                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6949                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6950                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6951
6952             if (demux->upstream_format_is_time) {
6953               demux->moof_offset = adapter_discont_offset;
6954               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6955                 demux->moof_offset += adapter_discont_dist;
6956               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6957                 demux->moof_offset = demux->offset;
6958             } else {
6959               demux->moof_offset = demux->offset;
6960             }
6961
6962             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6963                     demux->moof_offset, NULL)) {
6964               gst_adapter_unmap (demux->adapter);
6965               ret = GST_FLOW_ERROR;
6966               goto done;
6967             }
6968
6969             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6970             if (demux->mss_mode && !demux->exposed) {
6971               QTDEMUX_EXPOSE_LOCK (demux);
6972               qtdemux_expose_streams (demux);
6973               QTDEMUX_EXPOSE_UNLOCK (demux);
6974             }
6975
6976             gst_qtdemux_check_send_pending_segment (demux);
6977           } else {
6978             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6979           }
6980         } else if (fourcc == FOURCC_ftyp) {
6981           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6982           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6983         } else if (fourcc == FOURCC_uuid) {
6984           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6985           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6986         } else if (fourcc == FOURCC_sidx) {
6987           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6988           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6989         } else {
6990           switch (fourcc) {
6991             case FOURCC_styp:
6992               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6993                * FALLTHROUGH */
6994             case FOURCC_skip:
6995             case FOURCC_free:
6996               /* [free] and [skip] are padding atoms */
6997               GST_DEBUG_OBJECT (demux,
6998                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6999                   GST_FOURCC_ARGS (fourcc));
7000               break;
7001             default:
7002               GST_WARNING_OBJECT (demux,
7003                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7004                   GST_FOURCC_ARGS (fourcc));
7005               /* Let's jump that one and go back to initial state */
7006               break;
7007           }
7008         }
7009         gst_adapter_unmap (demux->adapter);
7010         data = NULL;
7011
7012         if (demux->mdatbuffer && demux->n_streams) {
7013           gsize remaining_data_size = 0;
7014
7015           /* the mdat was before the header */
7016           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7017               demux->n_streams, demux->mdatbuffer);
7018           /* restore our adapter/offset view of things with upstream;
7019            * put preceding buffered data ahead of current moov data.
7020            * This should also handle evil mdat, moov, mdat cases and alike */
7021           gst_adapter_flush (demux->adapter, demux->neededbytes);
7022
7023           /* Store any remaining data after the mdat for later usage */
7024           remaining_data_size = gst_adapter_available (demux->adapter);
7025           if (remaining_data_size > 0) {
7026             g_assert (demux->restoredata_buffer == NULL);
7027             demux->restoredata_buffer =
7028                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7029             demux->restoredata_offset = demux->offset + demux->neededbytes;
7030             GST_DEBUG_OBJECT (demux,
7031                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7032                 G_GUINT64_FORMAT, remaining_data_size,
7033                 demux->restoredata_offset);
7034           }
7035
7036           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7037           demux->mdatbuffer = NULL;
7038           demux->offset = demux->mdatoffset;
7039           demux->neededbytes = next_entry_size (demux);
7040           demux->state = QTDEMUX_STATE_MOVIE;
7041           demux->mdatleft = gst_adapter_available (demux->adapter);
7042           demux->mdatsize = demux->mdatleft;
7043         } else {
7044           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7045           gst_adapter_flush (demux->adapter, demux->neededbytes);
7046
7047           /* only go back to the mdat if there are samples to play */
7048           if (demux->got_moov && demux->first_mdat != -1
7049               && has_next_entry (demux)) {
7050             gboolean res;
7051
7052             /* we need to seek back */
7053             res = qtdemux_seek_offset (demux, demux->first_mdat);
7054             if (res) {
7055               demux->offset = demux->first_mdat;
7056             } else {
7057               GST_DEBUG_OBJECT (demux, "Seek back failed");
7058             }
7059           } else {
7060             demux->offset += demux->neededbytes;
7061           }
7062           demux->neededbytes = 16;
7063           demux->state = QTDEMUX_STATE_INITIAL;
7064         }
7065
7066         break;
7067       }
7068       case QTDEMUX_STATE_BUFFER_MDAT:{
7069         GstBuffer *buf;
7070         guint8 fourcc[4];
7071
7072         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7073             demux->offset);
7074         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7075         gst_buffer_extract (buf, 0, fourcc, 4);
7076         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7077             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7078         if (demux->mdatbuffer)
7079           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7080         else
7081           demux->mdatbuffer = buf;
7082         demux->offset += demux->neededbytes;
7083         demux->neededbytes = 16;
7084         demux->state = QTDEMUX_STATE_INITIAL;
7085         gst_qtdemux_post_progress (demux, 1, 1);
7086
7087         break;
7088       }
7089       case QTDEMUX_STATE_MOVIE:{
7090         QtDemuxStream *stream = NULL;
7091         QtDemuxSample *sample;
7092         GstClockTime dts, pts, duration;
7093         gboolean keyframe;
7094         GList *iter;
7095
7096         GST_DEBUG_OBJECT (demux,
7097             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7098
7099         if (demux->fragmented) {
7100           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7101               demux->mdatleft);
7102           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7103             /* if needed data starts within this atom,
7104              * then it should not exceed this atom */
7105             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7106               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7107                   (_("This file is invalid and cannot be played.")),
7108                   ("sample data crosses atom boundary"));
7109               ret = GST_FLOW_ERROR;
7110               break;
7111             }
7112             demux->mdatleft -= demux->neededbytes;
7113           } else {
7114             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7115             /* so we are dropping more than left in this atom */
7116             gst_qtdemux_drop_data (demux, demux->mdatleft);
7117             demux->mdatleft = 0;
7118
7119             /* need to resume atom parsing so we do not miss any other pieces */
7120             demux->state = QTDEMUX_STATE_INITIAL;
7121             demux->neededbytes = 16;
7122
7123             /* check if there was any stored post mdat data from previous buffers */
7124             if (demux->restoredata_buffer) {
7125               g_assert (gst_adapter_available (demux->adapter) == 0);
7126
7127               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7128               demux->restoredata_buffer = NULL;
7129               demux->offset = demux->restoredata_offset;
7130             }
7131
7132             break;
7133           }
7134         }
7135
7136         if (demux->todrop) {
7137           if (demux->cenc_aux_info_offset > 0) {
7138             GstByteReader br;
7139             const guint8 *data;
7140
7141             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7142             data = gst_adapter_map (demux->adapter, demux->todrop);
7143             gst_byte_reader_init (&br, data + 8, demux->todrop);
7144             if (!qtdemux_parse_cenc_aux_info (demux,
7145                     QTDEMUX_FIRST_STREAM (demux), &br,
7146                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7147               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7148               ret = GST_FLOW_ERROR;
7149               gst_adapter_unmap (demux->adapter);
7150               g_free (demux->cenc_aux_info_sizes);
7151               demux->cenc_aux_info_sizes = NULL;
7152               goto done;
7153             }
7154             demux->cenc_aux_info_offset = 0;
7155             g_free (demux->cenc_aux_info_sizes);
7156             demux->cenc_aux_info_sizes = NULL;
7157             gst_adapter_unmap (demux->adapter);
7158           }
7159           gst_qtdemux_drop_data (demux, demux->todrop);
7160         }
7161
7162         /* first buffer? */
7163         /* initial newsegment sent here after having added pads,
7164          * possible others in sink_event */
7165         gst_qtdemux_check_send_pending_segment (demux);
7166
7167         /* Figure out which stream this packet belongs to */
7168         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7169           stream = QTDEMUX_STREAM (iter->data);
7170           if (stream->sample_index >= stream->n_samples) {
7171             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7172             stream = NULL;
7173             continue;
7174           }
7175           GST_LOG_OBJECT (demux,
7176               "Checking track-id %u (sample_index:%d / offset:%"
7177               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7178               stream->sample_index,
7179               stream->samples[stream->sample_index].offset,
7180               stream->samples[stream->sample_index].size);
7181
7182           if (stream->samples[stream->sample_index].offset == demux->offset)
7183             break;
7184         }
7185
7186         if (G_UNLIKELY (stream == NULL))
7187           goto unknown_stream;
7188
7189         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7190
7191         if (stream->new_caps) {
7192           gst_qtdemux_configure_stream (demux, stream);
7193         }
7194
7195         /* Put data in a buffer, set timestamps, caps, ... */
7196         sample = &stream->samples[stream->sample_index];
7197
7198         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7199           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7200               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7201
7202           dts = QTSAMPLE_DTS (stream, sample);
7203           pts = QTSAMPLE_PTS (stream, sample);
7204           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7205           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7206
7207           /* check for segment end */
7208           if (G_UNLIKELY (demux->segment.stop != -1
7209                   && demux->segment.stop <= pts && stream->on_keyframe)
7210               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7211             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7212             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7213
7214             /* skip this data, stream is EOS */
7215             gst_adapter_flush (demux->adapter, demux->neededbytes);
7216             demux->offset += demux->neededbytes;
7217
7218             /* check if all streams are eos */
7219             ret = GST_FLOW_EOS;
7220             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7221               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7222                 ret = GST_FLOW_OK;
7223                 break;
7224               }
7225             }
7226           } else {
7227             GstBuffer *outbuf;
7228
7229             outbuf =
7230                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7231
7232             /* FIXME: should either be an assert or a plain check */
7233             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7234
7235             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7236                 dts, pts, duration, keyframe, dts, demux->offset);
7237           }
7238
7239           /* combine flows */
7240           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7241         } else {
7242           /* skip this data, stream is EOS */
7243           gst_adapter_flush (demux->adapter, demux->neededbytes);
7244         }
7245
7246         stream->sample_index++;
7247         stream->offset_in_sample = 0;
7248
7249         /* update current offset and figure out size of next buffer */
7250         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7251             demux->offset, demux->neededbytes);
7252         demux->offset += demux->neededbytes;
7253         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7254             demux->offset);
7255
7256
7257         if (ret == GST_FLOW_EOS) {
7258           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7259           demux->neededbytes = -1;
7260           goto eos;
7261         }
7262
7263         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7264           if (demux->fragmented) {
7265             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7266             /* there may be more to follow, only finish this atom */
7267             demux->todrop = demux->mdatleft;
7268             demux->neededbytes = demux->todrop;
7269             break;
7270           }
7271           goto eos;
7272         }
7273         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7274           goto non_ok_unlinked_flow;
7275         }
7276         break;
7277       }
7278       default:
7279         goto invalid_state;
7280     }
7281   }
7282
7283   /* when buffering movie data, at least show user something is happening */
7284   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7285       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7286     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7287         demux->neededbytes);
7288   }
7289 done:
7290
7291   return ret;
7292
7293   /* ERRORS */
7294 non_ok_unlinked_flow:
7295   {
7296     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7297         gst_flow_get_name (ret));
7298     return ret;
7299   }
7300 unknown_stream:
7301   {
7302     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7303     ret = GST_FLOW_ERROR;
7304     goto done;
7305   }
7306 eos:
7307   {
7308     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7309     ret = GST_FLOW_EOS;
7310     goto done;
7311   }
7312 invalid_state:
7313   {
7314     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7315         (NULL), ("qtdemuxer invalid state %d", demux->state));
7316     ret = GST_FLOW_ERROR;
7317     goto done;
7318   }
7319 no_moov:
7320   {
7321     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7322         (NULL), ("no 'moov' atom within the first 10 MB"));
7323     ret = GST_FLOW_ERROR;
7324     goto done;
7325   }
7326 }
7327
7328 static gboolean
7329 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7330 {
7331   GstQuery *query;
7332   gboolean pull_mode;
7333
7334   query = gst_query_new_scheduling ();
7335
7336   if (!gst_pad_peer_query (sinkpad, query)) {
7337     gst_query_unref (query);
7338     goto activate_push;
7339   }
7340
7341   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7342       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7343   gst_query_unref (query);
7344
7345   if (!pull_mode)
7346     goto activate_push;
7347
7348   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7349   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7350
7351 activate_push:
7352   {
7353     GST_DEBUG_OBJECT (sinkpad, "activating push");
7354     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7355   }
7356 }
7357
7358 static gboolean
7359 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7360     GstPadMode mode, gboolean active)
7361 {
7362   gboolean res;
7363   GstQTDemux *demux = GST_QTDEMUX (parent);
7364
7365   switch (mode) {
7366     case GST_PAD_MODE_PUSH:
7367       demux->pullbased = FALSE;
7368       res = TRUE;
7369       break;
7370     case GST_PAD_MODE_PULL:
7371       if (active) {
7372         demux->pullbased = TRUE;
7373         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7374             sinkpad, NULL);
7375       } else {
7376         res = gst_pad_stop_task (sinkpad);
7377       }
7378       break;
7379     default:
7380       res = FALSE;
7381       break;
7382   }
7383   return res;
7384 }
7385
7386 #ifdef HAVE_ZLIB
7387 static void *
7388 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7389 {
7390   guint8 *buffer;
7391   z_stream z;
7392   int ret;
7393
7394   memset (&z, 0, sizeof (z));
7395   z.zalloc = NULL;
7396   z.zfree = NULL;
7397   z.opaque = NULL;
7398
7399   if ((ret = inflateInit (&z)) != Z_OK) {
7400     GST_ERROR ("inflateInit() returned %d", ret);
7401     return NULL;
7402   }
7403
7404   z.next_in = z_buffer;
7405   z.avail_in = z_length;
7406
7407   buffer = (guint8 *) g_malloc (*length);
7408   z.avail_out = *length;
7409   z.next_out = (Bytef *) buffer;
7410   do {
7411     ret = inflate (&z, Z_NO_FLUSH);
7412     if (ret == Z_STREAM_END) {
7413       break;
7414     } else if (ret != Z_OK) {
7415       GST_WARNING ("inflate() returned %d", ret);
7416       break;
7417     }
7418
7419     *length += 4096;
7420     buffer = (guint8 *) g_realloc (buffer, *length);
7421     z.next_out = (Bytef *) (buffer + z.total_out);
7422     z.avail_out += 4096;
7423   } while (z.avail_in > 0);
7424
7425   if (ret != Z_STREAM_END) {
7426     g_free (buffer);
7427     buffer = NULL;
7428     *length = 0;
7429   } else {
7430     *length = z.total_out;
7431   }
7432
7433   inflateEnd (&z);
7434
7435   return buffer;
7436 }
7437 #endif /* HAVE_ZLIB */
7438
7439 static gboolean
7440 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7441 {
7442   GNode *cmov;
7443
7444   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7445
7446   /* counts as header data */
7447   qtdemux->header_size += length;
7448
7449   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7450   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7451
7452   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7453   if (cmov) {
7454     guint32 method;
7455     GNode *dcom;
7456     GNode *cmvd;
7457     guint32 dcom_len;
7458
7459     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7460     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7461     if (dcom == NULL || cmvd == NULL)
7462       goto invalid_compression;
7463
7464     dcom_len = QT_UINT32 (dcom->data);
7465     if (dcom_len < 12)
7466       goto invalid_compression;
7467
7468     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7469     switch (method) {
7470 #ifdef HAVE_ZLIB
7471       case FOURCC_zlib:{
7472         guint uncompressed_length;
7473         guint compressed_length;
7474         guint8 *buf;
7475         guint32 cmvd_len;
7476
7477         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7478         if (cmvd_len < 12)
7479           goto invalid_compression;
7480
7481         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7482         compressed_length = cmvd_len - 12;
7483         GST_LOG ("length = %u", uncompressed_length);
7484
7485         buf =
7486             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7487             compressed_length, &uncompressed_length);
7488
7489         if (buf) {
7490           qtdemux->moov_node_compressed = qtdemux->moov_node;
7491           qtdemux->moov_node = g_node_new (buf);
7492
7493           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7494               uncompressed_length);
7495         }
7496         break;
7497       }
7498 #endif /* HAVE_ZLIB */
7499       default:
7500         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7501             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7502         break;
7503     }
7504   }
7505   return TRUE;
7506
7507   /* ERRORS */
7508 invalid_compression:
7509   {
7510     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7511     return FALSE;
7512   }
7513 }
7514
7515 static gboolean
7516 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7517     const guint8 * end)
7518 {
7519   while (G_UNLIKELY (buf < end)) {
7520     GNode *child;
7521     guint32 len;
7522
7523     if (G_UNLIKELY (buf + 4 > end)) {
7524       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7525       break;
7526     }
7527     len = QT_UINT32 (buf);
7528     if (G_UNLIKELY (len == 0)) {
7529       GST_LOG_OBJECT (qtdemux, "empty container");
7530       break;
7531     }
7532     if (G_UNLIKELY (len < 8)) {
7533       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7534       break;
7535     }
7536     if (G_UNLIKELY (len > (end - buf))) {
7537       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7538           (gint) (end - buf));
7539       break;
7540     }
7541
7542     child = g_node_new ((guint8 *) buf);
7543     g_node_append (node, child);
7544     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7545     qtdemux_parse_node (qtdemux, child, buf, len);
7546
7547     buf += len;
7548   }
7549   return TRUE;
7550 }
7551
7552 static gboolean
7553 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7554     GNode * xdxt)
7555 {
7556   int len = QT_UINT32 (xdxt->data);
7557   guint8 *buf = xdxt->data;
7558   guint8 *end = buf + len;
7559   GstBuffer *buffer;
7560
7561   /* skip size and type */
7562   buf += 8;
7563   end -= 8;
7564
7565   while (buf < end) {
7566     gint size;
7567     guint32 type;
7568
7569     size = QT_UINT32 (buf);
7570     type = QT_FOURCC (buf + 4);
7571
7572     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7573
7574     if (buf + size > end || size <= 0)
7575       break;
7576
7577     buf += 8;
7578     size -= 8;
7579
7580     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7581         GST_FOURCC_ARGS (type));
7582
7583     switch (type) {
7584       case FOURCC_tCtH:
7585         buffer = gst_buffer_new_and_alloc (size);
7586         gst_buffer_fill (buffer, 0, buf, size);
7587         stream->buffers = g_slist_append (stream->buffers, buffer);
7588         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7589         break;
7590       case FOURCC_tCt_:
7591         buffer = gst_buffer_new_and_alloc (size);
7592         gst_buffer_fill (buffer, 0, buf, size);
7593         stream->buffers = g_slist_append (stream->buffers, buffer);
7594         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7595         break;
7596       case FOURCC_tCtC:
7597         buffer = gst_buffer_new_and_alloc (size);
7598         gst_buffer_fill (buffer, 0, buf, size);
7599         stream->buffers = g_slist_append (stream->buffers, buffer);
7600         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7601         break;
7602       default:
7603         GST_WARNING_OBJECT (qtdemux,
7604             "unknown theora cookie %" GST_FOURCC_FORMAT,
7605             GST_FOURCC_ARGS (type));
7606         break;
7607     }
7608     buf += size;
7609   }
7610   return TRUE;
7611 }
7612
7613 static gboolean
7614 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7615     guint length)
7616 {
7617   guint32 fourcc = 0;
7618   guint32 node_length = 0;
7619   const QtNodeType *type;
7620   const guint8 *end;
7621
7622   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7623
7624   if (G_UNLIKELY (length < 8))
7625     goto not_enough_data;
7626
7627   node_length = QT_UINT32 (buffer);
7628   fourcc = QT_FOURCC (buffer + 4);
7629
7630   /* ignore empty nodes */
7631   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7632     return TRUE;
7633
7634   type = qtdemux_type_get (fourcc);
7635
7636   end = buffer + length;
7637
7638   GST_LOG_OBJECT (qtdemux,
7639       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7640       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7641
7642   if (node_length > length)
7643     goto broken_atom_size;
7644
7645   if (type->flags & QT_FLAG_CONTAINER) {
7646     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7647   } else {
7648     switch (fourcc) {
7649       case FOURCC_stsd:
7650       {
7651         if (node_length < 20) {
7652           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7653           break;
7654         }
7655         GST_DEBUG_OBJECT (qtdemux,
7656             "parsing stsd (sample table, sample description) atom");
7657         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7658         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7659         break;
7660       }
7661       case FOURCC_mp4a:
7662       case FOURCC_alac:
7663       case FOURCC_fLaC:
7664       {
7665         guint32 version;
7666         guint32 offset;
7667         guint min_size;
7668
7669         /* also read alac (or whatever) in stead of mp4a in the following,
7670          * since a similar layout is used in other cases as well */
7671         if (fourcc == FOURCC_mp4a)
7672           min_size = 20;
7673         else if (fourcc == FOURCC_fLaC)
7674           min_size = 86;
7675         else
7676           min_size = 40;
7677
7678         /* There are two things we might encounter here: a true mp4a atom, and
7679            an mp4a entry in an stsd atom. The latter is what we're interested
7680            in, and it looks like an atom, but isn't really one. The true mp4a
7681            atom is short, so we detect it based on length here. */
7682         if (length < min_size) {
7683           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7684               GST_FOURCC_ARGS (fourcc));
7685           break;
7686         }
7687
7688         /* 'version' here is the sound sample description version. Types 0 and
7689            1 are documented in the QTFF reference, but type 2 is not: it's
7690            described in Apple header files instead (struct SoundDescriptionV2
7691            in Movies.h) */
7692         version = QT_UINT16 (buffer + 16);
7693
7694         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7695             GST_FOURCC_ARGS (fourcc), version);
7696
7697         /* parse any esds descriptors */
7698         switch (version) {
7699           case 0:
7700             offset = 0x24;
7701             break;
7702           case 1:
7703             offset = 0x34;
7704             break;
7705           case 2:
7706             offset = 0x48;
7707             break;
7708           default:
7709             GST_WARNING_OBJECT (qtdemux,
7710                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7711                 GST_FOURCC_ARGS (fourcc), version);
7712             offset = 0;
7713             break;
7714         }
7715         if (offset)
7716           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7717         break;
7718       }
7719       case FOURCC_mp4v:
7720       case FOURCC_MP4V:
7721       case FOURCC_fmp4:
7722       case FOURCC_FMP4:
7723       case FOURCC_apcs:
7724       case FOURCC_apch:
7725       case FOURCC_apcn:
7726       case FOURCC_apco:
7727       case FOURCC_ap4h:
7728       case FOURCC_xvid:
7729       case FOURCC_XVID:
7730       case FOURCC_H264:
7731       case FOURCC_avc1:
7732       case FOURCC_avc3:
7733       case FOURCC_H265:
7734       case FOURCC_hvc1:
7735       case FOURCC_hev1:
7736       case FOURCC_mjp2:
7737       case FOURCC_encv:
7738       {
7739         guint32 version;
7740         guint32 str_len;
7741
7742         /* codec_data is contained inside these atoms, which all have
7743          * the same format. */
7744         /* video sample description size is 86 bytes without extension.
7745          * node_length have to be bigger than 86 bytes because video sample
7746          * description can include extenstions such as esds, fiel, glbl, etc. */
7747         if (node_length < 86) {
7748           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7749               " sample description length too short (%u < 86)",
7750               GST_FOURCC_ARGS (fourcc), node_length);
7751           break;
7752         }
7753
7754         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7755             GST_FOURCC_ARGS (fourcc));
7756
7757         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7758          *              its data format.
7759          * revision level (2 bytes) : must be set to 0. */
7760         version = QT_UINT32 (buffer + 16);
7761         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7762
7763         /* compressor name : PASCAL string and informative purposes
7764          * first byte : the number of bytes to be displayed.
7765          *              it has to be less than 32 because it is reserved
7766          *              space of 32 bytes total including itself. */
7767         str_len = QT_UINT8 (buffer + 50);
7768         if (str_len < 32)
7769           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7770               (char *) buffer + 51);
7771         else
7772           GST_WARNING_OBJECT (qtdemux,
7773               "compressorname length too big (%u > 31)", str_len);
7774
7775         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7776             end - buffer);
7777         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7778         break;
7779       }
7780       case FOURCC_meta:
7781       {
7782         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7783
7784         /* You are reading this correctly. QTFF specifies that the
7785          * metadata atom is a short atom, whereas ISO BMFF specifies
7786          * it's a full atom. But since so many people are doing things
7787          * differently, we actually peek into the atom to see which
7788          * variant it is */
7789         if (length < 16) {
7790           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7791               GST_FOURCC_ARGS (fourcc));
7792           break;
7793         }
7794         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7795           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7796            * starts with a 'hdlr' atom */
7797           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7798         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7799           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7800            * with version/flags both set to zero */
7801           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7802         } else
7803           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7804         break;
7805       }
7806       case FOURCC_mp4s:
7807       {
7808         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7809         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7810         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7811         break;
7812       }
7813       case FOURCC_XiTh:
7814       {
7815         guint32 version;
7816         guint32 offset;
7817
7818         if (length < 16) {
7819           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7820               GST_FOURCC_ARGS (fourcc));
7821           break;
7822         }
7823
7824         version = QT_UINT32 (buffer + 12);
7825         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7826
7827         switch (version) {
7828           case 0x00000001:
7829             offset = 0x62;
7830             break;
7831           default:
7832             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7833             offset = 0;
7834             break;
7835         }
7836         if (offset) {
7837           if (length < offset) {
7838             GST_WARNING_OBJECT (qtdemux,
7839                 "skipping too small %" GST_FOURCC_FORMAT " box",
7840                 GST_FOURCC_ARGS (fourcc));
7841             break;
7842           }
7843           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7844         }
7845         break;
7846       }
7847       case FOURCC_in24:
7848       {
7849         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7850         break;
7851       }
7852       case FOURCC_uuid:
7853       {
7854         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7855         break;
7856       }
7857       case FOURCC_enca:
7858       {
7859         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7860         break;
7861       }
7862       default:
7863         if (!strcmp (type->name, "unknown"))
7864           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7865         break;
7866     }
7867   }
7868   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7869       GST_FOURCC_ARGS (fourcc));
7870   return TRUE;
7871
7872 /* ERRORS */
7873 not_enough_data:
7874   {
7875     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7876         (_("This file is corrupt and cannot be played.")),
7877         ("Not enough data for an atom header, got only %u bytes", length));
7878     return FALSE;
7879   }
7880 broken_atom_size:
7881   {
7882     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7883         (_("This file is corrupt and cannot be played.")),
7884         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7885             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7886             length));
7887     return FALSE;
7888   }
7889 }
7890
7891 static GNode *
7892 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7893 {
7894   GNode *child;
7895   guint8 *buffer;
7896   guint32 child_fourcc;
7897
7898   for (child = g_node_first_child (node); child;
7899       child = g_node_next_sibling (child)) {
7900     buffer = (guint8 *) child->data;
7901
7902     child_fourcc = QT_FOURCC (buffer + 4);
7903
7904     if (G_UNLIKELY (child_fourcc == fourcc)) {
7905       return child;
7906     }
7907   }
7908   return NULL;
7909 }
7910
7911 static GNode *
7912 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7913     GstByteReader * parser)
7914 {
7915   GNode *child;
7916   guint8 *buffer;
7917   guint32 child_fourcc, child_len;
7918
7919   for (child = g_node_first_child (node); child;
7920       child = g_node_next_sibling (child)) {
7921     buffer = (guint8 *) child->data;
7922
7923     child_len = QT_UINT32 (buffer);
7924     child_fourcc = QT_FOURCC (buffer + 4);
7925
7926     if (G_UNLIKELY (child_fourcc == fourcc)) {
7927       if (G_UNLIKELY (child_len < (4 + 4)))
7928         return NULL;
7929       /* FIXME: must verify if atom length < parent atom length */
7930       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7931       return child;
7932     }
7933   }
7934   return NULL;
7935 }
7936
7937 static GNode *
7938 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7939 {
7940   return g_node_nth_child (node, index);
7941 }
7942
7943 static GNode *
7944 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7945     GstByteReader * parser)
7946 {
7947   GNode *child;
7948   guint8 *buffer;
7949   guint32 child_fourcc, child_len;
7950
7951   for (child = g_node_next_sibling (node); child;
7952       child = g_node_next_sibling (child)) {
7953     buffer = (guint8 *) child->data;
7954
7955     child_fourcc = QT_FOURCC (buffer + 4);
7956
7957     if (child_fourcc == fourcc) {
7958       if (parser) {
7959         child_len = QT_UINT32 (buffer);
7960         if (G_UNLIKELY (child_len < (4 + 4)))
7961           return NULL;
7962         /* FIXME: must verify if atom length < parent atom length */
7963         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7964       }
7965       return child;
7966     }
7967   }
7968   return NULL;
7969 }
7970
7971 static GNode *
7972 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7973 {
7974   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7975 }
7976
7977 static void
7978 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7979 {
7980 /* FIXME: This can only reliably work if demuxers have a
7981  * separate streaming thread per srcpad. This should be
7982  * done in a demuxer base class, which integrates parts
7983  * of multiqueue
7984  *
7985  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7986  */
7987 #if 0
7988   GstQuery *query;
7989
7990   query = gst_query_new_allocation (stream->caps, FALSE);
7991
7992   if (!gst_pad_peer_query (stream->pad, query)) {
7993     /* not a problem, just debug a little */
7994     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7995   }
7996
7997   if (stream->allocator)
7998     gst_object_unref (stream->allocator);
7999
8000   if (gst_query_get_n_allocation_params (query) > 0) {
8001     /* try the allocator */
8002     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8003         &stream->params);
8004     stream->use_allocator = TRUE;
8005   } else {
8006     stream->allocator = NULL;
8007     gst_allocation_params_init (&stream->params);
8008     stream->use_allocator = FALSE;
8009   }
8010   gst_query_unref (query);
8011 #endif
8012 }
8013
8014 static gboolean
8015 pad_query (const GValue * item, GValue * value, gpointer user_data)
8016 {
8017   GstPad *pad = g_value_get_object (item);
8018   GstQuery *query = user_data;
8019   gboolean res;
8020
8021   res = gst_pad_peer_query (pad, query);
8022
8023   if (res) {
8024     g_value_set_boolean (value, TRUE);
8025     return FALSE;
8026   }
8027
8028   GST_INFO_OBJECT (pad, "pad peer query failed");
8029   return TRUE;
8030 }
8031
8032 static gboolean
8033 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8034     GstPadDirection direction)
8035 {
8036   GstIterator *it;
8037   GstIteratorFoldFunction func = pad_query;
8038   GValue res = { 0, };
8039
8040   g_value_init (&res, G_TYPE_BOOLEAN);
8041   g_value_set_boolean (&res, FALSE);
8042
8043   /* Ask neighbor */
8044   if (direction == GST_PAD_SRC)
8045     it = gst_element_iterate_src_pads (element);
8046   else
8047     it = gst_element_iterate_sink_pads (element);
8048
8049   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8050     gst_iterator_resync (it);
8051
8052   gst_iterator_free (it);
8053
8054   return g_value_get_boolean (&res);
8055 }
8056
8057 static void
8058 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8059     QtDemuxStream * stream)
8060 {
8061   GstQuery *query;
8062   GstContext *ctxt;
8063   GstElement *element = GST_ELEMENT (qtdemux);
8064   GstStructure *st;
8065   gchar **filtered_sys_ids;
8066   GValue event_list = G_VALUE_INIT;
8067   GList *walk;
8068
8069   /* 1. Check if we already have the context. */
8070   if (qtdemux->preferred_protection_system_id != NULL) {
8071     GST_LOG_OBJECT (element,
8072         "already have the protection context, no need to request it again");
8073     return;
8074   }
8075
8076   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8077   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8078       (const gchar **) qtdemux->protection_system_ids->pdata);
8079
8080   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8081       qtdemux->protection_system_ids->len - 1);
8082   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8083       "decryptors for %u of them, running context request",
8084       qtdemux->protection_system_ids->len, g_strv_length (filtered_sys_ids));
8085
8086   if (stream->protection_scheme_event_queue.length) {
8087     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8088         stream->protection_scheme_event_queue.length);
8089     walk = stream->protection_scheme_event_queue.tail;
8090   } else {
8091     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8092         qtdemux->protection_event_queue.length);
8093     walk = qtdemux->protection_event_queue.tail;
8094   }
8095
8096   g_value_init (&event_list, GST_TYPE_LIST);
8097   for (; walk; walk = g_list_previous (walk)) {
8098     GValue *event_value = g_new0 (GValue, 1);
8099     g_value_init (event_value, GST_TYPE_EVENT);
8100     g_value_set_boxed (event_value, walk->data);
8101     gst_value_list_append_and_take_value (&event_list, event_value);
8102   }
8103
8104   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8105    *      check if downstream already has a context of the specific type
8106    *  2b) Query upstream as above.
8107    */
8108   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8109   st = gst_query_writable_structure (query);
8110   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8111       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8112       NULL);
8113   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8114   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8115     gst_query_parse_context (query, &ctxt);
8116     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8117     gst_element_set_context (element, ctxt);
8118   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8119     gst_query_parse_context (query, &ctxt);
8120     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8121     gst_element_set_context (element, ctxt);
8122   } else {
8123     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8124      *    the required context type and afterwards check if a
8125      *    usable context was set now as in 1). The message could
8126      *    be handled by the parent bins of the element and the
8127      *    application.
8128      */
8129     GstMessage *msg;
8130
8131     GST_INFO_OBJECT (element, "posting need context message");
8132     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8133         "drm-preferred-decryption-system-id");
8134     st = (GstStructure *) gst_message_get_structure (msg);
8135     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8136         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8137         NULL);
8138
8139     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8140     gst_element_post_message (element, msg);
8141   }
8142
8143   g_strfreev (filtered_sys_ids);
8144   g_value_unset (&event_list);
8145   gst_query_unref (query);
8146 }
8147
8148 static gboolean
8149 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8150     QtDemuxStream * stream)
8151 {
8152   GstStructure *s;
8153   const gchar *selected_system = NULL;
8154
8155   g_return_val_if_fail (qtdemux != NULL, FALSE);
8156   g_return_val_if_fail (stream != NULL, FALSE);
8157   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8158       FALSE);
8159
8160   if (stream->protection_scheme_type != FOURCC_cenc) {
8161     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
8162     return FALSE;
8163   }
8164   if (qtdemux->protection_system_ids == NULL) {
8165     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8166         "cenc protection system information has been found");
8167     return FALSE;
8168   }
8169
8170   gst_qtdemux_request_protection_context (qtdemux, stream);
8171   if (qtdemux->preferred_protection_system_id != NULL) {
8172     const gchar *preferred_system_array[] =
8173         { qtdemux->preferred_protection_system_id, NULL };
8174
8175     selected_system = gst_protection_select_system (preferred_system_array);
8176
8177     if (selected_system) {
8178       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8179           qtdemux->preferred_protection_system_id);
8180     } else {
8181       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8182           "because there is no available decryptor",
8183           qtdemux->preferred_protection_system_id);
8184     }
8185   }
8186
8187   if (!selected_system) {
8188     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8189     selected_system = gst_protection_select_system ((const gchar **)
8190         qtdemux->protection_system_ids->pdata);
8191     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8192         qtdemux->protection_system_ids->len - 1);
8193   }
8194
8195   if (!selected_system) {
8196     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8197         "suitable decryptor element has been found");
8198     return FALSE;
8199   }
8200
8201   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8202       selected_system);
8203
8204   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8205   if (!gst_structure_has_name (s, "application/x-cenc")) {
8206     gst_structure_set (s,
8207         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8208         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8209         NULL);
8210     gst_structure_set_name (s, "application/x-cenc");
8211   }
8212   return TRUE;
8213 }
8214
8215 static gboolean
8216 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8217 {
8218   if (stream->subtype == FOURCC_vide) {
8219     /* fps is calculated base on the duration of the average framerate since
8220      * qt does not have a fixed framerate. */
8221     gboolean fps_available = TRUE;
8222     guint32 first_duration = 0;
8223
8224     if (stream->n_samples > 0)
8225       first_duration = stream->samples[0].duration;
8226
8227     if ((stream->n_samples == 1 && first_duration == 0)
8228         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8229       /* still frame */
8230       CUR_STREAM (stream)->fps_n = 0;
8231       CUR_STREAM (stream)->fps_d = 1;
8232     } else {
8233       if (stream->duration == 0 || stream->n_samples < 2) {
8234         CUR_STREAM (stream)->fps_n = stream->timescale;
8235         CUR_STREAM (stream)->fps_d = 1;
8236         fps_available = FALSE;
8237       } else {
8238         GstClockTime avg_duration;
8239         guint64 duration;
8240         guint32 n_samples;
8241
8242         /* duration and n_samples can be updated for fragmented format
8243          * so, framerate of fragmented format is calculated using data in a moof */
8244         if (qtdemux->fragmented && stream->n_samples_moof > 0
8245             && stream->duration_moof > 0) {
8246           n_samples = stream->n_samples_moof;
8247           duration = stream->duration_moof;
8248         } else {
8249           n_samples = stream->n_samples;
8250           duration = stream->duration;
8251         }
8252
8253         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8254         /* stream->duration is guint64, timescale, n_samples are guint32 */
8255         avg_duration =
8256             gst_util_uint64_scale_round (duration -
8257             first_duration, GST_SECOND,
8258             (guint64) (stream->timescale) * (n_samples - 1));
8259
8260         GST_LOG_OBJECT (qtdemux,
8261             "Calculating avg sample duration based on stream (or moof) duration %"
8262             G_GUINT64_FORMAT
8263             " minus first sample %u, leaving %d samples gives %"
8264             GST_TIME_FORMAT, duration, first_duration,
8265             n_samples - 1, GST_TIME_ARGS (avg_duration));
8266
8267         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8268             &CUR_STREAM (stream)->fps_d);
8269
8270         GST_DEBUG_OBJECT (qtdemux,
8271             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8272             stream->timescale, CUR_STREAM (stream)->fps_n,
8273             CUR_STREAM (stream)->fps_d);
8274       }
8275     }
8276
8277     if (CUR_STREAM (stream)->caps) {
8278       CUR_STREAM (stream)->caps =
8279           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8280
8281       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8282           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8283           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8284
8285       /* set framerate if calculated framerate is reliable */
8286       if (fps_available) {
8287         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8288             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8289             CUR_STREAM (stream)->fps_d, NULL);
8290       }
8291
8292       /* calculate pixel-aspect-ratio using display width and height */
8293       GST_DEBUG_OBJECT (qtdemux,
8294           "video size %dx%d, target display size %dx%d",
8295           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8296           stream->display_width, stream->display_height);
8297       /* qt file might have pasp atom */
8298       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8299         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8300             CUR_STREAM (stream)->par_h);
8301         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8302             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8303             CUR_STREAM (stream)->par_h, NULL);
8304       } else if (stream->display_width > 0 && stream->display_height > 0
8305           && CUR_STREAM (stream)->width > 0
8306           && CUR_STREAM (stream)->height > 0) {
8307         gint n, d;
8308
8309         /* calculate the pixel aspect ratio using the display and pixel w/h */
8310         n = stream->display_width * CUR_STREAM (stream)->height;
8311         d = stream->display_height * CUR_STREAM (stream)->width;
8312         if (n == d)
8313           n = d = 1;
8314         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8315         CUR_STREAM (stream)->par_w = n;
8316         CUR_STREAM (stream)->par_h = d;
8317         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8318             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8319             CUR_STREAM (stream)->par_h, NULL);
8320       }
8321
8322       if (CUR_STREAM (stream)->interlace_mode > 0) {
8323         if (CUR_STREAM (stream)->interlace_mode == 1) {
8324           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8325               G_TYPE_STRING, "progressive", NULL);
8326         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8327           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8328               G_TYPE_STRING, "interleaved", NULL);
8329           if (CUR_STREAM (stream)->field_order == 9) {
8330             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8331                 G_TYPE_STRING, "top-field-first", NULL);
8332           } else if (CUR_STREAM (stream)->field_order == 14) {
8333             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8334                 G_TYPE_STRING, "bottom-field-first", NULL);
8335           }
8336         }
8337       }
8338
8339       /* Create incomplete colorimetry here if needed */
8340       if (CUR_STREAM (stream)->colorimetry.range ||
8341           CUR_STREAM (stream)->colorimetry.matrix ||
8342           CUR_STREAM (stream)->colorimetry.transfer
8343           || CUR_STREAM (stream)->colorimetry.primaries) {
8344         gchar *colorimetry =
8345             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8346         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8347             G_TYPE_STRING, colorimetry, NULL);
8348         g_free (colorimetry);
8349       }
8350
8351       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8352         guint par_w = 1, par_h = 1;
8353
8354         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8355           par_w = CUR_STREAM (stream)->par_w;
8356           par_h = CUR_STREAM (stream)->par_h;
8357         }
8358
8359         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8360                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8361                 par_h)) {
8362           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8363         }
8364
8365         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8366             "multiview-mode", G_TYPE_STRING,
8367             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8368             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8369             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8370       }
8371     }
8372   }
8373
8374   else if (stream->subtype == FOURCC_soun) {
8375     if (CUR_STREAM (stream)->caps) {
8376       CUR_STREAM (stream)->caps =
8377           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8378       if (CUR_STREAM (stream)->rate > 0)
8379         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8380             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8381       if (CUR_STREAM (stream)->n_channels > 0)
8382         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8383             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8384       if (CUR_STREAM (stream)->n_channels > 2) {
8385         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8386          * correctly; this is just the minimum we can do - assume
8387          * we don't actually have any channel positions. */
8388         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8389             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8390       }
8391     }
8392   }
8393
8394   if (stream->pad) {
8395     GstCaps *prev_caps = NULL;
8396
8397     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8398     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8399     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8400     gst_pad_set_active (stream->pad, TRUE);
8401
8402     gst_pad_use_fixed_caps (stream->pad);
8403
8404     if (stream->protected) {
8405       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8406         GST_ERROR_OBJECT (qtdemux,
8407             "Failed to configure protected stream caps.");
8408         return FALSE;
8409       }
8410     }
8411
8412     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8413         CUR_STREAM (stream)->caps);
8414     if (stream->new_stream) {
8415       GstEvent *event;
8416       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8417
8418       event =
8419           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8420           0);
8421       if (event) {
8422         gst_event_parse_stream_flags (event, &stream_flags);
8423         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8424           qtdemux->have_group_id = TRUE;
8425         else
8426           qtdemux->have_group_id = FALSE;
8427         gst_event_unref (event);
8428       } else if (!qtdemux->have_group_id) {
8429         qtdemux->have_group_id = TRUE;
8430         qtdemux->group_id = gst_util_group_id_next ();
8431       }
8432
8433       stream->new_stream = FALSE;
8434       event = gst_event_new_stream_start (stream->stream_id);
8435       if (qtdemux->have_group_id)
8436         gst_event_set_group_id (event, qtdemux->group_id);
8437       if (stream->disabled)
8438         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8439       if (CUR_STREAM (stream)->sparse) {
8440         stream_flags |= GST_STREAM_FLAG_SPARSE;
8441       } else {
8442         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8443       }
8444       gst_event_set_stream_flags (event, stream_flags);
8445       gst_pad_push_event (stream->pad, event);
8446     }
8447
8448     prev_caps = gst_pad_get_current_caps (stream->pad);
8449
8450     if (CUR_STREAM (stream)->caps) {
8451       if (!prev_caps
8452           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8453         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8454             CUR_STREAM (stream)->caps);
8455         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8456       } else {
8457         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8458       }
8459     } else {
8460       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8461     }
8462
8463     if (prev_caps)
8464       gst_caps_unref (prev_caps);
8465     stream->new_caps = FALSE;
8466   }
8467   return TRUE;
8468 }
8469
8470 static void
8471 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8472     QtDemuxStream * stream)
8473 {
8474   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8475     return;
8476
8477   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8478       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8479   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8480           stream->stsd_entries_length)) {
8481     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8482         (_("This file is invalid and cannot be played.")),
8483         ("New sample description id is out of bounds (%d >= %d)",
8484             stream->stsd_sample_description_id, stream->stsd_entries_length));
8485   } else {
8486     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8487     stream->new_caps = TRUE;
8488   }
8489 }
8490
8491 static gboolean
8492 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8493     QtDemuxStream * stream, GstTagList * list)
8494 {
8495   gboolean ret = TRUE;
8496   /* consistent default for push based mode */
8497   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8498
8499   if (stream->subtype == FOURCC_vide) {
8500     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8501
8502     stream->pad =
8503         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8504     g_free (name);
8505
8506     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8507       gst_object_unref (stream->pad);
8508       stream->pad = NULL;
8509       ret = FALSE;
8510       goto done;
8511     }
8512
8513     qtdemux->n_video_streams++;
8514   } else if (stream->subtype == FOURCC_soun) {
8515     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8516
8517     stream->pad =
8518         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8519     g_free (name);
8520     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8521       gst_object_unref (stream->pad);
8522       stream->pad = NULL;
8523       ret = FALSE;
8524       goto done;
8525     }
8526     qtdemux->n_audio_streams++;
8527   } else if (stream->subtype == FOURCC_strm) {
8528     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8529   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8530       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8531       || stream->subtype == FOURCC_clcp) {
8532     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8533
8534     stream->pad =
8535         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8536     g_free (name);
8537     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8538       gst_object_unref (stream->pad);
8539       stream->pad = NULL;
8540       ret = FALSE;
8541       goto done;
8542     }
8543     qtdemux->n_sub_streams++;
8544   } else if (CUR_STREAM (stream)->caps) {
8545     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8546
8547     stream->pad =
8548         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8549     g_free (name);
8550     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8551       gst_object_unref (stream->pad);
8552       stream->pad = NULL;
8553       ret = FALSE;
8554       goto done;
8555     }
8556     qtdemux->n_video_streams++;
8557   } else {
8558     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8559     goto done;
8560   }
8561
8562   if (stream->pad) {
8563     GList *l;
8564
8565     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8566         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8567     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8568     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8569
8570     if (stream->stream_tags)
8571       gst_tag_list_unref (stream->stream_tags);
8572     stream->stream_tags = list;
8573     list = NULL;
8574     /* global tags go on each pad anyway */
8575     stream->send_global_tags = TRUE;
8576     /* send upstream GST_EVENT_PROTECTION events that were received before
8577        this source pad was created */
8578     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8579       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8580   }
8581 done:
8582   if (list)
8583     gst_tag_list_unref (list);
8584   return ret;
8585 }
8586
8587 /* find next atom with @fourcc starting at @offset */
8588 static GstFlowReturn
8589 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8590     guint64 * length, guint32 fourcc)
8591 {
8592   GstFlowReturn ret;
8593   guint32 lfourcc;
8594   GstBuffer *buf;
8595
8596   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8597       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8598
8599   while (TRUE) {
8600     GstMapInfo map;
8601
8602     buf = NULL;
8603     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8604     if (G_UNLIKELY (ret != GST_FLOW_OK))
8605       goto locate_failed;
8606     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8607       /* likely EOF */
8608       ret = GST_FLOW_EOS;
8609       gst_buffer_unref (buf);
8610       goto locate_failed;
8611     }
8612     gst_buffer_map (buf, &map, GST_MAP_READ);
8613     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8614     gst_buffer_unmap (buf, &map);
8615     gst_buffer_unref (buf);
8616
8617     if (G_UNLIKELY (*length == 0)) {
8618       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8619       ret = GST_FLOW_ERROR;
8620       goto locate_failed;
8621     }
8622
8623     if (lfourcc == fourcc) {
8624       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8625           *offset);
8626       break;
8627     } else {
8628       GST_LOG_OBJECT (qtdemux,
8629           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8630           GST_FOURCC_ARGS (fourcc), *offset);
8631       *offset += *length;
8632     }
8633   }
8634
8635   return GST_FLOW_OK;
8636
8637 locate_failed:
8638   {
8639     /* might simply have had last one */
8640     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8641     return ret;
8642   }
8643 }
8644
8645 /* should only do something in pull mode */
8646 /* call with OBJECT lock */
8647 static GstFlowReturn
8648 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8649 {
8650   guint64 length, offset;
8651   GstBuffer *buf = NULL;
8652   GstFlowReturn ret = GST_FLOW_OK;
8653   GstFlowReturn res = GST_FLOW_OK;
8654   GstMapInfo map;
8655
8656   offset = qtdemux->moof_offset;
8657   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8658
8659   if (!offset) {
8660     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8661     return GST_FLOW_EOS;
8662   }
8663
8664   /* best not do pull etc with lock held */
8665   GST_OBJECT_UNLOCK (qtdemux);
8666
8667   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8668   if (ret != GST_FLOW_OK)
8669     goto flow_failed;
8670
8671   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8672   if (G_UNLIKELY (ret != GST_FLOW_OK))
8673     goto flow_failed;
8674   gst_buffer_map (buf, &map, GST_MAP_READ);
8675   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8676     gst_buffer_unmap (buf, &map);
8677     gst_buffer_unref (buf);
8678     buf = NULL;
8679     goto parse_failed;
8680   }
8681
8682   gst_buffer_unmap (buf, &map);
8683   gst_buffer_unref (buf);
8684   buf = NULL;
8685
8686   offset += length;
8687   /* look for next moof */
8688   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8689   if (G_UNLIKELY (ret != GST_FLOW_OK))
8690     goto flow_failed;
8691
8692 exit:
8693   GST_OBJECT_LOCK (qtdemux);
8694
8695   qtdemux->moof_offset = offset;
8696
8697   return res;
8698
8699 parse_failed:
8700   {
8701     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8702     offset = 0;
8703     res = GST_FLOW_ERROR;
8704     goto exit;
8705   }
8706 flow_failed:
8707   {
8708     /* maybe upstream temporarily flushing */
8709     if (ret != GST_FLOW_FLUSHING) {
8710       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8711       offset = 0;
8712     } else {
8713       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8714       /* resume at current position next time */
8715     }
8716     res = ret;
8717     goto exit;
8718   }
8719 }
8720
8721 /* initialise bytereaders for stbl sub-atoms */
8722 static gboolean
8723 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8724 {
8725   stream->stbl_index = -1;      /* no samples have yet been parsed */
8726   stream->sample_index = -1;
8727
8728   /* time-to-sample atom */
8729   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8730     goto corrupt_file;
8731
8732   /* copy atom data into a new buffer for later use */
8733   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8734
8735   /* skip version + flags */
8736   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8737       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8738     goto corrupt_file;
8739   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8740
8741   /* make sure there's enough data */
8742   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8743     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8744     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8745         stream->n_sample_times);
8746     if (!stream->n_sample_times)
8747       goto corrupt_file;
8748   }
8749
8750   /* sync sample atom */
8751   stream->stps_present = FALSE;
8752   if ((stream->stss_present =
8753           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8754               &stream->stss) ? TRUE : FALSE) == TRUE) {
8755     /* copy atom data into a new buffer for later use */
8756     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8757
8758     /* skip version + flags */
8759     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8760         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8761       goto corrupt_file;
8762
8763     if (stream->n_sample_syncs) {
8764       /* make sure there's enough data */
8765       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8766         goto corrupt_file;
8767     }
8768
8769     /* partial sync sample atom */
8770     if ((stream->stps_present =
8771             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8772                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8773       /* copy atom data into a new buffer for later use */
8774       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8775
8776       /* skip version + flags */
8777       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8778           !gst_byte_reader_get_uint32_be (&stream->stps,
8779               &stream->n_sample_partial_syncs))
8780         goto corrupt_file;
8781
8782       /* if there are no entries, the stss table contains the real
8783        * sync samples */
8784       if (stream->n_sample_partial_syncs) {
8785         /* make sure there's enough data */
8786         if (!qt_atom_parser_has_chunks (&stream->stps,
8787                 stream->n_sample_partial_syncs, 4))
8788           goto corrupt_file;
8789       }
8790     }
8791   }
8792
8793   /* sample size */
8794   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8795     goto no_samples;
8796
8797   /* copy atom data into a new buffer for later use */
8798   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8799
8800   /* skip version + flags */
8801   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8802       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8803     goto corrupt_file;
8804
8805   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8806     goto corrupt_file;
8807
8808   if (!stream->n_samples)
8809     goto no_samples;
8810
8811   /* sample-to-chunk atom */
8812   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8813     goto corrupt_file;
8814
8815   /* copy atom data into a new buffer for later use */
8816   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8817
8818   /* skip version + flags */
8819   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8820       !gst_byte_reader_get_uint32_be (&stream->stsc,
8821           &stream->n_samples_per_chunk))
8822     goto corrupt_file;
8823
8824   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8825       stream->n_samples_per_chunk);
8826
8827   /* make sure there's enough data */
8828   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8829           12))
8830     goto corrupt_file;
8831
8832
8833   /* chunk offset */
8834   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8835     stream->co_size = sizeof (guint32);
8836   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8837           &stream->stco))
8838     stream->co_size = sizeof (guint64);
8839   else
8840     goto corrupt_file;
8841
8842   /* copy atom data into a new buffer for later use */
8843   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8844
8845   /* skip version + flags */
8846   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8847     goto corrupt_file;
8848
8849   /* chunks_are_samples == TRUE means treat chunks as samples */
8850   stream->chunks_are_samples = stream->sample_size
8851       && !CUR_STREAM (stream)->sampled;
8852   if (stream->chunks_are_samples) {
8853     /* treat chunks as samples */
8854     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8855       goto corrupt_file;
8856   } else {
8857     /* skip number of entries */
8858     if (!gst_byte_reader_skip (&stream->stco, 4))
8859       goto corrupt_file;
8860
8861     /* make sure there are enough data in the stsz atom */
8862     if (!stream->sample_size) {
8863       /* different sizes for each sample */
8864       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8865         goto corrupt_file;
8866     }
8867   }
8868
8869   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8870       stream->n_samples, (guint) sizeof (QtDemuxSample),
8871       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8872
8873   if (stream->n_samples >=
8874       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8875     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8876         "be larger than %uMB (broken file?)", stream->n_samples,
8877         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8878     return FALSE;
8879   }
8880
8881   g_assert (stream->samples == NULL);
8882   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8883   if (!stream->samples) {
8884     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8885         stream->n_samples);
8886     return FALSE;
8887   }
8888
8889   /* composition time-to-sample */
8890   if ((stream->ctts_present =
8891           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8892               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8893     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8894
8895     /* copy atom data into a new buffer for later use */
8896     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8897
8898     /* skip version + flags */
8899     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8900         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8901             &stream->n_composition_times))
8902       goto corrupt_file;
8903
8904     /* make sure there's enough data */
8905     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8906             4 + 4))
8907       goto corrupt_file;
8908
8909     /* This is optional, if missing we iterate the ctts */
8910     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8911       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8912           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8913         g_free ((gpointer) cslg.data);
8914         goto corrupt_file;
8915       }
8916     } else {
8917       gint32 cslg_least = 0;
8918       guint num_entries, pos;
8919       gint i;
8920
8921       pos = gst_byte_reader_get_pos (&stream->ctts);
8922       num_entries = stream->n_composition_times;
8923
8924       stream->cslg_shift = 0;
8925
8926       for (i = 0; i < num_entries; i++) {
8927         gint32 offset;
8928
8929         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8930         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8931
8932         if (offset < cslg_least)
8933           cslg_least = offset;
8934       }
8935
8936       if (cslg_least < 0)
8937         stream->cslg_shift = ABS (cslg_least);
8938       else
8939         stream->cslg_shift = 0;
8940
8941       /* reset the reader so we can generate sample table */
8942       gst_byte_reader_set_pos (&stream->ctts, pos);
8943     }
8944   } else {
8945     /* Ensure the cslg_shift value is consistent so we can use it
8946      * unconditionnally to produce TS and Segment */
8947     stream->cslg_shift = 0;
8948   }
8949
8950   return TRUE;
8951
8952 corrupt_file:
8953   {
8954     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8955         (_("This file is corrupt and cannot be played.")), (NULL));
8956     return FALSE;
8957   }
8958 no_samples:
8959   {
8960     gst_qtdemux_stbl_free (stream);
8961     if (!qtdemux->fragmented) {
8962       /* not quite good */
8963       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8964       return FALSE;
8965     } else {
8966       /* may pick up samples elsewhere */
8967       return TRUE;
8968     }
8969   }
8970 }
8971
8972 /* collect samples from the next sample to be parsed up to sample @n for @stream
8973  * by reading the info from @stbl
8974  *
8975  * This code can be executed from both the streaming thread and the seeking
8976  * thread so it takes the object lock to protect itself
8977  */
8978 static gboolean
8979 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8980 {
8981   gint i, j, k;
8982   QtDemuxSample *samples, *first, *cur, *last;
8983   guint32 n_samples_per_chunk;
8984   guint32 n_samples;
8985
8986   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8987       GST_FOURCC_FORMAT ", pad %s",
8988       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8989       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8990
8991   n_samples = stream->n_samples;
8992
8993   if (n >= n_samples)
8994     goto out_of_samples;
8995
8996   GST_OBJECT_LOCK (qtdemux);
8997   if (n <= stream->stbl_index)
8998     goto already_parsed;
8999
9000   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9001
9002   if (!stream->stsz.data) {
9003     /* so we already parsed and passed all the moov samples;
9004      * onto fragmented ones */
9005     g_assert (qtdemux->fragmented);
9006     goto done;
9007   }
9008
9009   /* pointer to the sample table */
9010   samples = stream->samples;
9011
9012   /* starts from -1, moves to the next sample index to parse */
9013   stream->stbl_index++;
9014
9015   /* keep track of the first and last sample to fill */
9016   first = &samples[stream->stbl_index];
9017   last = &samples[n];
9018
9019   if (!stream->chunks_are_samples) {
9020     /* set the sample sizes */
9021     if (stream->sample_size == 0) {
9022       /* different sizes for each sample */
9023       for (cur = first; cur <= last; cur++) {
9024         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9025         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9026             (guint) (cur - samples), cur->size);
9027       }
9028     } else {
9029       /* samples have the same size */
9030       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9031       for (cur = first; cur <= last; cur++)
9032         cur->size = stream->sample_size;
9033     }
9034   }
9035
9036   n_samples_per_chunk = stream->n_samples_per_chunk;
9037   cur = first;
9038
9039   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9040     guint32 last_chunk;
9041
9042     if (stream->stsc_chunk_index >= stream->last_chunk
9043         || stream->stsc_chunk_index < stream->first_chunk) {
9044       stream->first_chunk =
9045           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9046       stream->samples_per_chunk =
9047           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9048       /* starts from 1 */
9049       stream->stsd_sample_description_id =
9050           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9051
9052       /* chunk numbers are counted from 1 it seems */
9053       if (G_UNLIKELY (stream->first_chunk == 0))
9054         goto corrupt_file;
9055
9056       --stream->first_chunk;
9057
9058       /* the last chunk of each entry is calculated by taking the first chunk
9059        * of the next entry; except if there is no next, where we fake it with
9060        * INT_MAX */
9061       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9062         stream->last_chunk = G_MAXUINT32;
9063       } else {
9064         stream->last_chunk =
9065             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9066         if (G_UNLIKELY (stream->last_chunk == 0))
9067           goto corrupt_file;
9068
9069         --stream->last_chunk;
9070       }
9071
9072       GST_LOG_OBJECT (qtdemux,
9073           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9074           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9075           stream->samples_per_chunk, stream->stsd_sample_description_id);
9076
9077       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9078         goto corrupt_file;
9079
9080       if (stream->last_chunk != G_MAXUINT32) {
9081         if (!qt_atom_parser_peek_sub (&stream->stco,
9082                 stream->first_chunk * stream->co_size,
9083                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9084                 &stream->co_chunk))
9085           goto corrupt_file;
9086
9087       } else {
9088         stream->co_chunk = stream->stco;
9089         if (!gst_byte_reader_skip (&stream->co_chunk,
9090                 stream->first_chunk * stream->co_size))
9091           goto corrupt_file;
9092       }
9093
9094       stream->stsc_chunk_index = stream->first_chunk;
9095     }
9096
9097     last_chunk = stream->last_chunk;
9098
9099     if (stream->chunks_are_samples) {
9100       cur = &samples[stream->stsc_chunk_index];
9101
9102       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9103         if (j > n) {
9104           /* save state */
9105           stream->stsc_chunk_index = j;
9106           goto done;
9107         }
9108
9109         cur->offset =
9110             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9111             stream->co_size);
9112
9113         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9114             "%" G_GUINT64_FORMAT, j, cur->offset);
9115
9116         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9117             CUR_STREAM (stream)->bytes_per_frame > 0) {
9118           cur->size =
9119               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9120               CUR_STREAM (stream)->samples_per_frame *
9121               CUR_STREAM (stream)->bytes_per_frame;
9122         } else {
9123           cur->size = stream->samples_per_chunk;
9124         }
9125
9126         GST_DEBUG_OBJECT (qtdemux,
9127             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9128             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9129                     stream->stco_sample_index)), cur->size);
9130
9131         cur->timestamp = stream->stco_sample_index;
9132         cur->duration = stream->samples_per_chunk;
9133         cur->keyframe = TRUE;
9134         cur++;
9135
9136         stream->stco_sample_index += stream->samples_per_chunk;
9137       }
9138       stream->stsc_chunk_index = j;
9139     } else {
9140       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9141         guint32 samples_per_chunk;
9142         guint64 chunk_offset;
9143
9144         if (!stream->stsc_sample_index
9145             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9146                 &stream->chunk_offset))
9147           goto corrupt_file;
9148
9149         samples_per_chunk = stream->samples_per_chunk;
9150         chunk_offset = stream->chunk_offset;
9151
9152         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9153           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9154               G_GUINT64_FORMAT " and size %d",
9155               (guint) (cur - samples), chunk_offset, cur->size);
9156
9157           cur->offset = chunk_offset;
9158           chunk_offset += cur->size;
9159           cur++;
9160
9161           if (G_UNLIKELY (cur > last)) {
9162             /* save state */
9163             stream->stsc_sample_index = k + 1;
9164             stream->chunk_offset = chunk_offset;
9165             stream->stsc_chunk_index = j;
9166             goto done2;
9167           }
9168         }
9169         stream->stsc_sample_index = 0;
9170       }
9171       stream->stsc_chunk_index = j;
9172     }
9173     stream->stsc_index++;
9174   }
9175
9176   if (stream->chunks_are_samples)
9177     goto ctts;
9178 done2:
9179   {
9180     guint32 n_sample_times;
9181
9182     n_sample_times = stream->n_sample_times;
9183     cur = first;
9184
9185     for (i = stream->stts_index; i < n_sample_times; i++) {
9186       guint32 stts_samples;
9187       gint32 stts_duration;
9188       gint64 stts_time;
9189
9190       if (stream->stts_sample_index >= stream->stts_samples
9191           || !stream->stts_sample_index) {
9192
9193         stream->stts_samples =
9194             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9195         stream->stts_duration =
9196             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9197
9198         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9199             i, stream->stts_samples, stream->stts_duration);
9200
9201         stream->stts_sample_index = 0;
9202       }
9203
9204       stts_samples = stream->stts_samples;
9205       stts_duration = stream->stts_duration;
9206       stts_time = stream->stts_time;
9207
9208       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9209         GST_DEBUG_OBJECT (qtdemux,
9210             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9211             (guint) (cur - samples), j,
9212             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9213
9214         cur->timestamp = stts_time;
9215         cur->duration = stts_duration;
9216
9217         /* avoid 32-bit wrap-around,
9218          * but still mind possible 'negative' duration */
9219         stts_time += (gint64) stts_duration;
9220         cur++;
9221
9222         if (G_UNLIKELY (cur > last)) {
9223           /* save values */
9224           stream->stts_time = stts_time;
9225           stream->stts_sample_index = j + 1;
9226           if (stream->stts_sample_index >= stream->stts_samples)
9227             stream->stts_index++;
9228           goto done3;
9229         }
9230       }
9231       stream->stts_sample_index = 0;
9232       stream->stts_time = stts_time;
9233       stream->stts_index++;
9234     }
9235     /* fill up empty timestamps with the last timestamp, this can happen when
9236      * the last samples do not decode and so we don't have timestamps for them.
9237      * We however look at the last timestamp to estimate the track length so we
9238      * need something in here. */
9239     for (; cur < last; cur++) {
9240       GST_DEBUG_OBJECT (qtdemux,
9241           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9242           (guint) (cur - samples),
9243           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9244       cur->timestamp = stream->stts_time;
9245       cur->duration = -1;
9246     }
9247   }
9248 done3:
9249   {
9250     /* sample sync, can be NULL */
9251     if (stream->stss_present == TRUE) {
9252       guint32 n_sample_syncs;
9253
9254       n_sample_syncs = stream->n_sample_syncs;
9255
9256       if (!n_sample_syncs) {
9257         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9258         stream->all_keyframe = TRUE;
9259       } else {
9260         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9261           /* note that the first sample is index 1, not 0 */
9262           guint32 index;
9263
9264           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9265
9266           if (G_LIKELY (index > 0 && index <= n_samples)) {
9267             index -= 1;
9268             samples[index].keyframe = TRUE;
9269             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9270             /* and exit if we have enough samples */
9271             if (G_UNLIKELY (index >= n)) {
9272               i++;
9273               break;
9274             }
9275           }
9276         }
9277         /* save state */
9278         stream->stss_index = i;
9279       }
9280
9281       /* stps marks partial sync frames like open GOP I-Frames */
9282       if (stream->stps_present == TRUE) {
9283         guint32 n_sample_partial_syncs;
9284
9285         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9286
9287         /* if there are no entries, the stss table contains the real
9288          * sync samples */
9289         if (n_sample_partial_syncs) {
9290           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9291             /* note that the first sample is index 1, not 0 */
9292             guint32 index;
9293
9294             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9295
9296             if (G_LIKELY (index > 0 && index <= n_samples)) {
9297               index -= 1;
9298               samples[index].keyframe = TRUE;
9299               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9300               /* and exit if we have enough samples */
9301               if (G_UNLIKELY (index >= n)) {
9302                 i++;
9303                 break;
9304               }
9305             }
9306           }
9307           /* save state */
9308           stream->stps_index = i;
9309         }
9310       }
9311     } else {
9312       /* no stss, all samples are keyframes */
9313       stream->all_keyframe = TRUE;
9314       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9315     }
9316   }
9317
9318 ctts:
9319   /* composition time to sample */
9320   if (stream->ctts_present == TRUE) {
9321     guint32 n_composition_times;
9322     guint32 ctts_count;
9323     gint32 ctts_soffset;
9324
9325     /* Fill in the pts_offsets */
9326     cur = first;
9327     n_composition_times = stream->n_composition_times;
9328
9329     for (i = stream->ctts_index; i < n_composition_times; i++) {
9330       if (stream->ctts_sample_index >= stream->ctts_count
9331           || !stream->ctts_sample_index) {
9332         stream->ctts_count =
9333             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9334         stream->ctts_soffset =
9335             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9336         stream->ctts_sample_index = 0;
9337       }
9338
9339       ctts_count = stream->ctts_count;
9340       ctts_soffset = stream->ctts_soffset;
9341
9342       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9343         cur->pts_offset = ctts_soffset;
9344         cur++;
9345
9346         if (G_UNLIKELY (cur > last)) {
9347           /* save state */
9348           stream->ctts_sample_index = j + 1;
9349           goto done;
9350         }
9351       }
9352       stream->ctts_sample_index = 0;
9353       stream->ctts_index++;
9354     }
9355   }
9356 done:
9357   stream->stbl_index = n;
9358   /* if index has been completely parsed, free data that is no-longer needed */
9359   if (n + 1 == stream->n_samples) {
9360     gst_qtdemux_stbl_free (stream);
9361     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9362     if (qtdemux->pullbased) {
9363       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9364       while (n + 1 == stream->n_samples)
9365         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9366           break;
9367     }
9368   }
9369   GST_OBJECT_UNLOCK (qtdemux);
9370
9371   return TRUE;
9372
9373   /* SUCCESS */
9374 already_parsed:
9375   {
9376     GST_LOG_OBJECT (qtdemux,
9377         "Tried to parse up to sample %u but this sample has already been parsed",
9378         n);
9379     /* if fragmented, there may be more */
9380     if (qtdemux->fragmented && n == stream->stbl_index)
9381       goto done;
9382     GST_OBJECT_UNLOCK (qtdemux);
9383     return TRUE;
9384   }
9385   /* ERRORS */
9386 out_of_samples:
9387   {
9388     GST_LOG_OBJECT (qtdemux,
9389         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9390         stream->n_samples);
9391     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9392         (_("This file is corrupt and cannot be played.")), (NULL));
9393     return FALSE;
9394   }
9395 corrupt_file:
9396   {
9397     GST_OBJECT_UNLOCK (qtdemux);
9398     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9399         (_("This file is corrupt and cannot be played.")), (NULL));
9400     return FALSE;
9401   }
9402 }
9403
9404 /* collect all segment info for @stream.
9405  */
9406 static gboolean
9407 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9408     GNode * trak)
9409 {
9410   GNode *edts;
9411   /* accept edts if they contain gaps at start and there is only
9412    * one media segment */
9413   gboolean allow_pushbased_edts = TRUE;
9414   gint media_segments_count = 0;
9415
9416   /* parse and prepare segment info from the edit list */
9417   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9418   stream->n_segments = 0;
9419   stream->segments = NULL;
9420   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9421     GNode *elst;
9422     gint n_segments;
9423     gint segment_number, entry_size;
9424     guint64 time;
9425     GstClockTime stime;
9426     const guint8 *buffer;
9427     guint8 version;
9428     guint32 size;
9429
9430     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9431     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9432       goto done;
9433
9434     buffer = elst->data;
9435
9436     size = QT_UINT32 (buffer);
9437     /* version, flags, n_segments */
9438     if (size < 16) {
9439       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9440       goto done;
9441     }
9442     version = QT_UINT8 (buffer + 8);
9443     entry_size = (version == 1) ? 20 : 12;
9444
9445     n_segments = QT_UINT32 (buffer + 12);
9446
9447     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9448       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9449       goto done;
9450     }
9451
9452     /* we might allocate a bit too much, at least allocate 1 segment */
9453     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9454
9455     /* segments always start from 0 */
9456     time = 0;
9457     stime = 0;
9458     buffer += 16;
9459     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9460       guint64 duration;
9461       guint64 media_time;
9462       gboolean empty_edit = FALSE;
9463       QtDemuxSegment *segment;
9464       guint32 rate_int;
9465       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9466
9467       if (version == 1) {
9468         media_time = QT_UINT64 (buffer + 8);
9469         duration = QT_UINT64 (buffer);
9470         if (media_time == G_MAXUINT64)
9471           empty_edit = TRUE;
9472       } else {
9473         media_time = QT_UINT32 (buffer + 4);
9474         duration = QT_UINT32 (buffer);
9475         if (media_time == G_MAXUINT32)
9476           empty_edit = TRUE;
9477       }
9478
9479       if (!empty_edit)
9480         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9481
9482       segment = &stream->segments[segment_number];
9483
9484       /* time and duration expressed in global timescale */
9485       segment->time = stime;
9486       if (duration != 0 || empty_edit) {
9487         /* edge case: empty edits with duration=zero are treated here.
9488          * (files should not have these anyway). */
9489
9490         /* add non scaled values so we don't cause roundoff errors */
9491         time += duration;
9492         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9493         segment->duration = stime - segment->time;
9494       } else {
9495         /* zero duration does not imply media_start == media_stop
9496          * but, only specify media_start. The edit ends with the track. */
9497         stime = segment->duration = GST_CLOCK_TIME_NONE;
9498         /* Don't allow more edits after this one. */
9499         n_segments = segment_number + 1;
9500       }
9501       segment->stop_time = stime;
9502
9503       segment->trak_media_start = media_time;
9504       /* media_time expressed in stream timescale */
9505       if (!empty_edit) {
9506         segment->media_start = media_start;
9507         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9508             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9509         media_segments_count++;
9510       } else {
9511         segment->media_start = GST_CLOCK_TIME_NONE;
9512         segment->media_stop = GST_CLOCK_TIME_NONE;
9513       }
9514       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9515
9516       if (rate_int <= 1) {
9517         /* 0 is not allowed, some programs write 1 instead of the floating point
9518          * value */
9519         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9520             rate_int);
9521         segment->rate = 1;
9522       } else {
9523         segment->rate = rate_int / 65536.0;
9524       }
9525
9526       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9527           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9528           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9529           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9530           segment_number, GST_TIME_ARGS (segment->time),
9531           GST_TIME_ARGS (segment->duration),
9532           GST_TIME_ARGS (segment->media_start), media_time,
9533           GST_TIME_ARGS (segment->media_stop),
9534           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9535           stream->timescale);
9536       if (segment->stop_time > qtdemux->segment.stop &&
9537           !qtdemux->upstream_format_is_time) {
9538         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9539             " extends to %" GST_TIME_FORMAT
9540             " past the end of the declared movie duration %" GST_TIME_FORMAT
9541             " movie segment will be extended", segment_number,
9542             GST_TIME_ARGS (segment->stop_time),
9543             GST_TIME_ARGS (qtdemux->segment.stop));
9544         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9545       }
9546
9547       buffer += entry_size;
9548     }
9549     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9550     stream->n_segments = n_segments;
9551     if (media_segments_count != 1)
9552       allow_pushbased_edts = FALSE;
9553   }
9554 done:
9555
9556   /* push based does not handle segments, so act accordingly here,
9557    * and warn if applicable */
9558   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9559     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9560     /* remove and use default one below, we stream like it anyway */
9561     g_free (stream->segments);
9562     stream->segments = NULL;
9563     stream->n_segments = 0;
9564   }
9565
9566   /* no segments, create one to play the complete trak */
9567   if (stream->n_segments == 0) {
9568     GstClockTime stream_duration =
9569         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9570
9571     if (stream->segments == NULL)
9572       stream->segments = g_new (QtDemuxSegment, 1);
9573
9574     /* represent unknown our way */
9575     if (stream_duration == 0)
9576       stream_duration = GST_CLOCK_TIME_NONE;
9577
9578     stream->segments[0].time = 0;
9579     stream->segments[0].stop_time = stream_duration;
9580     stream->segments[0].duration = stream_duration;
9581     stream->segments[0].media_start = 0;
9582     stream->segments[0].media_stop = stream_duration;
9583     stream->segments[0].rate = 1.0;
9584     stream->segments[0].trak_media_start = 0;
9585
9586     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9587         GST_TIME_ARGS (stream_duration));
9588     stream->n_segments = 1;
9589     stream->dummy_segment = TRUE;
9590   }
9591   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9592
9593   return TRUE;
9594 }
9595
9596 /*
9597  * Parses the stsd atom of a svq3 trak looking for
9598  * the SMI and gama atoms.
9599  */
9600 static void
9601 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9602     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9603 {
9604   const guint8 *_gamma = NULL;
9605   GstBuffer *_seqh = NULL;
9606   const guint8 *stsd_data = stsd_entry_data;
9607   guint32 length = QT_UINT32 (stsd_data);
9608   guint16 version;
9609
9610   if (length < 32) {
9611     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9612     goto end;
9613   }
9614
9615   stsd_data += 16;
9616   length -= 16;
9617   version = QT_UINT16 (stsd_data);
9618   if (version == 3) {
9619     if (length >= 70) {
9620       length -= 70;
9621       stsd_data += 70;
9622       while (length > 8) {
9623         guint32 fourcc, size;
9624         const guint8 *data;
9625         size = QT_UINT32 (stsd_data);
9626         fourcc = QT_FOURCC (stsd_data + 4);
9627         data = stsd_data + 8;
9628
9629         if (size == 0) {
9630           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9631               "svq3 atom parsing");
9632           goto end;
9633         }
9634
9635         switch (fourcc) {
9636           case FOURCC_gama:{
9637             if (size == 12) {
9638               _gamma = data;
9639             } else {
9640               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9641                   " for gama atom, expected 12", size);
9642             }
9643             break;
9644           }
9645           case FOURCC_SMI_:{
9646             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9647               guint32 seqh_size;
9648               if (_seqh != NULL) {
9649                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9650                     " found, ignoring");
9651               } else {
9652                 seqh_size = QT_UINT32 (data + 4);
9653                 if (seqh_size > 0) {
9654                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9655                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9656                 }
9657               }
9658             }
9659             break;
9660           }
9661           default:{
9662             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9663                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9664           }
9665         }
9666
9667         if (size <= length) {
9668           length -= size;
9669           stsd_data += size;
9670         }
9671       }
9672     } else {
9673       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9674     }
9675   } else {
9676     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9677         G_GUINT16_FORMAT, version);
9678     goto end;
9679   }
9680
9681 end:
9682   if (gamma) {
9683     *gamma = _gamma;
9684   }
9685   if (seqh) {
9686     *seqh = _seqh;
9687   } else if (_seqh) {
9688     gst_buffer_unref (_seqh);
9689   }
9690 }
9691
9692 static gchar *
9693 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9694 {
9695   GNode *dinf;
9696   GstByteReader dref;
9697   gchar *uri = NULL;
9698
9699   /*
9700    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9701    * atom that might contain a 'data' atom with the rtsp uri.
9702    * This case was reported in bug #597497, some info about
9703    * the hndl atom can be found in TN1195
9704    */
9705   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9706   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9707
9708   if (dinf) {
9709     guint32 dref_num_entries = 0;
9710     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9711         gst_byte_reader_skip (&dref, 4) &&
9712         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9713       gint i;
9714
9715       /* search dref entries for hndl atom */
9716       for (i = 0; i < dref_num_entries; i++) {
9717         guint32 size = 0, type;
9718         guint8 string_len = 0;
9719         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9720             qt_atom_parser_get_fourcc (&dref, &type)) {
9721           if (type == FOURCC_hndl) {
9722             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9723
9724             /* skip data reference handle bytes and the
9725              * following pascal string and some extra 4
9726              * bytes I have no idea what are */
9727             if (!gst_byte_reader_skip (&dref, 4) ||
9728                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9729                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9730               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9731               break;
9732             }
9733
9734             /* iterate over the atoms to find the data atom */
9735             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9736               guint32 atom_size;
9737               guint32 atom_type;
9738
9739               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9740                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9741                 if (atom_type == FOURCC_data) {
9742                   const guint8 *uri_aux = NULL;
9743
9744                   /* found the data atom that might contain the rtsp uri */
9745                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9746                       "hndl atom, interpreting it as an URI");
9747                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9748                           &uri_aux)) {
9749                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9750                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9751                     else
9752                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9753                           "didn't contain a rtsp address");
9754                   } else {
9755                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9756                         "atom contents");
9757                   }
9758                   break;
9759                 }
9760                 /* skipping to the next entry */
9761                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9762                   break;
9763               } else {
9764                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9765                     "atom header");
9766                 break;
9767               }
9768             }
9769             break;
9770           }
9771           /* skip to the next entry */
9772           if (!gst_byte_reader_skip (&dref, size - 8))
9773             break;
9774         } else {
9775           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9776         }
9777       }
9778       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9779     }
9780   }
9781   return uri;
9782 }
9783
9784 #define AMR_NB_ALL_MODES        0x81ff
9785 #define AMR_WB_ALL_MODES        0x83ff
9786 static guint
9787 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9788 {
9789   /* The 'damr' atom is of the form:
9790    *
9791    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9792    *    32 b       8 b          16 b           8 b                 8 b
9793    *
9794    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9795    * represents the highest mode used in the stream (and thus the maximum
9796    * bitrate), with a couple of special cases as seen below.
9797    */
9798
9799   /* Map of frame type ID -> bitrate */
9800   static const guint nb_bitrates[] = {
9801     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9802   };
9803   static const guint wb_bitrates[] = {
9804     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9805   };
9806   GstMapInfo map;
9807   gsize max_mode;
9808   guint16 mode_set;
9809
9810   gst_buffer_map (buf, &map, GST_MAP_READ);
9811
9812   if (map.size != 0x11) {
9813     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9814     goto bad_data;
9815   }
9816
9817   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9818     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9819         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9820     goto bad_data;
9821   }
9822
9823   mode_set = QT_UINT16 (map.data + 13);
9824
9825   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9826     max_mode = 7 + (wb ? 1 : 0);
9827   else
9828     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9829     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9830
9831   if (max_mode == -1) {
9832     GST_DEBUG ("No mode indication was found (mode set) = %x",
9833         (guint) mode_set);
9834     goto bad_data;
9835   }
9836
9837   gst_buffer_unmap (buf, &map);
9838   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9839
9840 bad_data:
9841   gst_buffer_unmap (buf, &map);
9842   return 0;
9843 }
9844
9845 static gboolean
9846 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9847     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9848 {
9849   /*
9850    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9851    * [0 1 2]
9852    * [3 4 5]
9853    * [6 7 8]
9854    */
9855
9856   if (gst_byte_reader_get_remaining (reader) < 36)
9857     return FALSE;
9858
9859   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9860   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9861   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9862   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9863   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9864   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9865   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9866   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9867   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9868
9869   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9870   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9871       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9872       matrix[2] & 0xFF);
9873   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9874       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9875       matrix[5] & 0xFF);
9876   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9877       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9878       matrix[8] & 0xFF);
9879
9880   return TRUE;
9881 }
9882
9883 static void
9884 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9885     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9886 {
9887
9888 /* [a b c]
9889  * [d e f]
9890  * [g h i]
9891  *
9892  * This macro will only compare value abdegh, it expects cfi to have already
9893  * been checked
9894  */
9895 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9896                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9897
9898   /* only handle the cases where the last column has standard values */
9899   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9900     const gchar *rotation_tag = NULL;
9901
9902     /* no rotation needed */
9903     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9904       /* NOP */
9905     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9906       rotation_tag = "rotate-90";
9907     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9908       rotation_tag = "rotate-180";
9909     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9910       rotation_tag = "rotate-270";
9911     } else {
9912       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9913     }
9914
9915     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9916         rotation_tag);
9917     if (rotation_tag != NULL) {
9918       if (*taglist == NULL)
9919         *taglist = gst_tag_list_new_empty ();
9920       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9921           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9922     }
9923   } else {
9924     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9925   }
9926 }
9927
9928 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9929  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9930  * Common Encryption (cenc), the function will also parse the tenc box (defined
9931  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9932  * (typically an enc[v|a|t|s] sample entry); the function will set
9933  * @original_fmt to the fourcc of the original unencrypted stream format.
9934  * Returns TRUE if successful; FALSE otherwise. */
9935 static gboolean
9936 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9937     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9938 {
9939   GNode *sinf;
9940   GNode *frma;
9941   GNode *schm;
9942   GNode *schi;
9943
9944   g_return_val_if_fail (qtdemux != NULL, FALSE);
9945   g_return_val_if_fail (stream != NULL, FALSE);
9946   g_return_val_if_fail (container != NULL, FALSE);
9947   g_return_val_if_fail (original_fmt != NULL, FALSE);
9948
9949   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9950   if (G_UNLIKELY (!sinf)) {
9951     if (stream->protection_scheme_type == FOURCC_cenc) {
9952       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9953           "mandatory for Common Encryption");
9954       return FALSE;
9955     }
9956     return TRUE;
9957   }
9958
9959   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9960   if (G_UNLIKELY (!frma)) {
9961     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9962     return FALSE;
9963   }
9964
9965   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9966   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9967       GST_FOURCC_ARGS (*original_fmt));
9968
9969   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9970   if (!schm) {
9971     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9972     return FALSE;
9973   }
9974   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9975   stream->protection_scheme_version =
9976       QT_UINT32 ((const guint8 *) schm->data + 16);
9977
9978   GST_DEBUG_OBJECT (qtdemux,
9979       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9980       "protection_scheme_version: %#010x",
9981       GST_FOURCC_ARGS (stream->protection_scheme_type),
9982       stream->protection_scheme_version);
9983
9984   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9985   if (!schi) {
9986     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9987     return FALSE;
9988   }
9989   if (stream->protection_scheme_type == FOURCC_cenc) {
9990     QtDemuxCencSampleSetInfo *info;
9991     GNode *tenc;
9992     const guint8 *tenc_data;
9993     guint32 isEncrypted;
9994     guint8 iv_size;
9995     const guint8 *default_kid;
9996     GstBuffer *kid_buf;
9997
9998     if (G_UNLIKELY (!stream->protection_scheme_info))
9999       stream->protection_scheme_info =
10000           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10001
10002     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10003
10004     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10005     if (!tenc) {
10006       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10007           "which is mandatory for Common Encryption");
10008       return FALSE;
10009     }
10010     tenc_data = (const guint8 *) tenc->data + 12;
10011     isEncrypted = QT_UINT24 (tenc_data);
10012     iv_size = QT_UINT8 (tenc_data + 3);
10013     default_kid = (tenc_data + 4);
10014     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
10015     gst_buffer_fill (kid_buf, 0, default_kid, 16);
10016     if (info->default_properties)
10017       gst_structure_free (info->default_properties);
10018     info->default_properties =
10019         gst_structure_new ("application/x-cenc",
10020         "iv_size", G_TYPE_UINT, iv_size,
10021         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
10022         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
10023     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
10024         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
10025     gst_buffer_unref (kid_buf);
10026   }
10027   return TRUE;
10028 }
10029
10030 static gint
10031 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10032 {
10033   return (gint) stream1->track_id - (gint) stream2->track_id;
10034 }
10035
10036 /* parse the traks.
10037  * With each track we associate a new QtDemuxStream that contains all the info
10038  * about the trak.
10039  * traks that do not decode to something (like strm traks) will not have a pad.
10040  */
10041 static gboolean
10042 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10043 {
10044   GstByteReader tkhd;
10045   int offset;
10046   GNode *mdia;
10047   GNode *mdhd;
10048   GNode *hdlr;
10049   GNode *minf;
10050   GNode *stbl;
10051   GNode *stsd;
10052   GNode *mp4a;
10053   GNode *mp4v;
10054   GNode *esds;
10055   GNode *tref;
10056   GNode *udta;
10057   GNode *svmi;
10058
10059   QtDemuxStream *stream = NULL;
10060   const guint8 *stsd_data;
10061   const guint8 *stsd_entry_data;
10062   guint remaining_stsd_len;
10063   guint stsd_entry_count;
10064   guint stsd_index;
10065   guint16 lang_code;            /* quicktime lang code or packed iso code */
10066   guint32 version;
10067   guint32 tkhd_flags = 0;
10068   guint8 tkhd_version = 0;
10069   guint32 w = 0, h = 0;
10070   guint value_size, stsd_len, len;
10071   guint32 track_id;
10072   guint32 dummy;
10073
10074   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10075
10076   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10077       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10078       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10079     goto corrupt_file;
10080
10081   /* pick between 64 or 32 bits */
10082   value_size = tkhd_version == 1 ? 8 : 4;
10083   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10084       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10085     goto corrupt_file;
10086
10087   /* Check if current moov has duplicated track_id */
10088   if (qtdemux_find_stream (qtdemux, track_id))
10089     goto existing_stream;
10090
10091   stream = _create_stream (qtdemux, track_id);
10092   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10093
10094   /* need defaults for fragments */
10095   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10096
10097   if ((tkhd_flags & 1) == 0)
10098     stream->disabled = TRUE;
10099
10100   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10101       tkhd_version, tkhd_flags, stream->track_id);
10102
10103   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10104     goto corrupt_file;
10105
10106   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10107     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10108     if (qtdemux->major_brand != FOURCC_mjp2 ||
10109         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10110       goto corrupt_file;
10111   }
10112
10113   len = QT_UINT32 ((guint8 *) mdhd->data);
10114   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10115   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10116   if (version == 0x01000000) {
10117     if (len < 38)
10118       goto corrupt_file;
10119     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10120     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10121     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10122   } else {
10123     if (len < 30)
10124       goto corrupt_file;
10125     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10126     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10127     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10128   }
10129
10130   if (lang_code < 0x400) {
10131     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10132   } else if (lang_code == 0x7fff) {
10133     stream->lang_id[0] = 0;     /* unspecified */
10134   } else {
10135     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10136     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10137     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10138     stream->lang_id[3] = 0;
10139   }
10140
10141   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10142       stream->timescale);
10143   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10144       stream->duration);
10145   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10146       lang_code, stream->lang_id);
10147
10148   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10149     goto corrupt_file;
10150
10151   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10152     /* chapters track reference */
10153     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10154     if (chap) {
10155       gsize length = GST_READ_UINT32_BE (chap->data);
10156       if (qtdemux->chapters_track_id)
10157         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10158
10159       if (length >= 12) {
10160         qtdemux->chapters_track_id =
10161             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10162       }
10163     }
10164   }
10165
10166   /* fragmented files may have bogus duration in moov */
10167   if (!qtdemux->fragmented &&
10168       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10169     guint64 tdur1, tdur2;
10170
10171     /* don't overflow */
10172     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10173     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10174
10175     /* HACK:
10176      * some of those trailers, nowadays, have prologue images that are
10177      * themselves video tracks as well. I haven't really found a way to
10178      * identify those yet, except for just looking at their duration. */
10179     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10180       GST_WARNING_OBJECT (qtdemux,
10181           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10182           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10183           "found, assuming preview image or something; skipping track",
10184           stream->duration, stream->timescale, qtdemux->duration,
10185           qtdemux->timescale);
10186       gst_qtdemux_stream_free (stream);
10187       return TRUE;
10188     }
10189   }
10190
10191   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10192     goto corrupt_file;
10193
10194   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10195       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10196
10197   len = QT_UINT32 ((guint8 *) hdlr->data);
10198   if (len >= 20)
10199     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10200   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10201       GST_FOURCC_ARGS (stream->subtype));
10202
10203   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10204     goto corrupt_file;
10205
10206   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10207     goto corrupt_file;
10208
10209   /*parse svmi header if existing */
10210   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10211   if (svmi) {
10212     len = QT_UINT32 ((guint8 *) svmi->data);
10213     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10214     if (!version) {
10215       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10216       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10217       guint8 frame_type, frame_layout;
10218
10219       /* MPEG-A stereo video */
10220       if (qtdemux->major_brand == FOURCC_ss02)
10221         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10222
10223       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10224       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10225       switch (frame_type) {
10226         case 0:
10227           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10228           break;
10229         case 1:
10230           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10231           break;
10232         case 2:
10233           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10234           break;
10235         case 3:
10236           /* mode 3 is primary/secondary view sequence, ie
10237            * left/right views in separate tracks. See section 7.2
10238            * of ISO/IEC 23000-11:2009 */
10239           GST_FIXME_OBJECT (qtdemux,
10240               "Implement stereo video in separate streams");
10241       }
10242
10243       if ((frame_layout & 0x1) == 0)
10244         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10245
10246       GST_LOG_OBJECT (qtdemux,
10247           "StereoVideo: composition type: %u, is_left_first: %u",
10248           frame_type, frame_layout);
10249       stream->multiview_mode = mode;
10250       stream->multiview_flags = flags;
10251     }
10252   }
10253
10254   /* parse rest of tkhd */
10255   if (stream->subtype == FOURCC_vide) {
10256     guint32 matrix[9];
10257
10258     /* version 1 uses some 64-bit ints */
10259     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10260       goto corrupt_file;
10261
10262     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10263       goto corrupt_file;
10264
10265     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10266         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10267       goto corrupt_file;
10268
10269     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10270         &stream->stream_tags);
10271   }
10272
10273   /* parse stsd */
10274   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10275     goto corrupt_file;
10276   stsd_data = (const guint8 *) stsd->data;
10277
10278   /* stsd should at least have one entry */
10279   stsd_len = QT_UINT32 (stsd_data);
10280   if (stsd_len < 24) {
10281     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10282     if (stream->subtype == FOURCC_vivo) {
10283       gst_qtdemux_stream_free (stream);
10284       return TRUE;
10285     } else {
10286       goto corrupt_file;
10287     }
10288   }
10289
10290   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10291   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10292   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10293   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10294
10295   stsd_entry_data = stsd_data + 16;
10296   remaining_stsd_len = stsd_len - 16;
10297   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10298     guint32 fourcc;
10299     gchar *codec = NULL;
10300     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10301
10302     /* and that entry should fit within stsd */
10303     len = QT_UINT32 (stsd_entry_data);
10304     if (len > remaining_stsd_len)
10305       goto corrupt_file;
10306
10307     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10308     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10309         GST_FOURCC_ARGS (entry->fourcc));
10310     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10311
10312     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10313       goto error_encrypted;
10314
10315     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10316       /* FIXME this looks wrong, there might be multiple children
10317        * with the same type */
10318       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10319       stream->protected = TRUE;
10320       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10321         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10322     }
10323
10324     if (stream->subtype == FOURCC_vide) {
10325       GNode *colr;
10326       GNode *fiel;
10327       GNode *pasp;
10328       gboolean gray;
10329       gint depth, palette_size, palette_count;
10330       guint32 *palette_data = NULL;
10331
10332       entry->sampled = TRUE;
10333
10334       stream->display_width = w >> 16;
10335       stream->display_height = h >> 16;
10336
10337       offset = 16;
10338       if (len < 86)             /* TODO verify */
10339         goto corrupt_file;
10340
10341       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10342       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10343       entry->fps_n = 0;         /* this is filled in later */
10344       entry->fps_d = 0;         /* this is filled in later */
10345       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10346       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10347
10348       /* if color_table_id is 0, ctab atom must follow; however some files
10349        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10350        * if color table is not present we'll correct the value */
10351       if (entry->color_table_id == 0 &&
10352           (len < 90
10353               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10354         entry->color_table_id = -1;
10355       }
10356
10357       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10358           entry->width, entry->height, entry->bits_per_sample,
10359           entry->color_table_id);
10360
10361       depth = entry->bits_per_sample;
10362
10363       /* more than 32 bits means grayscale */
10364       gray = (depth > 32);
10365       /* low 32 bits specify the depth  */
10366       depth &= 0x1F;
10367
10368       /* different number of palette entries is determined by depth. */
10369       palette_count = 0;
10370       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10371         palette_count = (1 << depth);
10372       palette_size = palette_count * 4;
10373
10374       if (entry->color_table_id) {
10375         switch (palette_count) {
10376           case 0:
10377             break;
10378           case 2:
10379             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10380             break;
10381           case 4:
10382             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10383             break;
10384           case 16:
10385             if (gray)
10386               palette_data =
10387                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10388             else
10389               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10390             break;
10391           case 256:
10392             if (gray)
10393               palette_data =
10394                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10395             else
10396               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10397             break;
10398           default:
10399             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10400                 (_("The video in this file might not play correctly.")),
10401                 ("unsupported palette depth %d", depth));
10402             break;
10403         }
10404       } else {
10405         gint i, j, start, end;
10406
10407         if (len < 94)
10408           goto corrupt_file;
10409
10410         /* read table */
10411         start = QT_UINT32 (stsd_entry_data + offset + 70);
10412         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10413         end = QT_UINT16 (stsd_entry_data + offset + 76);
10414
10415         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10416             start, end, palette_count);
10417
10418         if (end > 255)
10419           end = 255;
10420         if (start > end)
10421           start = end;
10422
10423         if (len < 94 + (end - start) * 8)
10424           goto corrupt_file;
10425
10426         /* palette is always the same size */
10427         palette_data = g_malloc0 (256 * 4);
10428         palette_size = 256 * 4;
10429
10430         for (j = 0, i = start; i <= end; j++, i++) {
10431           guint32 a, r, g, b;
10432
10433           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10434           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10435           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10436           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10437
10438           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10439               (g & 0xff00) | (b >> 8);
10440         }
10441       }
10442
10443       if (entry->caps)
10444         gst_caps_unref (entry->caps);
10445
10446       entry->caps =
10447           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10448           &codec);
10449       if (G_UNLIKELY (!entry->caps)) {
10450         g_free (palette_data);
10451         goto unknown_stream;
10452       }
10453
10454       if (codec) {
10455         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10456             GST_TAG_VIDEO_CODEC, codec, NULL);
10457         g_free (codec);
10458         codec = NULL;
10459       }
10460
10461       if (palette_data) {
10462         GstStructure *s;
10463
10464         if (entry->rgb8_palette)
10465           gst_memory_unref (entry->rgb8_palette);
10466         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10467             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10468
10469         s = gst_caps_get_structure (entry->caps, 0);
10470
10471         /* non-raw video has a palette_data property. raw video has the palette as
10472          * an extra plane that we append to the output buffers before we push
10473          * them*/
10474         if (!gst_structure_has_name (s, "video/x-raw")) {
10475           GstBuffer *palette;
10476
10477           palette = gst_buffer_new ();
10478           gst_buffer_append_memory (palette, entry->rgb8_palette);
10479           entry->rgb8_palette = NULL;
10480
10481           gst_caps_set_simple (entry->caps, "palette_data",
10482               GST_TYPE_BUFFER, palette, NULL);
10483           gst_buffer_unref (palette);
10484         }
10485       } else if (palette_count != 0) {
10486         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10487             (NULL), ("Unsupported palette depth %d", depth));
10488       }
10489
10490       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10491           QT_UINT16 (stsd_entry_data + offset + 32));
10492
10493       esds = NULL;
10494       pasp = NULL;
10495       colr = NULL;
10496       fiel = NULL;
10497       /* pick 'the' stsd child */
10498       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10499       if (!stream->protected) {
10500         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10501           mp4v = NULL;
10502         }
10503       } else {
10504         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10505           mp4v = NULL;
10506         }
10507       }
10508
10509       if (mp4v) {
10510         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10511         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10512         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10513         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10514       }
10515
10516       if (pasp) {
10517         const guint8 *pasp_data = (const guint8 *) pasp->data;
10518         gint len = QT_UINT32 (pasp_data);
10519
10520         if (len == 16) {
10521           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10522           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10523         } else {
10524           CUR_STREAM (stream)->par_w = 0;
10525           CUR_STREAM (stream)->par_h = 0;
10526         }
10527       } else {
10528         CUR_STREAM (stream)->par_w = 0;
10529         CUR_STREAM (stream)->par_h = 0;
10530       }
10531
10532       if (fiel) {
10533         const guint8 *fiel_data = (const guint8 *) fiel->data;
10534         gint len = QT_UINT32 (fiel_data);
10535
10536         if (len == 10) {
10537           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10538           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10539         }
10540       }
10541
10542       if (colr) {
10543         const guint8 *colr_data = (const guint8 *) colr->data;
10544         gint len = QT_UINT32 (colr_data);
10545
10546         if (len == 19 || len == 18) {
10547           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10548
10549           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10550             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10551             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10552             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10553             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10554
10555             switch (primaries) {
10556               case 1:
10557                 CUR_STREAM (stream)->colorimetry.primaries =
10558                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10559                 break;
10560               case 5:
10561                 CUR_STREAM (stream)->colorimetry.primaries =
10562                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10563                 break;
10564               case 6:
10565                 CUR_STREAM (stream)->colorimetry.primaries =
10566                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10567                 break;
10568               case 9:
10569                 CUR_STREAM (stream)->colorimetry.primaries =
10570                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10571                 break;
10572               default:
10573                 break;
10574             }
10575
10576             switch (transfer_function) {
10577               case 1:
10578                 CUR_STREAM (stream)->colorimetry.transfer =
10579                     GST_VIDEO_TRANSFER_BT709;
10580                 break;
10581               case 7:
10582                 CUR_STREAM (stream)->colorimetry.transfer =
10583                     GST_VIDEO_TRANSFER_SMPTE240M;
10584                 break;
10585               default:
10586                 break;
10587             }
10588
10589             switch (matrix) {
10590               case 1:
10591                 CUR_STREAM (stream)->colorimetry.matrix =
10592                     GST_VIDEO_COLOR_MATRIX_BT709;
10593                 break;
10594               case 6:
10595                 CUR_STREAM (stream)->colorimetry.matrix =
10596                     GST_VIDEO_COLOR_MATRIX_BT601;
10597                 break;
10598               case 7:
10599                 CUR_STREAM (stream)->colorimetry.matrix =
10600                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10601                 break;
10602               case 9:
10603                 CUR_STREAM (stream)->colorimetry.matrix =
10604                     GST_VIDEO_COLOR_MATRIX_BT2020;
10605                 break;
10606               default:
10607                 break;
10608             }
10609
10610             CUR_STREAM (stream)->colorimetry.range =
10611                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10612                 GST_VIDEO_COLOR_RANGE_16_235;
10613           } else {
10614             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10615           }
10616         } else {
10617           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10618         }
10619       }
10620
10621       if (esds) {
10622         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10623             stream->stream_tags);
10624       } else {
10625         switch (fourcc) {
10626           case FOURCC_H264:
10627           case FOURCC_avc1:
10628           case FOURCC_avc3:
10629           {
10630             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10631             const guint8 *avc_data = stsd_entry_data + 0x56;
10632
10633             /* find avcC */
10634             while (len >= 0x8) {
10635               gint size;
10636
10637               if (QT_UINT32 (avc_data) <= len)
10638                 size = QT_UINT32 (avc_data) - 0x8;
10639               else
10640                 size = len - 0x8;
10641
10642               if (size < 1)
10643                 /* No real data, so break out */
10644                 break;
10645
10646               switch (QT_FOURCC (avc_data + 0x4)) {
10647                 case FOURCC_avcC:
10648                 {
10649                   /* parse, if found */
10650                   GstBuffer *buf;
10651
10652                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10653
10654                   /* First 4 bytes are the length of the atom, the next 4 bytes
10655                    * are the fourcc, the next 1 byte is the version, and the
10656                    * subsequent bytes are profile_tier_level structure like data. */
10657                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10658                       avc_data + 8 + 1, size - 1);
10659                   buf = gst_buffer_new_and_alloc (size);
10660                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10661                   gst_caps_set_simple (entry->caps,
10662                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10663                   gst_buffer_unref (buf);
10664
10665                   break;
10666                 }
10667                 case FOURCC_strf:
10668                 {
10669                   GstBuffer *buf;
10670
10671                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10672
10673                   /* First 4 bytes are the length of the atom, the next 4 bytes
10674                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10675                    * next 1 byte is the version, and the
10676                    * subsequent bytes are sequence parameter set like data. */
10677
10678                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10679                   if (size > 1) {
10680                     gst_codec_utils_h264_caps_set_level_and_profile
10681                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10682
10683                     buf = gst_buffer_new_and_alloc (size);
10684                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10685                     gst_caps_set_simple (entry->caps,
10686                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10687                     gst_buffer_unref (buf);
10688                   }
10689                   break;
10690                 }
10691                 case FOURCC_btrt:
10692                 {
10693                   guint avg_bitrate, max_bitrate;
10694
10695                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10696                   if (size < 12)
10697                     break;
10698
10699                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10700                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10701
10702                   if (!max_bitrate && !avg_bitrate)
10703                     break;
10704
10705                   /* Some muxers seem to swap the average and maximum bitrates
10706                    * (I'm looking at you, YouTube), so we swap for sanity. */
10707                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10708                     guint temp = avg_bitrate;
10709
10710                     avg_bitrate = max_bitrate;
10711                     max_bitrate = temp;
10712                   }
10713
10714                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10715                     gst_tag_list_add (stream->stream_tags,
10716                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10717                         max_bitrate, NULL);
10718                   }
10719                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10720                     gst_tag_list_add (stream->stream_tags,
10721                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10722                         NULL);
10723                   }
10724
10725                   break;
10726                 }
10727
10728                 default:
10729                   break;
10730               }
10731
10732               len -= size + 8;
10733               avc_data += size + 8;
10734             }
10735
10736             break;
10737           }
10738           case FOURCC_H265:
10739           case FOURCC_hvc1:
10740           case FOURCC_hev1:
10741           {
10742             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10743             const guint8 *hevc_data = stsd_entry_data + 0x56;
10744
10745             /* find hevc */
10746             while (len >= 0x8) {
10747               gint size;
10748
10749               if (QT_UINT32 (hevc_data) <= len)
10750                 size = QT_UINT32 (hevc_data) - 0x8;
10751               else
10752                 size = len - 0x8;
10753
10754               if (size < 1)
10755                 /* No real data, so break out */
10756                 break;
10757
10758               switch (QT_FOURCC (hevc_data + 0x4)) {
10759                 case FOURCC_hvcC:
10760                 {
10761                   /* parse, if found */
10762                   GstBuffer *buf;
10763
10764                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10765
10766                   /* First 4 bytes are the length of the atom, the next 4 bytes
10767                    * are the fourcc, the next 1 byte is the version, and the
10768                    * subsequent bytes are sequence parameter set like data. */
10769                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10770                       (entry->caps, hevc_data + 8 + 1, size - 1);
10771
10772                   buf = gst_buffer_new_and_alloc (size);
10773                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10774                   gst_caps_set_simple (entry->caps,
10775                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10776                   gst_buffer_unref (buf);
10777                   break;
10778                 }
10779                 default:
10780                   break;
10781               }
10782               len -= size + 8;
10783               hevc_data += size + 8;
10784             }
10785             break;
10786           }
10787           case FOURCC_mp4v:
10788           case FOURCC_MP4V:
10789           case FOURCC_fmp4:
10790           case FOURCC_FMP4:
10791           case FOURCC_xvid:
10792           case FOURCC_XVID:
10793           {
10794             GNode *glbl;
10795
10796             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10797                 GST_FOURCC_ARGS (fourcc));
10798
10799             /* codec data might be in glbl extension atom */
10800             glbl = mp4v ?
10801                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10802             if (glbl) {
10803               guint8 *data;
10804               GstBuffer *buf;
10805               gint len;
10806
10807               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10808               data = glbl->data;
10809               len = QT_UINT32 (data);
10810               if (len > 0x8) {
10811                 len -= 0x8;
10812                 buf = gst_buffer_new_and_alloc (len);
10813                 gst_buffer_fill (buf, 0, data + 8, len);
10814                 gst_caps_set_simple (entry->caps,
10815                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10816                 gst_buffer_unref (buf);
10817               }
10818             }
10819             break;
10820           }
10821           case FOURCC_mjp2:
10822           {
10823             /* see annex I of the jpeg2000 spec */
10824             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10825             const guint8 *data;
10826             const gchar *colorspace = NULL;
10827             gint ncomp = 0;
10828             guint32 ncomp_map = 0;
10829             gint32 *comp_map = NULL;
10830             guint32 nchan_def = 0;
10831             gint32 *chan_def = NULL;
10832
10833             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10834             /* some required atoms */
10835             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10836             if (!mjp2)
10837               break;
10838             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10839             if (!jp2h)
10840               break;
10841
10842             /* number of components; redundant with info in codestream, but useful
10843                to a muxer */
10844             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10845             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10846               break;
10847             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10848
10849             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10850             if (!colr)
10851               break;
10852             GST_DEBUG_OBJECT (qtdemux, "found colr");
10853             /* extract colour space info */
10854             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10855               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10856                 case 16:
10857                   colorspace = "sRGB";
10858                   break;
10859                 case 17:
10860                   colorspace = "GRAY";
10861                   break;
10862                 case 18:
10863                   colorspace = "sYUV";
10864                   break;
10865                 default:
10866                   colorspace = NULL;
10867                   break;
10868               }
10869             }
10870             if (!colorspace)
10871               /* colr is required, and only values 16, 17, and 18 are specified,
10872                  so error if we have no colorspace */
10873               break;
10874
10875             /* extract component mapping */
10876             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10877             if (cmap) {
10878               guint32 cmap_len = 0;
10879               int i;
10880               cmap_len = QT_UINT32 (cmap->data);
10881               if (cmap_len >= 8) {
10882                 /* normal box, subtract off header */
10883                 cmap_len -= 8;
10884                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10885                 if (cmap_len % 4 == 0) {
10886                   ncomp_map = (cmap_len / 4);
10887                   comp_map = g_new0 (gint32, ncomp_map);
10888                   for (i = 0; i < ncomp_map; i++) {
10889                     guint16 cmp;
10890                     guint8 mtyp, pcol;
10891                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10892                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10893                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10894                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10895                   }
10896                 }
10897               }
10898             }
10899             /* extract channel definitions */
10900             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10901             if (cdef) {
10902               guint32 cdef_len = 0;
10903               int i;
10904               cdef_len = QT_UINT32 (cdef->data);
10905               if (cdef_len >= 10) {
10906                 /* normal box, subtract off header and len */
10907                 cdef_len -= 10;
10908                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10909                 if (cdef_len % 6 == 0) {
10910                   nchan_def = (cdef_len / 6);
10911                   chan_def = g_new0 (gint32, nchan_def);
10912                   for (i = 0; i < nchan_def; i++)
10913                     chan_def[i] = -1;
10914                   for (i = 0; i < nchan_def; i++) {
10915                     guint16 cn, typ, asoc;
10916                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10917                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10918                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10919                     if (cn < nchan_def) {
10920                       switch (typ) {
10921                         case 0:
10922                           chan_def[cn] = asoc;
10923                           break;
10924                         case 1:
10925                           chan_def[cn] = 0;     /* alpha */
10926                           break;
10927                         default:
10928                           chan_def[cn] = -typ;
10929                       }
10930                     }
10931                   }
10932                 }
10933               }
10934             }
10935
10936             gst_caps_set_simple (entry->caps,
10937                 "num-components", G_TYPE_INT, ncomp, NULL);
10938             gst_caps_set_simple (entry->caps,
10939                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10940
10941             if (comp_map) {
10942               GValue arr = { 0, };
10943               GValue elt = { 0, };
10944               int i;
10945               g_value_init (&arr, GST_TYPE_ARRAY);
10946               g_value_init (&elt, G_TYPE_INT);
10947               for (i = 0; i < ncomp_map; i++) {
10948                 g_value_set_int (&elt, comp_map[i]);
10949                 gst_value_array_append_value (&arr, &elt);
10950               }
10951               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10952                   "component-map", &arr);
10953               g_value_unset (&elt);
10954               g_value_unset (&arr);
10955               g_free (comp_map);
10956             }
10957
10958             if (chan_def) {
10959               GValue arr = { 0, };
10960               GValue elt = { 0, };
10961               int i;
10962               g_value_init (&arr, GST_TYPE_ARRAY);
10963               g_value_init (&elt, G_TYPE_INT);
10964               for (i = 0; i < nchan_def; i++) {
10965                 g_value_set_int (&elt, chan_def[i]);
10966                 gst_value_array_append_value (&arr, &elt);
10967               }
10968               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10969                   "channel-definitions", &arr);
10970               g_value_unset (&elt);
10971               g_value_unset (&arr);
10972               g_free (chan_def);
10973             }
10974
10975             /* some optional atoms */
10976             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10977             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10978
10979             /* indicate possible fields in caps */
10980             if (field) {
10981               data = (guint8 *) field->data + 8;
10982               if (*data != 1)
10983                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10984                     (gint) * data, NULL);
10985             }
10986             /* add codec_data if provided */
10987             if (prefix) {
10988               GstBuffer *buf;
10989               gint len;
10990
10991               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10992               data = prefix->data;
10993               len = QT_UINT32 (data);
10994               if (len > 0x8) {
10995                 len -= 0x8;
10996                 buf = gst_buffer_new_and_alloc (len);
10997                 gst_buffer_fill (buf, 0, data + 8, len);
10998                 gst_caps_set_simple (entry->caps,
10999                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11000                 gst_buffer_unref (buf);
11001               }
11002             }
11003             break;
11004           }
11005           case FOURCC_SVQ3:
11006           case FOURCC_VP31:
11007           {
11008             GstBuffer *buf;
11009             GstBuffer *seqh = NULL;
11010             const guint8 *gamma_data = NULL;
11011             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11012
11013             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11014                 &seqh);
11015             if (gamma_data) {
11016               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11017                   QT_FP32 (gamma_data), NULL);
11018             }
11019             if (seqh) {
11020               /* sorry for the bad name, but we don't know what this is, other
11021                * than its own fourcc */
11022               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11023                   NULL);
11024               gst_buffer_unref (seqh);
11025             }
11026
11027             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11028             buf = gst_buffer_new_and_alloc (len);
11029             gst_buffer_fill (buf, 0, stsd_data, len);
11030             gst_caps_set_simple (entry->caps,
11031                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11032             gst_buffer_unref (buf);
11033             break;
11034           }
11035           case FOURCC_jpeg:
11036           {
11037             /* https://developer.apple.com/standards/qtff-2001.pdf,
11038              * page 92, "Video Sample Description", under table 3.1 */
11039             GstByteReader br;
11040
11041             const gint compressor_offset =
11042                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11043             const gint min_size = compressor_offset + 32 + 2 + 2;
11044             GNode *jpeg;
11045             guint32 len;
11046             guint16 color_table_id = 0;
11047             gboolean ok;
11048
11049             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11050
11051             /* recover information on interlaced/progressive */
11052             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11053             if (!jpeg)
11054               break;
11055
11056             len = QT_UINT32 (jpeg->data);
11057             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11058                 min_size);
11059             if (len >= min_size) {
11060               gst_byte_reader_init (&br, jpeg->data, len);
11061
11062               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11063               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11064               if (color_table_id != 0) {
11065                 /* the spec says there can be concatenated chunks in the data, and we want
11066                  * to find one called field. Walk through them. */
11067                 gint offset = min_size;
11068                 while (offset + 8 < len) {
11069                   guint32 size = 0, tag;
11070                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11071                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11072                   if (!ok || size < 8) {
11073                     GST_WARNING_OBJECT (qtdemux,
11074                         "Failed to walk optional chunk list");
11075                     break;
11076                   }
11077                   GST_DEBUG_OBJECT (qtdemux,
11078                       "Found optional %4.4s chunk, size %u",
11079                       (const char *) &tag, size);
11080                   if (tag == FOURCC_fiel) {
11081                     guint8 n_fields = 0, ordering = 0;
11082                     gst_byte_reader_get_uint8 (&br, &n_fields);
11083                     gst_byte_reader_get_uint8 (&br, &ordering);
11084                     if (n_fields == 1 || n_fields == 2) {
11085                       GST_DEBUG_OBJECT (qtdemux,
11086                           "Found fiel tag with %u fields, ordering %u",
11087                           n_fields, ordering);
11088                       if (n_fields == 2)
11089                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11090                             "interlace-mode", G_TYPE_STRING, "interleaved",
11091                             NULL);
11092                     } else {
11093                       GST_WARNING_OBJECT (qtdemux,
11094                           "Found fiel tag with invalid fields (%u)", n_fields);
11095                     }
11096                   }
11097                   offset += size;
11098                 }
11099               } else {
11100                 GST_DEBUG_OBJECT (qtdemux,
11101                     "Color table ID is 0, not trying to get interlacedness");
11102               }
11103             } else {
11104               GST_WARNING_OBJECT (qtdemux,
11105                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11106             }
11107
11108             break;
11109           }
11110           case FOURCC_rle_:
11111           case FOURCC_WRLE:
11112           {
11113             gst_caps_set_simple (entry->caps,
11114                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11115                 NULL);
11116             break;
11117           }
11118           case FOURCC_XiTh:
11119           {
11120             GNode *xith, *xdxt;
11121
11122             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11123             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11124             if (!xith)
11125               break;
11126
11127             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11128             if (!xdxt)
11129               break;
11130
11131             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11132             /* collect the headers and store them in a stream list so that we can
11133              * send them out first */
11134             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11135             break;
11136           }
11137           case FOURCC_ovc1:
11138           {
11139             GNode *ovc1;
11140             guint8 *ovc1_data;
11141             guint ovc1_len;
11142             GstBuffer *buf;
11143
11144             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11145             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11146             if (!ovc1)
11147               break;
11148             ovc1_data = ovc1->data;
11149             ovc1_len = QT_UINT32 (ovc1_data);
11150             if (ovc1_len <= 198) {
11151               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11152               break;
11153             }
11154             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11155             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11156             gst_caps_set_simple (entry->caps,
11157                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11158             gst_buffer_unref (buf);
11159             break;
11160           }
11161           case FOURCC_vc_1:
11162           {
11163             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11164             const guint8 *vc1_data = stsd_entry_data + 0x56;
11165
11166             /* find dvc1 */
11167             while (len >= 8) {
11168               gint size;
11169
11170               if (QT_UINT32 (vc1_data) <= len)
11171                 size = QT_UINT32 (vc1_data) - 8;
11172               else
11173                 size = len - 8;
11174
11175               if (size < 1)
11176                 /* No real data, so break out */
11177                 break;
11178
11179               switch (QT_FOURCC (vc1_data + 0x4)) {
11180                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11181                 {
11182                   GstBuffer *buf;
11183
11184                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11185                   buf = gst_buffer_new_and_alloc (size);
11186                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11187                   gst_caps_set_simple (entry->caps,
11188                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11189                   gst_buffer_unref (buf);
11190                   break;
11191                 }
11192                 default:
11193                   break;
11194               }
11195               len -= size + 8;
11196               vc1_data += size + 8;
11197             }
11198             break;
11199           }
11200           case FOURCC_av01:
11201           {
11202             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11203             const guint8 *av1_data = stsd_entry_data + 0x56;
11204
11205             /* find av1C */
11206             while (len >= 0x8) {
11207               gint size;
11208
11209               if (QT_UINT32 (av1_data) <= len)
11210                 size = QT_UINT32 (av1_data) - 0x8;
11211               else
11212                 size = len - 0x8;
11213
11214               if (size < 1)
11215                 /* No real data, so break out */
11216                 break;
11217
11218               switch (QT_FOURCC (av1_data + 0x4)) {
11219                 case FOURCC_av1C:
11220                 {
11221                   /* parse, if found */
11222                   GstBuffer *buf;
11223                   guint8 pres_delay_field;
11224
11225                   GST_DEBUG_OBJECT (qtdemux,
11226                       "found av1C codec_data in stsd of size %d", size);
11227
11228                   /* not enough data, just ignore and hope for the best */
11229                   if (size < 5)
11230                     break;
11231
11232                   /* Content is:
11233                    * 4 bytes: atom length
11234                    * 4 bytes: fourcc
11235                    * 1 byte: version
11236                    * 3 bytes: flags
11237                    * 3 bits: reserved
11238                    * 1 bits:  initial_presentation_delay_present
11239                    * 4 bits: initial_presentation_delay (if present else reserved
11240                    * rest: OBUs.
11241                    */
11242
11243                   if (av1_data[9] != 0) {
11244                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11245                     break;
11246                   }
11247
11248                   /* We skip initial_presentation_delay* for now */
11249                   pres_delay_field = *(av1_data + 12);
11250                   if (pres_delay_field & (1 << 5)) {
11251                     gst_caps_set_simple (entry->caps,
11252                         "presentation-delay", G_TYPE_INT,
11253                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11254                   }
11255                   if (size > 5) {
11256                     buf = gst_buffer_new_and_alloc (size - 5);
11257                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11258                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11259                     gst_caps_set_simple (entry->caps,
11260                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11261                     gst_buffer_unref (buf);
11262                   }
11263                   break;
11264                 }
11265                 default:
11266                   break;
11267               }
11268
11269               len -= size + 8;
11270               av1_data += size + 8;
11271             }
11272
11273             break;
11274           }
11275           default:
11276             break;
11277         }
11278       }
11279
11280       GST_INFO_OBJECT (qtdemux,
11281           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11282           GST_FOURCC_ARGS (fourcc), entry->caps);
11283
11284     } else if (stream->subtype == FOURCC_soun) {
11285       GNode *wave;
11286       int version, samplesize;
11287       guint16 compression_id;
11288       gboolean amrwb = FALSE;
11289
11290       offset = 16;
11291       /* sample description entry (16) + sound sample description v0 (20) */
11292       if (len < 36)
11293         goto corrupt_file;
11294
11295       version = QT_UINT32 (stsd_entry_data + offset);
11296       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11297       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11298       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11299       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11300
11301       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11302       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11303           QT_UINT32 (stsd_entry_data + offset + 4));
11304       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11305       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11306       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11307       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11308           QT_UINT16 (stsd_entry_data + offset + 14));
11309       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11310
11311       if (compression_id == 0xfffe)
11312         entry->sampled = TRUE;
11313
11314       /* first assume uncompressed audio */
11315       entry->bytes_per_sample = samplesize / 8;
11316       entry->samples_per_frame = entry->n_channels;
11317       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11318       entry->samples_per_packet = entry->samples_per_frame;
11319       entry->bytes_per_packet = entry->bytes_per_sample;
11320
11321       offset = 36;
11322       switch (fourcc) {
11323           /* Yes, these have to be hard-coded */
11324         case FOURCC_MAC6:
11325         {
11326           entry->samples_per_packet = 6;
11327           entry->bytes_per_packet = 1;
11328           entry->bytes_per_frame = 1 * entry->n_channels;
11329           entry->bytes_per_sample = 1;
11330           entry->samples_per_frame = 6 * entry->n_channels;
11331           break;
11332         }
11333         case FOURCC_MAC3:
11334         {
11335           entry->samples_per_packet = 3;
11336           entry->bytes_per_packet = 1;
11337           entry->bytes_per_frame = 1 * entry->n_channels;
11338           entry->bytes_per_sample = 1;
11339           entry->samples_per_frame = 3 * entry->n_channels;
11340           break;
11341         }
11342         case FOURCC_ima4:
11343         {
11344           entry->samples_per_packet = 64;
11345           entry->bytes_per_packet = 34;
11346           entry->bytes_per_frame = 34 * entry->n_channels;
11347           entry->bytes_per_sample = 2;
11348           entry->samples_per_frame = 64 * entry->n_channels;
11349           break;
11350         }
11351         case FOURCC_ulaw:
11352         case FOURCC_alaw:
11353         {
11354           entry->samples_per_packet = 1;
11355           entry->bytes_per_packet = 1;
11356           entry->bytes_per_frame = 1 * entry->n_channels;
11357           entry->bytes_per_sample = 1;
11358           entry->samples_per_frame = 1 * entry->n_channels;
11359           break;
11360         }
11361         case FOURCC_agsm:
11362         {
11363           entry->samples_per_packet = 160;
11364           entry->bytes_per_packet = 33;
11365           entry->bytes_per_frame = 33 * entry->n_channels;
11366           entry->bytes_per_sample = 2;
11367           entry->samples_per_frame = 160 * entry->n_channels;
11368           break;
11369         }
11370         default:
11371           break;
11372       }
11373
11374       if (version == 0x00010000) {
11375         /* sample description entry (16) + sound sample description v1 (20+16) */
11376         if (len < 52)
11377           goto corrupt_file;
11378
11379         switch (fourcc) {
11380           case FOURCC_twos:
11381           case FOURCC_sowt:
11382           case FOURCC_raw_:
11383           case FOURCC_lpcm:
11384             break;
11385           default:
11386           {
11387             /* only parse extra decoding config for non-pcm audio */
11388             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11389             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11390             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11391             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11392
11393             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11394                 entry->samples_per_packet);
11395             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11396                 entry->bytes_per_packet);
11397             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11398                 entry->bytes_per_frame);
11399             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11400                 entry->bytes_per_sample);
11401
11402             if (!entry->sampled && entry->bytes_per_packet) {
11403               entry->samples_per_frame = (entry->bytes_per_frame /
11404                   entry->bytes_per_packet) * entry->samples_per_packet;
11405               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11406                   entry->samples_per_frame);
11407             }
11408             break;
11409           }
11410         }
11411       } else if (version == 0x00020000) {
11412         union
11413         {
11414           gdouble fp;
11415           guint64 val;
11416         } qtfp;
11417
11418         /* sample description entry (16) + sound sample description v2 (56) */
11419         if (len < 72)
11420           goto corrupt_file;
11421
11422         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11423         entry->rate = qtfp.fp;
11424         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11425
11426         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11427         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11428         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11429         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11430             QT_UINT32 (stsd_entry_data + offset + 20));
11431         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11432             QT_UINT32 (stsd_entry_data + offset + 24));
11433         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11434             QT_UINT32 (stsd_entry_data + offset + 28));
11435         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11436             QT_UINT32 (stsd_entry_data + offset + 32));
11437       } else if (version != 0x00000) {
11438         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11439             version);
11440       }
11441
11442       if (entry->caps)
11443         gst_caps_unref (entry->caps);
11444
11445       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11446           stsd_entry_data + 32, len - 16, &codec);
11447
11448       switch (fourcc) {
11449         case FOURCC_in24:
11450         {
11451           GNode *enda;
11452           GNode *in24;
11453
11454           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11455
11456           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11457           if (!enda) {
11458             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11459             if (wave)
11460               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11461           }
11462           if (enda) {
11463             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11464             gst_caps_set_simple (entry->caps,
11465                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11466                 NULL);
11467           }
11468           break;
11469         }
11470         case FOURCC_owma:
11471         {
11472           const guint8 *owma_data;
11473           const gchar *codec_name = NULL;
11474           guint owma_len;
11475           GstBuffer *buf;
11476           gint version = 1;
11477           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11478           /* FIXME this should also be gst_riff_strf_auds,
11479            * but the latter one is actually missing bits-per-sample :( */
11480           typedef struct
11481           {
11482             gint16 wFormatTag;
11483             gint16 nChannels;
11484             gint32 nSamplesPerSec;
11485             gint32 nAvgBytesPerSec;
11486             gint16 nBlockAlign;
11487             gint16 wBitsPerSample;
11488             gint16 cbSize;
11489           } WAVEFORMATEX;
11490           WAVEFORMATEX *wfex;
11491
11492           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11493           owma_data = stsd_entry_data;
11494           owma_len = QT_UINT32 (owma_data);
11495           if (owma_len <= 54) {
11496             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11497             break;
11498           }
11499           wfex = (WAVEFORMATEX *) (owma_data + 36);
11500           buf = gst_buffer_new_and_alloc (owma_len - 54);
11501           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11502           if (wfex->wFormatTag == 0x0161) {
11503             codec_name = "Windows Media Audio";
11504             version = 2;
11505           } else if (wfex->wFormatTag == 0x0162) {
11506             codec_name = "Windows Media Audio 9 Pro";
11507             version = 3;
11508           } else if (wfex->wFormatTag == 0x0163) {
11509             codec_name = "Windows Media Audio 9 Lossless";
11510             /* is that correct? gstffmpegcodecmap.c is missing it, but
11511              * fluendo codec seems to support it */
11512             version = 4;
11513           }
11514
11515           gst_caps_set_simple (entry->caps,
11516               "codec_data", GST_TYPE_BUFFER, buf,
11517               "wmaversion", G_TYPE_INT, version,
11518               "block_align", G_TYPE_INT,
11519               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11520               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11521               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11522               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11523           gst_buffer_unref (buf);
11524
11525           if (codec_name) {
11526             g_free (codec);
11527             codec = g_strdup (codec_name);
11528           }
11529           break;
11530         }
11531         case FOURCC_wma_:
11532         {
11533           gint len = QT_UINT32 (stsd_entry_data) - offset;
11534           const guint8 *wfex_data = stsd_entry_data + offset;
11535           const gchar *codec_name = NULL;
11536           gint version = 1;
11537           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11538           /* FIXME this should also be gst_riff_strf_auds,
11539            * but the latter one is actually missing bits-per-sample :( */
11540           typedef struct
11541           {
11542             gint16 wFormatTag;
11543             gint16 nChannels;
11544             gint32 nSamplesPerSec;
11545             gint32 nAvgBytesPerSec;
11546             gint16 nBlockAlign;
11547             gint16 wBitsPerSample;
11548             gint16 cbSize;
11549           } WAVEFORMATEX;
11550           WAVEFORMATEX wfex;
11551
11552           /* FIXME: unify with similar wavformatex parsing code above */
11553           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11554
11555           /* find wfex */
11556           while (len >= 8) {
11557             gint size;
11558
11559             if (QT_UINT32 (wfex_data) <= len)
11560               size = QT_UINT32 (wfex_data) - 8;
11561             else
11562               size = len - 8;
11563
11564             if (size < 1)
11565               /* No real data, so break out */
11566               break;
11567
11568             switch (QT_FOURCC (wfex_data + 4)) {
11569               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11570               {
11571                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11572
11573                 if (size < 8 + 18)
11574                   break;
11575
11576                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11577                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11578                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11579                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11580                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11581                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11582                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11583
11584                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11585                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11586                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11587                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11588                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11589                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11590
11591                 if (wfex.wFormatTag == 0x0161) {
11592                   codec_name = "Windows Media Audio";
11593                   version = 2;
11594                 } else if (wfex.wFormatTag == 0x0162) {
11595                   codec_name = "Windows Media Audio 9 Pro";
11596                   version = 3;
11597                 } else if (wfex.wFormatTag == 0x0163) {
11598                   codec_name = "Windows Media Audio 9 Lossless";
11599                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11600                    * fluendo codec seems to support it */
11601                   version = 4;
11602                 }
11603
11604                 gst_caps_set_simple (entry->caps,
11605                     "wmaversion", G_TYPE_INT, version,
11606                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11607                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11608                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11609                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11610
11611                 if (size > wfex.cbSize) {
11612                   GstBuffer *buf;
11613
11614                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11615                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11616                       size - wfex.cbSize);
11617                   gst_caps_set_simple (entry->caps,
11618                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11619                   gst_buffer_unref (buf);
11620                 } else {
11621                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11622                 }
11623
11624                 if (codec_name) {
11625                   g_free (codec);
11626                   codec = g_strdup (codec_name);
11627                 }
11628                 break;
11629               }
11630               default:
11631                 break;
11632             }
11633             len -= size + 8;
11634             wfex_data += size + 8;
11635           }
11636           break;
11637         }
11638         case FOURCC_opus:
11639         {
11640           const guint8 *opus_data;
11641           guint8 *channel_mapping = NULL;
11642           guint32 rate;
11643           guint8 channels;
11644           guint8 channel_mapping_family;
11645           guint8 stream_count;
11646           guint8 coupled_count;
11647           guint8 i;
11648
11649           opus_data = stsd_entry_data;
11650
11651           channels = GST_READ_UINT8 (opus_data + 45);
11652           rate = GST_READ_UINT32_LE (opus_data + 48);
11653           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11654           stream_count = GST_READ_UINT8 (opus_data + 55);
11655           coupled_count = GST_READ_UINT8 (opus_data + 56);
11656
11657           if (channels > 0) {
11658             channel_mapping = g_malloc (channels * sizeof (guint8));
11659             for (i = 0; i < channels; i++)
11660               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11661           }
11662
11663           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11664               channel_mapping_family, stream_count, coupled_count,
11665               channel_mapping);
11666           break;
11667         }
11668         default:
11669           break;
11670       }
11671
11672       if (codec) {
11673         GstStructure *s;
11674         gint bitrate = 0;
11675
11676         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11677             GST_TAG_AUDIO_CODEC, codec, NULL);
11678         g_free (codec);
11679         codec = NULL;
11680
11681         /* some bitrate info may have ended up in caps */
11682         s = gst_caps_get_structure (entry->caps, 0);
11683         gst_structure_get_int (s, "bitrate", &bitrate);
11684         if (bitrate > 0)
11685           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11686               GST_TAG_BITRATE, bitrate, NULL);
11687       }
11688
11689       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11690       if (!stream->protected) {
11691       } else {
11692         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11693           mp4v = NULL;
11694         }
11695       }
11696       if (stream->protected && fourcc == FOURCC_mp4a) {
11697         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11698           mp4a = NULL;
11699         }
11700       } else {
11701         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11702           mp4a = NULL;
11703         }
11704       }
11705
11706       wave = NULL;
11707       esds = NULL;
11708       if (mp4a) {
11709         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11710         if (wave)
11711           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11712         if (!esds)
11713           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11714       }
11715
11716
11717       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11718          16 bits is a byte-swapped wave-style codec identifier,
11719          and we can find a WAVE header internally to a 'wave' atom here.
11720          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11721          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11722          is big-endian).
11723        */
11724       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11725         if (len < offset + 20) {
11726           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11727         } else {
11728           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11729           const guint8 *data = stsd_entry_data + offset + 16;
11730           GNode *wavenode;
11731           GNode *waveheadernode;
11732
11733           wavenode = g_node_new ((guint8 *) data);
11734           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11735             const guint8 *waveheader;
11736             guint32 headerlen;
11737
11738             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11739             if (waveheadernode) {
11740               waveheader = (const guint8 *) waveheadernode->data;
11741               headerlen = QT_UINT32 (waveheader);
11742
11743               if (headerlen > 8) {
11744                 gst_riff_strf_auds *header = NULL;
11745                 GstBuffer *headerbuf;
11746                 GstBuffer *extra;
11747
11748                 waveheader += 8;
11749                 headerlen -= 8;
11750
11751                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11752                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11753
11754                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11755                         headerbuf, &header, &extra)) {
11756                   gst_caps_unref (entry->caps);
11757                   /* FIXME: Need to do something with the channel reorder map */
11758                   entry->caps =
11759                       gst_riff_create_audio_caps (header->format, NULL, header,
11760                       extra, NULL, NULL, NULL);
11761
11762                   if (extra)
11763                     gst_buffer_unref (extra);
11764                   g_free (header);
11765                 }
11766               }
11767             } else
11768               GST_DEBUG ("Didn't find waveheadernode for this codec");
11769           }
11770           g_node_destroy (wavenode);
11771         }
11772       } else if (esds) {
11773         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11774             stream->stream_tags);
11775       } else {
11776         switch (fourcc) {
11777 #if 0
11778             /* FIXME: what is in the chunk? */
11779           case FOURCC_QDMC:
11780           {
11781             gint len = QT_UINT32 (stsd_data);
11782
11783             /* seems to be always = 116 = 0x74 */
11784             break;
11785           }
11786 #endif
11787           case FOURCC_QDM2:
11788           {
11789             gint len = QT_UINT32 (stsd_entry_data);
11790
11791             if (len > 0x3C) {
11792               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11793
11794               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11795               gst_caps_set_simple (entry->caps,
11796                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11797               gst_buffer_unref (buf);
11798             }
11799             gst_caps_set_simple (entry->caps,
11800                 "samplesize", G_TYPE_INT, samplesize, NULL);
11801             break;
11802           }
11803           case FOURCC_alac:
11804           {
11805             GNode *alac, *wave = NULL;
11806
11807             /* apparently, m4a has this atom appended directly in the stsd entry,
11808              * while mov has it in a wave atom */
11809             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11810             if (alac) {
11811               /* alac now refers to stsd entry atom */
11812               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11813               if (wave)
11814                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11815               else
11816                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11817             }
11818             if (alac) {
11819               const guint8 *alac_data = alac->data;
11820               gint len = QT_UINT32 (alac->data);
11821               GstBuffer *buf;
11822
11823               if (len < 36) {
11824                 GST_DEBUG_OBJECT (qtdemux,
11825                     "discarding alac atom with unexpected len %d", len);
11826               } else {
11827                 /* codec-data contains alac atom size and prefix,
11828                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11829                 buf = gst_buffer_new_and_alloc (len);
11830                 gst_buffer_fill (buf, 0, alac->data, len);
11831                 gst_caps_set_simple (entry->caps,
11832                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11833                 gst_buffer_unref (buf);
11834
11835                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11836                 entry->n_channels = QT_UINT8 (alac_data + 21);
11837                 entry->rate = QT_UINT32 (alac_data + 32);
11838               }
11839             }
11840             gst_caps_set_simple (entry->caps,
11841                 "samplesize", G_TYPE_INT, samplesize, NULL);
11842             break;
11843           }
11844           case FOURCC_fLaC:
11845           {
11846             /* The codingname of the sample entry is 'fLaC' */
11847             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11848
11849             if (flac) {
11850               /* The 'dfLa' box is added to the sample entry to convey
11851                  initializing information for the decoder. */
11852               const GNode *dfla =
11853                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11854
11855               if (dfla) {
11856                 const guint32 len = QT_UINT32 (dfla->data);
11857
11858                 /* Must contain at least dfLa box header (12),
11859                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11860                 if (len < 50) {
11861                   GST_DEBUG_OBJECT (qtdemux,
11862                       "discarding dfla atom with unexpected len %d", len);
11863                 } else {
11864                   /* skip dfLa header to get the METADATA_BLOCKs */
11865                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11866                   const guint32 metadata_blocks_len = len - 12;
11867
11868                   gchar *stream_marker = g_strdup ("fLaC");
11869                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11870                       strlen (stream_marker));
11871
11872                   guint32 index = 0;
11873                   guint32 remainder = 0;
11874                   guint32 block_size = 0;
11875                   gboolean is_last = FALSE;
11876
11877                   GValue array = G_VALUE_INIT;
11878                   GValue value = G_VALUE_INIT;
11879
11880                   g_value_init (&array, GST_TYPE_ARRAY);
11881                   g_value_init (&value, GST_TYPE_BUFFER);
11882
11883                   gst_value_set_buffer (&value, block);
11884                   gst_value_array_append_value (&array, &value);
11885                   g_value_reset (&value);
11886
11887                   gst_buffer_unref (block);
11888
11889                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11890                    * of data, and we haven't already finished parsing */
11891                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11892                     remainder = metadata_blocks_len - index;
11893
11894                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11895                     block_size = 4 +
11896                         (metadata_blocks[index + 1] << 16) +
11897                         (metadata_blocks[index + 2] << 8) +
11898                         metadata_blocks[index + 3];
11899
11900                     /* be careful not to read off end of box */
11901                     if (block_size > remainder) {
11902                       break;
11903                     }
11904
11905                     is_last = metadata_blocks[index] >> 7;
11906
11907                     block = gst_buffer_new_and_alloc (block_size);
11908
11909                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11910                         block_size);
11911
11912                     gst_value_set_buffer (&value, block);
11913                     gst_value_array_append_value (&array, &value);
11914                     g_value_reset (&value);
11915
11916                     gst_buffer_unref (block);
11917
11918                     index += block_size;
11919                   }
11920
11921                   /* only append the metadata if we successfully read all of it */
11922                   if (is_last) {
11923                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11924                             (stream)->caps, 0), "streamheader", &array);
11925                   } else {
11926                     GST_WARNING_OBJECT (qtdemux,
11927                         "discarding all METADATA_BLOCKs due to invalid "
11928                         "block_size %d at idx %d, rem %d", block_size, index,
11929                         remainder);
11930                   }
11931
11932                   g_value_unset (&value);
11933                   g_value_unset (&array);
11934
11935                   /* The sample rate obtained from the stsd may not be accurate
11936                    * since it cannot represent rates greater than 65535Hz, so
11937                    * override that value with the sample rate from the
11938                    * METADATA_BLOCK_STREAMINFO block */
11939                   CUR_STREAM (stream)->rate =
11940                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11941                 }
11942               }
11943             }
11944             break;
11945           }
11946           case FOURCC_sawb:
11947             /* Fallthrough! */
11948             amrwb = TRUE;
11949           case FOURCC_samr:
11950           {
11951             gint len = QT_UINT32 (stsd_entry_data);
11952
11953             if (len > 0x24) {
11954               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11955               guint bitrate;
11956
11957               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11958
11959               /* If we have enough data, let's try to get the 'damr' atom. See
11960                * the 3GPP container spec (26.244) for more details. */
11961               if ((len - 0x34) > 8 &&
11962                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11963                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11964                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11965               }
11966
11967               gst_caps_set_simple (entry->caps,
11968                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11969               gst_buffer_unref (buf);
11970             }
11971             break;
11972           }
11973           case FOURCC_mp4a:
11974           {
11975             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11976             gint len = QT_UINT32 (stsd_entry_data);
11977
11978             if (len >= 34) {
11979               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11980
11981               if (sound_version == 1) {
11982                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11983                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11984                 guint8 codec_data[2];
11985                 GstBuffer *buf;
11986                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11987
11988                 gint sample_rate_index =
11989                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11990
11991                 /* build AAC codec data */
11992                 codec_data[0] = profile << 3;
11993                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11994                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11995                 codec_data[1] |= (channels & 0xF) << 3;
11996
11997                 buf = gst_buffer_new_and_alloc (2);
11998                 gst_buffer_fill (buf, 0, codec_data, 2);
11999                 gst_caps_set_simple (entry->caps,
12000                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12001                 gst_buffer_unref (buf);
12002               }
12003             }
12004             break;
12005           }
12006           case FOURCC_lpcm:
12007             /* Fully handled elsewhere */
12008             break;
12009           default:
12010             GST_INFO_OBJECT (qtdemux,
12011                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12012             break;
12013         }
12014       }
12015       GST_INFO_OBJECT (qtdemux,
12016           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12017           GST_FOURCC_ARGS (fourcc), entry->caps);
12018
12019     } else if (stream->subtype == FOURCC_strm) {
12020       if (fourcc == FOURCC_rtsp) {
12021         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12022       } else {
12023         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12024             GST_FOURCC_ARGS (fourcc));
12025         goto unknown_stream;
12026       }
12027       entry->sampled = TRUE;
12028     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12029         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12030         || stream->subtype == FOURCC_clcp) {
12031
12032       entry->sampled = TRUE;
12033       entry->sparse = TRUE;
12034
12035       entry->caps =
12036           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12037           &codec);
12038       if (codec) {
12039         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12040             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12041         g_free (codec);
12042         codec = NULL;
12043       }
12044
12045       /* hunt for sort-of codec data */
12046       switch (fourcc) {
12047         case FOURCC_mp4s:
12048         {
12049           GNode *mp4s = NULL;
12050           GNode *esds = NULL;
12051
12052           /* look for palette in a stsd->mp4s->esds sub-atom */
12053           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12054           if (mp4s)
12055             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12056           if (esds == NULL) {
12057             /* Invalid STSD */
12058             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12059             break;
12060           }
12061
12062           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12063               stream->stream_tags);
12064           break;
12065         }
12066         default:
12067           GST_INFO_OBJECT (qtdemux,
12068               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12069           break;
12070       }
12071       GST_INFO_OBJECT (qtdemux,
12072           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12073           GST_FOURCC_ARGS (fourcc), entry->caps);
12074     } else {
12075       /* everything in 1 sample */
12076       entry->sampled = TRUE;
12077
12078       entry->caps =
12079           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12080           &codec);
12081
12082       if (entry->caps == NULL)
12083         goto unknown_stream;
12084
12085       if (codec) {
12086         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12087             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12088         g_free (codec);
12089         codec = NULL;
12090       }
12091     }
12092
12093     /* promote to sampled format */
12094     if (entry->fourcc == FOURCC_samr) {
12095       /* force mono 8000 Hz for AMR */
12096       entry->sampled = TRUE;
12097       entry->n_channels = 1;
12098       entry->rate = 8000;
12099     } else if (entry->fourcc == FOURCC_sawb) {
12100       /* force mono 16000 Hz for AMR-WB */
12101       entry->sampled = TRUE;
12102       entry->n_channels = 1;
12103       entry->rate = 16000;
12104     } else if (entry->fourcc == FOURCC_mp4a) {
12105       entry->sampled = TRUE;
12106     }
12107
12108
12109     stsd_entry_data += len;
12110     remaining_stsd_len -= len;
12111
12112   }
12113
12114   /* collect sample information */
12115   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12116     goto samples_failed;
12117
12118   if (qtdemux->fragmented) {
12119     guint64 offset;
12120
12121     /* need all moov samples as basis; probably not many if any at all */
12122     /* prevent moof parsing taking of at this time */
12123     offset = qtdemux->moof_offset;
12124     qtdemux->moof_offset = 0;
12125     if (stream->n_samples &&
12126         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12127       qtdemux->moof_offset = offset;
12128       goto samples_failed;
12129     }
12130     qtdemux->moof_offset = 0;
12131     /* movie duration more reliable in this case (e.g. mehd) */
12132     if (qtdemux->segment.duration &&
12133         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12134       stream->duration =
12135           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12136   }
12137
12138   /* configure segments */
12139   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12140     goto segments_failed;
12141
12142   /* add some language tag, if useful */
12143   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12144       strcmp (stream->lang_id, "und")) {
12145     const gchar *lang_code;
12146
12147     /* convert ISO 639-2 code to ISO 639-1 */
12148     lang_code = gst_tag_get_language_code (stream->lang_id);
12149     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12150         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12151   }
12152
12153   /* Check for UDTA tags */
12154   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12155     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12156   }
12157
12158   /* Insert and sort new stream in track-id order.
12159    * This will help in comparing old/new streams during stream update check */
12160   qtdemux->active_streams =
12161       g_list_insert_sorted (qtdemux->active_streams, stream,
12162       (GCompareFunc) qtdemux_track_id_compare_func);
12163   qtdemux->n_streams++;
12164   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12165
12166   return TRUE;
12167
12168 /* ERRORS */
12169 corrupt_file:
12170   {
12171     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12172         (_("This file is corrupt and cannot be played.")), (NULL));
12173     if (stream)
12174       gst_qtdemux_stream_free (stream);
12175     return FALSE;
12176   }
12177 error_encrypted:
12178   {
12179     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12180     gst_qtdemux_stream_free (stream);
12181     return FALSE;
12182   }
12183 samples_failed:
12184 segments_failed:
12185   {
12186     /* we posted an error already */
12187     /* free stbl sub-atoms */
12188     gst_qtdemux_stbl_free (stream);
12189     gst_qtdemux_stream_free (stream);
12190     return FALSE;
12191   }
12192 existing_stream:
12193   {
12194     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12195         track_id);
12196     return TRUE;
12197   }
12198 unknown_stream:
12199   {
12200     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12201         GST_FOURCC_ARGS (stream->subtype));
12202     gst_qtdemux_stream_free (stream);
12203     return TRUE;
12204   }
12205 }
12206
12207 /* If we can estimate the overall bitrate, and don't have information about the
12208  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12209  * the overall bitrate minus the sum of the bitrates of all other streams. This
12210  * should be useful for the common case where we have one audio and one video
12211  * stream and can estimate the bitrate of one, but not the other. */
12212 static void
12213 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12214 {
12215   QtDemuxStream *stream = NULL;
12216   gint64 size, sys_bitrate, sum_bitrate = 0;
12217   GstClockTime duration;
12218   guint bitrate;
12219   GList *iter;
12220
12221   if (qtdemux->fragmented)
12222     return;
12223
12224   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12225
12226   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12227       || size <= 0) {
12228     GST_DEBUG_OBJECT (qtdemux,
12229         "Size in bytes of the stream not known - bailing");
12230     return;
12231   }
12232
12233   /* Subtract the header size */
12234   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12235       size, qtdemux->header_size);
12236
12237   if (size < qtdemux->header_size)
12238     return;
12239
12240   size = size - qtdemux->header_size;
12241
12242   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12243     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12244     return;
12245   }
12246
12247   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12248     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12249     switch (str->subtype) {
12250       case FOURCC_soun:
12251       case FOURCC_vide:
12252         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12253             CUR_STREAM (str)->caps);
12254         /* retrieve bitrate, prefer avg then max */
12255         bitrate = 0;
12256         if (str->stream_tags) {
12257           if (gst_tag_list_get_uint (str->stream_tags,
12258                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12259             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12260           if (gst_tag_list_get_uint (str->stream_tags,
12261                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12262             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12263           if (gst_tag_list_get_uint (str->stream_tags,
12264                   GST_TAG_BITRATE, &bitrate))
12265             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12266         }
12267         if (bitrate)
12268           sum_bitrate += bitrate;
12269         else {
12270           if (stream) {
12271             GST_DEBUG_OBJECT (qtdemux,
12272                 ">1 stream with unknown bitrate - bailing");
12273             return;
12274           } else
12275             stream = str;
12276         }
12277
12278       default:
12279         /* For other subtypes, we assume no significant impact on bitrate */
12280         break;
12281     }
12282   }
12283
12284   if (!stream) {
12285     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12286     return;
12287   }
12288
12289   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12290
12291   if (sys_bitrate < sum_bitrate) {
12292     /* This can happen, since sum_bitrate might be derived from maximum
12293      * bitrates and not average bitrates */
12294     GST_DEBUG_OBJECT (qtdemux,
12295         "System bitrate less than sum bitrate - bailing");
12296     return;
12297   }
12298
12299   bitrate = sys_bitrate - sum_bitrate;
12300   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12301       ", Stream bitrate = %u", sys_bitrate, bitrate);
12302
12303   if (!stream->stream_tags)
12304     stream->stream_tags = gst_tag_list_new_empty ();
12305   else
12306     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12307
12308   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12309       GST_TAG_BITRATE, bitrate, NULL);
12310 }
12311
12312 static GstFlowReturn
12313 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12314 {
12315   GstFlowReturn ret = GST_FLOW_OK;
12316   GList *iter, *next;
12317
12318   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12319
12320   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12321     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12322     guint32 sample_num = 0;
12323
12324     next = iter->next;
12325
12326     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12327         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12328
12329     if (qtdemux->fragmented) {
12330       /* need all moov samples first */
12331       GST_OBJECT_LOCK (qtdemux);
12332       while (stream->n_samples == 0)
12333         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12334           break;
12335       GST_OBJECT_UNLOCK (qtdemux);
12336     } else {
12337       /* discard any stray moof */
12338       qtdemux->moof_offset = 0;
12339     }
12340
12341     /* prepare braking */
12342     if (ret != GST_FLOW_ERROR)
12343       ret = GST_FLOW_OK;
12344
12345     /* in pull mode, we should have parsed some sample info by now;
12346      * and quite some code will not handle no samples.
12347      * in push mode, we'll just have to deal with it */
12348     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12349       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12350       gst_qtdemux_remove_stream (qtdemux, stream);
12351       continue;
12352     } else if (stream->track_id == qtdemux->chapters_track_id &&
12353         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12354       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12355          so that it doesn't look like a subtitle track */
12356       gst_qtdemux_remove_stream (qtdemux, stream);
12357       continue;
12358     }
12359
12360     /* parse the initial sample for use in setting the frame rate cap */
12361     while (sample_num == 0 && sample_num < stream->n_samples) {
12362       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12363         break;
12364       ++sample_num;
12365     }
12366   }
12367
12368   return ret;
12369 }
12370
12371 static GList *
12372 _stream_in_list (GList * list, QtDemuxStream * stream)
12373 {
12374   GList *iter;
12375
12376   for (iter = list; iter; iter = g_list_next (iter)) {
12377     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12378     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12379       return iter;
12380   }
12381
12382   return NULL;
12383 }
12384
12385 static gboolean
12386 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12387 {
12388   GList *new, *old;
12389
12390   if (!qtdemux->active_streams)
12391     return FALSE;
12392
12393   /* streams in list are sorted in track-id order */
12394   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12395       new = g_list_next (new), old = g_list_next (old)) {
12396
12397     /* Different stream-id, updated */
12398     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12399             QTDEMUX_STREAM (old->data)->stream_id))
12400       return TRUE;
12401   }
12402
12403   /* Different length, updated */
12404   if (new != NULL || old != NULL)
12405     return TRUE;
12406
12407   return FALSE;
12408 }
12409
12410 static gboolean
12411 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12412     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12413 {
12414   /* Connect old stream's srcpad to new stream */
12415   newstream->pad = oldstream->pad;
12416   oldstream->pad = NULL;
12417
12418   /* unset new_stream to prevent stream-start event */
12419   newstream->new_stream = FALSE;
12420
12421   return gst_qtdemux_configure_stream (qtdemux, newstream);
12422 }
12423
12424 static gboolean
12425 qtdemux_update_streams (GstQTDemux * qtdemux)
12426 {
12427   GList *iter, *next;
12428   g_assert (qtdemux->streams_aware);
12429
12430   /* At below, figure out which stream in active_streams has identical stream-id
12431    * with that of in old_streams. If there is matching stream-id,
12432    * corresponding newstream will not be exposed again,
12433    * but demux will reuse srcpad of matched old stream
12434    *
12435    * active_streams : newly created streams from the latest moov
12436    * old_streams : existing streams (belong to previous moov)
12437    */
12438
12439   /* Count n_streams again */
12440   qtdemux->n_streams = 0;
12441
12442   for (iter = qtdemux->active_streams; iter; iter = next) {
12443     GList *tmp;
12444     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12445
12446     next = iter->next;
12447
12448     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12449         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12450
12451     qtdemux->n_streams++;
12452
12453     if ((tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12454         && QTDEMUX_STREAM (tmp->data)->pad) {
12455       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12456
12457       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12458
12459       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12460         return FALSE;
12461
12462       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12463       gst_qtdemux_stream_free (oldstream);
12464     } else {
12465       GstTagList *list;
12466
12467       /* now we have all info and can expose */
12468       list = stream->stream_tags;
12469       stream->stream_tags = NULL;
12470       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12471         return FALSE;
12472     }
12473   }
12474
12475   return TRUE;
12476 }
12477
12478 /* Must be called with expose lock */
12479 static GstFlowReturn
12480 qtdemux_expose_streams (GstQTDemux * qtdemux)
12481 {
12482   GList *iter, *next;
12483
12484   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12485
12486   if (!qtdemux_is_streams_update (qtdemux)) {
12487     GList *new, *old;
12488
12489     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12490     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12491         new = g_list_next (new), old = g_list_next (old)) {
12492       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12493               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12494         return GST_FLOW_ERROR;
12495     }
12496
12497     g_list_free_full (qtdemux->old_streams,
12498         (GDestroyNotify) gst_qtdemux_stream_free);
12499     qtdemux->old_streams = NULL;
12500
12501     return GST_FLOW_OK;
12502   }
12503
12504   if (qtdemux->streams_aware) {
12505     if (!qtdemux_update_streams (qtdemux))
12506       return GST_FLOW_ERROR;
12507   } else {
12508     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12509       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12510       GstTagList *list;
12511
12512       /* now we have all info and can expose */
12513       list = stream->stream_tags;
12514       stream->stream_tags = NULL;
12515       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12516         return GST_FLOW_ERROR;
12517
12518     }
12519   }
12520
12521   gst_qtdemux_guess_bitrate (qtdemux);
12522
12523   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12524
12525   /* If we have still old_streams, it's no more used stream */
12526   for (iter = qtdemux->old_streams; iter; iter = next) {
12527     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12528     next = g_list_next (iter);
12529
12530     if (stream->pad) {
12531       GstEvent *event;
12532
12533       event = gst_event_new_eos ();
12534       if (qtdemux->segment_seqnum)
12535         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12536
12537       gst_pad_push_event (stream->pad, event);
12538     }
12539
12540     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12541     gst_qtdemux_stream_free (stream);
12542   }
12543
12544   /* check if we should post a redirect in case there is a single trak
12545    * and it is a redirecting trak */
12546   if (qtdemux->n_streams == 1 &&
12547       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12548     GstMessage *m;
12549
12550     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12551         "an external content");
12552     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12553         gst_structure_new ("redirect",
12554             "new-location", G_TYPE_STRING,
12555             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12556     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12557     qtdemux->posted_redirect = TRUE;
12558   }
12559
12560   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12561     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (iter->data));
12562   }
12563
12564   qtdemux->need_segment = TRUE;
12565
12566   qtdemux->exposed = TRUE;
12567   return GST_FLOW_OK;
12568 }
12569
12570 /* check if major or compatible brand is 3GP */
12571 static inline gboolean
12572 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12573 {
12574   if (major) {
12575     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12576         FOURCC_3g__);
12577   } else if (qtdemux->comp_brands != NULL) {
12578     GstMapInfo map;
12579     guint8 *data;
12580     gsize size;
12581     gboolean res = FALSE;
12582
12583     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12584     data = map.data;
12585     size = map.size;
12586     while (size >= 4) {
12587       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12588           FOURCC_3g__);
12589       data += 4;
12590       size -= 4;
12591     }
12592     gst_buffer_unmap (qtdemux->comp_brands, &map);
12593     return res;
12594   } else {
12595     return FALSE;
12596   }
12597 }
12598
12599 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12600 static inline gboolean
12601 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12602 {
12603   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12604       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12605       || fourcc == FOURCC_albm;
12606 }
12607
12608 static void
12609 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12610     const char *tag, const char *dummy, GNode * node)
12611 {
12612   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12613   int offset;
12614   char *name;
12615   gchar *data;
12616   gdouble longitude, latitude, altitude;
12617   gint len;
12618
12619   len = QT_UINT32 (node->data);
12620   if (len <= 14)
12621     goto short_read;
12622
12623   data = node->data;
12624   offset = 14;
12625
12626   /* TODO: language code skipped */
12627
12628   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12629
12630   if (!name) {
12631     /* do not alarm in trivial case, but bail out otherwise */
12632     if (*(data + offset) != 0) {
12633       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12634           "giving up", tag);
12635     }
12636   } else {
12637     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12638         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12639     offset += strlen (name);
12640     g_free (name);
12641   }
12642
12643   if (len < offset + 2 + 4 + 4 + 4)
12644     goto short_read;
12645
12646   /* +1 +1 = skip null-terminator and location role byte */
12647   offset += 1 + 1;
12648   /* table in spec says unsigned, semantics say negative has meaning ... */
12649   longitude = QT_SFP32 (data + offset);
12650
12651   offset += 4;
12652   latitude = QT_SFP32 (data + offset);
12653
12654   offset += 4;
12655   altitude = QT_SFP32 (data + offset);
12656
12657   /* one invalid means all are invalid */
12658   if (longitude >= -180.0 && longitude <= 180.0 &&
12659       latitude >= -90.0 && latitude <= 90.0) {
12660     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12661         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12662         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12663         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12664   }
12665
12666   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12667
12668   return;
12669
12670   /* ERRORS */
12671 short_read:
12672   {
12673     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12674     return;
12675   }
12676 }
12677
12678
12679 static void
12680 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12681     const char *tag, const char *dummy, GNode * node)
12682 {
12683   guint16 y;
12684   GDate *date;
12685   gint len;
12686
12687   len = QT_UINT32 (node->data);
12688   if (len < 14)
12689     return;
12690
12691   y = QT_UINT16 ((guint8 *) node->data + 12);
12692   if (y == 0) {
12693     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12694     return;
12695   }
12696   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12697
12698   date = g_date_new_dmy (1, 1, y);
12699   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12700   g_date_free (date);
12701 }
12702
12703 static void
12704 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12705     const char *tag, const char *dummy, GNode * node)
12706 {
12707   int offset;
12708   char *tag_str = NULL;
12709   guint8 *entity;
12710   guint16 table;
12711   gint len;
12712
12713   len = QT_UINT32 (node->data);
12714   if (len <= 20)
12715     goto short_read;
12716
12717   offset = 12;
12718   entity = (guint8 *) node->data + offset;
12719   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12720     GST_DEBUG_OBJECT (qtdemux,
12721         "classification info: %c%c%c%c invalid classification entity",
12722         entity[0], entity[1], entity[2], entity[3]);
12723     return;
12724   }
12725
12726   offset += 4;
12727   table = QT_UINT16 ((guint8 *) node->data + offset);
12728
12729   /* Language code skipped */
12730
12731   offset += 4;
12732
12733   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12734    * XXXX: classification entity, fixed length 4 chars.
12735    * Y[YYYY]: classification table, max 5 chars.
12736    */
12737   tag_str = g_strdup_printf ("----://%u/%s",
12738       table, (char *) node->data + offset);
12739
12740   /* memcpy To be sure we're preserving byte order */
12741   memcpy (tag_str, entity, 4);
12742   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12743
12744   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12745
12746   g_free (tag_str);
12747
12748   return;
12749
12750   /* ERRORS */
12751 short_read:
12752   {
12753     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12754     return;
12755   }
12756 }
12757
12758 static gboolean
12759 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12760     const char *tag, const char *dummy, GNode * node)
12761 {
12762   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12763   GNode *data;
12764   char *s;
12765   int len;
12766   guint32 type;
12767   int offset;
12768   gboolean ret = TRUE;
12769   const gchar *charset = NULL;
12770
12771   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12772   if (data) {
12773     len = QT_UINT32 (data->data);
12774     type = QT_UINT32 ((guint8 *) data->data + 8);
12775     if (type == 0x00000001 && len > 16) {
12776       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12777           env_vars);
12778       if (s) {
12779         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12780         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12781         g_free (s);
12782       } else {
12783         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12784       }
12785     }
12786   } else {
12787     len = QT_UINT32 (node->data);
12788     type = QT_UINT32 ((guint8 *) node->data + 4);
12789     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12790       gint str_len;
12791       gint lang_code;
12792
12793       /* Type starts with the (C) symbol, so the next data is a list
12794        * of (string size(16), language code(16), string) */
12795
12796       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12797       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12798
12799       /* the string + fourcc + size + 2 16bit fields,
12800        * means that there are more tags in this atom */
12801       if (len > str_len + 8 + 4) {
12802         /* TODO how to represent the same tag in different languages? */
12803         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12804             "text alternatives, reading only first one");
12805       }
12806
12807       offset = 12;
12808       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12809       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12810
12811       if (lang_code < 0x800) {  /* MAC encoded string */
12812         charset = "mac";
12813       }
12814     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12815             QT_FOURCC ((guint8 *) node->data + 4))) {
12816       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12817
12818       /* we go for 3GP style encoding if major brands claims so,
12819        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12820       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12821           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12822               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12823         offset = 14;
12824         /* 16-bit Language code is ignored here as well */
12825         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12826       } else {
12827         goto normal;
12828       }
12829     } else {
12830     normal:
12831       offset = 8;
12832       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12833       ret = FALSE;              /* may have to fallback */
12834     }
12835     if (charset) {
12836       GError *err = NULL;
12837
12838       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12839           charset, NULL, NULL, &err);
12840       if (err) {
12841         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12842             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12843             err->message);
12844         g_error_free (err);
12845       }
12846     } else {
12847       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12848           len - offset, env_vars);
12849     }
12850     if (s) {
12851       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12852       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12853       g_free (s);
12854       ret = TRUE;
12855     } else {
12856       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12857     }
12858   }
12859   return ret;
12860 }
12861
12862 static void
12863 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12864     const char *tag, const char *dummy, GNode * node)
12865 {
12866   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12867 }
12868
12869 static void
12870 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12871     const char *tag, const char *dummy, GNode * node)
12872 {
12873   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12874   guint8 *data;
12875   char *s, *t, *k = NULL;
12876   int len;
12877   int offset;
12878   int count;
12879
12880   /* first try normal string tag if major brand not 3GP */
12881   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12882     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12883       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12884        * let's try it 3gpp way after minor safety check */
12885       data = node->data;
12886       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12887         return;
12888     } else
12889       return;
12890   }
12891
12892   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12893
12894   data = node->data;
12895
12896   len = QT_UINT32 (data);
12897   if (len < 15)
12898     goto short_read;
12899
12900   count = QT_UINT8 (data + 14);
12901   offset = 15;
12902   for (; count; count--) {
12903     gint slen;
12904
12905     if (offset + 1 > len)
12906       goto short_read;
12907     slen = QT_UINT8 (data + offset);
12908     offset += 1;
12909     if (offset + slen > len)
12910       goto short_read;
12911     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12912         slen, env_vars);
12913     if (s) {
12914       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12915       if (k) {
12916         t = g_strjoin (",", k, s, NULL);
12917         g_free (s);
12918         g_free (k);
12919         k = t;
12920       } else {
12921         k = s;
12922       }
12923     } else {
12924       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12925     }
12926     offset += slen;
12927   }
12928
12929 done:
12930   if (k) {
12931     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12932     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12933   }
12934   g_free (k);
12935
12936   return;
12937
12938   /* ERRORS */
12939 short_read:
12940   {
12941     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12942     goto done;
12943   }
12944 }
12945
12946 static void
12947 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12948     const char *tag1, const char *tag2, GNode * node)
12949 {
12950   GNode *data;
12951   int len;
12952   int type;
12953   int n1, n2;
12954
12955   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12956   if (data) {
12957     len = QT_UINT32 (data->data);
12958     type = QT_UINT32 ((guint8 *) data->data + 8);
12959     if (type == 0x00000000 && len >= 22) {
12960       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12961       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12962       if (n1 > 0) {
12963         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12964         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12965       }
12966       if (n2 > 0) {
12967         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12968         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12969       }
12970     }
12971   }
12972 }
12973
12974 static void
12975 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12976     const char *tag1, const char *dummy, GNode * node)
12977 {
12978   GNode *data;
12979   int len;
12980   int type;
12981   int n1;
12982
12983   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12984   if (data) {
12985     len = QT_UINT32 (data->data);
12986     type = QT_UINT32 ((guint8 *) data->data + 8);
12987     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12988     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12989     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12990       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12991       if (n1) {
12992         /* do not add bpm=0 */
12993         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12994         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12995             NULL);
12996       }
12997     }
12998   }
12999 }
13000
13001 static void
13002 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13003     const char *tag1, const char *dummy, GNode * node)
13004 {
13005   GNode *data;
13006   int len;
13007   int type;
13008   guint32 num;
13009
13010   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13011   if (data) {
13012     len = QT_UINT32 (data->data);
13013     type = QT_UINT32 ((guint8 *) data->data + 8);
13014     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13015     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13016     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13017       num = QT_UINT32 ((guint8 *) data->data + 16);
13018       if (num) {
13019         /* do not add num=0 */
13020         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13021         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13022       }
13023     }
13024   }
13025 }
13026
13027 static void
13028 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13029     const char *tag1, const char *dummy, GNode * node)
13030 {
13031   GNode *data;
13032   int len;
13033   int type;
13034   GstSample *sample;
13035
13036   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13037   if (data) {
13038     len = QT_UINT32 (data->data);
13039     type = QT_UINT32 ((guint8 *) data->data + 8);
13040     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13041     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13042       GstTagImageType image_type;
13043
13044       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13045         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13046       else
13047         image_type = GST_TAG_IMAGE_TYPE_NONE;
13048
13049       if ((sample =
13050               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13051                   len - 16, image_type))) {
13052         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13053         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13054         gst_sample_unref (sample);
13055       }
13056     }
13057   }
13058 }
13059
13060 static void
13061 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13062     const char *tag, const char *dummy, GNode * node)
13063 {
13064   GNode *data;
13065   GstDateTime *datetime = NULL;
13066   char *s;
13067   int len;
13068   int type;
13069
13070   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13071   if (data) {
13072     len = QT_UINT32 (data->data);
13073     type = QT_UINT32 ((guint8 *) data->data + 8);
13074     if (type == 0x00000001 && len > 16) {
13075       guint y, m = 1, d = 1;
13076       gint ret;
13077
13078       s = g_strndup ((char *) data->data + 16, len - 16);
13079       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13080       datetime = gst_date_time_new_from_iso8601_string (s);
13081       if (datetime != NULL) {
13082         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13083             datetime, NULL);
13084         gst_date_time_unref (datetime);
13085       }
13086
13087       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13088       if (ret >= 1 && y > 1500 && y < 3000) {
13089         GDate *date;
13090
13091         date = g_date_new_dmy (d, m, y);
13092         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13093         g_date_free (date);
13094       } else {
13095         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13096       }
13097       g_free (s);
13098     }
13099   }
13100 }
13101
13102 static void
13103 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13104     const char *tag, const char *dummy, GNode * node)
13105 {
13106   GNode *data;
13107
13108   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13109
13110   /* re-route to normal string tag if major brand says so
13111    * or no data atom and compatible brand suggests so */
13112   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13113       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13114     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13115     return;
13116   }
13117
13118   if (data) {
13119     guint len, type, n;
13120
13121     len = QT_UINT32 (data->data);
13122     type = QT_UINT32 ((guint8 *) data->data + 8);
13123     if (type == 0x00000000 && len >= 18) {
13124       n = QT_UINT16 ((guint8 *) data->data + 16);
13125       if (n > 0) {
13126         const gchar *genre;
13127
13128         genre = gst_tag_id3_genre_get (n - 1);
13129         if (genre != NULL) {
13130           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13131           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13132         }
13133       }
13134     }
13135   }
13136 }
13137
13138 static void
13139 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13140     const gchar * tag, guint8 * data, guint32 datasize)
13141 {
13142   gdouble value;
13143   gchar *datacopy;
13144
13145   /* make a copy to have \0 at the end */
13146   datacopy = g_strndup ((gchar *) data, datasize);
13147
13148   /* convert the str to double */
13149   if (sscanf (datacopy, "%lf", &value) == 1) {
13150     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13151     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13152   } else {
13153     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13154         datacopy);
13155   }
13156   g_free (datacopy);
13157 }
13158
13159
13160 static void
13161 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13162     const char *tag, const char *tag_bis, GNode * node)
13163 {
13164   GNode *mean;
13165   GNode *name;
13166   GNode *data;
13167   guint32 meansize;
13168   guint32 namesize;
13169   guint32 datatype;
13170   guint32 datasize;
13171   const gchar *meanstr;
13172   const gchar *namestr;
13173
13174   /* checking the whole ---- atom size for consistency */
13175   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13176     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13177     return;
13178   }
13179
13180   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13181   if (!mean) {
13182     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13183     return;
13184   }
13185
13186   meansize = QT_UINT32 (mean->data);
13187   if (meansize <= 12) {
13188     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13189     return;
13190   }
13191   meanstr = ((gchar *) mean->data) + 12;
13192   meansize -= 12;
13193
13194   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13195   if (!name) {
13196     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13197     return;
13198   }
13199
13200   namesize = QT_UINT32 (name->data);
13201   if (namesize <= 12) {
13202     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13203     return;
13204   }
13205   namestr = ((gchar *) name->data) + 12;
13206   namesize -= 12;
13207
13208   /*
13209    * Data atom is:
13210    * uint32 - size
13211    * uint32 - name
13212    * uint8  - version
13213    * uint24 - data type
13214    * uint32 - all 0
13215    * rest   - the data
13216    */
13217   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13218   if (!data) {
13219     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13220     return;
13221   }
13222   datasize = QT_UINT32 (data->data);
13223   if (datasize <= 16) {
13224     GST_WARNING_OBJECT (demux, "Data atom too small");
13225     return;
13226   }
13227   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13228
13229   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13230       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13231     static const struct
13232     {
13233       const gchar name[28];
13234       const gchar tag[28];
13235     } tags[] = {
13236       {
13237       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13238       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13239       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13240       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13241       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13242       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13243       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13244       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13245     };
13246     int i;
13247
13248     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13249       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13250         switch (gst_tag_get_type (tags[i].tag)) {
13251           case G_TYPE_DOUBLE:
13252             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13253                 ((guint8 *) data->data) + 16, datasize - 16);
13254             break;
13255           case G_TYPE_STRING:
13256             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13257             break;
13258           default:
13259             /* not reached */
13260             break;
13261         }
13262         break;
13263       }
13264     }
13265     if (i == G_N_ELEMENTS (tags))
13266       goto unknown_tag;
13267   } else {
13268     goto unknown_tag;
13269   }
13270
13271   return;
13272
13273 /* errors */
13274 unknown_tag:
13275 #ifndef GST_DISABLE_GST_DEBUG
13276   {
13277     gchar *namestr_dbg;
13278     gchar *meanstr_dbg;
13279
13280     meanstr_dbg = g_strndup (meanstr, meansize);
13281     namestr_dbg = g_strndup (namestr, namesize);
13282
13283     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13284         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13285
13286     g_free (namestr_dbg);
13287     g_free (meanstr_dbg);
13288   }
13289 #endif
13290   return;
13291 }
13292
13293 static void
13294 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13295     const char *tag_bis, GNode * node)
13296 {
13297   guint8 *data;
13298   GstBuffer *buf;
13299   guint len;
13300   GstTagList *id32_taglist = NULL;
13301
13302   GST_LOG_OBJECT (demux, "parsing ID32");
13303
13304   data = node->data;
13305   len = GST_READ_UINT32_BE (data);
13306
13307   /* need at least full box and language tag */
13308   if (len < 12 + 2)
13309     return;
13310
13311   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13312   gst_buffer_fill (buf, 0, data + 14, len - 14);
13313
13314   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13315   if (id32_taglist) {
13316     GST_LOG_OBJECT (demux, "parsing ok");
13317     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13318     gst_tag_list_unref (id32_taglist);
13319   } else {
13320     GST_LOG_OBJECT (demux, "parsing failed");
13321   }
13322
13323   gst_buffer_unref (buf);
13324 }
13325
13326 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13327     const char *tag, const char *tag_bis, GNode * node);
13328
13329 /* unmapped tags
13330 FOURCC_pcst -> if media is a podcast -> bool
13331 FOURCC_cpil -> if media is part of a compilation -> bool
13332 FOURCC_pgap -> if media is part of a gapless context -> bool
13333 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13334 */
13335
13336 static const struct
13337 {
13338   guint32 fourcc;
13339   const gchar *gst_tag;
13340   const gchar *gst_tag_bis;
13341   const GstQTDemuxAddTagFunc func;
13342 } add_funcs[] = {
13343   {
13344   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13345   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13346   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13347   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13348   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13349   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13350   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13351   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13352   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13353   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13354   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13355   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13356   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13357   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13358   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13359   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13360   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13361   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13362   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13363   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13364   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13365   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13366   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13367         qtdemux_tag_add_num}, {
13368   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13369         qtdemux_tag_add_num}, {
13370   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13371   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13372   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13373   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13374   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13375   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13376   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13377   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13378   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13379   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13380   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13381   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13382   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13383   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13384   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13385   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13386   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13387   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13388         qtdemux_tag_add_classification}, {
13389   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13390   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13391   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13392
13393     /* This is a special case, some tags are stored in this
13394      * 'reverse dns naming', according to:
13395      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13396      * bug #614471
13397      */
13398   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13399     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13400   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13401 };
13402
13403 struct _GstQtDemuxTagList
13404 {
13405   GstQTDemux *demux;
13406   GstTagList *taglist;
13407 };
13408 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13409
13410 static void
13411 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13412 {
13413   gint len;
13414   guint8 *data;
13415   GstBuffer *buf;
13416   gchar *media_type;
13417   const gchar *style;
13418   GstSample *sample;
13419   GstStructure *s;
13420   guint i;
13421   guint8 ndata[4];
13422   GstQTDemux *demux = qtdemuxtaglist->demux;
13423   GstTagList *taglist = qtdemuxtaglist->taglist;
13424
13425   data = node->data;
13426   len = QT_UINT32 (data);
13427   buf = gst_buffer_new_and_alloc (len);
13428   gst_buffer_fill (buf, 0, data, len);
13429
13430   /* heuristic to determine style of tag */
13431   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13432       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13433     style = "itunes";
13434   else if (demux->major_brand == FOURCC_qt__)
13435     style = "quicktime";
13436   /* fall back to assuming iso/3gp tag style */
13437   else
13438     style = "iso";
13439
13440   /* santize the name for the caps. */
13441   for (i = 0; i < 4; i++) {
13442     guint8 d = data[4 + i];
13443     if (g_ascii_isalnum (d))
13444       ndata[i] = g_ascii_tolower (d);
13445     else
13446       ndata[i] = '_';
13447   }
13448
13449   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13450       ndata[0], ndata[1], ndata[2], ndata[3]);
13451   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13452
13453   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13454   sample = gst_sample_new (buf, NULL, NULL, s);
13455   gst_buffer_unref (buf);
13456   g_free (media_type);
13457
13458   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13459       len, s);
13460
13461   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13462       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13463
13464   gst_sample_unref (sample);
13465 }
13466
13467 static void
13468 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13469 {
13470   GNode *meta;
13471   GNode *ilst;
13472   GNode *xmp_;
13473   GNode *node;
13474   gint i;
13475   GstQtDemuxTagList demuxtaglist;
13476
13477   demuxtaglist.demux = qtdemux;
13478   demuxtaglist.taglist = taglist;
13479
13480   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13481   if (meta != NULL) {
13482     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13483     if (ilst == NULL) {
13484       GST_LOG_OBJECT (qtdemux, "no ilst");
13485       return;
13486     }
13487   } else {
13488     ilst = udta;
13489     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13490   }
13491
13492   i = 0;
13493   while (i < G_N_ELEMENTS (add_funcs)) {
13494     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13495     if (node) {
13496       gint len;
13497
13498       len = QT_UINT32 (node->data);
13499       if (len < 12) {
13500         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13501             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13502       } else {
13503         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13504             add_funcs[i].gst_tag_bis, node);
13505       }
13506       g_node_destroy (node);
13507     } else {
13508       i++;
13509     }
13510   }
13511
13512   /* parsed nodes have been removed, pass along remainder as blob */
13513   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13514       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13515
13516   /* parse up XMP_ node if existing */
13517   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13518   if (xmp_ != NULL) {
13519     GstBuffer *buf;
13520     GstTagList *xmptaglist;
13521
13522     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13523         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13524     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13525     gst_buffer_unref (buf);
13526
13527     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13528   } else {
13529     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13530   }
13531 }
13532
13533 typedef struct
13534 {
13535   GstStructure *structure;      /* helper for sort function */
13536   gchar *location;
13537   guint min_req_bitrate;
13538   guint min_req_qt_version;
13539 } GstQtReference;
13540
13541 static gint
13542 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13543 {
13544   GstQtReference *ref_a = (GstQtReference *) a;
13545   GstQtReference *ref_b = (GstQtReference *) b;
13546
13547   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13548     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13549
13550   /* known bitrates go before unknown; higher bitrates go first */
13551   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13552 }
13553
13554 /* sort the redirects and post a message for the application.
13555  */
13556 static void
13557 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13558 {
13559   GstQtReference *best;
13560   GstStructure *s;
13561   GstMessage *msg;
13562   GValue list_val = { 0, };
13563   GList *l;
13564
13565   g_assert (references != NULL);
13566
13567   references = g_list_sort (references, qtdemux_redirects_sort_func);
13568
13569   best = (GstQtReference *) references->data;
13570
13571   g_value_init (&list_val, GST_TYPE_LIST);
13572
13573   for (l = references; l != NULL; l = l->next) {
13574     GstQtReference *ref = (GstQtReference *) l->data;
13575     GValue struct_val = { 0, };
13576
13577     ref->structure = gst_structure_new ("redirect",
13578         "new-location", G_TYPE_STRING, ref->location, NULL);
13579
13580     if (ref->min_req_bitrate > 0) {
13581       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13582           ref->min_req_bitrate, NULL);
13583     }
13584
13585     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13586     g_value_set_boxed (&struct_val, ref->structure);
13587     gst_value_list_append_value (&list_val, &struct_val);
13588     g_value_unset (&struct_val);
13589     /* don't free anything here yet, since we need best->structure below */
13590   }
13591
13592   g_assert (best != NULL);
13593   s = gst_structure_copy (best->structure);
13594
13595   if (g_list_length (references) > 1) {
13596     gst_structure_set_value (s, "locations", &list_val);
13597   }
13598
13599   g_value_unset (&list_val);
13600
13601   for (l = references; l != NULL; l = l->next) {
13602     GstQtReference *ref = (GstQtReference *) l->data;
13603
13604     gst_structure_free (ref->structure);
13605     g_free (ref->location);
13606     g_free (ref);
13607   }
13608   g_list_free (references);
13609
13610   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13611   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13612   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13613   qtdemux->posted_redirect = TRUE;
13614 }
13615
13616 /* look for redirect nodes, collect all redirect information and
13617  * process it.
13618  */
13619 static gboolean
13620 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13621 {
13622   GNode *rmra, *rmda, *rdrf;
13623
13624   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13625   if (rmra) {
13626     GList *redirects = NULL;
13627
13628     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13629     while (rmda) {
13630       GstQtReference ref = { NULL, NULL, 0, 0 };
13631       GNode *rmdr, *rmvc;
13632
13633       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13634         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13635         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13636             ref.min_req_bitrate);
13637       }
13638
13639       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13640         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13641         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13642
13643 #ifndef GST_DISABLE_GST_DEBUG
13644         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13645 #endif
13646         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13647
13648         GST_LOG_OBJECT (qtdemux,
13649             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13650             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13651             bitmask, check_type);
13652         if (package == FOURCC_qtim && check_type == 0) {
13653           ref.min_req_qt_version = version;
13654         }
13655       }
13656
13657       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13658       if (rdrf) {
13659         guint32 ref_type;
13660         guint8 *ref_data;
13661         guint ref_len;
13662
13663         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13664         if (ref_len > 20) {
13665           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13666           ref_data = (guint8 *) rdrf->data + 20;
13667           if (ref_type == FOURCC_alis) {
13668             guint record_len, record_version, fn_len;
13669
13670             if (ref_len > 70) {
13671               /* MacOSX alias record, google for alias-layout.txt */
13672               record_len = QT_UINT16 (ref_data + 4);
13673               record_version = QT_UINT16 (ref_data + 4 + 2);
13674               fn_len = QT_UINT8 (ref_data + 50);
13675               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13676                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13677               }
13678             } else {
13679               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13680                   ref_len);
13681             }
13682           } else if (ref_type == FOURCC_url_) {
13683             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13684           } else {
13685             GST_DEBUG_OBJECT (qtdemux,
13686                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13687                 GST_FOURCC_ARGS (ref_type));
13688           }
13689           if (ref.location != NULL) {
13690             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13691             redirects =
13692                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13693           } else {
13694             GST_WARNING_OBJECT (qtdemux,
13695                 "Failed to extract redirect location from rdrf atom");
13696           }
13697         } else {
13698           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13699         }
13700       }
13701
13702       /* look for others */
13703       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13704     }
13705
13706     if (redirects != NULL) {
13707       qtdemux_process_redirects (qtdemux, redirects);
13708     }
13709   }
13710   return TRUE;
13711 }
13712
13713 static GstTagList *
13714 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13715 {
13716   const gchar *fmt;
13717
13718   if (tags == NULL) {
13719     tags = gst_tag_list_new_empty ();
13720     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13721   }
13722
13723   if (qtdemux->major_brand == FOURCC_mjp2)
13724     fmt = "Motion JPEG 2000";
13725   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13726     fmt = "3GP";
13727   else if (qtdemux->major_brand == FOURCC_qt__)
13728     fmt = "Quicktime";
13729   else if (qtdemux->fragmented)
13730     fmt = "ISO fMP4";
13731   else
13732     fmt = "ISO MP4/M4A";
13733
13734   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13735       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13736
13737   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13738       fmt, NULL);
13739
13740   return tags;
13741 }
13742
13743 /* we have read the complete moov node now.
13744  * This function parses all of the relevant info, creates the traks and
13745  * prepares all data structures for playback
13746  */
13747 static gboolean
13748 qtdemux_parse_tree (GstQTDemux * qtdemux)
13749 {
13750   GNode *mvhd;
13751   GNode *trak;
13752   GNode *udta;
13753   GNode *mvex;
13754   GNode *pssh;
13755   guint64 creation_time;
13756   GstDateTime *datetime = NULL;
13757   gint version;
13758
13759   /* make sure we have a usable taglist */
13760   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13761
13762   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13763   if (mvhd == NULL) {
13764     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13765     return qtdemux_parse_redirects (qtdemux);
13766   }
13767
13768   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13769   if (version == 1) {
13770     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13771     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13772     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13773   } else if (version == 0) {
13774     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13775     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13776     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13777   } else {
13778     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13779     return FALSE;
13780   }
13781
13782   /* Moving qt creation time (secs since 1904) to unix time */
13783   if (creation_time != 0) {
13784     /* Try to use epoch first as it should be faster and more commonly found */
13785     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13786       GTimeVal now;
13787
13788       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13789       /* some data cleansing sanity */
13790       g_get_current_time (&now);
13791       if (now.tv_sec + 24 * 3600 < creation_time) {
13792         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13793       } else {
13794         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13795       }
13796     } else {
13797       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13798       GDateTime *dt, *dt_local;
13799
13800       dt = g_date_time_add_seconds (base_dt, creation_time);
13801       dt_local = g_date_time_to_local (dt);
13802       datetime = gst_date_time_new_from_g_date_time (dt_local);
13803
13804       g_date_time_unref (base_dt);
13805       g_date_time_unref (dt);
13806     }
13807   }
13808   if (datetime) {
13809     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13810     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13811         datetime, NULL);
13812     gst_date_time_unref (datetime);
13813   }
13814
13815   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13816   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13817
13818   /* check for fragmented file and get some (default) data */
13819   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13820   if (mvex) {
13821     GNode *mehd;
13822     GstByteReader mehd_data;
13823
13824     /* let track parsing or anyone know weird stuff might happen ... */
13825     qtdemux->fragmented = TRUE;
13826
13827     /* compensate for total duration */
13828     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13829     if (mehd)
13830       qtdemux_parse_mehd (qtdemux, &mehd_data);
13831   }
13832
13833   /* Update the movie segment duration, unless it was directly given to us
13834    * by upstream. Otherwise let it as is, as we don't want to mangle the
13835    * duration provided by upstream that may come e.g. from a MPD file. */
13836   if (!qtdemux->upstream_format_is_time) {
13837     GstClockTime duration;
13838     /* set duration in the segment info */
13839     gst_qtdemux_get_duration (qtdemux, &duration);
13840     qtdemux->segment.duration = duration;
13841     /* also do not exceed duration; stop is set that way post seek anyway,
13842      * and segment activation falls back to duration,
13843      * whereas loop only checks stop, so let's align this here as well */
13844     qtdemux->segment.stop = duration;
13845   }
13846
13847   /* parse all traks */
13848   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13849   while (trak) {
13850     qtdemux_parse_trak (qtdemux, trak);
13851     /* iterate all siblings */
13852     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13853   }
13854
13855   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13856
13857   /* find tags */
13858   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13859   if (udta) {
13860     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13861   } else {
13862     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13863   }
13864
13865   /* maybe also some tags in meta box */
13866   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13867   if (udta) {
13868     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13869     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13870   } else {
13871     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13872   }
13873
13874   /* parse any protection system info */
13875   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13876   while (pssh) {
13877     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13878     qtdemux_parse_pssh (qtdemux, pssh);
13879     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13880   }
13881
13882   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13883
13884   return TRUE;
13885 }
13886
13887 /* taken from ffmpeg */
13888 static int
13889 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13890 {
13891   int count = 4;
13892   int len = 0;
13893
13894   while (count--) {
13895     int c;
13896
13897     if (ptr >= end)
13898       return -1;
13899
13900     c = *ptr++;
13901     len = (len << 7) | (c & 0x7f);
13902     if (!(c & 0x80))
13903       break;
13904   }
13905   *end_out = ptr;
13906   return len;
13907 }
13908
13909 static GList *
13910 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13911     gsize codec_data_size)
13912 {
13913   GList *list = NULL;
13914   guint8 *p = codec_data;
13915   gint i, offset, num_packets;
13916   guint *length, last;
13917
13918   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13919
13920   if (codec_data == NULL || codec_data_size == 0)
13921     goto error;
13922
13923   /* start of the stream and vorbis audio or theora video, need to
13924    * send the codec_priv data as first three packets */
13925   num_packets = p[0] + 1;
13926   GST_DEBUG_OBJECT (qtdemux,
13927       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13928       (guint) num_packets, codec_data_size);
13929
13930   /* Let's put some limits, Don't think there even is a xiph codec
13931    * with more than 3-4 headers */
13932   if (G_UNLIKELY (num_packets > 16)) {
13933     GST_WARNING_OBJECT (qtdemux,
13934         "Unlikely number of xiph headers, most likely not valid");
13935     goto error;
13936   }
13937
13938   length = g_alloca (num_packets * sizeof (guint));
13939   last = 0;
13940   offset = 1;
13941
13942   /* first packets, read length values */
13943   for (i = 0; i < num_packets - 1; i++) {
13944     length[i] = 0;
13945     while (offset < codec_data_size) {
13946       length[i] += p[offset];
13947       if (p[offset++] != 0xff)
13948         break;
13949     }
13950     last += length[i];
13951   }
13952   if (offset + last > codec_data_size)
13953     goto error;
13954
13955   /* last packet is the remaining size */
13956   length[i] = codec_data_size - offset - last;
13957
13958   for (i = 0; i < num_packets; i++) {
13959     GstBuffer *hdr;
13960
13961     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13962
13963     if (offset + length[i] > codec_data_size)
13964       goto error;
13965
13966     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13967     list = g_list_append (list, hdr);
13968
13969     offset += length[i];
13970   }
13971
13972   return list;
13973
13974   /* ERRORS */
13975 error:
13976   {
13977     if (list != NULL)
13978       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13979     return NULL;
13980   }
13981
13982 }
13983
13984 /* this can change the codec originally present in @list */
13985 static void
13986 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13987     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13988 {
13989   int len = QT_UINT32 (esds->data);
13990   guint8 *ptr = esds->data;
13991   guint8 *end = ptr + len;
13992   int tag;
13993   guint8 *data_ptr = NULL;
13994   int data_len = 0;
13995   guint8 object_type_id = 0;
13996   guint8 stream_type = 0;
13997   const char *codec_name = NULL;
13998   GstCaps *caps = NULL;
13999
14000   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14001   ptr += 8;
14002   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14003   ptr += 4;
14004   while (ptr + 1 < end) {
14005     tag = QT_UINT8 (ptr);
14006     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14007     ptr++;
14008     len = read_descr_size (ptr, end, &ptr);
14009     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14010
14011     /* Check the stated amount of data is available for reading */
14012     if (len < 0 || ptr + len > end)
14013       break;
14014
14015     switch (tag) {
14016       case ES_DESCRIPTOR_TAG:
14017         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14018         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14019         ptr += 3;
14020         break;
14021       case DECODER_CONFIG_DESC_TAG:{
14022         guint max_bitrate, avg_bitrate;
14023
14024         object_type_id = QT_UINT8 (ptr);
14025         stream_type = QT_UINT8 (ptr + 1) >> 2;
14026         max_bitrate = QT_UINT32 (ptr + 5);
14027         avg_bitrate = QT_UINT32 (ptr + 9);
14028         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14029         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14030         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14031         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14032         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14033         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14034           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14035               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14036         }
14037         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14038           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14039               avg_bitrate, NULL);
14040         }
14041         ptr += 13;
14042         break;
14043       }
14044       case DECODER_SPECIFIC_INFO_TAG:
14045         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14046         if (object_type_id == 0xe0 && len == 0x40) {
14047           guint8 *data;
14048           GstStructure *s;
14049           guint32 clut[16];
14050           gint i;
14051
14052           GST_DEBUG_OBJECT (qtdemux,
14053               "Have VOBSUB palette. Creating palette event");
14054           /* move to decConfigDescr data and read palette */
14055           data = ptr;
14056           for (i = 0; i < 16; i++) {
14057             clut[i] = QT_UINT32 (data);
14058             data += 4;
14059           }
14060
14061           s = gst_structure_new ("application/x-gst-dvd", "event",
14062               G_TYPE_STRING, "dvd-spu-clut-change",
14063               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14064               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14065               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14066               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14067               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14068               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14069               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14070               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14071               NULL);
14072
14073           /* store event and trigger custom processing */
14074           stream->pending_event =
14075               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14076         } else {
14077           /* Generic codec_data handler puts it on the caps */
14078           data_ptr = ptr;
14079           data_len = len;
14080         }
14081
14082         ptr += len;
14083         break;
14084       case SL_CONFIG_DESC_TAG:
14085         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14086         ptr += 1;
14087         break;
14088       default:
14089         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14090             tag);
14091         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14092         ptr += len;
14093         break;
14094     }
14095   }
14096
14097   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14098    * in use, and should also be used to override some other parameters for some
14099    * codecs. */
14100   switch (object_type_id) {
14101     case 0x20:                 /* MPEG-4 */
14102       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14103        * profile_and_level_indication */
14104       if (data_ptr != NULL && data_len >= 5 &&
14105           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14106         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14107             data_ptr + 4, data_len - 4);
14108       }
14109       break;                    /* Nothing special needed here */
14110     case 0x21:                 /* H.264 */
14111       codec_name = "H.264 / AVC";
14112       caps = gst_caps_new_simple ("video/x-h264",
14113           "stream-format", G_TYPE_STRING, "avc",
14114           "alignment", G_TYPE_STRING, "au", NULL);
14115       break;
14116     case 0x40:                 /* AAC (any) */
14117     case 0x66:                 /* AAC Main */
14118     case 0x67:                 /* AAC LC */
14119     case 0x68:                 /* AAC SSR */
14120       /* Override channels and rate based on the codec_data, as it's often
14121        * wrong. */
14122       /* Only do so for basic setup without HE-AAC extension */
14123       if (data_ptr && data_len == 2) {
14124         guint channels, rate;
14125
14126         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14127         if (channels > 0)
14128           entry->n_channels = channels;
14129
14130         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14131         if (rate > 0)
14132           entry->rate = rate;
14133       }
14134
14135       /* Set level and profile if possible */
14136       if (data_ptr != NULL && data_len >= 2) {
14137         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14138             data_ptr, data_len);
14139       } else {
14140         const gchar *profile_str = NULL;
14141         GstBuffer *buffer;
14142         GstMapInfo map;
14143         guint8 *codec_data;
14144         gint rate_idx, profile;
14145
14146         /* No codec_data, let's invent something.
14147          * FIXME: This is wrong for SBR! */
14148
14149         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14150
14151         buffer = gst_buffer_new_and_alloc (2);
14152         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14153         codec_data = map.data;
14154
14155         rate_idx =
14156             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14157             (stream)->rate);
14158
14159         switch (object_type_id) {
14160           case 0x66:
14161             profile_str = "main";
14162             profile = 0;
14163             break;
14164           case 0x67:
14165             profile_str = "lc";
14166             profile = 1;
14167             break;
14168           case 0x68:
14169             profile_str = "ssr";
14170             profile = 2;
14171             break;
14172           default:
14173             profile = 3;
14174             break;
14175         }
14176
14177         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14178         codec_data[1] =
14179             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14180
14181         gst_buffer_unmap (buffer, &map);
14182         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14183             GST_TYPE_BUFFER, buffer, NULL);
14184         gst_buffer_unref (buffer);
14185
14186         if (profile_str) {
14187           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14188               G_TYPE_STRING, profile_str, NULL);
14189         }
14190       }
14191       break;
14192     case 0x60:                 /* MPEG-2, various profiles */
14193     case 0x61:
14194     case 0x62:
14195     case 0x63:
14196     case 0x64:
14197     case 0x65:
14198       codec_name = "MPEG-2 video";
14199       caps = gst_caps_new_simple ("video/mpeg",
14200           "mpegversion", G_TYPE_INT, 2,
14201           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14202       break;
14203     case 0x69:                 /* MPEG-2 BC audio */
14204     case 0x6B:                 /* MPEG-1 audio */
14205       caps = gst_caps_new_simple ("audio/mpeg",
14206           "mpegversion", G_TYPE_INT, 1, NULL);
14207       codec_name = "MPEG-1 audio";
14208       break;
14209     case 0x6A:                 /* MPEG-1 */
14210       codec_name = "MPEG-1 video";
14211       caps = gst_caps_new_simple ("video/mpeg",
14212           "mpegversion", G_TYPE_INT, 1,
14213           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14214       break;
14215     case 0x6C:                 /* MJPEG */
14216       caps =
14217           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14218           NULL);
14219       codec_name = "Motion-JPEG";
14220       break;
14221     case 0x6D:                 /* PNG */
14222       caps =
14223           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14224           NULL);
14225       codec_name = "PNG still images";
14226       break;
14227     case 0x6E:                 /* JPEG2000 */
14228       codec_name = "JPEG-2000";
14229       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14230       break;
14231     case 0xA4:                 /* Dirac */
14232       codec_name = "Dirac";
14233       caps = gst_caps_new_empty_simple ("video/x-dirac");
14234       break;
14235     case 0xA5:                 /* AC3 */
14236       codec_name = "AC-3 audio";
14237       caps = gst_caps_new_simple ("audio/x-ac3",
14238           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14239       break;
14240     case 0xA9:                 /* AC3 */
14241       codec_name = "DTS audio";
14242       caps = gst_caps_new_simple ("audio/x-dts",
14243           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14244       break;
14245     case 0xDD:
14246       if (stream_type == 0x05 && data_ptr) {
14247         GList *headers =
14248             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14249         if (headers) {
14250           GList *tmp;
14251           GValue arr_val = G_VALUE_INIT;
14252           GValue buf_val = G_VALUE_INIT;
14253           GstStructure *s;
14254
14255           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14256           codec_name = "Vorbis";
14257           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14258           g_value_init (&arr_val, GST_TYPE_ARRAY);
14259           g_value_init (&buf_val, GST_TYPE_BUFFER);
14260           for (tmp = headers; tmp; tmp = tmp->next) {
14261             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14262             gst_value_array_append_value (&arr_val, &buf_val);
14263           }
14264           s = gst_caps_get_structure (caps, 0);
14265           gst_structure_take_value (s, "streamheader", &arr_val);
14266           g_value_unset (&buf_val);
14267           g_list_free (headers);
14268
14269           data_ptr = NULL;
14270           data_len = 0;
14271         }
14272       }
14273       break;
14274     case 0xE1:                 /* QCELP */
14275       /* QCELP, the codec_data is a riff tag (little endian) with
14276        * 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). */
14277       caps = gst_caps_new_empty_simple ("audio/qcelp");
14278       codec_name = "QCELP";
14279       break;
14280     default:
14281       break;
14282   }
14283
14284   /* If we have a replacement caps, then change our caps for this stream */
14285   if (caps) {
14286     gst_caps_unref (entry->caps);
14287     entry->caps = caps;
14288   }
14289
14290   if (codec_name && list)
14291     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14292         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14293
14294   /* Add the codec_data attribute to caps, if we have it */
14295   if (data_ptr) {
14296     GstBuffer *buffer;
14297
14298     buffer = gst_buffer_new_and_alloc (data_len);
14299     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14300
14301     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14302     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14303
14304     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14305         buffer, NULL);
14306     gst_buffer_unref (buffer);
14307   }
14308
14309 }
14310
14311 static inline GstCaps *
14312 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14313 {
14314   GstCaps *caps;
14315   guint i;
14316   char *s, fourstr[5];
14317
14318   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14319   for (i = 0; i < 4; i++) {
14320     if (!g_ascii_isalnum (fourstr[i]))
14321       fourstr[i] = '_';
14322   }
14323   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14324   caps = gst_caps_new_empty_simple (s);
14325   g_free (s);
14326   return caps;
14327 }
14328
14329 #define _codec(name) \
14330   do { \
14331     if (codec_name) { \
14332       *codec_name = g_strdup (name); \
14333     } \
14334   } while (0)
14335
14336 static GstCaps *
14337 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14338     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14339     const guint8 * stsd_entry_data, gchar ** codec_name)
14340 {
14341   GstCaps *caps = NULL;
14342   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14343
14344   switch (fourcc) {
14345     case FOURCC_png:
14346       _codec ("PNG still images");
14347       caps = gst_caps_new_empty_simple ("image/png");
14348       break;
14349     case FOURCC_jpeg:
14350       _codec ("JPEG still images");
14351       caps =
14352           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14353           NULL);
14354       break;
14355     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14356     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14357     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14358     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14359       _codec ("Motion-JPEG");
14360       caps =
14361           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14362           NULL);
14363       break;
14364     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14365       _codec ("Motion-JPEG format B");
14366       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14367       break;
14368     case FOURCC_mjp2:
14369       _codec ("JPEG-2000");
14370       /* override to what it should be according to spec, avoid palette_data */
14371       entry->bits_per_sample = 24;
14372       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14373       break;
14374     case FOURCC_SVQ3:
14375       _codec ("Sorensen video v.3");
14376       caps = gst_caps_new_simple ("video/x-svq",
14377           "svqversion", G_TYPE_INT, 3, NULL);
14378       break;
14379     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14380     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14381       _codec ("Sorensen video v.1");
14382       caps = gst_caps_new_simple ("video/x-svq",
14383           "svqversion", G_TYPE_INT, 1, NULL);
14384       break;
14385     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14386       caps = gst_caps_new_empty_simple ("video/x-raw");
14387       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14388       _codec ("Windows Raw RGB");
14389       stream->alignment = 32;
14390       break;
14391     case FOURCC_raw_:
14392     {
14393       guint16 bps;
14394
14395       bps = QT_UINT16 (stsd_entry_data + 82);
14396       switch (bps) {
14397         case 15:
14398           format = GST_VIDEO_FORMAT_RGB15;
14399           break;
14400         case 16:
14401           format = GST_VIDEO_FORMAT_RGB16;
14402           break;
14403         case 24:
14404           format = GST_VIDEO_FORMAT_RGB;
14405           break;
14406         case 32:
14407           format = GST_VIDEO_FORMAT_ARGB;
14408           break;
14409         default:
14410           /* unknown */
14411           break;
14412       }
14413       break;
14414     }
14415     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14416       format = GST_VIDEO_FORMAT_I420;
14417       break;
14418     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14419     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14420       format = GST_VIDEO_FORMAT_I420;
14421       break;
14422     case FOURCC_2vuy:
14423     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14424       format = GST_VIDEO_FORMAT_UYVY;
14425       break;
14426     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14427       format = GST_VIDEO_FORMAT_v308;
14428       break;
14429     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14430       format = GST_VIDEO_FORMAT_v216;
14431       break;
14432     case FOURCC_v210:
14433       format = GST_VIDEO_FORMAT_v210;
14434       break;
14435     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14436       format = GST_VIDEO_FORMAT_r210;
14437       break;
14438       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14439          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14440          format = GST_VIDEO_FORMAT_v410;
14441          break;
14442        */
14443       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14444        * but different order than AYUV
14445        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14446        format = GST_VIDEO_FORMAT_v408;
14447        break;
14448        */
14449     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14450     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14451       _codec ("MPEG-1 video");
14452       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14453           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14454       break;
14455     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14456     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14457     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14458     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14459     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14460     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14461     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14462     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14463     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14464     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14465     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14466     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14467     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14468     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14469     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14470     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14471     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14472     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14473     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14474     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14475     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14476     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14477     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14478     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14479     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14480     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14481     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14482     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14483     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14484     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14485     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14486     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14487     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14488     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14489     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14490     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14491     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14492     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14493     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14494     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14495     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14496     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14497     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14498     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14499     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14500     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14501     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14502       _codec ("MPEG-2 video");
14503       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14504           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14505       break;
14506     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14507       _codec ("GIF still images");
14508       caps = gst_caps_new_empty_simple ("image/gif");
14509       break;
14510     case FOURCC_h263:
14511     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14512     case FOURCC_s263:
14513     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14514       _codec ("H.263");
14515       /* ffmpeg uses the height/width props, don't know why */
14516       caps = gst_caps_new_simple ("video/x-h263",
14517           "variant", G_TYPE_STRING, "itu", NULL);
14518       break;
14519     case FOURCC_mp4v:
14520     case FOURCC_MP4V:
14521       _codec ("MPEG-4 video");
14522       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14523           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14524       break;
14525     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14526     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14527       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14528       caps = gst_caps_new_simple ("video/x-msmpeg",
14529           "msmpegversion", G_TYPE_INT, 43, NULL);
14530       break;
14531     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14532       _codec ("DivX 3");
14533       caps = gst_caps_new_simple ("video/x-divx",
14534           "divxversion", G_TYPE_INT, 3, NULL);
14535       break;
14536     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14537     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14538       _codec ("DivX 4");
14539       caps = gst_caps_new_simple ("video/x-divx",
14540           "divxversion", G_TYPE_INT, 4, NULL);
14541       break;
14542     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14543       _codec ("DivX 5");
14544       caps = gst_caps_new_simple ("video/x-divx",
14545           "divxversion", G_TYPE_INT, 5, NULL);
14546       break;
14547
14548     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14549       _codec ("FFV1");
14550       caps = gst_caps_new_simple ("video/x-ffv",
14551           "ffvversion", G_TYPE_INT, 1, NULL);
14552       break;
14553
14554     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14555     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14556     case FOURCC_XVID:
14557     case FOURCC_xvid:
14558     case FOURCC_FMP4:
14559     case FOURCC_fmp4:
14560     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14561       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14562           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14563       _codec ("MPEG-4");
14564       break;
14565
14566     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14567       _codec ("Cinepak");
14568       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14569       break;
14570     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14571       _codec ("Apple QuickDraw");
14572       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14573       break;
14574     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14575       _codec ("Apple video");
14576       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14577       break;
14578     case FOURCC_H264:
14579     case FOURCC_avc1:
14580       _codec ("H.264 / AVC");
14581       caps = gst_caps_new_simple ("video/x-h264",
14582           "stream-format", G_TYPE_STRING, "avc",
14583           "alignment", G_TYPE_STRING, "au", NULL);
14584       break;
14585     case FOURCC_avc3:
14586       _codec ("H.264 / AVC");
14587       caps = gst_caps_new_simple ("video/x-h264",
14588           "stream-format", G_TYPE_STRING, "avc3",
14589           "alignment", G_TYPE_STRING, "au", NULL);
14590       break;
14591     case FOURCC_H265:
14592     case FOURCC_hvc1:
14593       _codec ("H.265 / HEVC");
14594       caps = gst_caps_new_simple ("video/x-h265",
14595           "stream-format", G_TYPE_STRING, "hvc1",
14596           "alignment", G_TYPE_STRING, "au", NULL);
14597       break;
14598     case FOURCC_hev1:
14599       _codec ("H.265 / HEVC");
14600       caps = gst_caps_new_simple ("video/x-h265",
14601           "stream-format", G_TYPE_STRING, "hev1",
14602           "alignment", G_TYPE_STRING, "au", NULL);
14603       break;
14604     case FOURCC_rle_:
14605       _codec ("Run-length encoding");
14606       caps = gst_caps_new_simple ("video/x-rle",
14607           "layout", G_TYPE_STRING, "quicktime", NULL);
14608       break;
14609     case FOURCC_WRLE:
14610       _codec ("Run-length encoding");
14611       caps = gst_caps_new_simple ("video/x-rle",
14612           "layout", G_TYPE_STRING, "microsoft", NULL);
14613       break;
14614     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14615     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14616       _codec ("Indeo Video 3");
14617       caps = gst_caps_new_simple ("video/x-indeo",
14618           "indeoversion", G_TYPE_INT, 3, NULL);
14619       break;
14620     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14621     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14622       _codec ("Intel Video 4");
14623       caps = gst_caps_new_simple ("video/x-indeo",
14624           "indeoversion", G_TYPE_INT, 4, NULL);
14625       break;
14626     case FOURCC_dvcp:
14627     case FOURCC_dvc_:
14628     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14629     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14630     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14631     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14632     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14633     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14634       _codec ("DV Video");
14635       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14636           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14637       break;
14638     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14639     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14640       _codec ("DVCPro50 Video");
14641       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14642           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14643       break;
14644     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14645     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14646       _codec ("DVCProHD Video");
14647       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14648           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14649       break;
14650     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14651       _codec ("Apple Graphics (SMC)");
14652       caps = gst_caps_new_empty_simple ("video/x-smc");
14653       break;
14654     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14655       _codec ("VP3");
14656       caps = gst_caps_new_empty_simple ("video/x-vp3");
14657       break;
14658     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14659       _codec ("VP6 Flash");
14660       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14661       break;
14662     case FOURCC_XiTh:
14663       _codec ("Theora");
14664       caps = gst_caps_new_empty_simple ("video/x-theora");
14665       /* theora uses one byte of padding in the data stream because it does not
14666        * allow 0 sized packets while theora does */
14667       entry->padding = 1;
14668       break;
14669     case FOURCC_drac:
14670       _codec ("Dirac");
14671       caps = gst_caps_new_empty_simple ("video/x-dirac");
14672       break;
14673     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14674       _codec ("TIFF still images");
14675       caps = gst_caps_new_empty_simple ("image/tiff");
14676       break;
14677     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14678       _codec ("Apple Intermediate Codec");
14679       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14680       break;
14681     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14682       _codec ("AVID DNxHD");
14683       caps = gst_caps_from_string ("video/x-dnxhd");
14684       break;
14685     case FOURCC_VP80:
14686     case FOURCC_vp08:
14687       _codec ("On2 VP8");
14688       caps = gst_caps_from_string ("video/x-vp8");
14689       break;
14690     case FOURCC_vp09:
14691       _codec ("Google VP9");
14692       caps = gst_caps_from_string ("video/x-vp9");
14693       break;
14694     case FOURCC_apcs:
14695       _codec ("Apple ProRes LT");
14696       caps =
14697           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14698           NULL);
14699       break;
14700     case FOURCC_apch:
14701       _codec ("Apple ProRes HQ");
14702       caps =
14703           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14704           NULL);
14705       break;
14706     case FOURCC_apcn:
14707       _codec ("Apple ProRes");
14708       caps =
14709           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14710           "standard", NULL);
14711       break;
14712     case FOURCC_apco:
14713       _codec ("Apple ProRes Proxy");
14714       caps =
14715           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14716           "proxy", NULL);
14717       break;
14718     case FOURCC_ap4h:
14719       _codec ("Apple ProRes 4444");
14720       caps =
14721           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14722           "4444", NULL);
14723       break;
14724     case FOURCC_ap4x:
14725       _codec ("Apple ProRes 4444 XQ");
14726       caps =
14727           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14728           "4444xq", NULL);
14729       break;
14730     case FOURCC_cfhd:
14731       _codec ("GoPro CineForm");
14732       caps = gst_caps_from_string ("video/x-cineform");
14733       break;
14734     case FOURCC_vc_1:
14735     case FOURCC_ovc1:
14736       _codec ("VC-1");
14737       caps = gst_caps_new_simple ("video/x-wmv",
14738           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14739       break;
14740     case FOURCC_av01:
14741       _codec ("AV1");
14742       caps = gst_caps_new_empty_simple ("video/x-av1");
14743       break;
14744     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14745     default:
14746     {
14747       caps = _get_unknown_codec_name ("video", fourcc);
14748       break;
14749     }
14750   }
14751
14752   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14753     GstVideoInfo info;
14754
14755     gst_video_info_init (&info);
14756     gst_video_info_set_format (&info, format, entry->width, entry->height);
14757
14758     caps = gst_video_info_to_caps (&info);
14759     *codec_name = gst_pb_utils_get_codec_description (caps);
14760
14761     /* enable clipping for raw video streams */
14762     stream->need_clip = TRUE;
14763     stream->alignment = 32;
14764   }
14765
14766   return caps;
14767 }
14768
14769 static guint
14770 round_up_pow2 (guint n)
14771 {
14772   n = n - 1;
14773   n = n | (n >> 1);
14774   n = n | (n >> 2);
14775   n = n | (n >> 4);
14776   n = n | (n >> 8);
14777   n = n | (n >> 16);
14778   return n + 1;
14779 }
14780
14781 static GstCaps *
14782 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14783     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14784     int len, gchar ** codec_name)
14785 {
14786   GstCaps *caps;
14787   const GstStructure *s;
14788   const gchar *name;
14789   gint endian = 0;
14790   GstAudioFormat format = 0;
14791   gint depth;
14792
14793   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14794
14795   depth = entry->bytes_per_packet * 8;
14796
14797   switch (fourcc) {
14798     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14799     case FOURCC_raw_:
14800       /* 8-bit audio is unsigned */
14801       if (depth == 8)
14802         format = GST_AUDIO_FORMAT_U8;
14803       /* otherwise it's signed and big-endian just like 'twos' */
14804     case FOURCC_twos:
14805       endian = G_BIG_ENDIAN;
14806       /* fall-through */
14807     case FOURCC_sowt:
14808     {
14809       gchar *str;
14810
14811       if (!endian)
14812         endian = G_LITTLE_ENDIAN;
14813
14814       if (!format)
14815         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14816
14817       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14818       _codec (str);
14819       g_free (str);
14820
14821       caps = gst_caps_new_simple ("audio/x-raw",
14822           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14823           "layout", G_TYPE_STRING, "interleaved", NULL);
14824       stream->alignment = GST_ROUND_UP_8 (depth);
14825       stream->alignment = round_up_pow2 (stream->alignment);
14826       break;
14827     }
14828     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14829       _codec ("Raw 64-bit floating-point audio");
14830       caps = gst_caps_new_simple ("audio/x-raw",
14831           "format", G_TYPE_STRING, "F64BE",
14832           "layout", G_TYPE_STRING, "interleaved", NULL);
14833       stream->alignment = 8;
14834       break;
14835     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14836       _codec ("Raw 32-bit floating-point audio");
14837       caps = gst_caps_new_simple ("audio/x-raw",
14838           "format", G_TYPE_STRING, "F32BE",
14839           "layout", G_TYPE_STRING, "interleaved", NULL);
14840       stream->alignment = 4;
14841       break;
14842     case FOURCC_in24:
14843       _codec ("Raw 24-bit PCM audio");
14844       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14845        * endian later */
14846       caps = gst_caps_new_simple ("audio/x-raw",
14847           "format", G_TYPE_STRING, "S24BE",
14848           "layout", G_TYPE_STRING, "interleaved", NULL);
14849       stream->alignment = 4;
14850       break;
14851     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14852       _codec ("Raw 32-bit PCM audio");
14853       caps = gst_caps_new_simple ("audio/x-raw",
14854           "format", G_TYPE_STRING, "S32BE",
14855           "layout", G_TYPE_STRING, "interleaved", NULL);
14856       stream->alignment = 4;
14857       break;
14858     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14859       _codec ("Raw 16-bit PCM audio");
14860       caps = gst_caps_new_simple ("audio/x-raw",
14861           "format", G_TYPE_STRING, "S16LE",
14862           "layout", G_TYPE_STRING, "interleaved", NULL);
14863       stream->alignment = 2;
14864       break;
14865     case FOURCC_ulaw:
14866       _codec ("Mu-law audio");
14867       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14868       break;
14869     case FOURCC_alaw:
14870       _codec ("A-law audio");
14871       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14872       break;
14873     case 0x0200736d:
14874     case 0x6d730002:
14875       _codec ("Microsoft ADPCM");
14876       /* Microsoft ADPCM-ACM code 2 */
14877       caps = gst_caps_new_simple ("audio/x-adpcm",
14878           "layout", G_TYPE_STRING, "microsoft", NULL);
14879       break;
14880     case 0x1100736d:
14881     case 0x6d730011:
14882       _codec ("DVI/IMA ADPCM");
14883       caps = gst_caps_new_simple ("audio/x-adpcm",
14884           "layout", G_TYPE_STRING, "dvi", NULL);
14885       break;
14886     case 0x1700736d:
14887     case 0x6d730017:
14888       _codec ("DVI/Intel IMA ADPCM");
14889       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14890       caps = gst_caps_new_simple ("audio/x-adpcm",
14891           "layout", G_TYPE_STRING, "quicktime", NULL);
14892       break;
14893     case 0x5500736d:
14894     case 0x6d730055:
14895       /* MPEG layer 3, CBR only (pre QT4.1) */
14896     case FOURCC__mp3:
14897       _codec ("MPEG-1 layer 3");
14898       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14899       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14900           "mpegversion", G_TYPE_INT, 1, NULL);
14901       break;
14902     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14903       _codec ("MPEG-1 layer 2");
14904       /* MPEG layer 2 */
14905       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14906           "mpegversion", G_TYPE_INT, 1, NULL);
14907       break;
14908     case 0x20736d:
14909     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14910       _codec ("EAC-3 audio");
14911       caps = gst_caps_new_simple ("audio/x-eac3",
14912           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14913       entry->sampled = TRUE;
14914       break;
14915     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14916     case FOURCC_ac_3:
14917       _codec ("AC-3 audio");
14918       caps = gst_caps_new_simple ("audio/x-ac3",
14919           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14920       entry->sampled = TRUE;
14921       break;
14922     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14923     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14924       _codec ("DTS audio");
14925       caps = gst_caps_new_simple ("audio/x-dts",
14926           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14927       entry->sampled = TRUE;
14928       break;
14929     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14930     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14931       _codec ("DTS-HD audio");
14932       caps = gst_caps_new_simple ("audio/x-dts",
14933           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14934       entry->sampled = TRUE;
14935       break;
14936     case FOURCC_MAC3:
14937       _codec ("MACE-3");
14938       caps = gst_caps_new_simple ("audio/x-mace",
14939           "maceversion", G_TYPE_INT, 3, NULL);
14940       break;
14941     case FOURCC_MAC6:
14942       _codec ("MACE-6");
14943       caps = gst_caps_new_simple ("audio/x-mace",
14944           "maceversion", G_TYPE_INT, 6, NULL);
14945       break;
14946     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14947       /* ogg/vorbis */
14948       caps = gst_caps_new_empty_simple ("application/ogg");
14949       break;
14950     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14951       _codec ("DV audio");
14952       caps = gst_caps_new_empty_simple ("audio/x-dv");
14953       break;
14954     case FOURCC_mp4a:
14955       _codec ("MPEG-4 AAC audio");
14956       caps = gst_caps_new_simple ("audio/mpeg",
14957           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14958           "stream-format", G_TYPE_STRING, "raw", NULL);
14959       break;
14960     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14961       _codec ("QDesign Music");
14962       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14963       break;
14964     case FOURCC_QDM2:
14965       _codec ("QDesign Music v.2");
14966       /* FIXME: QDesign music version 2 (no constant) */
14967       if (FALSE && data) {
14968         caps = gst_caps_new_simple ("audio/x-qdm2",
14969             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14970             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14971             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14972       } else {
14973         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14974       }
14975       break;
14976     case FOURCC_agsm:
14977       _codec ("GSM audio");
14978       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14979       break;
14980     case FOURCC_samr:
14981       _codec ("AMR audio");
14982       caps = gst_caps_new_empty_simple ("audio/AMR");
14983       break;
14984     case FOURCC_sawb:
14985       _codec ("AMR-WB audio");
14986       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14987       break;
14988     case FOURCC_ima4:
14989       _codec ("Quicktime IMA ADPCM");
14990       caps = gst_caps_new_simple ("audio/x-adpcm",
14991           "layout", G_TYPE_STRING, "quicktime", NULL);
14992       break;
14993     case FOURCC_alac:
14994       _codec ("Apple lossless audio");
14995       caps = gst_caps_new_empty_simple ("audio/x-alac");
14996       break;
14997     case FOURCC_fLaC:
14998       _codec ("Free Lossless Audio Codec");
14999       caps = gst_caps_new_simple ("audio/x-flac",
15000           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15001       break;
15002     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15003       _codec ("QualComm PureVoice");
15004       caps = gst_caps_from_string ("audio/qcelp");
15005       break;
15006     case FOURCC_wma_:
15007     case FOURCC_owma:
15008       _codec ("WMA");
15009       caps = gst_caps_new_empty_simple ("audio/x-wma");
15010       break;
15011     case FOURCC_opus:
15012       _codec ("Opus");
15013       caps = gst_caps_new_empty_simple ("audio/x-opus");
15014       break;
15015     case FOURCC_lpcm:
15016     {
15017       guint32 flags = 0;
15018       guint32 depth = 0;
15019       guint32 width = 0;
15020       GstAudioFormat format;
15021       enum
15022       {
15023         FLAG_IS_FLOAT = 0x1,
15024         FLAG_IS_BIG_ENDIAN = 0x2,
15025         FLAG_IS_SIGNED = 0x4,
15026         FLAG_IS_PACKED = 0x8,
15027         FLAG_IS_ALIGNED_HIGH = 0x10,
15028         FLAG_IS_NON_INTERLEAVED = 0x20
15029       };
15030       _codec ("Raw LPCM audio");
15031
15032       if (data && len >= 36) {
15033         depth = QT_UINT32 (data + 24);
15034         flags = QT_UINT32 (data + 28);
15035         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15036       }
15037       if ((flags & FLAG_IS_FLOAT) == 0) {
15038         if (depth == 0)
15039           depth = 16;
15040         if (width == 0)
15041           width = 16;
15042         if ((flags & FLAG_IS_ALIGNED_HIGH))
15043           depth = width;
15044
15045         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15046             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15047             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15048         caps = gst_caps_new_simple ("audio/x-raw",
15049             "format", G_TYPE_STRING,
15050             format !=
15051             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15052             "UNKNOWN", "layout", G_TYPE_STRING,
15053             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15054             "interleaved", NULL);
15055         stream->alignment = GST_ROUND_UP_8 (depth);
15056         stream->alignment = round_up_pow2 (stream->alignment);
15057       } else {
15058         if (width == 0)
15059           width = 32;
15060         if (width == 64) {
15061           if (flags & FLAG_IS_BIG_ENDIAN)
15062             format = GST_AUDIO_FORMAT_F64BE;
15063           else
15064             format = GST_AUDIO_FORMAT_F64LE;
15065         } else {
15066           if (flags & FLAG_IS_BIG_ENDIAN)
15067             format = GST_AUDIO_FORMAT_F32BE;
15068           else
15069             format = GST_AUDIO_FORMAT_F32LE;
15070         }
15071         caps = gst_caps_new_simple ("audio/x-raw",
15072             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15073             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15074             "non-interleaved" : "interleaved", NULL);
15075         stream->alignment = width / 8;
15076       }
15077       break;
15078     }
15079     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15080       /* ? */
15081     default:
15082     {
15083       caps = _get_unknown_codec_name ("audio", fourcc);
15084       break;
15085     }
15086   }
15087
15088   if (caps) {
15089     GstCaps *templ_caps =
15090         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15091     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15092     gst_caps_unref (caps);
15093     gst_caps_unref (templ_caps);
15094     caps = intersection;
15095   }
15096
15097   /* enable clipping for raw audio streams */
15098   s = gst_caps_get_structure (caps, 0);
15099   name = gst_structure_get_name (s);
15100   if (g_str_has_prefix (name, "audio/x-raw")) {
15101     stream->need_clip = TRUE;
15102     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15103     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15104   }
15105   return caps;
15106 }
15107
15108 static GstCaps *
15109 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15110     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15111     const guint8 * stsd_entry_data, gchar ** codec_name)
15112 {
15113   GstCaps *caps;
15114
15115   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15116
15117   switch (fourcc) {
15118     case FOURCC_mp4s:
15119       _codec ("DVD subtitle");
15120       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15121       stream->need_process = TRUE;
15122       break;
15123     case FOURCC_text:
15124       _codec ("Quicktime timed text");
15125       goto text;
15126     case FOURCC_tx3g:
15127       _codec ("3GPP timed text");
15128     text:
15129       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15130           "utf8", NULL);
15131       /* actual text piece needs to be extracted */
15132       stream->need_process = TRUE;
15133       break;
15134     case FOURCC_stpp:
15135       _codec ("XML subtitles");
15136       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15137       break;
15138     case FOURCC_c608:
15139       _codec ("CEA 608 Closed Caption");
15140       caps =
15141           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15142           G_TYPE_STRING, "cc_data", NULL);
15143       stream->need_process = TRUE;
15144       break;
15145     case FOURCC_c708:
15146       _codec ("CEA 708 Closed Caption");
15147       caps =
15148           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15149           G_TYPE_STRING, "cdp", NULL);
15150       stream->need_process = TRUE;
15151       break;
15152
15153     default:
15154     {
15155       caps = _get_unknown_codec_name ("text", fourcc);
15156       break;
15157     }
15158   }
15159   return caps;
15160 }
15161
15162 static GstCaps *
15163 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15164     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15165     const guint8 * stsd_entry_data, gchar ** codec_name)
15166 {
15167   GstCaps *caps;
15168
15169   switch (fourcc) {
15170     case FOURCC_m1v:
15171       _codec ("MPEG 1 video");
15172       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15173           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15174       break;
15175     default:
15176       caps = NULL;
15177       break;
15178   }
15179   return caps;
15180 }
15181
15182 static void
15183 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15184     const gchar * system_id)
15185 {
15186   gint i;
15187
15188   if (!qtdemux->protection_system_ids)
15189     qtdemux->protection_system_ids =
15190         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15191   /* Check whether we already have an entry for this system ID. */
15192   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15193     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15194     if (g_ascii_strcasecmp (system_id, id) == 0) {
15195       return;
15196     }
15197   }
15198   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15199   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15200           -1));
15201 }