qtdemux: fix AAC codec_data values
[platform/upstream/gstreamer.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * 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
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 GST_DEBUG_CATEGORY (qtdemux_debug);
99
100 typedef struct _QtDemuxSegment QtDemuxSegment;
101 typedef struct _QtDemuxSample QtDemuxSample;
102
103 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
104
105 struct _QtDemuxSample
106 {
107   guint32 size;
108   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
109   guint64 offset;
110   guint64 timestamp;            /* DTS In mov time */
111   guint32 duration;             /* In mov time */
112   gboolean keyframe;            /* TRUE when this packet is a keyframe */
113 };
114
115 /* Macros for converting to/from timescale */
116 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
117 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
118
119 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
120 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
121
122 /* timestamp is the DTS */
123 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
124 /* timestamp + offset is the PTS */
125 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
126 /* timestamp + duration - dts is the duration */
127 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
128
129 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
130
131 /*
132  * Quicktime has tracks and segments. A track is a continuous piece of
133  * multimedia content. The track is not always played from start to finish but
134  * instead, pieces of the track are 'cut out' and played in sequence. This is
135  * what the segments do.
136  *
137  * Inside the track we have keyframes (K) and delta frames. The track has its
138  * own timing, which starts from 0 and extends to end. The position in the track
139  * is called the media_time.
140  *
141  * The segments now describe the pieces that should be played from this track
142  * and are basically tuples of media_time/duration/rate entries. We can have
143  * multiple segments and they are all played after one another. An example:
144  *
145  * segment 1: media_time: 1 second, duration: 1 second, rate 1
146  * segment 2: media_time: 3 second, duration: 2 second, rate 2
147  *
148  * To correctly play back this track, one must play: 1 second of media starting
149  * from media_time 1 followed by 2 seconds of media starting from media_time 3
150  * at a rate of 2.
151  *
152  * Each of the segments will be played at a specific time, the first segment at
153  * time 0, the second one after the duration of the first one, etc.. Note that
154  * the time in resulting playback is not identical to the media_time of the
155  * track anymore.
156  *
157  * Visually, assuming the track has 4 second of media_time:
158  *
159  *                (a)                   (b)          (c)              (d)
160  *         .-----------------------------------------------------------.
161  * track:  | K.....K.........K........K.......K.......K...........K... |
162  *         '-----------------------------------------------------------'
163  *         0              1              2              3              4
164  *           .------------^              ^   .----------^              ^
165  *          /              .-------------'  /       .------------------'
166  *         /              /          .-----'       /
167  *         .--------------.         .--------------.
168  *         | segment 1    |         | segment 2    |
169  *         '--------------'         '--------------'
170  *
171  * The challenge here is to cut out the right pieces of the track for each of
172  * the playback segments. This fortunately can easily be done with the SEGMENT
173  * events of GStreamer.
174  *
175  * For playback of segment 1, we need to provide the decoder with the keyframe
176  * (a), in the above figure, but we must instruct it only to output the decoded
177  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
178  * position set to the time of the segment: 0.
179  *
180  * We then proceed to push data from keyframe (a) to frame (b). The decoder
181  * decodes but clips all before media_time 1.
182  *
183  * After finishing a segment, we push out a new SEGMENT event with the clipping
184  * boundaries of the new data.
185  *
186  * This is a good usecase for the GStreamer accumulated SEGMENT events.
187  */
188
189 struct _QtDemuxSegment
190 {
191   /* global time and duration, all gst time */
192   GstClockTime time;
193   GstClockTime stop_time;
194   GstClockTime duration;
195   /* media time of trak, all gst time */
196   GstClockTime media_start;
197   GstClockTime media_stop;
198   gdouble rate;
199   /* Media start time in trak timescale units */
200   guint32 trak_media_start;
201 };
202
203 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
204
205 /* Used with fragmented MP4 files (mfra atom) */
206 typedef struct
207 {
208   GstClockTime ts;
209   guint64 moof_offset;
210 } QtDemuxRandomAccessEntry;
211
212 struct _QtDemuxStream
213 {
214   GstPad *pad;
215
216   /* stream type */
217   guint32 subtype;
218   GstCaps *caps;
219   guint32 fourcc;
220   gboolean sparse;
221
222   gboolean new_caps;            /* If TRUE, caps need to be generated (by
223                                  * calling _configure_stream()) This happens
224                                  * for MSS and fragmented streams */
225
226   gboolean new_stream;          /* signals that a stream_start is required */
227   gboolean on_keyframe;         /* if this stream last pushed buffer was a
228                                  * keyframe. This is important to identify
229                                  * where to stop pushing buffers after a
230                                  * segment stop time */
231
232   /* if the stream has a redirect URI in its headers, we store it here */
233   gchar *redirect_uri;
234
235   /* track id */
236   guint track_id;
237
238   /* duration/scale */
239   guint64 duration;             /* in timescale units */
240   guint32 timescale;
241
242   /* language */
243   gchar lang_id[4];             /* ISO 639-2T language code */
244
245   /* our samples */
246   guint32 n_samples;
247   QtDemuxSample *samples;
248   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
249   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
250                                    the framerate */
251   guint32 n_samples_moof;       /* sample count in a moof */
252   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
253                                  * the framerate of fragmented format stream */
254
255   guint32 offset_in_sample;     /* Offset in the current sample, used for
256                                  * streams which have got exceedingly big
257                                  * sample size (such as 24s of raw audio).
258                                  * Only used when max_buffer_size is non-NULL */
259   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
260                                  * Currently only set for raw audio streams*/
261
262   /* if we use chunks or samples */
263   gboolean sampled;
264   guint padding;
265
266   /* video info */
267   gint width;
268   gint height;
269   /* aspect ratio */
270   gint display_width;
271   gint display_height;
272   gint par_w;
273   gint par_h;
274   /* Numerator/denominator framerate */
275   gint fps_n;
276   gint fps_d;
277   guint16 bits_per_sample;
278   guint16 color_table_id;
279   GstMemory *rgb8_palette;
280
281   /* audio info */
282   gdouble rate;
283   gint n_channels;
284   guint samples_per_packet;
285   guint samples_per_frame;
286   guint bytes_per_packet;
287   guint bytes_per_sample;
288   guint bytes_per_frame;
289   guint compression;
290
291   /* allocation */
292   gboolean use_allocator;
293   GstAllocator *allocator;
294   GstAllocationParams params;
295
296   /* when a discontinuity is pending */
297   gboolean discont;
298
299   /* list of buffers to push first */
300   GSList *buffers;
301
302   /* if we need to clip this buffer. This is only needed for uncompressed
303    * data */
304   gboolean need_clip;
305
306   /* buffer needs some custom processing, e.g. subtitles */
307   gboolean need_process;
308
309   /* current position */
310   guint32 segment_index;
311   guint32 sample_index;
312   GstClockTime time_position;   /* in gst time */
313   guint64 accumulated_base;
314
315   /* the Gst segment we are processing out, used for clipping */
316   GstSegment segment;
317
318   /* quicktime segments */
319   guint32 n_segments;
320   QtDemuxSegment *segments;
321   gboolean dummy_segment;
322   guint32 from_sample;
323   guint32 to_sample;
324
325   gboolean sent_eos;
326   GstTagList *pending_tags;
327   gboolean send_global_tags;
328
329   GstEvent *pending_event;
330
331   GstByteReader stco;
332   GstByteReader stsz;
333   GstByteReader stsc;
334   GstByteReader stts;
335   GstByteReader stss;
336   GstByteReader stps;
337   GstByteReader ctts;
338
339   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
340   gint64 stbl_index;
341   /* stco */
342   guint co_size;
343   GstByteReader co_chunk;
344   guint32 first_chunk;
345   guint32 current_chunk;
346   guint32 last_chunk;
347   guint32 samples_per_chunk;
348   guint32 stco_sample_index;
349   /* stsz */
350   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
351   /* stsc */
352   guint32 stsc_index;
353   guint32 n_samples_per_chunk;
354   guint32 stsc_chunk_index;
355   guint32 stsc_sample_index;
356   guint64 chunk_offset;
357   /* stts */
358   guint32 stts_index;
359   guint32 stts_samples;
360   guint32 n_sample_times;
361   guint32 stts_sample_index;
362   guint64 stts_time;
363   guint32 stts_duration;
364   /* stss */
365   gboolean stss_present;
366   guint32 n_sample_syncs;
367   guint32 stss_index;
368   /* stps */
369   gboolean stps_present;
370   guint32 n_sample_partial_syncs;
371   guint32 stps_index;
372   QtDemuxRandomAccessEntry *ra_entries;
373   guint n_ra_entries;
374
375   const QtDemuxRandomAccessEntry *pending_seek;
376
377   /* ctts */
378   gboolean ctts_present;
379   guint32 n_composition_times;
380   guint32 ctts_index;
381   guint32 ctts_sample_index;
382   guint32 ctts_count;
383   gint32 ctts_soffset;
384
385   /* cslg */
386   guint32 cslg_shift;
387
388   /* fragmented */
389   gboolean parsed_trex;
390   guint32 def_sample_duration;
391   guint32 def_sample_size;
392   guint32 def_sample_flags;
393
394   gboolean disabled;
395
396   /* stereoscopic video streams */
397   GstVideoMultiviewMode multiview_mode;
398   GstVideoMultiviewFlags multiview_flags;
399
400   /* protected streams */
401   gboolean protected;
402   guint32 protection_scheme_type;
403   guint32 protection_scheme_version;
404   gpointer protection_scheme_info;      /* specific to the protection scheme */
405   GQueue protection_scheme_event_queue;
406 };
407
408 /* Contains properties and cryptographic info for a set of samples from a
409  * track protected using Common Encryption (cenc) */
410 struct _QtDemuxCencSampleSetInfo
411 {
412   GstStructure *default_properties;
413
414   /* @crypto_info holds one GstStructure per sample */
415   GPtrArray *crypto_info;
416 };
417
418 static const gchar *
419 qt_demux_state_string (enum QtDemuxState state)
420 {
421   switch (state) {
422     case QTDEMUX_STATE_INITIAL:
423       return "<INITIAL>";
424     case QTDEMUX_STATE_HEADER:
425       return "<HEADER>";
426     case QTDEMUX_STATE_MOVIE:
427       return "<MOVIE>";
428     case QTDEMUX_STATE_BUFFER_MDAT:
429       return "<BUFFER_MDAT>";
430     default:
431       return "<UNKNOWN>";
432   }
433 }
434
435 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
436 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
437     guint32 fourcc, GstByteReader * parser);
438 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
439 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
440     guint32 fourcc, GstByteReader * parser);
441
442 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
443
444 static GstStaticPadTemplate gst_qtdemux_sink_template =
445     GST_STATIC_PAD_TEMPLATE ("sink",
446     GST_PAD_SINK,
447     GST_PAD_ALWAYS,
448     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
449         "application/x-3gp")
450     );
451
452 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
453 GST_STATIC_PAD_TEMPLATE ("video_%u",
454     GST_PAD_SRC,
455     GST_PAD_SOMETIMES,
456     GST_STATIC_CAPS_ANY);
457
458 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
459 GST_STATIC_PAD_TEMPLATE ("audio_%u",
460     GST_PAD_SRC,
461     GST_PAD_SOMETIMES,
462     GST_STATIC_CAPS_ANY);
463
464 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
465 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
466     GST_PAD_SRC,
467     GST_PAD_SOMETIMES,
468     GST_STATIC_CAPS_ANY);
469
470 #define gst_qtdemux_parent_class parent_class
471 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
472
473 static void gst_qtdemux_dispose (GObject * object);
474
475 static guint32
476 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
477     GstClockTime media_time);
478 static guint32
479 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
480     QtDemuxStream * str, gint64 media_offset);
481
482 #if 0
483 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
484 static GstIndex *gst_qtdemux_get_index (GstElement * element);
485 #endif
486 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
487     GstStateChange transition);
488 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
489 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
490     GstObject * parent, GstPadMode mode, gboolean active);
491
492 static void gst_qtdemux_loop (GstPad * pad);
493 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
494     GstBuffer * inbuf);
495 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
496     GstEvent * event);
497 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
498 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
499     QtDemuxStream * stream);
500 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
501     gboolean force);
502
503 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
504     const guint8 * buffer, guint length);
505 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
506     const guint8 * buffer, guint length);
507 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
508 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
509     GNode * udta);
510
511 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, GNode * esds, GstTagList * list);
513 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
514     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
515     gchar ** codec_name);
516 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
517     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
518     gchar ** codec_name);
519 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
520     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
521     gchar ** codec_name);
522 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
523     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
524     gchar ** codec_name);
525
526 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
527     QtDemuxStream * stream, guint32 n);
528 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
529 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
530     QtDemuxStream * stream);
531 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
532     QtDemuxStream * stream);
533 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
534 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
535 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
536     QtDemuxStream * stream);
537 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
538     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
539 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
540     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
541     GstClockTime * _start, GstClockTime * _stop);
542 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
543     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
544
545 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
546 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
547
548 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
549
550 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
551     QtDemuxStream * stream, guint sample_index);
552 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
553     const gchar * id);
554 static void qtdemux_gst_structure_free (GstStructure * gststructure);
555
556 static void
557 gst_qtdemux_class_init (GstQTDemuxClass * klass)
558 {
559   GObjectClass *gobject_class;
560   GstElementClass *gstelement_class;
561
562   gobject_class = (GObjectClass *) klass;
563   gstelement_class = (GstElementClass *) klass;
564
565   parent_class = g_type_class_peek_parent (klass);
566
567   gobject_class->dispose = gst_qtdemux_dispose;
568
569   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
570 #if 0
571   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
572   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
573 #endif
574
575   gst_tag_register_musicbrainz_tags ();
576
577   gst_element_class_add_static_pad_template (gstelement_class,
578       &gst_qtdemux_sink_template);
579   gst_element_class_add_static_pad_template (gstelement_class,
580       &gst_qtdemux_videosrc_template);
581   gst_element_class_add_static_pad_template (gstelement_class,
582       &gst_qtdemux_audiosrc_template);
583   gst_element_class_add_static_pad_template (gstelement_class,
584       &gst_qtdemux_subsrc_template);
585   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
586       "Codec/Demuxer",
587       "Demultiplex a QuickTime file into audio and video streams",
588       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
589
590   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
591
592 }
593
594 static void
595 gst_qtdemux_init (GstQTDemux * qtdemux)
596 {
597   qtdemux->sinkpad =
598       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
599   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
600   gst_pad_set_activatemode_function (qtdemux->sinkpad,
601       qtdemux_sink_activate_mode);
602   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
603   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
604   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
605
606   qtdemux->state = QTDEMUX_STATE_INITIAL;
607   qtdemux->pullbased = FALSE;
608   qtdemux->posted_redirect = FALSE;
609   qtdemux->neededbytes = 16;
610   qtdemux->todrop = 0;
611   qtdemux->adapter = gst_adapter_new ();
612   qtdemux->offset = 0;
613   qtdemux->first_mdat = -1;
614   qtdemux->got_moov = FALSE;
615   qtdemux->mdatoffset = -1;
616   qtdemux->mdatbuffer = NULL;
617   qtdemux->restoredata_buffer = NULL;
618   qtdemux->restoredata_offset = -1;
619   qtdemux->fragment_start = -1;
620   qtdemux->fragment_start_offset = -1;
621   qtdemux->media_caps = NULL;
622   qtdemux->exposed = FALSE;
623   qtdemux->mss_mode = FALSE;
624   qtdemux->pending_newsegment = NULL;
625   qtdemux->upstream_format_is_time = FALSE;
626   qtdemux->have_group_id = FALSE;
627   qtdemux->group_id = G_MAXUINT;
628   qtdemux->cenc_aux_info_offset = 0;
629   qtdemux->cenc_aux_info_sizes = NULL;
630   qtdemux->cenc_aux_sample_count = 0;
631   qtdemux->protection_system_ids = NULL;
632   g_queue_init (&qtdemux->protection_event_queue);
633   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
634   qtdemux->flowcombiner = gst_flow_combiner_new ();
635
636   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
637 }
638
639 static void
640 gst_qtdemux_dispose (GObject * object)
641 {
642   GstQTDemux *qtdemux = GST_QTDEMUX (object);
643
644   if (qtdemux->adapter) {
645     g_object_unref (G_OBJECT (qtdemux->adapter));
646     qtdemux->adapter = NULL;
647   }
648   gst_flow_combiner_free (qtdemux->flowcombiner);
649   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
650       NULL);
651   g_queue_clear (&qtdemux->protection_event_queue);
652
653   g_free (qtdemux->cenc_aux_info_sizes);
654   qtdemux->cenc_aux_info_sizes = NULL;
655
656   G_OBJECT_CLASS (parent_class)->dispose (object);
657 }
658
659 static void
660 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
661 {
662   if (qtdemux->posted_redirect) {
663     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
664         (_("This file contains no playable streams.")),
665         ("no known streams found, a redirect message has been posted"));
666   } else {
667     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
668         (_("This file contains no playable streams.")),
669         ("no known streams found"));
670   }
671 }
672
673 static GstBuffer *
674 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
675 {
676   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
677       mem, size, 0, size, mem, free_func);
678 }
679
680 static GstFlowReturn
681 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
682     GstBuffer ** buf)
683 {
684   GstFlowReturn flow;
685   GstMapInfo map;
686   gsize bsize;
687
688   if (G_UNLIKELY (size == 0)) {
689     GstFlowReturn ret;
690     GstBuffer *tmp = NULL;
691
692     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
693     if (ret != GST_FLOW_OK)
694       return ret;
695
696     gst_buffer_map (tmp, &map, GST_MAP_READ);
697     size = QT_UINT32 (map.data);
698     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
699
700     gst_buffer_unmap (tmp, &map);
701     gst_buffer_unref (tmp);
702   }
703
704   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
705   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
706     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
707       /* we're pulling header but already got most interesting bits,
708        * so never mind the rest (e.g. tags) (that much) */
709       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
710           size);
711       return GST_FLOW_EOS;
712     } else {
713       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
714           (_("This file is invalid and cannot be played.")),
715           ("atom has bogus size %" G_GUINT64_FORMAT, size));
716       return GST_FLOW_ERROR;
717     }
718   }
719
720   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
721
722   if (G_UNLIKELY (flow != GST_FLOW_OK))
723     return flow;
724
725   bsize = gst_buffer_get_size (*buf);
726   /* Catch short reads - we don't want any partial atoms */
727   if (G_UNLIKELY (bsize < size)) {
728     GST_WARNING_OBJECT (qtdemux,
729         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
730     gst_buffer_unref (*buf);
731     *buf = NULL;
732     return GST_FLOW_EOS;
733   }
734
735   return flow;
736 }
737
738 #if 1
739 static gboolean
740 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
741     GstFormat src_format, gint64 src_value, GstFormat dest_format,
742     gint64 * dest_value)
743 {
744   gboolean res = TRUE;
745   QtDemuxStream *stream = gst_pad_get_element_private (pad);
746   gint32 index;
747
748   if (stream->subtype != FOURCC_vide) {
749     res = FALSE;
750     goto done;
751   }
752
753   switch (src_format) {
754     case GST_FORMAT_TIME:
755       switch (dest_format) {
756         case GST_FORMAT_BYTES:{
757           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
758           if (-1 == index) {
759             res = FALSE;
760             goto done;
761           }
762
763           *dest_value = stream->samples[index].offset;
764
765           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
766               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
767               GST_TIME_ARGS (src_value), *dest_value);
768           break;
769         }
770         default:
771           res = FALSE;
772           break;
773       }
774       break;
775     case GST_FORMAT_BYTES:
776       switch (dest_format) {
777         case GST_FORMAT_TIME:{
778           index =
779               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
780               stream, src_value);
781
782           if (-1 == index) {
783             res = FALSE;
784             goto done;
785           }
786
787           *dest_value =
788               QTSTREAMTIME_TO_GSTTIME (stream,
789               stream->samples[index].timestamp);
790           GST_DEBUG_OBJECT (qtdemux,
791               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
792               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
793           break;
794         }
795         default:
796           res = FALSE;
797           break;
798       }
799       break;
800     default:
801       res = FALSE;
802       break;
803   }
804
805 done:
806   return res;
807 }
808 #endif
809
810 static gboolean
811 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
812 {
813   gboolean res = FALSE;
814
815   *duration = GST_CLOCK_TIME_NONE;
816
817   if (qtdemux->duration != 0 &&
818       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
819     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
820     res = TRUE;
821   } else {
822     *duration = GST_CLOCK_TIME_NONE;
823   }
824
825   return res;
826 }
827
828 static gboolean
829 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
830     GstQuery * query)
831 {
832   gboolean res = FALSE;
833   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
834
835   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
836
837   switch (GST_QUERY_TYPE (query)) {
838     case GST_QUERY_POSITION:{
839       GstFormat fmt;
840
841       gst_query_parse_position (query, &fmt, NULL);
842       if (fmt == GST_FORMAT_TIME
843           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
844         gst_query_set_position (query, GST_FORMAT_TIME,
845             qtdemux->segment.position);
846         res = TRUE;
847       }
848     }
849       break;
850     case GST_QUERY_DURATION:{
851       GstFormat fmt;
852
853       gst_query_parse_duration (query, &fmt, NULL);
854       if (fmt == GST_FORMAT_TIME) {
855         /* First try to query upstream */
856         res = gst_pad_query_default (pad, parent, query);
857         if (!res) {
858           GstClockTime duration;
859           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
860             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
861             res = TRUE;
862           }
863         }
864       }
865       break;
866     }
867     case GST_QUERY_CONVERT:{
868       GstFormat src_fmt, dest_fmt;
869       gint64 src_value, dest_value = 0;
870
871       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
872
873       res = gst_qtdemux_src_convert (qtdemux, pad,
874           src_fmt, src_value, dest_fmt, &dest_value);
875       if (res) {
876         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
877         res = TRUE;
878       }
879       break;
880     }
881     case GST_QUERY_FORMATS:
882       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
883       res = TRUE;
884       break;
885     case GST_QUERY_SEEKING:{
886       GstFormat fmt;
887       gboolean seekable;
888
889       /* try upstream first */
890       res = gst_pad_query_default (pad, parent, query);
891
892       if (!res) {
893         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
894         if (fmt == GST_FORMAT_TIME) {
895           GstClockTime duration;
896
897           gst_qtdemux_get_duration (qtdemux, &duration);
898           seekable = TRUE;
899           if (!qtdemux->pullbased) {
900             GstQuery *q;
901
902             /* we might be able with help from upstream */
903             seekable = FALSE;
904             q = gst_query_new_seeking (GST_FORMAT_BYTES);
905             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
906               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
907               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
908             }
909             gst_query_unref (q);
910           }
911           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
912           res = TRUE;
913         }
914       }
915       break;
916     }
917     case GST_QUERY_SEGMENT:
918     {
919       GstFormat format;
920       gint64 start, stop;
921
922       format = qtdemux->segment.format;
923
924       start =
925           gst_segment_to_stream_time (&qtdemux->segment, format,
926           qtdemux->segment.start);
927       if ((stop = qtdemux->segment.stop) == -1)
928         stop = qtdemux->segment.duration;
929       else
930         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
931
932       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
933       res = TRUE;
934       break;
935     }
936     default:
937       res = gst_pad_query_default (pad, parent, query);
938       break;
939   }
940
941   return res;
942 }
943
944 static void
945 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
946 {
947   if (G_LIKELY (stream->pad)) {
948     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
949         GST_DEBUG_PAD_NAME (stream->pad));
950
951     if (G_UNLIKELY (stream->pending_tags)) {
952       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
953           stream->pending_tags);
954       gst_pad_push_event (stream->pad,
955           gst_event_new_tag (stream->pending_tags));
956       stream->pending_tags = NULL;
957     }
958
959     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
960       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
961           qtdemux->tag_list);
962       gst_pad_push_event (stream->pad,
963           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
964       stream->send_global_tags = FALSE;
965     }
966   }
967 }
968
969 /* push event on all source pads; takes ownership of the event */
970 static void
971 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
972 {
973   guint n;
974   gboolean has_valid_stream = FALSE;
975   GstEventType etype = GST_EVENT_TYPE (event);
976
977   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
978       GST_EVENT_TYPE_NAME (event));
979
980   for (n = 0; n < qtdemux->n_streams; n++) {
981     GstPad *pad;
982     QtDemuxStream *stream = qtdemux->streams[n];
983     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
984
985     if ((pad = stream->pad)) {
986       has_valid_stream = TRUE;
987
988       if (etype == GST_EVENT_EOS) {
989         /* let's not send twice */
990         if (stream->sent_eos)
991           continue;
992         stream->sent_eos = TRUE;
993       }
994
995       gst_pad_push_event (pad, gst_event_ref (event));
996     }
997   }
998
999   gst_event_unref (event);
1000
1001   /* if it is EOS and there are no pads, post an error */
1002   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1003     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1004   }
1005 }
1006
1007 /* push a pending newsegment event, if any from the streaming thread */
1008 static void
1009 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1010 {
1011   if (qtdemux->pending_newsegment) {
1012     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1013     qtdemux->pending_newsegment = NULL;
1014   }
1015 }
1016
1017 typedef struct
1018 {
1019   guint64 media_time;
1020 } FindData;
1021
1022 static gint
1023 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1024 {
1025   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1026     return 1;
1027   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1028     return 0;
1029
1030   return -1;
1031 }
1032
1033 /* find the index of the sample that includes the data for @media_time using a
1034  * binary search.  Only to be called in optimized cases of linear search below.
1035  *
1036  * Returns the index of the sample.
1037  */
1038 static guint32
1039 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1040     guint64 media_time)
1041 {
1042   QtDemuxSample *result;
1043   guint32 index;
1044
1045   /* convert media_time to mov format */
1046   media_time =
1047       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1048
1049   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1050       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1051       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1052
1053   if (G_LIKELY (result))
1054     index = result - str->samples;
1055   else
1056     index = 0;
1057
1058   return index;
1059 }
1060
1061
1062
1063 /* find the index of the sample that includes the data for @media_offset using a
1064  * linear search
1065  *
1066  * Returns the index of the sample.
1067  */
1068 static guint32
1069 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1070     QtDemuxStream * str, gint64 media_offset)
1071 {
1072   QtDemuxSample *result = str->samples;
1073   guint32 index = 0;
1074
1075   if (result == NULL || str->n_samples == 0)
1076     return -1;
1077
1078   if (media_offset == result->offset)
1079     return index;
1080
1081   result++;
1082   while (index < str->n_samples - 1) {
1083     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1084       goto parse_failed;
1085
1086     if (media_offset < result->offset)
1087       break;
1088
1089     index++;
1090     result++;
1091   }
1092   return index;
1093
1094   /* ERRORS */
1095 parse_failed:
1096   {
1097     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1098     return -1;
1099   }
1100 }
1101
1102 /* find the index of the sample that includes the data for @media_time using a
1103  * linear search, and keeping in mind that not all samples may have been parsed
1104  * yet.  If possible, it will delegate to binary search.
1105  *
1106  * Returns the index of the sample.
1107  */
1108 static guint32
1109 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1110     GstClockTime media_time)
1111 {
1112   guint32 index = 0;
1113   guint64 mov_time;
1114   QtDemuxSample *sample;
1115
1116   /* convert media_time to mov format */
1117   mov_time =
1118       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1119
1120   sample = str->samples;
1121   if (mov_time == sample->timestamp + sample->pts_offset)
1122     return index;
1123
1124   /* use faster search if requested time in already parsed range */
1125   sample = str->samples + str->stbl_index;
1126   if (str->stbl_index >= 0 &&
1127       mov_time <= (sample->timestamp + sample->pts_offset))
1128     return gst_qtdemux_find_index (qtdemux, str, media_time);
1129
1130   while (index < str->n_samples - 1) {
1131     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1132       goto parse_failed;
1133
1134     sample = str->samples + index + 1;
1135     if (mov_time < (sample->timestamp + sample->pts_offset))
1136       break;
1137
1138     index++;
1139   }
1140   return index;
1141
1142   /* ERRORS */
1143 parse_failed:
1144   {
1145     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1146     return -1;
1147   }
1148 }
1149
1150 /* find the index of the keyframe needed to decode the sample at @index
1151  * of stream @str.
1152  *
1153  * Returns the index of the keyframe.
1154  */
1155 static guint32
1156 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1157     guint32 index)
1158 {
1159   guint32 new_index = index;
1160
1161   if (index >= str->n_samples) {
1162     new_index = str->n_samples;
1163     goto beach;
1164   }
1165
1166   /* all keyframes, return index */
1167   if (str->all_keyframe) {
1168     new_index = index;
1169     goto beach;
1170   }
1171
1172   /* else go back until we have a keyframe */
1173   while (TRUE) {
1174     if (str->samples[new_index].keyframe)
1175       break;
1176
1177     if (new_index == 0)
1178       break;
1179
1180     new_index--;
1181   }
1182
1183 beach:
1184   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1185       "gave %u", index, new_index);
1186
1187   return new_index;
1188 }
1189
1190 /* find the segment for @time_position for @stream
1191  *
1192  * Returns the index of the segment containing @time_position.
1193  * Returns the last segment and sets the @eos variable to TRUE
1194  * if the time is beyond the end. @eos may be NULL
1195  */
1196 static guint32
1197 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1198     GstClockTime time_position)
1199 {
1200   gint i;
1201   guint32 seg_idx;
1202
1203   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1204       GST_TIME_ARGS (time_position));
1205
1206   seg_idx = -1;
1207   for (i = 0; i < stream->n_segments; i++) {
1208     QtDemuxSegment *segment = &stream->segments[i];
1209
1210     GST_LOG_OBJECT (stream->pad,
1211         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1212         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1213
1214     /* For the last segment we include stop_time in the last segment */
1215     if (i < stream->n_segments - 1) {
1216       if (segment->time <= time_position && time_position < segment->stop_time) {
1217         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1218         seg_idx = i;
1219         break;
1220       }
1221     } else {
1222       /* Last segment always matches */
1223       seg_idx = i;
1224       break;
1225     }
1226   }
1227   return seg_idx;
1228 }
1229
1230 /* move the stream @str to the sample position @index.
1231  *
1232  * Updates @str->sample_index and marks discontinuity if needed.
1233  */
1234 static void
1235 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1236     guint32 index)
1237 {
1238   /* no change needed */
1239   if (index == str->sample_index)
1240     return;
1241
1242   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1243       str->n_samples);
1244
1245   /* position changed, we have a discont */
1246   str->sample_index = index;
1247   str->offset_in_sample = 0;
1248   /* Each time we move in the stream we store the position where we are
1249    * starting from */
1250   str->from_sample = index;
1251   str->discont = TRUE;
1252 }
1253
1254 static void
1255 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1256     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1257 {
1258   guint64 min_offset;
1259   gint64 min_byte_offset = -1;
1260   gint n;
1261
1262   min_offset = desired_time;
1263
1264   /* for each stream, find the index of the sample in the segment
1265    * and move back to the previous keyframe. */
1266   for (n = 0; n < qtdemux->n_streams; n++) {
1267     QtDemuxStream *str;
1268     guint32 index, kindex;
1269     guint32 seg_idx;
1270     GstClockTime media_start;
1271     GstClockTime media_time;
1272     GstClockTime seg_time;
1273     QtDemuxSegment *seg;
1274     gboolean empty_segment = FALSE;
1275
1276     str = qtdemux->streams[n];
1277
1278     if (str->sparse && !use_sparse)
1279       continue;
1280
1281     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1282     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1283
1284     /* get segment and time in the segment */
1285     seg = &str->segments[seg_idx];
1286     seg_time = (desired_time - seg->time) * seg->rate;
1287
1288     while (QTSEGMENT_IS_EMPTY (seg)) {
1289       seg_time = 0;
1290       empty_segment = TRUE;
1291       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1292           seg_idx);
1293       seg_idx++;
1294       if (seg_idx == str->n_segments)
1295         break;
1296       seg = &str->segments[seg_idx];
1297     }
1298
1299     if (seg_idx == str->n_segments) {
1300       /* FIXME track shouldn't have the last segment as empty, but if it
1301        * happens we better handle it */
1302       continue;
1303     }
1304
1305     /* get the media time in the segment */
1306     media_start = seg->media_start + seg_time;
1307
1308     /* get the index of the sample with media time */
1309     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1310     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1311         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1312         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1313         empty_segment);
1314
1315     if (!empty_segment) {
1316       /* find previous keyframe */
1317       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1318
1319       /* if the keyframe is at a different position, we need to update the
1320        * requested seek time */
1321       if (index != kindex) {
1322         index = kindex;
1323
1324         /* get timestamp of keyframe */
1325         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1326         GST_DEBUG_OBJECT (qtdemux,
1327             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1328             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1329             str->samples[kindex].offset);
1330
1331         /* keyframes in the segment get a chance to change the
1332          * desired_offset. keyframes out of the segment are
1333          * ignored. */
1334         if (media_time >= seg->media_start) {
1335           GstClockTime seg_time;
1336
1337           /* this keyframe is inside the segment, convert back to
1338            * segment time */
1339           seg_time = (media_time - seg->media_start) + seg->time;
1340           if (seg_time < min_offset)
1341             min_offset = seg_time;
1342         }
1343       }
1344     }
1345
1346     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1347       min_byte_offset = str->samples[index].offset;
1348   }
1349
1350   if (key_time)
1351     *key_time = min_offset;
1352   if (key_offset)
1353     *key_offset = min_byte_offset;
1354 }
1355
1356 static gboolean
1357 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1358     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1359 {
1360   gboolean res;
1361
1362   g_return_val_if_fail (format != NULL, FALSE);
1363   g_return_val_if_fail (cur != NULL, FALSE);
1364   g_return_val_if_fail (stop != NULL, FALSE);
1365
1366   if (*format == GST_FORMAT_TIME)
1367     return TRUE;
1368
1369   res = TRUE;
1370   if (cur_type != GST_SEEK_TYPE_NONE)
1371     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1372   if (res && stop_type != GST_SEEK_TYPE_NONE)
1373     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1374
1375   if (res)
1376     *format = GST_FORMAT_TIME;
1377
1378   return res;
1379 }
1380
1381 /* perform seek in push based mode:
1382    find BYTE position to move to based on time and delegate to upstream
1383 */
1384 static gboolean
1385 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1386 {
1387   gdouble rate;
1388   GstFormat format;
1389   GstSeekFlags flags;
1390   GstSeekType cur_type, stop_type;
1391   gint64 cur, stop, key_cur;
1392   gboolean res;
1393   gint64 byte_cur;
1394   gint64 original_stop;
1395   guint32 seqnum;
1396
1397   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1398
1399   gst_event_parse_seek (event, &rate, &format, &flags,
1400       &cur_type, &cur, &stop_type, &stop);
1401   seqnum = gst_event_get_seqnum (event);
1402
1403   /* only forward streaming and seeking is possible */
1404   if (rate <= 0)
1405     goto unsupported_seek;
1406
1407   /* convert to TIME if needed and possible */
1408   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1409           stop_type, &stop))
1410     goto no_format;
1411
1412   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1413    * the original stop position to use when upstream pushes the new segment
1414    * for this seek */
1415   original_stop = stop;
1416   stop = -1;
1417
1418   /* find reasonable corresponding BYTE position,
1419    * also try to mind about keyframes, since we can not go back a bit for them
1420    * later on */
1421   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1422
1423   if (byte_cur == -1)
1424     goto abort_seek;
1425
1426   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1427       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1428       stop);
1429
1430   GST_OBJECT_LOCK (qtdemux);
1431   qtdemux->seek_offset = byte_cur;
1432   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1433     qtdemux->push_seek_start = cur;
1434   } else {
1435     qtdemux->push_seek_start = key_cur;
1436   }
1437
1438   if (stop_type == GST_SEEK_TYPE_NONE) {
1439     qtdemux->push_seek_stop = qtdemux->segment.stop;
1440   } else {
1441     qtdemux->push_seek_stop = original_stop;
1442   }
1443   GST_OBJECT_UNLOCK (qtdemux);
1444
1445   /* BYTE seek event */
1446   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1447       stop_type, stop);
1448   gst_event_set_seqnum (event, seqnum);
1449   res = gst_pad_push_event (qtdemux->sinkpad, event);
1450
1451   return res;
1452
1453   /* ERRORS */
1454 abort_seek:
1455   {
1456     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1457         "seek aborted.");
1458     return FALSE;
1459   }
1460 unsupported_seek:
1461   {
1462     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1463     return FALSE;
1464   }
1465 no_format:
1466   {
1467     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1468     return FALSE;
1469   }
1470 }
1471
1472 /* perform the seek.
1473  *
1474  * We set all segment_indexes in the streams to unknown and
1475  * adjust the time_position to the desired position. this is enough
1476  * to trigger a segment switch in the streaming thread to start
1477  * streaming from the desired position.
1478  *
1479  * Keyframe seeking is a little more complicated when dealing with
1480  * segments. Ideally we want to move to the previous keyframe in
1481  * the segment but there might not be a keyframe in the segment. In
1482  * fact, none of the segments could contain a keyframe. We take a
1483  * practical approach: seek to the previous keyframe in the segment,
1484  * if there is none, seek to the beginning of the segment.
1485  *
1486  * Called with STREAM_LOCK
1487  */
1488 static gboolean
1489 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1490     guint32 seqnum, GstSeekFlags flags)
1491 {
1492   gint64 desired_offset;
1493   gint n;
1494
1495   desired_offset = segment->position;
1496
1497   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1498       GST_TIME_ARGS (desired_offset));
1499
1500   /* may not have enough fragmented info to do this adjustment,
1501    * and we can't scan (and probably should not) at this time with
1502    * possibly flushing upstream */
1503   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1504     gint64 min_offset;
1505
1506     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1507     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1508         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1509     desired_offset = min_offset;
1510   }
1511
1512   /* and set all streams to the final position */
1513   gst_flow_combiner_reset (qtdemux->flowcombiner);
1514   qtdemux->segment_seqnum = seqnum;
1515   for (n = 0; n < qtdemux->n_streams; n++) {
1516     QtDemuxStream *stream = qtdemux->streams[n];
1517
1518     stream->time_position = desired_offset;
1519     stream->accumulated_base = 0;
1520     stream->sample_index = -1;
1521     stream->offset_in_sample = 0;
1522     stream->segment_index = -1;
1523     stream->sent_eos = FALSE;
1524
1525     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1526       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1527   }
1528   segment->position = desired_offset;
1529   segment->time = desired_offset;
1530   if (segment->rate >= 0) {
1531     segment->start = desired_offset;
1532
1533     /* we stop at the end */
1534     if (segment->stop == -1)
1535       segment->stop = segment->duration;
1536   } else {
1537     segment->stop = desired_offset;
1538   }
1539
1540   if (qtdemux->fragmented)
1541     qtdemux->fragmented_seek_pending = TRUE;
1542
1543   return TRUE;
1544 }
1545
1546 /* do a seek in pull based mode */
1547 static gboolean
1548 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1549 {
1550   gdouble rate;
1551   GstFormat format;
1552   GstSeekFlags flags;
1553   GstSeekType cur_type, stop_type;
1554   gint64 cur, stop;
1555   gboolean flush;
1556   gboolean update;
1557   GstSegment seeksegment;
1558   guint32 seqnum = 0;
1559   GstEvent *flush_event;
1560
1561   if (event) {
1562     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1563
1564     gst_event_parse_seek (event, &rate, &format, &flags,
1565         &cur_type, &cur, &stop_type, &stop);
1566     seqnum = gst_event_get_seqnum (event);
1567
1568     /* we have to have a format as the segment format. Try to convert
1569      * if not. */
1570     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1571             stop_type, &stop))
1572       goto no_format;
1573
1574     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1575   } else {
1576     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1577     flags = 0;
1578   }
1579
1580   flush = flags & GST_SEEK_FLAG_FLUSH;
1581
1582   /* stop streaming, either by flushing or by pausing the task */
1583   if (flush) {
1584     flush_event = gst_event_new_flush_start ();
1585     if (seqnum)
1586       gst_event_set_seqnum (flush_event, seqnum);
1587     /* unlock upstream pull_range */
1588     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1589     /* make sure out loop function exits */
1590     gst_qtdemux_push_event (qtdemux, flush_event);
1591   } else {
1592     /* non flushing seek, pause the task */
1593     gst_pad_pause_task (qtdemux->sinkpad);
1594   }
1595
1596   /* wait for streaming to finish */
1597   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1598
1599   /* copy segment, we need this because we still need the old
1600    * segment when we close the current segment. */
1601   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1602
1603   if (event) {
1604     /* configure the segment with the seek variables */
1605     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1606     gst_segment_do_seek (&seeksegment, rate, format, flags,
1607         cur_type, cur, stop_type, stop, &update);
1608   }
1609
1610   /* now do the seek, this actually never returns FALSE */
1611   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1612
1613   /* prepare for streaming again */
1614   if (flush) {
1615     flush_event = gst_event_new_flush_stop (TRUE);
1616     if (seqnum)
1617       gst_event_set_seqnum (flush_event, seqnum);
1618
1619     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1620     gst_qtdemux_push_event (qtdemux, flush_event);
1621   }
1622
1623   /* commit the new segment */
1624   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1625
1626   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1627     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1628         qtdemux->segment.format, qtdemux->segment.position);
1629     if (seqnum)
1630       gst_message_set_seqnum (msg, seqnum);
1631     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1632   }
1633
1634   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1635   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1636       qtdemux->sinkpad, NULL);
1637
1638   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1639
1640   return TRUE;
1641
1642   /* ERRORS */
1643 no_format:
1644   {
1645     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1646     return FALSE;
1647   }
1648 }
1649
1650 static gboolean
1651 qtdemux_ensure_index (GstQTDemux * qtdemux)
1652 {
1653   guint i;
1654
1655   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1656
1657   /* Build complete index */
1658   for (i = 0; i < qtdemux->n_streams; i++) {
1659     QtDemuxStream *stream = qtdemux->streams[i];
1660
1661     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1662       goto parse_error;
1663   }
1664   return TRUE;
1665
1666   /* ERRORS */
1667 parse_error:
1668   {
1669     GST_LOG_OBJECT (qtdemux,
1670         "Building complete index of stream %u for seeking failed!", i);
1671     return FALSE;
1672   }
1673 }
1674
1675 static gboolean
1676 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1677     GstEvent * event)
1678 {
1679   gboolean res = TRUE;
1680   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1681
1682   switch (GST_EVENT_TYPE (event)) {
1683     case GST_EVENT_SEEK:
1684     {
1685 #ifndef GST_DISABLE_GST_DEBUG
1686       GstClockTime ts = gst_util_get_timestamp ();
1687 #endif
1688
1689       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1690         /* seek should be handled by upstream, we might need to re-download fragments */
1691         GST_DEBUG_OBJECT (qtdemux,
1692             "let upstream handle seek for fragmented playback");
1693         goto upstream;
1694       }
1695
1696       /* Build complete index for seeking;
1697        * if not a fragmented file at least */
1698       if (!qtdemux->fragmented)
1699         if (!qtdemux_ensure_index (qtdemux))
1700           goto index_failed;
1701 #ifndef GST_DISABLE_GST_DEBUG
1702       ts = gst_util_get_timestamp () - ts;
1703       GST_INFO_OBJECT (qtdemux,
1704           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1705 #endif
1706     }
1707       if (qtdemux->pullbased) {
1708         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1709       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1710         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1711         res = TRUE;
1712       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1713           && !qtdemux->fragmented) {
1714         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1715       } else {
1716         GST_DEBUG_OBJECT (qtdemux,
1717             "ignoring seek in push mode in current state");
1718         res = FALSE;
1719       }
1720       gst_event_unref (event);
1721       break;
1722     case GST_EVENT_QOS:
1723     case GST_EVENT_NAVIGATION:
1724       res = FALSE;
1725       gst_event_unref (event);
1726       break;
1727     default:
1728     upstream:
1729       res = gst_pad_event_default (pad, parent, event);
1730       break;
1731   }
1732
1733 done:
1734   return res;
1735
1736   /* ERRORS */
1737 index_failed:
1738   {
1739     GST_ERROR_OBJECT (qtdemux, "Index failed");
1740     gst_event_unref (event);
1741     res = FALSE;
1742     goto done;
1743   }
1744 }
1745
1746 /* stream/index return sample that is min/max w.r.t. byte position,
1747  * time is min/max w.r.t. time of samples,
1748  * the latter need not be time of the former sample */
1749 static void
1750 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1751     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1752 {
1753   gint i, n, index;
1754   gint64 time, min_time;
1755   QtDemuxStream *stream;
1756
1757   min_time = -1;
1758   stream = NULL;
1759   index = -1;
1760
1761   for (n = 0; n < qtdemux->n_streams; ++n) {
1762     QtDemuxStream *str;
1763     gint inc;
1764     gboolean set_sample;
1765
1766     str = qtdemux->streams[n];
1767     set_sample = !set;
1768
1769     if (fw) {
1770       i = 0;
1771       inc = 1;
1772     } else {
1773       i = str->n_samples - 1;
1774       inc = -1;
1775     }
1776
1777     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1778       if (str->samples[i].size == 0)
1779         continue;
1780
1781       if (fw && (str->samples[i].offset < byte_pos))
1782         continue;
1783
1784       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1785         continue;
1786
1787       /* move stream to first available sample */
1788       if (set) {
1789         gst_qtdemux_move_stream (qtdemux, str, i);
1790         set_sample = TRUE;
1791       }
1792
1793       /* avoid index from sparse streams since they might be far away */
1794       if (!str->sparse) {
1795         /* determine min/max time */
1796         time = QTSAMPLE_PTS (str, &str->samples[i]);
1797         if (min_time == -1 || (!fw && time > min_time) ||
1798             (fw && time < min_time)) {
1799           min_time = time;
1800         }
1801
1802         /* determine stream with leading sample, to get its position */
1803         if (!stream ||
1804             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1805             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1806           stream = str;
1807           index = i;
1808         }
1809       }
1810       break;
1811     }
1812
1813     /* no sample for this stream, mark eos */
1814     if (!set_sample)
1815       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1816   }
1817
1818   if (_time)
1819     *_time = min_time;
1820   if (_stream)
1821     *_stream = stream;
1822   if (_index)
1823     *_index = index;
1824 }
1825
1826 static QtDemuxStream *
1827 _create_stream (void)
1828 {
1829   QtDemuxStream *stream;
1830
1831   stream = g_new0 (QtDemuxStream, 1);
1832   /* new streams always need a discont */
1833   stream->discont = TRUE;
1834   /* we enable clipping for raw audio/video streams */
1835   stream->need_clip = FALSE;
1836   stream->need_process = FALSE;
1837   stream->segment_index = -1;
1838   stream->time_position = 0;
1839   stream->sample_index = -1;
1840   stream->offset_in_sample = 0;
1841   stream->new_stream = TRUE;
1842   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1843   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1844   stream->protected = FALSE;
1845   stream->protection_scheme_type = 0;
1846   stream->protection_scheme_version = 0;
1847   stream->protection_scheme_info = NULL;
1848   stream->n_samples_moof = 0;
1849   stream->duration_moof = 0;
1850   g_queue_init (&stream->protection_scheme_event_queue);
1851   return stream;
1852 }
1853
1854 static gboolean
1855 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1856 {
1857   GstStructure *structure;
1858   const gchar *variant;
1859   const GstCaps *mediacaps = NULL;
1860
1861   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1862
1863   structure = gst_caps_get_structure (caps, 0);
1864   variant = gst_structure_get_string (structure, "variant");
1865
1866   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1867     QtDemuxStream *stream;
1868     const GValue *value;
1869
1870     demux->fragmented = TRUE;
1871     demux->mss_mode = TRUE;
1872
1873     if (demux->n_streams > 1) {
1874       /* can't do this, we can only renegotiate for another mss format */
1875       return FALSE;
1876     }
1877
1878     value = gst_structure_get_value (structure, "media-caps");
1879     /* create stream */
1880     if (value) {
1881       const GValue *timescale_v;
1882
1883       /* TODO update when stream changes during playback */
1884
1885       if (demux->n_streams == 0) {
1886         stream = _create_stream ();
1887         demux->streams[demux->n_streams] = stream;
1888         demux->n_streams = 1;
1889       } else {
1890         stream = demux->streams[0];
1891       }
1892
1893       timescale_v = gst_structure_get_value (structure, "timescale");
1894       if (timescale_v) {
1895         stream->timescale = g_value_get_uint64 (timescale_v);
1896       } else {
1897         /* default mss timescale */
1898         stream->timescale = 10000000;
1899       }
1900       demux->timescale = stream->timescale;
1901
1902       mediacaps = gst_value_get_caps (value);
1903       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1904         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1905             mediacaps);
1906         stream->new_caps = TRUE;
1907       }
1908       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1909       structure = gst_caps_get_structure (mediacaps, 0);
1910       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1911         stream->subtype = FOURCC_vide;
1912
1913         gst_structure_get_int (structure, "width", &stream->width);
1914         gst_structure_get_int (structure, "height", &stream->height);
1915         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1916             &stream->fps_d);
1917       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1918         gint rate = 0;
1919         stream->subtype = FOURCC_soun;
1920         gst_structure_get_int (structure, "channels", &stream->n_channels);
1921         gst_structure_get_int (structure, "rate", &rate);
1922         stream->rate = rate;
1923       }
1924     }
1925     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1926   } else {
1927     demux->mss_mode = FALSE;
1928   }
1929
1930   return TRUE;
1931 }
1932
1933 static void
1934 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1935 {
1936   gint n;
1937
1938   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1939   gst_pad_stop_task (qtdemux->sinkpad);
1940
1941   if (hard || qtdemux->upstream_format_is_time) {
1942     qtdemux->state = QTDEMUX_STATE_INITIAL;
1943     qtdemux->neededbytes = 16;
1944     qtdemux->todrop = 0;
1945     qtdemux->pullbased = FALSE;
1946     qtdemux->posted_redirect = FALSE;
1947     qtdemux->first_mdat = -1;
1948     qtdemux->header_size = 0;
1949     qtdemux->mdatoffset = -1;
1950     qtdemux->restoredata_offset = -1;
1951     if (qtdemux->mdatbuffer)
1952       gst_buffer_unref (qtdemux->mdatbuffer);
1953     if (qtdemux->restoredata_buffer)
1954       gst_buffer_unref (qtdemux->restoredata_buffer);
1955     qtdemux->mdatbuffer = NULL;
1956     qtdemux->restoredata_buffer = NULL;
1957     qtdemux->mdatleft = 0;
1958     if (qtdemux->comp_brands)
1959       gst_buffer_unref (qtdemux->comp_brands);
1960     qtdemux->comp_brands = NULL;
1961     qtdemux->last_moov_offset = -1;
1962     if (qtdemux->moov_node)
1963       g_node_destroy (qtdemux->moov_node);
1964     qtdemux->moov_node = NULL;
1965     qtdemux->moov_node_compressed = NULL;
1966     if (qtdemux->tag_list)
1967       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1968     qtdemux->tag_list = NULL;
1969 #if 0
1970     if (qtdemux->element_index)
1971       gst_object_unref (qtdemux->element_index);
1972     qtdemux->element_index = NULL;
1973 #endif
1974     qtdemux->major_brand = 0;
1975     if (qtdemux->pending_newsegment)
1976       gst_event_unref (qtdemux->pending_newsegment);
1977     qtdemux->pending_newsegment = NULL;
1978     qtdemux->upstream_format_is_time = FALSE;
1979     qtdemux->upstream_seekable = FALSE;
1980     qtdemux->upstream_size = 0;
1981
1982     qtdemux->fragment_start = -1;
1983     qtdemux->fragment_start_offset = -1;
1984     qtdemux->duration = 0;
1985     qtdemux->moof_offset = 0;
1986     qtdemux->chapters_track_id = 0;
1987     qtdemux->have_group_id = FALSE;
1988     qtdemux->group_id = G_MAXUINT;
1989
1990     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1991         NULL);
1992     g_queue_clear (&qtdemux->protection_event_queue);
1993   }
1994   qtdemux->offset = 0;
1995   gst_adapter_clear (qtdemux->adapter);
1996   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1997   qtdemux->segment_seqnum = 0;
1998
1999   if (hard) {
2000     for (n = 0; n < qtdemux->n_streams; n++) {
2001       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2002       qtdemux->streams[n] = NULL;
2003     }
2004     qtdemux->n_streams = 0;
2005     qtdemux->n_video_streams = 0;
2006     qtdemux->n_audio_streams = 0;
2007     qtdemux->n_sub_streams = 0;
2008     qtdemux->exposed = FALSE;
2009     qtdemux->fragmented = FALSE;
2010     qtdemux->mss_mode = FALSE;
2011     gst_caps_replace (&qtdemux->media_caps, NULL);
2012     qtdemux->timescale = 0;
2013     qtdemux->got_moov = FALSE;
2014     if (qtdemux->protection_system_ids) {
2015       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2016       qtdemux->protection_system_ids = NULL;
2017     }
2018   } else if (qtdemux->mss_mode) {
2019     gst_flow_combiner_reset (qtdemux->flowcombiner);
2020     for (n = 0; n < qtdemux->n_streams; n++)
2021       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2022   } else {
2023     gst_flow_combiner_reset (qtdemux->flowcombiner);
2024     for (n = 0; n < qtdemux->n_streams; n++) {
2025       qtdemux->streams[n]->sent_eos = FALSE;
2026       qtdemux->streams[n]->time_position = 0;
2027       qtdemux->streams[n]->accumulated_base = 0;
2028     }
2029     if (!qtdemux->pending_newsegment) {
2030       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2031       if (qtdemux->segment_seqnum)
2032         gst_event_set_seqnum (qtdemux->pending_newsegment,
2033             qtdemux->segment_seqnum);
2034     }
2035   }
2036 }
2037
2038
2039 /* Maps the @segment to the qt edts internal segments and pushes
2040  * the correspnding segment event.
2041  *
2042  * If it ends up being at a empty segment, a gap will be pushed and the next
2043  * edts segment will be activated in sequence.
2044  *
2045  * To be used in push-mode only */
2046 static void
2047 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2048 {
2049   gint n, i;
2050
2051   for (n = 0; n < qtdemux->n_streams; n++) {
2052     QtDemuxStream *stream = qtdemux->streams[n];
2053
2054     stream->time_position = segment->start;
2055
2056     /* in push mode we should be guaranteed that we will have empty segments
2057      * at the beginning and then one segment after, other scenarios are not
2058      * supported and are discarded when parsing the edts */
2059     for (i = 0; i < stream->n_segments; i++) {
2060       if (stream->segments[i].stop_time > segment->start) {
2061         gst_qtdemux_activate_segment (qtdemux, stream, i,
2062             stream->time_position);
2063         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2064           /* push the empty segment and move to the next one */
2065           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2066               stream->time_position);
2067           continue;
2068         }
2069
2070         g_assert (i == stream->n_segments - 1);
2071       }
2072     }
2073   }
2074 }
2075
2076 static gboolean
2077 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2078     GstEvent * event)
2079 {
2080   GstQTDemux *demux = GST_QTDEMUX (parent);
2081   gboolean res = TRUE;
2082
2083   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2084
2085   switch (GST_EVENT_TYPE (event)) {
2086     case GST_EVENT_SEGMENT:
2087     {
2088       gint64 offset = 0;
2089       QtDemuxStream *stream;
2090       gint idx;
2091       GstSegment segment;
2092
2093       /* some debug output */
2094       gst_event_copy_segment (event, &segment);
2095       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2096           &segment);
2097
2098       /* erase any previously set segment */
2099       gst_event_replace (&demux->pending_newsegment, NULL);
2100
2101       if (segment.format == GST_FORMAT_TIME) {
2102         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2103         gst_event_replace (&demux->pending_newsegment, event);
2104         demux->upstream_format_is_time = TRUE;
2105       } else {
2106         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2107             "not in time format");
2108
2109         /* chain will send initial newsegment after pads have been added */
2110         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2111           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2112           goto exit;
2113         }
2114       }
2115
2116       /* check if this matches a time seek we received previously
2117        * FIXME for backwards compatibility reasons we use the
2118        * seek_offset here to compare. In the future we might want to
2119        * change this to use the seqnum as it uniquely should identify
2120        * the segment that corresponds to the seek. */
2121       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2122           ", received segment offset %" G_GINT64_FORMAT,
2123           demux->seek_offset, segment.start);
2124       if (segment.format == GST_FORMAT_BYTES
2125           && demux->seek_offset == segment.start) {
2126         GST_OBJECT_LOCK (demux);
2127         offset = segment.start;
2128
2129         segment.format = GST_FORMAT_TIME;
2130         segment.start = demux->push_seek_start;
2131         segment.stop = demux->push_seek_stop;
2132         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2133             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2134             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2135         GST_OBJECT_UNLOCK (demux);
2136       }
2137
2138       /* we only expect a BYTE segment, e.g. following a seek */
2139       if (segment.format == GST_FORMAT_BYTES) {
2140         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2141           offset = segment.start;
2142
2143           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2144               NULL, (gint64 *) & segment.start);
2145           if ((gint64) segment.start < 0)
2146             segment.start = 0;
2147         }
2148         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2149           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2150               NULL, (gint64 *) & segment.stop);
2151           /* keyframe seeking should already arrange for start >= stop,
2152            * but make sure in other rare cases */
2153           segment.stop = MAX (segment.stop, segment.start);
2154         }
2155       } else if (segment.format == GST_FORMAT_TIME) {
2156         /* push all data on the adapter before starting this
2157          * new segment */
2158         gst_qtdemux_process_adapter (demux, TRUE);
2159       } else {
2160         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2161         goto exit;
2162       }
2163
2164       /* accept upstream's notion of segment and distribute along */
2165       segment.format = GST_FORMAT_TIME;
2166       segment.position = segment.time = segment.start;
2167       segment.duration = demux->segment.duration;
2168       segment.base = gst_segment_to_running_time (&demux->segment,
2169           GST_FORMAT_TIME, demux->segment.position);
2170
2171       gst_segment_copy_into (&segment, &demux->segment);
2172       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2173
2174       /* map segment to internal qt segments and push on each stream */
2175       if (demux->n_streams) {
2176         if (demux->fragmented) {
2177           GstEvent *segment_event = gst_event_new_segment (&segment);
2178
2179           gst_event_replace (&demux->pending_newsegment, NULL);
2180           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2181           gst_qtdemux_push_event (demux, segment_event);
2182         } else {
2183           gst_event_replace (&demux->pending_newsegment, NULL);
2184           gst_qtdemux_map_and_push_segments (demux, &segment);
2185         }
2186       }
2187
2188       /* clear leftover in current segment, if any */
2189       gst_adapter_clear (demux->adapter);
2190
2191       /* set up streaming thread */
2192       demux->offset = offset;
2193       if (demux->upstream_format_is_time) {
2194         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2195             "set values to restart reading from a new atom");
2196         demux->neededbytes = 16;
2197         demux->todrop = 0;
2198       } else {
2199         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2200             NULL);
2201         if (stream) {
2202           demux->todrop = stream->samples[idx].offset - offset;
2203           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2204         } else {
2205           /* set up for EOS */
2206           demux->neededbytes = -1;
2207           demux->todrop = 0;
2208         }
2209       }
2210     exit:
2211       gst_event_unref (event);
2212       res = TRUE;
2213       goto drop;
2214     }
2215     case GST_EVENT_FLUSH_START:
2216     {
2217       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2218         gst_event_unref (event);
2219         goto drop;
2220       }
2221       break;
2222     }
2223     case GST_EVENT_FLUSH_STOP:
2224     {
2225       guint64 dur;
2226
2227       dur = demux->segment.duration;
2228       gst_qtdemux_reset (demux, FALSE);
2229       demux->segment.duration = dur;
2230
2231       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2232         gst_event_unref (event);
2233         goto drop;
2234       }
2235       break;
2236     }
2237     case GST_EVENT_EOS:
2238       /* If we are in push mode, and get an EOS before we've seen any streams,
2239        * then error out - we have nowhere to send the EOS */
2240       if (!demux->pullbased) {
2241         gint i;
2242         gboolean has_valid_stream = FALSE;
2243         for (i = 0; i < demux->n_streams; i++) {
2244           if (demux->streams[i]->pad != NULL) {
2245             has_valid_stream = TRUE;
2246             break;
2247           }
2248         }
2249         if (!has_valid_stream)
2250           gst_qtdemux_post_no_playable_stream_error (demux);
2251         else {
2252           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2253               (guint) gst_adapter_available (demux->adapter));
2254           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2255             res = FALSE;
2256           }
2257         }
2258       }
2259       break;
2260     case GST_EVENT_CAPS:{
2261       GstCaps *caps = NULL;
2262
2263       gst_event_parse_caps (event, &caps);
2264       gst_qtdemux_setcaps (demux, caps);
2265       res = TRUE;
2266       gst_event_unref (event);
2267       goto drop;
2268     }
2269     case GST_EVENT_PROTECTION:
2270     {
2271       const gchar *system_id = NULL;
2272
2273       gst_event_parse_protection (event, &system_id, NULL, NULL);
2274       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2275           system_id);
2276       gst_qtdemux_append_protection_system_id (demux, system_id);
2277       /* save the event for later, for source pads that have not been created */
2278       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2279       /* send it to all pads that already exist */
2280       gst_qtdemux_push_event (demux, event);
2281       res = TRUE;
2282       goto drop;
2283     }
2284     default:
2285       break;
2286   }
2287
2288   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2289
2290 drop:
2291   return res;
2292 }
2293
2294 #if 0
2295 static void
2296 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2297 {
2298   GstQTDemux *demux = GST_QTDEMUX (element);
2299
2300   GST_OBJECT_LOCK (demux);
2301   if (demux->element_index)
2302     gst_object_unref (demux->element_index);
2303   if (index) {
2304     demux->element_index = gst_object_ref (index);
2305   } else {
2306     demux->element_index = NULL;
2307   }
2308   GST_OBJECT_UNLOCK (demux);
2309   /* object lock might be taken again */
2310   if (index)
2311     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2312   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2313       demux->element_index, demux->index_id);
2314 }
2315
2316 static GstIndex *
2317 gst_qtdemux_get_index (GstElement * element)
2318 {
2319   GstIndex *result = NULL;
2320   GstQTDemux *demux = GST_QTDEMUX (element);
2321
2322   GST_OBJECT_LOCK (demux);
2323   if (demux->element_index)
2324     result = gst_object_ref (demux->element_index);
2325   GST_OBJECT_UNLOCK (demux);
2326
2327   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2328
2329   return result;
2330 }
2331 #endif
2332
2333 static void
2334 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2335 {
2336   g_free ((gpointer) stream->stco.data);
2337   stream->stco.data = NULL;
2338   g_free ((gpointer) stream->stsz.data);
2339   stream->stsz.data = NULL;
2340   g_free ((gpointer) stream->stsc.data);
2341   stream->stsc.data = NULL;
2342   g_free ((gpointer) stream->stts.data);
2343   stream->stts.data = NULL;
2344   g_free ((gpointer) stream->stss.data);
2345   stream->stss.data = NULL;
2346   g_free ((gpointer) stream->stps.data);
2347   stream->stps.data = NULL;
2348   g_free ((gpointer) stream->ctts.data);
2349   stream->ctts.data = NULL;
2350 }
2351
2352 static void
2353 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2354     QtDemuxStream * stream)
2355 {
2356   g_free (stream->segments);
2357   stream->segments = NULL;
2358   stream->segment_index = -1;
2359   stream->accumulated_base = 0;
2360 }
2361
2362 static void
2363 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2364     QtDemuxStream * stream)
2365 {
2366   g_free (stream->samples);
2367   stream->samples = NULL;
2368   gst_qtdemux_stbl_free (stream);
2369
2370   /* fragments */
2371   g_free (stream->ra_entries);
2372   stream->ra_entries = NULL;
2373   stream->n_ra_entries = 0;
2374
2375   stream->sample_index = -1;
2376   stream->stbl_index = -1;
2377   stream->n_samples = 0;
2378   stream->time_position = 0;
2379
2380   stream->n_samples_moof = 0;
2381   stream->duration_moof = 0;
2382 }
2383
2384 static void
2385 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2386 {
2387   if (stream->allocator)
2388     gst_object_unref (stream->allocator);
2389   while (stream->buffers) {
2390     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2391     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2392   }
2393   if (stream->rgb8_palette) {
2394     gst_memory_unref (stream->rgb8_palette);
2395     stream->rgb8_palette = NULL;
2396   }
2397
2398   if (stream->pending_tags)
2399     gst_tag_list_unref (stream->pending_tags);
2400   stream->pending_tags = NULL;
2401   g_free (stream->redirect_uri);
2402   stream->redirect_uri = NULL;
2403   stream->sent_eos = FALSE;
2404   stream->sparse = FALSE;
2405   stream->protected = FALSE;
2406   if (stream->protection_scheme_info) {
2407     if (stream->protection_scheme_type == FOURCC_cenc) {
2408       QtDemuxCencSampleSetInfo *info =
2409           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2410       if (info->default_properties)
2411         gst_structure_free (info->default_properties);
2412       if (info->crypto_info)
2413         g_ptr_array_free (info->crypto_info, TRUE);
2414     }
2415     g_free (stream->protection_scheme_info);
2416     stream->protection_scheme_info = NULL;
2417   }
2418   stream->protection_scheme_type = 0;
2419   stream->protection_scheme_version = 0;
2420   g_queue_foreach (&stream->protection_scheme_event_queue,
2421       (GFunc) gst_event_unref, NULL);
2422   g_queue_clear (&stream->protection_scheme_event_queue);
2423   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2424   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2425 }
2426
2427 static void
2428 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2429 {
2430   gst_qtdemux_stream_clear (qtdemux, stream);
2431   if (stream->caps)
2432     gst_caps_unref (stream->caps);
2433   stream->caps = NULL;
2434   if (stream->pad) {
2435     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2436     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2437   }
2438   g_free (stream);
2439 }
2440
2441 static void
2442 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2443 {
2444   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2445
2446   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2447   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2448   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2449   qtdemux->n_streams--;
2450 }
2451
2452 static GstStateChangeReturn
2453 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2454 {
2455   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2456   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2457
2458   switch (transition) {
2459     case GST_STATE_CHANGE_PAUSED_TO_READY:
2460       break;
2461     default:
2462       break;
2463   }
2464
2465   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2466
2467   switch (transition) {
2468     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2469       gst_qtdemux_reset (qtdemux, TRUE);
2470       break;
2471     }
2472     default:
2473       break;
2474   }
2475
2476   return result;
2477 }
2478
2479 static void
2480 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2481 {
2482   /* counts as header data */
2483   qtdemux->header_size += length;
2484
2485   /* only consider at least a sufficiently complete ftyp atom */
2486   if (length >= 20) {
2487     GstBuffer *buf;
2488
2489     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2490     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2491         GST_FOURCC_ARGS (qtdemux->major_brand));
2492     if (qtdemux->comp_brands)
2493       gst_buffer_unref (qtdemux->comp_brands);
2494     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2495     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2496   }
2497 }
2498
2499 static void
2500 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2501     GstTagList * xmptaglist)
2502 {
2503   /* Strip out bogus fields */
2504   if (xmptaglist) {
2505     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2506       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2507       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2508     } else {
2509       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2510     }
2511
2512     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2513
2514     /* prioritize native tags using _KEEP mode */
2515     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2516     gst_tag_list_unref (xmptaglist);
2517   }
2518 }
2519
2520 static void
2521 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2522     guint offset)
2523 {
2524   GstByteReader br;
2525   guint8 version;
2526   guint32 flags = 0;
2527   guint i;
2528   guint8 iv_size = 8;
2529   QtDemuxStream *stream;
2530   GstStructure *structure;
2531   QtDemuxCencSampleSetInfo *ss_info = NULL;
2532   const gchar *system_id;
2533   gboolean uses_sub_sample_encryption = FALSE;
2534
2535   if (qtdemux->n_streams == 0)
2536     return;
2537
2538   stream = qtdemux->streams[0];
2539
2540   structure = gst_caps_get_structure (stream->caps, 0);
2541   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2542     GST_WARNING_OBJECT (qtdemux,
2543         "Attempting PIFF box parsing on an unencrypted stream.");
2544     return;
2545   }
2546
2547   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2548       G_TYPE_STRING, &system_id, NULL);
2549   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2550
2551   stream->protected = TRUE;
2552   stream->protection_scheme_type = FOURCC_cenc;
2553
2554   if (!stream->protection_scheme_info)
2555     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2556
2557   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2558
2559   if (ss_info->default_properties)
2560     gst_structure_free (ss_info->default_properties);
2561
2562   ss_info->default_properties =
2563       gst_structure_new ("application/x-cenc",
2564       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2565
2566   if (ss_info->crypto_info) {
2567     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2568     g_ptr_array_free (ss_info->crypto_info, TRUE);
2569     ss_info->crypto_info = NULL;
2570   }
2571
2572   /* skip UUID */
2573   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2574
2575   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2576     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2577     return;
2578   }
2579
2580   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2581     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2582     return;
2583   }
2584
2585   if ((flags & 0x000001)) {
2586     guint32 algorithm_id = 0;
2587     const guint8 *kid;
2588     GstBuffer *kid_buf;
2589     gboolean is_encrypted = TRUE;
2590
2591     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2592       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2593       return;
2594     }
2595
2596     algorithm_id >>= 8;
2597     if (algorithm_id == 0) {
2598       is_encrypted = FALSE;
2599     } else if (algorithm_id == 1) {
2600       /* FIXME: maybe store this in properties? */
2601       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2602     } else if (algorithm_id == 2) {
2603       /* FIXME: maybe store this in properties? */
2604       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2605     }
2606
2607     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2608       return;
2609
2610     if (!gst_byte_reader_get_data (&br, 16, &kid))
2611       return;
2612
2613     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2614     gst_buffer_fill (kid_buf, 0, kid, 16);
2615     if (ss_info->default_properties)
2616       gst_structure_free (ss_info->default_properties);
2617     ss_info->default_properties =
2618         gst_structure_new ("application/x-cenc",
2619         "iv_size", G_TYPE_UINT, iv_size,
2620         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2621         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2622     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2623         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2624     gst_buffer_unref (kid_buf);
2625   } else if ((flags & 0x000002)) {
2626     uses_sub_sample_encryption = TRUE;
2627   }
2628
2629   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2630     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2631     return;
2632   }
2633
2634   ss_info->crypto_info =
2635       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2636       (GDestroyNotify) qtdemux_gst_structure_free);
2637
2638   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2639     GstStructure *properties;
2640     guint8 *data;
2641     GstBuffer *buf;
2642
2643     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2644     if (properties == NULL) {
2645       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2646       return;
2647     }
2648
2649     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2650       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2651       gst_structure_free (properties);
2652       return;
2653     }
2654     buf = gst_buffer_new_wrapped (data, iv_size);
2655     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2656     gst_buffer_unref (buf);
2657
2658     if (uses_sub_sample_encryption) {
2659       guint16 n_subsamples;
2660
2661       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2662           || n_subsamples == 0) {
2663         GST_ERROR_OBJECT (qtdemux,
2664             "failed to get subsample count for sample %u", i);
2665         gst_structure_free (properties);
2666         return;
2667       }
2668       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2669       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2670         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2671             i);
2672         gst_structure_free (properties);
2673         return;
2674       }
2675       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2676       gst_structure_set (properties,
2677           "subsample_count", G_TYPE_UINT, n_subsamples,
2678           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2679       gst_buffer_unref (buf);
2680     } else {
2681       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2682     }
2683
2684     g_ptr_array_add (ss_info->crypto_info, properties);
2685   }
2686 }
2687
2688 static void
2689 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2690 {
2691   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2692     0x97, 0xA9, 0x42, 0xE8,
2693     0x9C, 0x71, 0x99, 0x94,
2694     0x91, 0xE3, 0xAF, 0xAC
2695   };
2696   static const guint8 playready_uuid[] = {
2697     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2698     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2699   };
2700
2701   static const guint8 piff_sample_encryption_uuid[] = {
2702     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2703     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2704   };
2705
2706   guint offset;
2707
2708   /* counts as header data */
2709   qtdemux->header_size += length;
2710
2711   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2712
2713   if (length <= offset + 16) {
2714     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2715     return;
2716   }
2717
2718   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2719     GstBuffer *buf;
2720     GstTagList *taglist;
2721
2722     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2723         length - offset - 16, NULL);
2724     taglist = gst_tag_list_from_xmp_buffer (buf);
2725     gst_buffer_unref (buf);
2726
2727     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2728
2729   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2730     int len;
2731     const gunichar2 *s_utf16;
2732     char *contents;
2733
2734     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2735     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2736     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2737     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2738
2739     g_free (contents);
2740
2741     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2742         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2743         (NULL));
2744   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2745     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2746   } else {
2747     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2748         GST_READ_UINT32_LE (buffer + offset),
2749         GST_READ_UINT32_LE (buffer + offset + 4),
2750         GST_READ_UINT32_LE (buffer + offset + 8),
2751         GST_READ_UINT32_LE (buffer + offset + 12));
2752   }
2753 }
2754
2755 static void
2756 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2757 {
2758   GstSidxParser sidx_parser;
2759   GstIsoffParserResult res;
2760   guint consumed;
2761
2762   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2763
2764   res =
2765       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2766       &consumed);
2767   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2768   if (res == GST_ISOFF_QT_PARSER_DONE) {
2769     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2770   }
2771   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2772 }
2773
2774 /* caller verifies at least 8 bytes in buf */
2775 static void
2776 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2777     guint64 * plength, guint32 * pfourcc)
2778 {
2779   guint64 length;
2780   guint32 fourcc;
2781
2782   length = QT_UINT32 (data);
2783   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2784   fourcc = QT_FOURCC (data + 4);
2785   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2786
2787   if (length == 0) {
2788     length = G_MAXUINT64;
2789   } else if (length == 1 && size >= 16) {
2790     /* this means we have an extended size, which is the 64 bit value of
2791      * the next 8 bytes */
2792     length = QT_UINT64 (data + 8);
2793     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2794   }
2795
2796   if (plength)
2797     *plength = length;
2798   if (pfourcc)
2799     *pfourcc = fourcc;
2800 }
2801
2802 static gboolean
2803 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2804 {
2805   guint32 version = 0;
2806   GstClockTime duration = 0;
2807
2808   if (!gst_byte_reader_get_uint32_be (br, &version))
2809     goto failed;
2810
2811   version >>= 24;
2812   if (version == 1) {
2813     if (!gst_byte_reader_get_uint64_be (br, &duration))
2814       goto failed;
2815   } else {
2816     guint32 dur = 0;
2817
2818     if (!gst_byte_reader_get_uint32_be (br, &dur))
2819       goto failed;
2820     duration = dur;
2821   }
2822
2823   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2824   qtdemux->duration = duration;
2825
2826   return TRUE;
2827
2828 failed:
2829   {
2830     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2831     return FALSE;
2832   }
2833 }
2834
2835 static gboolean
2836 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2837     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2838 {
2839   if (!stream->parsed_trex && qtdemux->moov_node) {
2840     GNode *mvex, *trex;
2841     GstByteReader trex_data;
2842
2843     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2844     if (mvex) {
2845       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2846           &trex_data);
2847       while (trex) {
2848         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2849
2850         /* skip version/flags */
2851         if (!gst_byte_reader_skip (&trex_data, 4))
2852           goto next;
2853         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2854           goto next;
2855         if (id != stream->track_id)
2856           goto next;
2857         /* sample description index; ignore */
2858         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2859           goto next;
2860         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2861           goto next;
2862         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2863           goto next;
2864         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2865           goto next;
2866
2867         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2868             "duration %d,  size %d, flags 0x%x", stream->track_id,
2869             dur, size, flags);
2870
2871         stream->parsed_trex = TRUE;
2872         stream->def_sample_duration = dur;
2873         stream->def_sample_size = size;
2874         stream->def_sample_flags = flags;
2875
2876       next:
2877         /* iterate all siblings */
2878         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2879             &trex_data);
2880       }
2881     }
2882   }
2883
2884   *ds_duration = stream->def_sample_duration;
2885   *ds_size = stream->def_sample_size;
2886   *ds_flags = stream->def_sample_flags;
2887
2888   /* even then, above values are better than random ... */
2889   if (G_UNLIKELY (!stream->parsed_trex)) {
2890     GST_WARNING_OBJECT (qtdemux,
2891         "failed to find fragment defaults for stream %d", stream->track_id);
2892     return FALSE;
2893   }
2894
2895   return TRUE;
2896 }
2897
2898 /* This method should be called whenever a more accurate duration might
2899  * have been found. It will update all relevant variables if/where needed
2900  */
2901 static void
2902 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2903 {
2904   guint i;
2905   guint64 movdur;
2906   GstClockTime prevdur;
2907
2908   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2909
2910   if (movdur > qtdemux->duration) {
2911     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2912     GST_DEBUG_OBJECT (qtdemux,
2913         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2914         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2915     qtdemux->duration = movdur;
2916     GST_DEBUG_OBJECT (qtdemux,
2917         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2918         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2919         GST_TIME_ARGS (qtdemux->segment.stop));
2920     if (qtdemux->segment.duration == prevdur) {
2921       /* If the current segment has duration/stop identical to previous duration
2922        * update them also (because they were set at that point in time with
2923        * the wrong duration */
2924       /* We convert the value *from* the timescale version to avoid rounding errors */
2925       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2926       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2927       qtdemux->segment.duration = fixeddur;
2928       qtdemux->segment.stop = fixeddur;
2929     }
2930   }
2931   for (i = 0; i < qtdemux->n_streams; i++) {
2932     QtDemuxStream *stream = qtdemux->streams[i];
2933     if (stream) {
2934       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2935       if (movdur > stream->duration) {
2936         GST_DEBUG_OBJECT (qtdemux,
2937             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2938             GST_TIME_ARGS (duration));
2939         stream->duration = movdur;
2940         if (stream->dummy_segment) {
2941           /* Update all dummy values to new duration */
2942           stream->segments[0].stop_time = duration;
2943           stream->segments[0].duration = duration;
2944           stream->segments[0].media_stop = duration;
2945
2946           /* let downstream know we possibly have a new stop time */
2947           if (stream->segment_index != -1) {
2948             GstClockTime pos;
2949
2950             if (qtdemux->segment.rate >= 0) {
2951               pos = stream->segment.start;
2952             } else {
2953               pos = stream->segment.stop;
2954             }
2955
2956             gst_qtdemux_stream_update_segment (qtdemux, stream,
2957                 stream->segment_index, pos, NULL, NULL);
2958           }
2959         }
2960       }
2961     }
2962   }
2963 }
2964
2965 static gboolean
2966 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2967     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2968     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2969     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2970 {
2971   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2972   guint64 timestamp;
2973   gint32 data_offset = 0;
2974   guint32 flags = 0, first_flags = 0, samples_count = 0;
2975   gint i;
2976   guint8 *data;
2977   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2978   QtDemuxSample *sample;
2979   gboolean ismv = FALSE;
2980   gint64 initial_offset;
2981
2982   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2983       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2984       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2985       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2986
2987   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2988     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2989     return TRUE;
2990   }
2991
2992   /* presence of stss or not can't really tell us much,
2993    * and flags and so on tend to be marginally reliable in these files */
2994   if (stream->subtype == FOURCC_soun) {
2995     GST_DEBUG_OBJECT (qtdemux,
2996         "sound track in fragmented file; marking all keyframes");
2997     stream->all_keyframe = TRUE;
2998   }
2999
3000   if (!gst_byte_reader_skip (trun, 1) ||
3001       !gst_byte_reader_get_uint24_be (trun, &flags))
3002     goto fail;
3003
3004   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3005     goto fail;
3006
3007   if (flags & TR_DATA_OFFSET) {
3008     /* note this is really signed */
3009     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3010       goto fail;
3011     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3012     /* default base offset = first byte of moof */
3013     if (*base_offset == -1) {
3014       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3015       *base_offset = moof_offset;
3016     }
3017     *running_offset = *base_offset + data_offset;
3018   } else {
3019     /* if no offset at all, that would mean data starts at moof start,
3020      * which is a bit wrong and is ismv crappy way, so compensate
3021      * assuming data is in mdat following moof */
3022     if (*base_offset == -1) {
3023       *base_offset = moof_offset + moof_length + 8;
3024       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3025       ismv = TRUE;
3026     }
3027     if (*running_offset == -1)
3028       *running_offset = *base_offset;
3029   }
3030
3031   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3032       *running_offset);
3033   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3034       data_offset, flags, samples_count);
3035
3036   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3037     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3038       GST_DEBUG_OBJECT (qtdemux,
3039           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3040       flags ^= TR_FIRST_SAMPLE_FLAGS;
3041     } else {
3042       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3043         goto fail;
3044       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3045     }
3046   }
3047
3048   /* FIXME ? spec says other bits should also be checked to determine
3049    * entry size (and prefix size for that matter) */
3050   entry_size = 0;
3051   dur_offset = size_offset = 0;
3052   if (flags & TR_SAMPLE_DURATION) {
3053     GST_LOG_OBJECT (qtdemux, "entry duration present");
3054     dur_offset = entry_size;
3055     entry_size += 4;
3056   }
3057   if (flags & TR_SAMPLE_SIZE) {
3058     GST_LOG_OBJECT (qtdemux, "entry size present");
3059     size_offset = entry_size;
3060     entry_size += 4;
3061   }
3062   if (flags & TR_SAMPLE_FLAGS) {
3063     GST_LOG_OBJECT (qtdemux, "entry flags present");
3064     flags_offset = entry_size;
3065     entry_size += 4;
3066   }
3067   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3068     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3069     ct_offset = entry_size;
3070     entry_size += 4;
3071   }
3072
3073   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3074     goto fail;
3075   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3076
3077   if (stream->n_samples + samples_count >=
3078       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3079     goto index_too_big;
3080
3081   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3082       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3083       (stream->n_samples + samples_count) *
3084       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3085
3086   /* create a new array of samples if it's the first sample parsed */
3087   if (stream->n_samples == 0) {
3088     g_assert (stream->samples == NULL);
3089     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3090     /* or try to reallocate it with space enough to insert the new samples */
3091   } else
3092     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3093         stream->n_samples + samples_count);
3094   if (stream->samples == NULL)
3095     goto out_of_memory;
3096
3097   if (qtdemux->fragment_start != -1) {
3098     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3099     qtdemux->fragment_start = -1;
3100   } else {
3101     if (stream->n_samples == 0) {
3102       if (decode_ts > 0) {
3103         timestamp = decode_ts;
3104       } else if (stream->pending_seek != NULL) {
3105         /* if we don't have a timestamp from a tfdt box, we'll use the one
3106          * from the mfra seek table */
3107         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3108             GST_TIME_ARGS (stream->pending_seek->ts));
3109
3110         /* FIXME: this is not fully correct, the timestamp refers to the random
3111          * access sample refered to in the tfra entry, which may not necessarily
3112          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3113         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3114       } else {
3115         timestamp = 0;
3116       }
3117
3118       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3119       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3120           GST_TIME_ARGS (gst_ts));
3121     } else {
3122       /* subsequent fragments extend stream */
3123       timestamp =
3124           stream->samples[stream->n_samples - 1].timestamp +
3125           stream->samples[stream->n_samples - 1].duration;
3126
3127       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3128       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3129           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3130     }
3131   }
3132
3133   initial_offset = *running_offset;
3134
3135   sample = stream->samples + stream->n_samples;
3136   for (i = 0; i < samples_count; i++) {
3137     guint32 dur, size, sflags, ct;
3138
3139     /* first read sample data */
3140     if (flags & TR_SAMPLE_DURATION) {
3141       dur = QT_UINT32 (data + dur_offset);
3142     } else {
3143       dur = d_sample_duration;
3144     }
3145     if (flags & TR_SAMPLE_SIZE) {
3146       size = QT_UINT32 (data + size_offset);
3147     } else {
3148       size = d_sample_size;
3149     }
3150     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3151       if (i == 0) {
3152         sflags = first_flags;
3153       } else {
3154         sflags = d_sample_flags;
3155       }
3156     } else if (flags & TR_SAMPLE_FLAGS) {
3157       sflags = QT_UINT32 (data + flags_offset);
3158     } else {
3159       sflags = d_sample_flags;
3160     }
3161     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3162       ct = QT_UINT32 (data + ct_offset);
3163     } else {
3164       ct = 0;
3165     }
3166     data += entry_size;
3167
3168     /* fill the sample information */
3169     sample->offset = *running_offset;
3170     sample->pts_offset = ct;
3171     sample->size = size;
3172     sample->timestamp = timestamp;
3173     sample->duration = dur;
3174     /* sample-is-difference-sample */
3175     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3176      * now idea how it relates to bitfield other than massive LE/BE confusion */
3177     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3178     *running_offset += size;
3179     timestamp += dur;
3180     stream->duration_moof += dur;
3181     sample++;
3182   }
3183
3184   /* Update total duration if needed */
3185   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3186
3187   /* Pre-emptively figure out size of mdat based on trun information.
3188    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3189    * size, else we will still be able to use this when dealing with gap'ed
3190    * input */
3191   qtdemux->mdatleft = *running_offset - initial_offset;
3192
3193   stream->n_samples += samples_count;
3194   stream->n_samples_moof += samples_count;
3195
3196   if (stream->pending_seek != NULL)
3197     stream->pending_seek = NULL;
3198
3199   return TRUE;
3200
3201 fail:
3202   {
3203     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3204     return FALSE;
3205   }
3206 out_of_memory:
3207   {
3208     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3209         stream->n_samples);
3210     return FALSE;
3211   }
3212 index_too_big:
3213   {
3214     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3215         "be larger than %uMB (broken file?)", stream->n_samples,
3216         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3217     return FALSE;
3218   }
3219 }
3220
3221 /* find stream with @id */
3222 static inline QtDemuxStream *
3223 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3224 {
3225   QtDemuxStream *stream;
3226   gint i;
3227
3228   /* check */
3229   if (G_UNLIKELY (!id)) {
3230     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3231     return NULL;
3232   }
3233
3234   /* try to get it fast and simple */
3235   if (G_LIKELY (id <= qtdemux->n_streams)) {
3236     stream = qtdemux->streams[id - 1];
3237     if (G_LIKELY (stream->track_id == id))
3238       return stream;
3239   }
3240
3241   /* linear search otherwise */
3242   for (i = 0; i < qtdemux->n_streams; i++) {
3243     stream = qtdemux->streams[i];
3244     if (stream->track_id == id)
3245       return stream;
3246   }
3247   if (qtdemux->mss_mode) {
3248     /* mss should have only 1 stream anyway */
3249     return qtdemux->streams[0];
3250   }
3251
3252   return NULL;
3253 }
3254
3255 static gboolean
3256 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3257     guint32 * fragment_number)
3258 {
3259   if (!gst_byte_reader_skip (mfhd, 4))
3260     goto fail;
3261   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3262     goto fail;
3263   return TRUE;
3264 fail:
3265   {
3266     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3267     return FALSE;
3268   }
3269 }
3270
3271 static gboolean
3272 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3273     QtDemuxStream ** stream, guint32 * default_sample_duration,
3274     guint32 * default_sample_size, guint32 * default_sample_flags,
3275     gint64 * base_offset)
3276 {
3277   guint32 flags = 0;
3278   guint32 track_id = 0;
3279
3280   if (!gst_byte_reader_skip (tfhd, 1) ||
3281       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3282     goto invalid_track;
3283
3284   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3285     goto invalid_track;
3286
3287   *stream = qtdemux_find_stream (qtdemux, track_id);
3288   if (G_UNLIKELY (!*stream))
3289     goto unknown_stream;
3290
3291   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3292     *base_offset = qtdemux->moof_offset;
3293
3294   if (flags & TF_BASE_DATA_OFFSET)
3295     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3296       goto invalid_track;
3297
3298   /* obtain stream defaults */
3299   qtdemux_parse_trex (qtdemux, *stream,
3300       default_sample_duration, default_sample_size, default_sample_flags);
3301
3302   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3303   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3304     if (!gst_byte_reader_skip (tfhd, 4))
3305       goto invalid_track;
3306
3307   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3308     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3309       goto invalid_track;
3310
3311   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3312     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3313       goto invalid_track;
3314
3315   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3316     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3317       goto invalid_track;
3318
3319   return TRUE;
3320
3321 invalid_track:
3322   {
3323     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3324     return FALSE;
3325   }
3326 unknown_stream:
3327   {
3328     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3329     return TRUE;
3330   }
3331 }
3332
3333 static gboolean
3334 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3335     guint64 * decode_time)
3336 {
3337   guint32 version = 0;
3338
3339   if (!gst_byte_reader_get_uint32_be (br, &version))
3340     return FALSE;
3341
3342   version >>= 24;
3343   if (version == 1) {
3344     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3345       goto failed;
3346   } else {
3347     guint32 dec_time = 0;
3348     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3349       goto failed;
3350     *decode_time = dec_time;
3351   }
3352
3353   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3354       *decode_time);
3355
3356   return TRUE;
3357
3358 failed:
3359   {
3360     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3361     return FALSE;
3362   }
3363 }
3364
3365 /* Returns a pointer to a GstStructure containing the properties of
3366  * the stream sample identified by @sample_index. The caller must unref
3367  * the returned object after use. Returns NULL if unsuccessful. */
3368 static GstStructure *
3369 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3370     QtDemuxStream * stream, guint sample_index)
3371 {
3372   QtDemuxCencSampleSetInfo *info = NULL;
3373
3374   g_return_val_if_fail (stream != NULL, NULL);
3375   g_return_val_if_fail (stream->protected, NULL);
3376   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3377
3378   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3379
3380   /* Currently, cenc properties for groups of samples are not supported, so
3381    * simply return a copy of the default sample properties */
3382   return gst_structure_copy (info->default_properties);
3383 }
3384
3385 /* Parses the sizes of sample auxiliary information contained within a stream,
3386  * as given in a saiz box. Returns array of sample_count guint8 size values,
3387  * or NULL on failure */
3388 static guint8 *
3389 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3390     GstByteReader * br, guint32 * sample_count)
3391 {
3392   guint32 flags = 0;
3393   guint8 *info_sizes;
3394   guint8 default_info_size;
3395
3396   g_return_val_if_fail (qtdemux != NULL, NULL);
3397   g_return_val_if_fail (stream != NULL, NULL);
3398   g_return_val_if_fail (br != NULL, NULL);
3399   g_return_val_if_fail (sample_count != NULL, NULL);
3400
3401   if (!gst_byte_reader_get_uint32_be (br, &flags))
3402     return NULL;
3403
3404   if (flags & 0x1) {
3405     /* aux_info_type and aux_info_type_parameter are ignored */
3406     if (!gst_byte_reader_skip (br, 8))
3407       return NULL;
3408   }
3409
3410   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3411     return NULL;
3412   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3413
3414   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3415     return NULL;
3416   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3417
3418
3419   if (default_info_size == 0) {
3420     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3421       return NULL;
3422     }
3423   } else {
3424     info_sizes = g_new (guint8, *sample_count);
3425     memset (info_sizes, default_info_size, *sample_count);
3426   }
3427
3428   return info_sizes;
3429 }
3430
3431 /* Parses the offset of sample auxiliary information contained within a stream,
3432  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3433 static gboolean
3434 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3435     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3436     guint64 * offset)
3437 {
3438   guint8 version = 0;
3439   guint32 flags = 0;
3440   guint32 aux_info_type = 0;
3441   guint32 aux_info_type_parameter = 0;
3442   guint32 entry_count;
3443   guint32 off_32;
3444   guint64 off_64;
3445   const guint8 *aux_info_type_data = NULL;
3446
3447   g_return_val_if_fail (qtdemux != NULL, FALSE);
3448   g_return_val_if_fail (stream != NULL, FALSE);
3449   g_return_val_if_fail (br != NULL, FALSE);
3450   g_return_val_if_fail (offset != NULL, FALSE);
3451
3452   if (!gst_byte_reader_get_uint8 (br, &version))
3453     return FALSE;
3454
3455   if (!gst_byte_reader_get_uint24_be (br, &flags))
3456     return FALSE;
3457
3458   if (flags & 0x1) {
3459
3460     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3461       return FALSE;
3462     aux_info_type = QT_FOURCC (aux_info_type_data);
3463
3464     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3465       return FALSE;
3466   } else if (stream->protected) {
3467     aux_info_type = stream->protection_scheme_type;
3468   } else {
3469     aux_info_type = stream->fourcc;
3470   }
3471
3472   if (info_type)
3473     *info_type = aux_info_type;
3474   if (info_type_parameter)
3475     *info_type_parameter = aux_info_type_parameter;
3476
3477   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3478       "aux_info_type_parameter:  %#06x",
3479       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3480
3481   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3482     return FALSE;
3483
3484   if (entry_count != 1) {
3485     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3486     return FALSE;
3487   }
3488
3489   if (version == 0) {
3490     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3491       return FALSE;
3492     *offset = (guint64) off_32;
3493   } else {
3494     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3495       return FALSE;
3496     *offset = off_64;
3497   }
3498
3499   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3500   return TRUE;
3501 }
3502
3503 static void
3504 qtdemux_gst_structure_free (GstStructure * gststructure)
3505 {
3506   if (gststructure) {
3507     gst_structure_free (gststructure);
3508   }
3509 }
3510
3511 /* Parses auxiliary information relating to samples protected using Common
3512  * Encryption (cenc); the format of this information is defined in
3513  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3514 static gboolean
3515 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3516     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3517 {
3518   QtDemuxCencSampleSetInfo *ss_info = NULL;
3519   guint8 size;
3520   gint i;
3521
3522   g_return_val_if_fail (qtdemux != NULL, FALSE);
3523   g_return_val_if_fail (stream != NULL, FALSE);
3524   g_return_val_if_fail (br != NULL, FALSE);
3525   g_return_val_if_fail (stream->protected, FALSE);
3526   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3527
3528   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3529
3530   if (ss_info->crypto_info) {
3531     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3532     g_ptr_array_free (ss_info->crypto_info, TRUE);
3533   }
3534
3535   ss_info->crypto_info =
3536       g_ptr_array_new_full (sample_count,
3537       (GDestroyNotify) qtdemux_gst_structure_free);
3538
3539   for (i = 0; i < sample_count; ++i) {
3540     GstStructure *properties;
3541     guint16 n_subsamples = 0;
3542     guint8 *data;
3543     guint iv_size;
3544     GstBuffer *buf;
3545
3546     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3547     if (properties == NULL) {
3548       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3549       return FALSE;
3550     }
3551     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3552       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3553       gst_structure_free (properties);
3554       return FALSE;
3555     }
3556     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3557       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3558       gst_structure_free (properties);
3559       return FALSE;
3560     }
3561     buf = gst_buffer_new_wrapped (data, iv_size);
3562     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3563     gst_buffer_unref (buf);
3564     size = info_sizes[i];
3565     if (size > iv_size) {
3566       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3567           || !(n_subsamples > 0)) {
3568         gst_structure_free (properties);
3569         GST_ERROR_OBJECT (qtdemux,
3570             "failed to get subsample count for sample %u", i);
3571         return FALSE;
3572       }
3573       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3574       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3575         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3576             i);
3577         gst_structure_free (properties);
3578         return FALSE;
3579       }
3580       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3581       if (!buf) {
3582         gst_structure_free (properties);
3583         return FALSE;
3584       }
3585       gst_structure_set (properties,
3586           "subsample_count", G_TYPE_UINT, n_subsamples,
3587           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3588       gst_buffer_unref (buf);
3589     } else {
3590       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3591     }
3592     g_ptr_array_add (ss_info->crypto_info, properties);
3593   }
3594   return TRUE;
3595 }
3596
3597 /* Converts a UUID in raw byte form to a string representation, as defined in
3598  * RFC 4122. The caller takes ownership of the returned string and is
3599  * responsible for freeing it after use. */
3600 static gchar *
3601 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3602 {
3603   const guint8 *uuid = (const guint8 *) uuid_bytes;
3604
3605   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3606       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3607       uuid[0], uuid[1], uuid[2], uuid[3],
3608       uuid[4], uuid[5], uuid[6], uuid[7],
3609       uuid[8], uuid[9], uuid[10], uuid[11],
3610       uuid[12], uuid[13], uuid[14], uuid[15]);
3611 }
3612
3613 /* Parses a Protection System Specific Header box (pssh), as defined in the
3614  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3615  * information needed by a specific content protection system in order to
3616  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3617  * otherwise. */
3618 static gboolean
3619 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3620 {
3621   gchar *sysid_string;
3622   guint32 pssh_size = QT_UINT32 (node->data);
3623   GstBuffer *pssh = NULL;
3624   GstEvent *event = NULL;
3625   guint32 parent_box_type;
3626   gint i;
3627
3628   if (G_UNLIKELY (pssh_size < 32U)) {
3629     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3630     return FALSE;
3631   }
3632
3633   sysid_string =
3634       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3635
3636   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3637
3638   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3639   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3640       gst_buffer_get_size (pssh));
3641
3642   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3643
3644   /* Push an event containing the pssh box onto the queues of all streams. */
3645   event = gst_event_new_protection (sysid_string, pssh,
3646       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3647   for (i = 0; i < qtdemux->n_streams; ++i) {
3648     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3649         gst_event_ref (event));
3650   }
3651   g_free (sysid_string);
3652   gst_event_unref (event);
3653   gst_buffer_unref (pssh);
3654   return TRUE;
3655 }
3656
3657 static gboolean
3658 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3659     guint64 moof_offset, QtDemuxStream * stream)
3660 {
3661   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3662   GNode *uuid_node;
3663   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3664   GNode *saiz_node, *saio_node, *pssh_node;
3665   GstByteReader saiz_data, saio_data;
3666   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3667   gint64 base_offset, running_offset;
3668   guint32 frag_num;
3669
3670   /* NOTE @stream ignored */
3671
3672   moof_node = g_node_new ((guint8 *) buffer);
3673   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3674   qtdemux_node_dump (qtdemux, moof_node);
3675
3676   /* Get fragment number from mfhd and check it's valid */
3677   mfhd_node =
3678       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3679   if (mfhd_node == NULL)
3680     goto missing_mfhd;
3681   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3682     goto fail;
3683   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3684
3685   /* unknown base_offset to start with */
3686   base_offset = running_offset = -1;
3687   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3688   while (traf_node) {
3689     guint64 decode_time = 0;
3690
3691     /* Fragment Header node */
3692     tfhd_node =
3693         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3694         &tfhd_data);
3695     if (!tfhd_node)
3696       goto missing_tfhd;
3697     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3698             &ds_size, &ds_flags, &base_offset))
3699       goto missing_tfhd;
3700
3701     /* The following code assumes at most a single set of sample auxiliary
3702      * data in the fragment (consisting of a saiz box and a corresponding saio
3703      * box); in theory, however, there could be multiple sets of sample
3704      * auxiliary data in a fragment. */
3705     saiz_node =
3706         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3707         &saiz_data);
3708     if (saiz_node) {
3709       guint32 info_type = 0;
3710       guint64 offset = 0;
3711       guint32 info_type_parameter = 0;
3712
3713       g_free (qtdemux->cenc_aux_info_sizes);
3714
3715       qtdemux->cenc_aux_info_sizes =
3716           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3717           &qtdemux->cenc_aux_sample_count);
3718       if (qtdemux->cenc_aux_info_sizes == NULL) {
3719         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3720         goto fail;
3721       }
3722       saio_node =
3723           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3724           &saio_data);
3725       if (!saio_node) {
3726         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3727         g_free (qtdemux->cenc_aux_info_sizes);
3728         qtdemux->cenc_aux_info_sizes = NULL;
3729         goto fail;
3730       }
3731
3732       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3733                   &info_type, &info_type_parameter, &offset))) {
3734         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3735         g_free (qtdemux->cenc_aux_info_sizes);
3736         qtdemux->cenc_aux_info_sizes = NULL;
3737         goto fail;
3738       }
3739       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3740         offset += (guint64) (base_offset - qtdemux->moof_offset);
3741       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3742         GstByteReader br;
3743         if (offset > length) {
3744           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3745           qtdemux->cenc_aux_info_offset = offset;
3746         } else {
3747           gst_byte_reader_init (&br, buffer + offset, length - offset);
3748           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3749                   qtdemux->cenc_aux_info_sizes,
3750                   qtdemux->cenc_aux_sample_count)) {
3751             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3752             g_free (qtdemux->cenc_aux_info_sizes);
3753             qtdemux->cenc_aux_info_sizes = NULL;
3754             goto fail;
3755           }
3756         }
3757       }
3758     }
3759
3760     tfdt_node =
3761         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3762         &tfdt_data);
3763     if (tfdt_node) {
3764       /* We'll use decode_time to interpolate timestamps
3765        * in case the input timestamps are missing */
3766       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3767
3768       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3769           " (%" GST_TIME_FORMAT ")", decode_time,
3770           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3771
3772       /* Discard the fragment buffer timestamp info to avoid using it.
3773        * Rely on tfdt instead as it is more accurate than the timestamp
3774        * that is fetched from a manifest/playlist and is usually
3775        * less accurate. */
3776       qtdemux->fragment_start = -1;
3777     }
3778
3779     if (G_UNLIKELY (!stream)) {
3780       /* we lost track of offset, we'll need to regain it,
3781        * but can delay complaining until later or avoid doing so altogether */
3782       base_offset = -2;
3783       goto next;
3784     }
3785     if (G_UNLIKELY (base_offset < -1))
3786       goto lost_offset;
3787
3788     if (qtdemux->upstream_format_is_time)
3789       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3790
3791     /* initialise moof sample data */
3792     stream->n_samples_moof = 0;
3793     stream->duration_moof = 0;
3794
3795     /* Track Run node */
3796     trun_node =
3797         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3798         &trun_data);
3799     while (trun_node) {
3800       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3801           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3802           &running_offset, decode_time);
3803       /* iterate all siblings */
3804       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3805           &trun_data);
3806     }
3807
3808     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3809     if (uuid_node) {
3810       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3811       guint32 box_length = QT_UINT32 (uuid_buffer);
3812
3813       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3814     }
3815
3816     /* if no new base_offset provided for next traf,
3817      * base is end of current traf */
3818     base_offset = running_offset;
3819     running_offset = -1;
3820
3821     if (stream->n_samples_moof && stream->duration_moof)
3822       stream->new_caps = TRUE;
3823
3824   next:
3825     /* iterate all siblings */
3826     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3827   }
3828
3829   /* parse any protection system info */
3830   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3831   while (pssh_node) {
3832     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3833     qtdemux_parse_pssh (qtdemux, pssh_node);
3834     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3835   }
3836
3837   g_node_destroy (moof_node);
3838   return TRUE;
3839
3840 missing_tfhd:
3841   {
3842     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3843     goto fail;
3844   }
3845 missing_mfhd:
3846   {
3847     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3848     goto fail;
3849   }
3850 lost_offset:
3851   {
3852     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3853     goto fail;
3854   }
3855 fail:
3856   {
3857     g_node_destroy (moof_node);
3858     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3859         (_("This file is corrupt and cannot be played.")), (NULL));
3860     return FALSE;
3861   }
3862 }
3863
3864 #if 0
3865 /* might be used if some day we actually use mfra & co
3866  * for random access to fragments,
3867  * but that will require quite some modifications and much less relying
3868  * on a sample array */
3869 #endif
3870
3871 static gboolean
3872 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3873 {
3874   QtDemuxStream *stream;
3875   guint32 ver_flags, track_id, len, num_entries, i;
3876   guint value_size, traf_size, trun_size, sample_size;
3877   guint64 time = 0, moof_offset = 0;
3878 #if 0
3879   GstBuffer *buf = NULL;
3880   GstFlowReturn ret;
3881 #endif
3882   GstByteReader tfra;
3883
3884   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3885
3886   if (!gst_byte_reader_skip (&tfra, 8))
3887     return FALSE;
3888
3889   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3890     return FALSE;
3891
3892   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3893       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3894       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3895     return FALSE;
3896
3897   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3898
3899   stream = qtdemux_find_stream (qtdemux, track_id);
3900   if (stream == NULL)
3901     goto unknown_trackid;
3902
3903   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3904   sample_size = (len & 3) + 1;
3905   trun_size = ((len & 12) >> 2) + 1;
3906   traf_size = ((len & 48) >> 4) + 1;
3907
3908   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3909       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3910
3911   if (num_entries == 0)
3912     goto no_samples;
3913
3914   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3915           value_size + value_size + traf_size + trun_size + sample_size))
3916     goto corrupt_file;
3917
3918   g_free (stream->ra_entries);
3919   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3920   stream->n_ra_entries = num_entries;
3921
3922   for (i = 0; i < num_entries; i++) {
3923     qt_atom_parser_get_offset (&tfra, value_size, &time);
3924     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3925     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3926     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3927     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3928
3929     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3930
3931     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3932         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3933
3934     stream->ra_entries[i].ts = time;
3935     stream->ra_entries[i].moof_offset = moof_offset;
3936
3937     /* don't want to go through the entire file and read all moofs at startup */
3938 #if 0
3939     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3940     if (ret != GST_FLOW_OK)
3941       goto corrupt_file;
3942     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3943         moof_offset, stream);
3944     gst_buffer_unref (buf);
3945 #endif
3946   }
3947
3948   check_update_duration (qtdemux, time);
3949
3950   return TRUE;
3951
3952 /* ERRORS */
3953 unknown_trackid:
3954   {
3955     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3956     return FALSE;
3957   }
3958 corrupt_file:
3959   {
3960     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3961     return FALSE;
3962   }
3963 no_samples:
3964   {
3965     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3966     return FALSE;
3967   }
3968 }
3969
3970 static gboolean
3971 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3972 {
3973   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3974   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3975   GstBuffer *mfro = NULL, *mfra = NULL;
3976   GstFlowReturn flow;
3977   gboolean ret = FALSE;
3978   GNode *mfra_node, *tfra_node;
3979   guint64 mfra_offset = 0;
3980   guint32 fourcc, mfra_size;
3981   gint64 len;
3982
3983   /* query upstream size in bytes */
3984   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3985     goto size_query_failed;
3986
3987   /* mfro box should be at the very end of the file */
3988   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3989   if (flow != GST_FLOW_OK)
3990     goto exit;
3991
3992   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3993
3994   fourcc = QT_FOURCC (mfro_map.data + 4);
3995   if (fourcc != FOURCC_mfro)
3996     goto exit;
3997
3998   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3999   if (mfro_map.size < 16)
4000     goto invalid_mfro_size;
4001
4002   mfra_size = QT_UINT32 (mfro_map.data + 12);
4003   if (mfra_size >= len)
4004     goto invalid_mfra_size;
4005
4006   mfra_offset = len - mfra_size;
4007
4008   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4009       mfra_offset, mfra_size);
4010
4011   /* now get and parse mfra box */
4012   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4013   if (flow != GST_FLOW_OK)
4014     goto broken_file;
4015
4016   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4017
4018   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4019   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4020
4021   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4022
4023   while (tfra_node) {
4024     qtdemux_parse_tfra (qtdemux, tfra_node);
4025     /* iterate all siblings */
4026     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4027   }
4028   g_node_destroy (mfra_node);
4029
4030   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4031   ret = TRUE;
4032
4033 exit:
4034
4035   if (mfro) {
4036     if (mfro_map.memory != NULL)
4037       gst_buffer_unmap (mfro, &mfro_map);
4038     gst_buffer_unref (mfro);
4039   }
4040   if (mfra) {
4041     if (mfra_map.memory != NULL)
4042       gst_buffer_unmap (mfra, &mfra_map);
4043     gst_buffer_unref (mfra);
4044   }
4045   return ret;
4046
4047 /* ERRORS */
4048 size_query_failed:
4049   {
4050     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4051     goto exit;
4052   }
4053 invalid_mfro_size:
4054   {
4055     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4056     goto exit;
4057   }
4058 invalid_mfra_size:
4059   {
4060     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4061     goto exit;
4062   }
4063 broken_file:
4064   {
4065     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4066     goto exit;
4067   }
4068 }
4069
4070 static guint64
4071 add_offset (guint64 offset, guint64 advance)
4072 {
4073   /* Avoid 64-bit overflow by clamping */
4074   if (offset > G_MAXUINT64 - advance)
4075     return G_MAXUINT64;
4076   return offset + advance;
4077 }
4078
4079 static GstFlowReturn
4080 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4081 {
4082   guint64 length = 0;
4083   guint32 fourcc = 0;
4084   GstBuffer *buf = NULL;
4085   GstFlowReturn ret = GST_FLOW_OK;
4086   guint64 cur_offset = qtdemux->offset;
4087   GstMapInfo map;
4088
4089   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4090   if (G_UNLIKELY (ret != GST_FLOW_OK))
4091     goto beach;
4092   gst_buffer_map (buf, &map, GST_MAP_READ);
4093   if (G_LIKELY (map.size >= 8))
4094     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4095   gst_buffer_unmap (buf, &map);
4096   gst_buffer_unref (buf);
4097
4098   /* maybe we already got most we needed, so only consider this eof */
4099   if (G_UNLIKELY (length == 0)) {
4100     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4101         (_("Invalid atom size.")),
4102         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4103             GST_FOURCC_ARGS (fourcc)));
4104     ret = GST_FLOW_EOS;
4105     goto beach;
4106   }
4107
4108   switch (fourcc) {
4109     case FOURCC_moof:
4110       /* record for later parsing when needed */
4111       if (!qtdemux->moof_offset) {
4112         qtdemux->moof_offset = qtdemux->offset;
4113       }
4114       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4115         /* FIXME */
4116       } else {
4117         qtdemux->offset += length;      /* skip moof and keep going */
4118       }
4119       if (qtdemux->got_moov) {
4120         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4121         ret = GST_FLOW_EOS;
4122         goto beach;
4123       }
4124       break;
4125     case FOURCC_mdat:
4126     case FOURCC_free:
4127     case FOURCC_wide:
4128     case FOURCC_PICT:
4129     case FOURCC_pnot:
4130     {
4131       GST_LOG_OBJECT (qtdemux,
4132           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4133           GST_FOURCC_ARGS (fourcc), cur_offset);
4134       qtdemux->offset = add_offset (qtdemux->offset, length);
4135       break;
4136     }
4137     case FOURCC_moov:
4138     {
4139       GstBuffer *moov = NULL;
4140
4141       if (qtdemux->got_moov) {
4142         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4143         qtdemux->offset = add_offset (qtdemux->offset, length);
4144         goto beach;
4145       }
4146
4147       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4148       if (ret != GST_FLOW_OK)
4149         goto beach;
4150       gst_buffer_map (moov, &map, GST_MAP_READ);
4151
4152       if (length != map.size) {
4153         /* Some files have a 'moov' atom at the end of the file which contains
4154          * a terminal 'free' atom where the body of the atom is missing.
4155          * Check for, and permit, this special case.
4156          */
4157         if (map.size >= 8) {
4158           guint8 *final_data = map.data + (map.size - 8);
4159           guint32 final_length = QT_UINT32 (final_data);
4160           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4161
4162           if (final_fourcc == FOURCC_free
4163               && map.size + final_length - 8 == length) {
4164             /* Ok, we've found that special case. Allocate a new buffer with
4165              * that free atom actually present. */
4166             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4167             gst_buffer_fill (newmoov, 0, map.data, map.size);
4168             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4169             gst_buffer_unmap (moov, &map);
4170             gst_buffer_unref (moov);
4171             moov = newmoov;
4172             gst_buffer_map (moov, &map, GST_MAP_READ);
4173           }
4174         }
4175       }
4176
4177       if (length != map.size) {
4178         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4179             (_("This file is incomplete and cannot be played.")),
4180             ("We got less than expected (received %" G_GSIZE_FORMAT
4181                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4182                 (guint) length, cur_offset));
4183         gst_buffer_unmap (moov, &map);
4184         gst_buffer_unref (moov);
4185         ret = GST_FLOW_ERROR;
4186         goto beach;
4187       }
4188       qtdemux->offset += length;
4189
4190       qtdemux_parse_moov (qtdemux, map.data, length);
4191       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4192
4193       qtdemux_parse_tree (qtdemux);
4194       g_node_destroy (qtdemux->moov_node);
4195       gst_buffer_unmap (moov, &map);
4196       gst_buffer_unref (moov);
4197       qtdemux->moov_node = NULL;
4198       qtdemux->got_moov = TRUE;
4199
4200       break;
4201     }
4202     case FOURCC_ftyp:
4203     {
4204       GstBuffer *ftyp = NULL;
4205
4206       /* extract major brand; might come in handy for ISO vs QT issues */
4207       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4208       if (ret != GST_FLOW_OK)
4209         goto beach;
4210       qtdemux->offset += length;
4211       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4212       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4213       gst_buffer_unmap (ftyp, &map);
4214       gst_buffer_unref (ftyp);
4215       break;
4216     }
4217     case FOURCC_uuid:
4218     {
4219       GstBuffer *uuid = NULL;
4220
4221       /* uuid are extension atoms */
4222       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4223       if (ret != GST_FLOW_OK)
4224         goto beach;
4225       qtdemux->offset += length;
4226       gst_buffer_map (uuid, &map, GST_MAP_READ);
4227       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4228       gst_buffer_unmap (uuid, &map);
4229       gst_buffer_unref (uuid);
4230       break;
4231     }
4232     case FOURCC_sidx:
4233     {
4234       GstBuffer *sidx = NULL;
4235       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4236       if (ret != GST_FLOW_OK)
4237         goto beach;
4238       qtdemux->offset += length;
4239       gst_buffer_map (sidx, &map, GST_MAP_READ);
4240       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4241       gst_buffer_unmap (sidx, &map);
4242       gst_buffer_unref (sidx);
4243       break;
4244     }
4245     default:
4246     {
4247       GstBuffer *unknown = NULL;
4248
4249       GST_LOG_OBJECT (qtdemux,
4250           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4251           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4252           cur_offset);
4253       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4254       if (ret != GST_FLOW_OK)
4255         goto beach;
4256       gst_buffer_map (unknown, &map, GST_MAP_READ);
4257       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4258       gst_buffer_unmap (unknown, &map);
4259       gst_buffer_unref (unknown);
4260       qtdemux->offset += length;
4261       break;
4262     }
4263   }
4264
4265 beach:
4266   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4267     /* digested all data, show what we have */
4268     qtdemux_prepare_streams (qtdemux);
4269     ret = qtdemux_expose_streams (qtdemux);
4270
4271     qtdemux->state = QTDEMUX_STATE_MOVIE;
4272     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4273         qtdemux->state);
4274     return ret;
4275   }
4276   return ret;
4277 }
4278
4279 /* Seeks to the previous keyframe of the indexed stream and
4280  * aligns other streams with respect to the keyframe timestamp
4281  * of indexed stream. Only called in case of Reverse Playback
4282  */
4283 static GstFlowReturn
4284 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4285 {
4286   guint8 n = 0;
4287   guint32 seg_idx = 0, k_index = 0;
4288   guint32 ref_seg_idx, ref_k_index;
4289   GstClockTime k_pos = 0, last_stop = 0;
4290   QtDemuxSegment *seg = NULL;
4291   QtDemuxStream *ref_str = NULL;
4292   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4293   guint64 target_ts;
4294
4295   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4296    * and finally align all the other streams on that timestamp with their
4297    * respective keyframes */
4298   for (n = 0; n < qtdemux->n_streams; n++) {
4299     QtDemuxStream *str = qtdemux->streams[n];
4300
4301     /* No candidate yet, take the first stream */
4302     if (!ref_str) {
4303       ref_str = str;
4304       continue;
4305     }
4306
4307     /* So that stream has a segment, we prefer video streams */
4308     if (str->subtype == FOURCC_vide) {
4309       ref_str = str;
4310       break;
4311     }
4312   }
4313
4314   if (G_UNLIKELY (!ref_str)) {
4315     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4316     goto eos;
4317   }
4318
4319   if (G_UNLIKELY (!ref_str->from_sample)) {
4320     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4321     goto eos;
4322   }
4323
4324   /* So that stream has been playing from from_sample to to_sample. We will
4325    * get the timestamp of the previous sample and search for a keyframe before
4326    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4327   if (ref_str->subtype == FOURCC_vide) {
4328     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4329         ref_str->from_sample - 1);
4330   } else {
4331     if (ref_str->from_sample >= 10)
4332       k_index = ref_str->from_sample - 10;
4333     else
4334       k_index = 0;
4335   }
4336
4337   target_ts =
4338       ref_str->samples[k_index].timestamp +
4339       ref_str->samples[k_index].pts_offset;
4340
4341   /* get current segment for that stream */
4342   seg = &ref_str->segments[ref_str->segment_index];
4343   /* Use segment start in original timescale for comparisons */
4344   seg_media_start_mov = seg->trak_media_start;
4345
4346   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4347       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4348       k_index, target_ts, seg_media_start_mov,
4349       GST_TIME_ARGS (seg->media_start));
4350
4351   /* Crawl back through segments to find the one containing this I frame */
4352   while (target_ts < seg_media_start_mov) {
4353     GST_DEBUG_OBJECT (qtdemux,
4354         "keyframe position (sample %u) is out of segment %u " " target %"
4355         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4356         ref_str->segment_index, target_ts, seg_media_start_mov);
4357
4358     if (G_UNLIKELY (!ref_str->segment_index)) {
4359       /* Reached first segment, let's consider it's EOS */
4360       goto eos;
4361     }
4362     ref_str->segment_index--;
4363     seg = &ref_str->segments[ref_str->segment_index];
4364     /* Use segment start in original timescale for comparisons */
4365     seg_media_start_mov = seg->trak_media_start;
4366   }
4367   /* Calculate time position of the keyframe and where we should stop */
4368   k_pos =
4369       QTSTREAMTIME_TO_GSTTIME (ref_str,
4370       target_ts - seg->trak_media_start) + seg->time;
4371   last_stop =
4372       QTSTREAMTIME_TO_GSTTIME (ref_str,
4373       ref_str->samples[ref_str->from_sample].timestamp -
4374       seg->trak_media_start) + seg->time;
4375
4376   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4377       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4378       k_index, GST_TIME_ARGS (k_pos));
4379
4380   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4381   qtdemux->segment.position = last_stop;
4382   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4383       GST_TIME_ARGS (last_stop));
4384
4385   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4386     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4387     goto eos;
4388   }
4389
4390   ref_seg_idx = ref_str->segment_index;
4391   ref_k_index = k_index;
4392
4393   /* Align them all on this */
4394   for (n = 0; n < qtdemux->n_streams; n++) {
4395     guint32 index = 0;
4396     GstClockTime seg_time = 0;
4397     QtDemuxStream *str = qtdemux->streams[n];
4398
4399     /* aligning reference stream again might lead to backing up to yet another
4400      * keyframe (due to timestamp rounding issues),
4401      * potentially putting more load on downstream; so let's try to avoid */
4402     if (str == ref_str) {
4403       seg_idx = ref_seg_idx;
4404       seg = &str->segments[seg_idx];
4405       k_index = ref_k_index;
4406       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4407           "sample at index %d", n, ref_str->segment_index, k_index);
4408     } else {
4409       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4410       GST_DEBUG_OBJECT (qtdemux,
4411           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4412           seg_idx, GST_TIME_ARGS (k_pos));
4413
4414       /* get segment and time in the segment */
4415       seg = &str->segments[seg_idx];
4416       seg_time = k_pos - seg->time;
4417
4418       /* get the media time in the segment.
4419        * No adjustment for empty "filler" segments */
4420       if (seg->media_start != GST_CLOCK_TIME_NONE)
4421         seg_time += seg->media_start;
4422
4423       /* get the index of the sample with media time */
4424       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4425       GST_DEBUG_OBJECT (qtdemux,
4426           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4427           GST_TIME_ARGS (seg_time), index);
4428
4429       /* find previous keyframe */
4430       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4431     }
4432
4433     /* Remember until where we want to go */
4434     str->to_sample = str->from_sample - 1;
4435     /* Define our time position */
4436     target_ts =
4437         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4438     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4439     if (seg->media_start != GST_CLOCK_TIME_NONE)
4440       str->time_position -= seg->media_start;
4441
4442     /* Now seek back in time */
4443     gst_qtdemux_move_stream (qtdemux, str, k_index);
4444     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4445         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4446         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4447   }
4448
4449   return GST_FLOW_OK;
4450
4451 eos:
4452   return GST_FLOW_EOS;
4453 }
4454
4455 /*
4456  * Gets the current qt segment start, stop and position for the
4457  * given time offset. This is used in update_segment()
4458  */
4459 static void
4460 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4461     QtDemuxStream * stream, GstClockTime offset,
4462     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4463 {
4464   GstClockTime seg_time;
4465   GstClockTime start, stop, time;
4466   QtDemuxSegment *segment;
4467
4468   segment = &stream->segments[stream->segment_index];
4469
4470   /* get time in this segment */
4471   seg_time = (offset - segment->time) * segment->rate;
4472
4473   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4474       GST_TIME_ARGS (seg_time));
4475
4476   if (G_UNLIKELY (seg_time > segment->duration)) {
4477     GST_LOG_OBJECT (stream->pad,
4478         "seg_time > segment->duration %" GST_TIME_FORMAT,
4479         GST_TIME_ARGS (segment->duration));
4480     seg_time = segment->duration;
4481   }
4482
4483   /* qtdemux->segment.stop is in outside-time-realm, whereas
4484    * segment->media_stop is in track-time-realm.
4485    *
4486    * In order to compare the two, we need to bring segment.stop
4487    * into the track-time-realm
4488    *
4489    * FIXME - does this comment still hold? Don't see any conversion here */
4490
4491   stop = qtdemux->segment.stop;
4492   if (stop == GST_CLOCK_TIME_NONE)
4493     stop = qtdemux->segment.duration;
4494   if (stop == GST_CLOCK_TIME_NONE)
4495     stop = segment->media_stop;
4496   else
4497     stop =
4498         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4499
4500   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4501     start = segment->time + seg_time;
4502     time = offset;
4503     stop = start - seg_time + segment->duration;
4504   } else if (qtdemux->segment.rate >= 0) {
4505     start = MIN (segment->media_start + seg_time, stop);
4506     time = offset;
4507   } else {
4508     if (segment->media_start >= qtdemux->segment.start) {
4509       time = segment->time;
4510     } else {
4511       time = segment->time + (qtdemux->segment.start - segment->media_start);
4512     }
4513
4514     start = MAX (segment->media_start, qtdemux->segment.start);
4515     stop = MIN (segment->media_start + seg_time, stop);
4516   }
4517
4518   *_start = start;
4519   *_stop = stop;
4520   *_time = time;
4521 }
4522
4523 /*
4524  * Updates the qt segment used for the stream and pushes a new segment event
4525  * downstream on this stream's pad.
4526  */
4527 static gboolean
4528 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4529     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4530     GstClockTime * _stop)
4531 {
4532   QtDemuxSegment *segment;
4533   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4534   gdouble rate;
4535   GstEvent *event;
4536
4537   /* update the current segment */
4538   stream->segment_index = seg_idx;
4539
4540   /* get the segment */
4541   segment = &stream->segments[seg_idx];
4542
4543   if (G_UNLIKELY (offset < segment->time)) {
4544     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4545         GST_TIME_ARGS (segment->time));
4546     return FALSE;
4547   }
4548
4549   /* segment lies beyond total indicated duration */
4550   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4551           segment->time > qtdemux->segment.duration)) {
4552     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4553         " < segment->time %" GST_TIME_FORMAT,
4554         GST_TIME_ARGS (qtdemux->segment.duration),
4555         GST_TIME_ARGS (segment->time));
4556     return FALSE;
4557   }
4558
4559   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4560       &start, &stop, &time);
4561
4562   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4563       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4564       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4565
4566   /* combine global rate with that of the segment */
4567   rate = segment->rate * qtdemux->segment.rate;
4568
4569   /* Copy flags from main segment */
4570   stream->segment.flags = qtdemux->segment.flags;
4571
4572   /* update the segment values used for clipping */
4573   stream->segment.offset = qtdemux->segment.offset;
4574   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4575   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4576   stream->segment.rate = rate;
4577   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4578       stream->cslg_shift);
4579   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4580       stream->cslg_shift);
4581   stream->segment.time = time;
4582   stream->segment.position = stream->segment.start;
4583
4584   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4585       &stream->segment);
4586
4587   /* now prepare and send the segment */
4588   if (stream->pad) {
4589     event = gst_event_new_segment (&stream->segment);
4590     if (qtdemux->segment_seqnum) {
4591       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4592     }
4593     gst_pad_push_event (stream->pad, event);
4594     /* assume we can send more data now */
4595     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4596     /* clear to send tags on this pad now */
4597     gst_qtdemux_push_tags (qtdemux, stream);
4598   }
4599
4600   if (_start)
4601     *_start = start;
4602   if (_stop)
4603     *_stop = stop;
4604
4605   return TRUE;
4606 }
4607
4608 /* activate the given segment number @seg_idx of @stream at time @offset.
4609  * @offset is an absolute global position over all the segments.
4610  *
4611  * This will push out a NEWSEGMENT event with the right values and
4612  * position the stream index to the first decodable sample before
4613  * @offset.
4614  */
4615 static gboolean
4616 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4617     guint32 seg_idx, GstClockTime offset)
4618 {
4619   QtDemuxSegment *segment;
4620   guint32 index, kf_index;
4621   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4622
4623   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4624       seg_idx, GST_TIME_ARGS (offset));
4625
4626   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4627           &start, &stop))
4628     return FALSE;
4629
4630   segment = &stream->segments[stream->segment_index];
4631
4632   /* in the fragmented case, we pick a fragment that starts before our
4633    * desired position and rely on downstream to wait for a keyframe
4634    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4635    * tfra entries tells us which trun/sample the key unit is in, but we don't
4636    * make use of this additional information at the moment) */
4637   if (qtdemux->fragmented) {
4638     stream->to_sample = G_MAXUINT32;
4639     return TRUE;
4640   }
4641
4642   /* We don't need to look for a sample in push-based */
4643   if (!qtdemux->pullbased)
4644     return TRUE;
4645
4646   /* and move to the keyframe before the indicated media time of the
4647    * segment */
4648   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4649     if (qtdemux->segment.rate >= 0) {
4650       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4651       stream->to_sample = G_MAXUINT32;
4652       GST_DEBUG_OBJECT (stream->pad,
4653           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4654           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4655           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4656     } else {
4657       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4658       stream->to_sample = index;
4659       GST_DEBUG_OBJECT (stream->pad,
4660           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4661           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4662           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4663     }
4664   } else {
4665     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4666         "this is an empty segment");
4667     return TRUE;
4668   }
4669
4670   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4671    * encountered an error and printed a message so we return appropriately */
4672   if (index == -1)
4673     return FALSE;
4674
4675   /* we're at the right spot */
4676   if (index == stream->sample_index) {
4677     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4678     return TRUE;
4679   }
4680
4681   /* find keyframe of the target index */
4682   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4683
4684 /* *INDENT-OFF* */
4685 /* indent does stupid stuff with stream->samples[].timestamp */
4686
4687   /* if we move forwards, we don't have to go back to the previous
4688    * keyframe since we already sent that. We can also just jump to
4689    * the keyframe right before the target index if there is one. */
4690   if (index > stream->sample_index) {
4691     /* moving forwards check if we move past a keyframe */
4692     if (kf_index > stream->sample_index) {
4693       GST_DEBUG_OBJECT (stream->pad,
4694            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4695            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4696            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4697       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4698     } else {
4699       GST_DEBUG_OBJECT (stream->pad,
4700           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4701           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4702           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4703     }
4704   } else {
4705     GST_DEBUG_OBJECT (stream->pad,
4706         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4707         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4708         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4709     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4710   }
4711
4712 /* *INDENT-ON* */
4713
4714   return TRUE;
4715 }
4716
4717 /* prepare to get the current sample of @stream, getting essential values.
4718  *
4719  * This function will also prepare and send the segment when needed.
4720  *
4721  * Return FALSE if the stream is EOS.
4722  *
4723  * PULL-BASED
4724  */
4725 static gboolean
4726 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4727     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4728     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4729     gboolean * keyframe)
4730 {
4731   QtDemuxSample *sample;
4732   GstClockTime time_position;
4733   guint32 seg_idx;
4734
4735   g_return_val_if_fail (stream != NULL, FALSE);
4736
4737   time_position = stream->time_position;
4738   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4739     goto eos;
4740
4741   seg_idx = stream->segment_index;
4742   if (G_UNLIKELY (seg_idx == -1)) {
4743     /* find segment corresponding to time_position if we are looking
4744      * for a segment. */
4745     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4746   }
4747
4748   /* different segment, activate it, sample_index will be set. */
4749   if (G_UNLIKELY (stream->segment_index != seg_idx))
4750     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4751
4752   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4753                   segment_index]))) {
4754     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4755
4756     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4757         " prepare empty sample");
4758
4759     *empty = TRUE;
4760     *pts = *dts = time_position;
4761     *duration = seg->duration - (time_position - seg->time);
4762
4763     return TRUE;
4764   }
4765
4766   *empty = FALSE;
4767
4768   if (stream->sample_index == -1)
4769     stream->sample_index = 0;
4770
4771   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4772       stream->sample_index, stream->n_samples);
4773
4774   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4775     if (!qtdemux->fragmented)
4776       goto eos;
4777
4778     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4779     do {
4780       GstFlowReturn flow;
4781
4782       GST_OBJECT_LOCK (qtdemux);
4783       flow = qtdemux_add_fragmented_samples (qtdemux);
4784       GST_OBJECT_UNLOCK (qtdemux);
4785
4786       if (flow != GST_FLOW_OK)
4787         goto eos;
4788     }
4789     while (stream->sample_index >= stream->n_samples);
4790   }
4791
4792   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4793     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4794         stream->sample_index);
4795     return FALSE;
4796   }
4797
4798   /* now get the info for the sample we're at */
4799   sample = &stream->samples[stream->sample_index];
4800
4801   *dts = QTSAMPLE_DTS (stream, sample);
4802   *pts = QTSAMPLE_PTS (stream, sample);
4803   *offset = sample->offset;
4804   *size = sample->size;
4805   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4806   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4807
4808   return TRUE;
4809
4810   /* special cases */
4811 eos:
4812   {
4813     stream->time_position = GST_CLOCK_TIME_NONE;
4814     return FALSE;
4815   }
4816 }
4817
4818 /* move to the next sample in @stream.
4819  *
4820  * Moves to the next segment when needed.
4821  */
4822 static void
4823 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4824 {
4825   QtDemuxSample *sample;
4826   QtDemuxSegment *segment;
4827
4828   /* get current segment */
4829   segment = &stream->segments[stream->segment_index];
4830
4831   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4832     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4833     goto next_segment;
4834   }
4835
4836   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4837     /* Mark the stream as EOS */
4838     GST_DEBUG_OBJECT (qtdemux,
4839         "reached max allowed sample %u, mark EOS", stream->to_sample);
4840     stream->time_position = GST_CLOCK_TIME_NONE;
4841     return;
4842   }
4843
4844   /* move to next sample */
4845   stream->sample_index++;
4846   stream->offset_in_sample = 0;
4847
4848   /* reached the last sample, we need the next segment */
4849   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4850     goto next_segment;
4851
4852   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4853     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4854         stream->sample_index);
4855     return;
4856   }
4857
4858   /* get next sample */
4859   sample = &stream->samples[stream->sample_index];
4860
4861   /* see if we are past the segment */
4862   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4863     goto next_segment;
4864
4865   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4866     /* inside the segment, update time_position, looks very familiar to
4867      * GStreamer segments, doesn't it? */
4868     stream->time_position =
4869         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4870   } else {
4871     /* not yet in segment, time does not yet increment. This means
4872      * that we are still prerolling keyframes to the decoder so it can
4873      * decode the first sample of the segment. */
4874     stream->time_position = segment->time;
4875   }
4876   return;
4877
4878   /* move to the next segment */
4879 next_segment:
4880   {
4881     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4882
4883     if (stream->segment_index == stream->n_segments - 1) {
4884       /* are we at the end of the last segment, we're EOS */
4885       stream->time_position = GST_CLOCK_TIME_NONE;
4886     } else {
4887       /* else we're only at the end of the current segment */
4888       stream->time_position = segment->stop_time;
4889     }
4890     /* make sure we select a new segment */
4891
4892     /* accumulate previous segments */
4893     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4894       stream->accumulated_base +=
4895           (stream->segment.stop -
4896           stream->segment.start) / ABS (stream->segment.rate);
4897
4898     stream->segment_index = -1;
4899   }
4900 }
4901
4902 static void
4903 gst_qtdemux_sync_streams (GstQTDemux * demux)
4904 {
4905   gint i;
4906
4907   if (demux->n_streams <= 1)
4908     return;
4909
4910   for (i = 0; i < demux->n_streams; i++) {
4911     QtDemuxStream *stream;
4912     GstClockTime end_time;
4913
4914     stream = demux->streams[i];
4915
4916     if (!stream->pad)
4917       continue;
4918
4919     /* TODO advance time on subtitle streams here, if any some day */
4920
4921     /* some clips/trailers may have unbalanced streams at the end,
4922      * so send EOS on shorter stream to prevent stalling others */
4923
4924     /* do not mess with EOS if SEGMENT seeking */
4925     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4926       continue;
4927
4928     if (demux->pullbased) {
4929       /* loop mode is sample time based */
4930       if (!STREAM_IS_EOS (stream))
4931         continue;
4932     } else {
4933       /* push mode is byte position based */
4934       if (stream->n_samples &&
4935           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4936         continue;
4937     }
4938
4939     if (stream->sent_eos)
4940       continue;
4941
4942     /* only act if some gap */
4943     end_time = stream->segments[stream->n_segments - 1].stop_time;
4944     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4945         ", stream end: %" GST_TIME_FORMAT,
4946         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4947     if (GST_CLOCK_TIME_IS_VALID (end_time)
4948         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4949       GstEvent *event;
4950
4951       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4952           GST_PAD_NAME (stream->pad));
4953       stream->sent_eos = TRUE;
4954       event = gst_event_new_eos ();
4955       if (demux->segment_seqnum)
4956         gst_event_set_seqnum (event, demux->segment_seqnum);
4957       gst_pad_push_event (stream->pad, event);
4958     }
4959   }
4960 }
4961
4962 /* EOS and NOT_LINKED need to be combined. This means that we return:
4963  *
4964  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4965  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4966  */
4967 static GstFlowReturn
4968 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4969     GstFlowReturn ret)
4970 {
4971   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4972
4973   if (stream->pad)
4974     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4975         ret);
4976   else
4977     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4978
4979   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4980   return ret;
4981 }
4982
4983 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4984  * completely clipped
4985  *
4986  * Should be used only with raw buffers */
4987 static GstBuffer *
4988 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4989     GstBuffer * buf)
4990 {
4991   guint64 start, stop, cstart, cstop, diff;
4992   GstClockTime pts, duration;
4993   gsize size, osize;
4994   gint num_rate, denom_rate;
4995   gint frame_size;
4996   gboolean clip_data;
4997   guint offset;
4998
4999   osize = size = gst_buffer_get_size (buf);
5000   offset = 0;
5001
5002   /* depending on the type, setup the clip parameters */
5003   if (stream->subtype == FOURCC_soun) {
5004     frame_size = stream->bytes_per_frame;
5005     num_rate = GST_SECOND;
5006     denom_rate = (gint) stream->rate;
5007     clip_data = TRUE;
5008   } else if (stream->subtype == FOURCC_vide) {
5009     frame_size = size;
5010     num_rate = stream->fps_n;
5011     denom_rate = stream->fps_d;
5012     clip_data = FALSE;
5013   } else
5014     goto wrong_type;
5015
5016   if (frame_size <= 0)
5017     goto bad_frame_size;
5018
5019   /* we can only clip if we have a valid pts */
5020   pts = GST_BUFFER_PTS (buf);
5021   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5022     goto no_pts;
5023
5024   duration = GST_BUFFER_DURATION (buf);
5025
5026   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5027     duration =
5028         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5029   }
5030
5031   start = pts;
5032   stop = start + duration;
5033
5034   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5035               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5036     goto clipped;
5037
5038   /* see if some clipping happened */
5039   diff = cstart - start;
5040   if (diff > 0) {
5041     pts += diff;
5042     duration -= diff;
5043
5044     if (clip_data) {
5045       /* bring clipped time to samples and to bytes */
5046       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5047       diff *= frame_size;
5048
5049       GST_DEBUG_OBJECT (qtdemux,
5050           "clipping start to %" GST_TIME_FORMAT " %"
5051           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5052
5053       offset = diff;
5054       size -= diff;
5055     }
5056   }
5057   diff = stop - cstop;
5058   if (diff > 0) {
5059     duration -= diff;
5060
5061     if (clip_data) {
5062       /* bring clipped time to samples and then to bytes */
5063       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5064       diff *= frame_size;
5065       GST_DEBUG_OBJECT (qtdemux,
5066           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5067           " bytes", GST_TIME_ARGS (cstop), diff);
5068       size -= diff;
5069     }
5070   }
5071
5072   if (offset != 0 || size != osize)
5073     gst_buffer_resize (buf, offset, size);
5074
5075   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5076   GST_BUFFER_PTS (buf) = pts;
5077   GST_BUFFER_DURATION (buf) = duration;
5078
5079   return buf;
5080
5081   /* dropped buffer */
5082 wrong_type:
5083   {
5084     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5085     return buf;
5086   }
5087 bad_frame_size:
5088   {
5089     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5090     return buf;
5091   }
5092 no_pts:
5093   {
5094     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5095     return buf;
5096   }
5097 clipped:
5098   {
5099     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5100     gst_buffer_unref (buf);
5101     return NULL;
5102   }
5103 }
5104
5105 /* the input buffer metadata must be writable,
5106  * but time/duration etc not yet set and need not be preserved */
5107 static GstBuffer *
5108 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5109     GstBuffer * buf)
5110 {
5111   GstMapInfo map;
5112   guint nsize = 0;
5113   gchar *str;
5114
5115   /* not many cases for now */
5116   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5117     /* send a one time dvd clut event */
5118     if (stream->pending_event && stream->pad)
5119       gst_pad_push_event (stream->pad, stream->pending_event);
5120     stream->pending_event = NULL;
5121   }
5122
5123   if (G_UNLIKELY (stream->subtype != FOURCC_text
5124           && stream->subtype != FOURCC_sbtl &&
5125           stream->subtype != FOURCC_subp)) {
5126     return buf;
5127   }
5128
5129   gst_buffer_map (buf, &map, GST_MAP_READ);
5130
5131   /* empty buffer is sent to terminate previous subtitle */
5132   if (map.size <= 2) {
5133     gst_buffer_unmap (buf, &map);
5134     gst_buffer_unref (buf);
5135     return NULL;
5136   }
5137   if (stream->subtype == FOURCC_subp) {
5138     /* That's all the processing needed for subpictures */
5139     gst_buffer_unmap (buf, &map);
5140     return buf;
5141   }
5142
5143   nsize = GST_READ_UINT16_BE (map.data);
5144   nsize = MIN (nsize, map.size - 2);
5145
5146   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5147       nsize, map.size);
5148
5149   /* takes care of UTF-8 validation or UTF-16 recognition,
5150    * no other encoding expected */
5151   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5152   gst_buffer_unmap (buf, &map);
5153   if (str) {
5154     gst_buffer_unref (buf);
5155     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5156   } else {
5157     /* this should not really happen unless the subtitle is corrupted */
5158     gst_buffer_unref (buf);
5159     buf = NULL;
5160   }
5161
5162   /* FIXME ? convert optional subsequent style info to markup */
5163
5164   return buf;
5165 }
5166
5167 /* Sets a buffer's attributes properly and pushes it downstream.
5168  * Also checks for additional actions and custom processing that may
5169  * need to be done first.
5170  */
5171 static GstFlowReturn
5172 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5173     QtDemuxStream * stream, GstBuffer * buf,
5174     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5175     gboolean keyframe, GstClockTime position, guint64 byte_position)
5176 {
5177   GstFlowReturn ret = GST_FLOW_OK;
5178
5179   /* offset the timestamps according to the edit list */
5180
5181   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5182     gchar *url;
5183     GstMapInfo map;
5184
5185     gst_buffer_map (buf, &map, GST_MAP_READ);
5186     url = g_strndup ((gchar *) map.data, map.size);
5187     gst_buffer_unmap (buf, &map);
5188     if (url != NULL && strlen (url) != 0) {
5189       /* we have RTSP redirect now */
5190       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5191           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5192               gst_structure_new ("redirect",
5193                   "new-location", G_TYPE_STRING, url, NULL)));
5194       qtdemux->posted_redirect = TRUE;
5195     } else {
5196       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5197           "posting");
5198     }
5199     g_free (url);
5200   }
5201
5202   /* position reporting */
5203   if (qtdemux->segment.rate >= 0) {
5204     qtdemux->segment.position = position;
5205     gst_qtdemux_sync_streams (qtdemux);
5206   }
5207
5208   if (G_UNLIKELY (!stream->pad)) {
5209     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5210     gst_buffer_unref (buf);
5211     goto exit;
5212   }
5213
5214   /* send out pending buffers */
5215   while (stream->buffers) {
5216     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5217
5218     if (G_UNLIKELY (stream->discont)) {
5219       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5220       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5221       stream->discont = FALSE;
5222     } else {
5223       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5224     }
5225
5226     gst_pad_push (stream->pad, buffer);
5227
5228     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5229   }
5230
5231   /* we're going to modify the metadata */
5232   buf = gst_buffer_make_writable (buf);
5233
5234   if (G_UNLIKELY (stream->need_process))
5235     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5236
5237   if (!buf) {
5238     goto exit;
5239   }
5240
5241   GST_BUFFER_DTS (buf) = dts;
5242   GST_BUFFER_PTS (buf) = pts;
5243   GST_BUFFER_DURATION (buf) = duration;
5244   GST_BUFFER_OFFSET (buf) = -1;
5245   GST_BUFFER_OFFSET_END (buf) = -1;
5246
5247   if (G_UNLIKELY (stream->rgb8_palette))
5248     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5249
5250   if (G_UNLIKELY (stream->padding)) {
5251     gst_buffer_resize (buf, stream->padding, -1);
5252   }
5253 #if 0
5254   if (G_UNLIKELY (qtdemux->element_index)) {
5255     GstClockTime stream_time;
5256
5257     stream_time =
5258         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5259         timestamp);
5260     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5261       GST_LOG_OBJECT (qtdemux,
5262           "adding association %" GST_TIME_FORMAT "-> %"
5263           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5264       gst_index_add_association (qtdemux->element_index,
5265           qtdemux->index_id,
5266           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5267           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5268           GST_FORMAT_BYTES, byte_position, NULL);
5269     }
5270   }
5271 #endif
5272
5273   if (stream->need_clip)
5274     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5275
5276   if (G_UNLIKELY (buf == NULL))
5277     goto exit;
5278
5279   if (G_UNLIKELY (stream->discont)) {
5280     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5281     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5282     stream->discont = FALSE;
5283   } else {
5284     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5285   }
5286
5287   if (!keyframe) {
5288     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5289     stream->on_keyframe = FALSE;
5290   } else {
5291     stream->on_keyframe = TRUE;
5292   }
5293
5294
5295   GST_LOG_OBJECT (qtdemux,
5296       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5297       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5298       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5299       GST_PAD_NAME (stream->pad));
5300
5301   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5302     GstStructure *crypto_info;
5303     QtDemuxCencSampleSetInfo *info =
5304         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5305     gint index;
5306     GstEvent *event;
5307
5308     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5309       gst_pad_push_event (stream->pad, event);
5310     }
5311
5312     if (qtdemux->cenc_aux_info_offset > 0 && info->crypto_info == NULL) {
5313       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5314       gst_buffer_unref (buf);
5315       goto exit;
5316     }
5317
5318     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5319     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5320       /* steal structure from array */
5321       crypto_info = g_ptr_array_index (info->crypto_info, index);
5322       g_ptr_array_index (info->crypto_info, index) = NULL;
5323       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5324       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5325         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5326     }
5327   }
5328
5329   ret = gst_pad_push (stream->pad, buf);
5330
5331   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5332     /* mark position in stream, we'll need this to know when to send GAP event */
5333     stream->segment.position = pts + duration;
5334   }
5335
5336 exit:
5337   return ret;
5338 }
5339
5340 static const QtDemuxRandomAccessEntry *
5341 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5342     GstClockTime pos, gboolean after)
5343 {
5344   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5345   guint n_entries = stream->n_ra_entries;
5346   guint i;
5347
5348   /* we assume the table is sorted */
5349   for (i = 0; i < n_entries; ++i) {
5350     if (entries[i].ts > pos)
5351       break;
5352   }
5353
5354   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5355    * probably okay to assume that the index lists the very first fragment */
5356   if (i == 0)
5357     return &entries[0];
5358
5359   if (after)
5360     return &entries[i];
5361   else
5362     return &entries[i - 1];
5363 }
5364
5365 static gboolean
5366 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5367 {
5368   const QtDemuxRandomAccessEntry *best_entry = NULL;
5369   guint i;
5370
5371   GST_OBJECT_LOCK (qtdemux);
5372
5373   g_assert (qtdemux->n_streams > 0);
5374
5375   for (i = 0; i < qtdemux->n_streams; i++) {
5376     const QtDemuxRandomAccessEntry *entry;
5377     QtDemuxStream *stream;
5378     gboolean is_audio_or_video;
5379
5380     stream = qtdemux->streams[i];
5381
5382     g_free (stream->samples);
5383     stream->samples = NULL;
5384     stream->n_samples = 0;
5385     stream->stbl_index = -1;    /* no samples have yet been parsed */
5386     stream->sample_index = -1;
5387
5388     if (stream->ra_entries == NULL)
5389       continue;
5390
5391     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5392       is_audio_or_video = TRUE;
5393     else
5394       is_audio_or_video = FALSE;
5395
5396     entry =
5397         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5398         stream->time_position, !is_audio_or_video);
5399
5400     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5401         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5402
5403     stream->pending_seek = entry;
5404
5405     /* decide position to jump to just based on audio/video tracks, not subs */
5406     if (!is_audio_or_video)
5407       continue;
5408
5409     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5410       best_entry = entry;
5411   }
5412
5413   if (best_entry == NULL) {
5414     GST_OBJECT_UNLOCK (qtdemux);
5415     return FALSE;
5416   }
5417
5418   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5419       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5420       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5421       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5422
5423   qtdemux->moof_offset = best_entry->moof_offset;
5424
5425   qtdemux_add_fragmented_samples (qtdemux);
5426
5427   GST_OBJECT_UNLOCK (qtdemux);
5428   return TRUE;
5429 }
5430
5431 static GstFlowReturn
5432 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5433 {
5434   GstFlowReturn ret = GST_FLOW_OK;
5435   GstBuffer *buf = NULL;
5436   QtDemuxStream *stream;
5437   GstClockTime min_time;
5438   guint64 offset = 0;
5439   GstClockTime dts = GST_CLOCK_TIME_NONE;
5440   GstClockTime pts = GST_CLOCK_TIME_NONE;
5441   GstClockTime duration = 0;
5442   gboolean keyframe = FALSE;
5443   guint sample_size = 0;
5444   gboolean empty = 0;
5445   guint size;
5446   gint index;
5447   gint i;
5448
5449   gst_qtdemux_push_pending_newsegment (qtdemux);
5450
5451   if (qtdemux->fragmented_seek_pending) {
5452     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5453     gst_qtdemux_do_fragmented_seek (qtdemux);
5454     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5455     qtdemux->fragmented_seek_pending = FALSE;
5456   }
5457
5458   /* Figure out the next stream sample to output, min_time is expressed in
5459    * global time and runs over the edit list segments. */
5460   min_time = G_MAXUINT64;
5461   index = -1;
5462   for (i = 0; i < qtdemux->n_streams; i++) {
5463     GstClockTime position;
5464
5465     stream = qtdemux->streams[i];
5466     position = stream->time_position;
5467
5468     /* position of -1 is EOS */
5469     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5470       min_time = position;
5471       index = i;
5472     }
5473   }
5474   /* all are EOS */
5475   if (G_UNLIKELY (index == -1)) {
5476     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5477     goto eos;
5478   }
5479
5480   /* check for segment end */
5481   if (G_UNLIKELY (qtdemux->segment.stop != -1
5482           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5483               || (qtdemux->segment.rate < 0
5484                   && qtdemux->segment.start > min_time))
5485           && qtdemux->streams[index]->on_keyframe)) {
5486     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5487     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5488     goto eos_stream;
5489   }
5490
5491   /* gap events for subtitle streams */
5492   for (i = 0; i < qtdemux->n_streams; i++) {
5493     stream = qtdemux->streams[i];
5494     if (stream->pad && (stream->subtype == FOURCC_subp
5495             || stream->subtype == FOURCC_text
5496             || stream->subtype == FOURCC_sbtl)) {
5497       /* send one second gap events until the stream catches up */
5498       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5499       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5500           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5501           stream->segment.position + GST_SECOND < min_time) {
5502         GstEvent *gap =
5503             gst_event_new_gap (stream->segment.position, GST_SECOND);
5504         gst_pad_push_event (stream->pad, gap);
5505         stream->segment.position += GST_SECOND;
5506       }
5507     }
5508   }
5509
5510   stream = qtdemux->streams[index];
5511   if (stream->new_caps) {
5512     gst_qtdemux_configure_stream (qtdemux, stream);
5513     qtdemux_do_allocation (qtdemux, stream);
5514   }
5515
5516   /* fetch info for the current sample of this stream */
5517   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5518               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5519     goto eos_stream;
5520
5521   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5522   if (G_UNLIKELY (qtdemux->
5523           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5524     if (stream->subtype == FOURCC_vide && !keyframe) {
5525       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5526       goto next;
5527     }
5528   }
5529
5530   GST_DEBUG_OBJECT (qtdemux,
5531       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5532       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5533       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5534       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5535
5536   if (G_UNLIKELY (empty)) {
5537     /* empty segment, push a gap and move to the next one */
5538     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5539     stream->segment.position = pts + duration;
5540     goto next;
5541   }
5542
5543   /* hmm, empty sample, skip and move to next sample */
5544   if (G_UNLIKELY (sample_size <= 0))
5545     goto next;
5546
5547   /* last pushed sample was out of boundary, goto next sample */
5548   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5549     goto next;
5550
5551   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5552     size = sample_size;
5553   } else {
5554     GST_DEBUG_OBJECT (qtdemux,
5555         "size %d larger than stream max_buffer_size %d, trimming",
5556         sample_size, stream->max_buffer_size);
5557     size =
5558         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5559   }
5560
5561   if (qtdemux->cenc_aux_info_offset > 0) {
5562     GstMapInfo map;
5563     GstByteReader br;
5564     GstBuffer *aux_info = NULL;
5565
5566     /* pull the data stored before the sample */
5567     ret =
5568         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5569         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5570     if (G_UNLIKELY (ret != GST_FLOW_OK))
5571       goto beach;
5572     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5573     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5574     gst_byte_reader_init (&br, map.data + 8, map.size);
5575     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5576             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5577       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5578       gst_buffer_unmap (aux_info, &map);
5579       gst_buffer_unref (aux_info);
5580       ret = GST_FLOW_ERROR;
5581       goto beach;
5582     }
5583     gst_buffer_unmap (aux_info, &map);
5584     gst_buffer_unref (aux_info);
5585   }
5586
5587   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5588       offset);
5589
5590   if (stream->use_allocator) {
5591     /* if we have a per-stream allocator, use it */
5592     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5593   }
5594
5595   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5596       size, &buf);
5597   if (G_UNLIKELY (ret != GST_FLOW_OK))
5598     goto beach;
5599
5600   if (size != sample_size) {
5601     pts += gst_util_uint64_scale_int (GST_SECOND,
5602         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5603     dts += gst_util_uint64_scale_int (GST_SECOND,
5604         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5605     duration = gst_util_uint64_scale_int (GST_SECOND,
5606         size / stream->bytes_per_frame, stream->timescale);
5607   }
5608
5609   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5610       dts, pts, duration, keyframe, min_time, offset);
5611
5612   if (size != sample_size) {
5613     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5614     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5615
5616     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5617         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5618     if (time_position >= segment->media_start) {
5619       /* inside the segment, update time_position, looks very familiar to
5620        * GStreamer segments, doesn't it? */
5621       stream->time_position = (time_position - segment->media_start) +
5622           segment->time;
5623     } else {
5624       /* not yet in segment, time does not yet increment. This means
5625        * that we are still prerolling keyframes to the decoder so it can
5626        * decode the first sample of the segment. */
5627       stream->time_position = segment->time;
5628     }
5629   }
5630
5631   /* combine flows */
5632   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5633   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5634    * we have no more data for the pad to push */
5635   if (ret == GST_FLOW_EOS)
5636     ret = GST_FLOW_OK;
5637
5638   stream->offset_in_sample += size;
5639   if (stream->offset_in_sample >= sample_size) {
5640     gst_qtdemux_advance_sample (qtdemux, stream);
5641   }
5642   goto beach;
5643
5644 next:
5645   gst_qtdemux_advance_sample (qtdemux, stream);
5646
5647 beach:
5648   return ret;
5649
5650   /* special cases */
5651 eos:
5652   {
5653     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5654     ret = GST_FLOW_EOS;
5655     goto beach;
5656   }
5657 eos_stream:
5658   {
5659     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5660     /* EOS will be raised if all are EOS */
5661     ret = GST_FLOW_OK;
5662     goto beach;
5663   }
5664 }
5665
5666 static void
5667 gst_qtdemux_loop (GstPad * pad)
5668 {
5669   GstQTDemux *qtdemux;
5670   guint64 cur_offset;
5671   GstFlowReturn ret;
5672
5673   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5674
5675   cur_offset = qtdemux->offset;
5676   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5677       cur_offset, qt_demux_state_string (qtdemux->state));
5678
5679   switch (qtdemux->state) {
5680     case QTDEMUX_STATE_INITIAL:
5681     case QTDEMUX_STATE_HEADER:
5682       ret = gst_qtdemux_loop_state_header (qtdemux);
5683       break;
5684     case QTDEMUX_STATE_MOVIE:
5685       ret = gst_qtdemux_loop_state_movie (qtdemux);
5686       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5687         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5688       }
5689       break;
5690     default:
5691       /* ouch */
5692       goto invalid_state;
5693   }
5694
5695   /* if something went wrong, pause */
5696   if (ret != GST_FLOW_OK)
5697     goto pause;
5698
5699 done:
5700   gst_object_unref (qtdemux);
5701   return;
5702
5703   /* ERRORS */
5704 invalid_state:
5705   {
5706     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5707         (NULL), ("streaming stopped, invalid state"));
5708     gst_pad_pause_task (pad);
5709     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5710     goto done;
5711   }
5712 pause:
5713   {
5714     const gchar *reason = gst_flow_get_name (ret);
5715
5716     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5717
5718     gst_pad_pause_task (pad);
5719
5720     /* fatal errors need special actions */
5721     /* check EOS */
5722     if (ret == GST_FLOW_EOS) {
5723       if (qtdemux->n_streams == 0) {
5724         /* we have no streams, post an error */
5725         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5726       }
5727       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5728         gint64 stop;
5729
5730         if ((stop = qtdemux->segment.stop) == -1)
5731           stop = qtdemux->segment.duration;
5732
5733         if (qtdemux->segment.rate >= 0) {
5734           GstMessage *message;
5735           GstEvent *event;
5736
5737           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5738           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5739               GST_FORMAT_TIME, stop);
5740           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5741           if (qtdemux->segment_seqnum) {
5742             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5743             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5744           }
5745           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5746           gst_qtdemux_push_event (qtdemux, event);
5747         } else {
5748           GstMessage *message;
5749           GstEvent *event;
5750
5751           /*  For Reverse Playback */
5752           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5753           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5754               GST_FORMAT_TIME, qtdemux->segment.start);
5755           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5756               qtdemux->segment.start);
5757           if (qtdemux->segment_seqnum) {
5758             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5759             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5760           }
5761           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5762           gst_qtdemux_push_event (qtdemux, event);
5763         }
5764       } else {
5765         GstEvent *event;
5766
5767         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5768         event = gst_event_new_eos ();
5769         if (qtdemux->segment_seqnum)
5770           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5771         gst_qtdemux_push_event (qtdemux, event);
5772       }
5773     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5774       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5775           (NULL), ("streaming stopped, reason %s", reason));
5776       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5777     }
5778     goto done;
5779   }
5780 }
5781
5782 /*
5783  * has_next_entry
5784  *
5785  * Returns if there are samples to be played.
5786  */
5787 static gboolean
5788 has_next_entry (GstQTDemux * demux)
5789 {
5790   QtDemuxStream *stream;
5791   int i;
5792
5793   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5794
5795   for (i = 0; i < demux->n_streams; i++) {
5796     stream = demux->streams[i];
5797
5798     if (stream->sample_index == -1) {
5799       stream->sample_index = 0;
5800       stream->offset_in_sample = 0;
5801     }
5802
5803     if (stream->sample_index >= stream->n_samples) {
5804       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5805       continue;
5806     }
5807     GST_DEBUG_OBJECT (demux, "Found a sample");
5808     return TRUE;
5809   }
5810
5811   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5812   return FALSE;
5813 }
5814
5815 /*
5816  * next_entry_size
5817  *
5818  * Returns the size of the first entry at the current offset.
5819  * If -1, there are none (which means EOS or empty file).
5820  */
5821 static guint64
5822 next_entry_size (GstQTDemux * demux)
5823 {
5824   QtDemuxStream *stream;
5825   int i;
5826   int smallidx = -1;
5827   guint64 smalloffs = (guint64) - 1;
5828   QtDemuxSample *sample;
5829
5830   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5831       demux->offset);
5832
5833   for (i = 0; i < demux->n_streams; i++) {
5834     stream = demux->streams[i];
5835
5836     if (stream->sample_index == -1) {
5837       stream->sample_index = 0;
5838       stream->offset_in_sample = 0;
5839     }
5840
5841     if (stream->sample_index >= stream->n_samples) {
5842       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5843       continue;
5844     }
5845
5846     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5847       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5848           stream->sample_index);
5849       return -1;
5850     }
5851
5852     sample = &stream->samples[stream->sample_index];
5853
5854     GST_LOG_OBJECT (demux,
5855         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5856         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5857         sample->offset, sample->size);
5858
5859     if (((smalloffs == -1)
5860             || (sample->offset < smalloffs)) && (sample->size)) {
5861       smallidx = i;
5862       smalloffs = sample->offset;
5863     }
5864   }
5865
5866   GST_LOG_OBJECT (demux,
5867       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5868       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5869
5870   if (smallidx == -1)
5871     return -1;
5872
5873   stream = demux->streams[smallidx];
5874   sample = &stream->samples[stream->sample_index];
5875
5876   if (sample->offset >= demux->offset) {
5877     demux->todrop = sample->offset - demux->offset;
5878     return sample->size + demux->todrop;
5879   }
5880
5881   GST_DEBUG_OBJECT (demux,
5882       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5883   return -1;
5884 }
5885
5886 static void
5887 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5888 {
5889   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5890
5891   gst_element_post_message (GST_ELEMENT_CAST (demux),
5892       gst_message_new_element (GST_OBJECT_CAST (demux),
5893           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5894 }
5895
5896 static gboolean
5897 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5898 {
5899   GstEvent *event;
5900   gboolean res = 0;
5901
5902   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5903
5904   event =
5905       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5906       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5907       GST_SEEK_TYPE_NONE, -1);
5908
5909   /* store seqnum to drop flush events, they don't need to reach downstream */
5910   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5911   res = gst_pad_push_event (demux->sinkpad, event);
5912   demux->offset_seek_seqnum = 0;
5913
5914   return res;
5915 }
5916
5917 /* check for seekable upstream, above and beyond a mere query */
5918 static void
5919 gst_qtdemux_check_seekability (GstQTDemux * demux)
5920 {
5921   GstQuery *query;
5922   gboolean seekable = FALSE;
5923   gint64 start = -1, stop = -1;
5924
5925   if (demux->upstream_size)
5926     return;
5927
5928   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5929   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5930     GST_DEBUG_OBJECT (demux, "seeking query failed");
5931     goto done;
5932   }
5933
5934   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5935
5936   /* try harder to query upstream size if we didn't get it the first time */
5937   if (seekable && stop == -1) {
5938     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5939     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5940   }
5941
5942   /* if upstream doesn't know the size, it's likely that it's not seekable in
5943    * practice even if it technically may be seekable */
5944   if (seekable && (start != 0 || stop <= start)) {
5945     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5946     seekable = FALSE;
5947   }
5948
5949 done:
5950   gst_query_unref (query);
5951
5952   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5953       G_GUINT64_FORMAT ")", seekable, start, stop);
5954   demux->upstream_seekable = seekable;
5955   demux->upstream_size = seekable ? stop : -1;
5956 }
5957
5958 static void
5959 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5960 {
5961   g_return_if_fail (bytes <= demux->todrop);
5962
5963   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5964   gst_adapter_flush (demux->adapter, bytes);
5965   demux->neededbytes -= bytes;
5966   demux->offset += bytes;
5967   demux->todrop -= bytes;
5968 }
5969
5970 static void
5971 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5972 {
5973   if (G_UNLIKELY (demux->pending_newsegment)) {
5974     gint i;
5975
5976     gst_qtdemux_push_pending_newsegment (demux);
5977     /* clear to send tags on all streams */
5978     for (i = 0; i < demux->n_streams; i++) {
5979       QtDemuxStream *stream;
5980       stream = demux->streams[i];
5981       gst_qtdemux_push_tags (demux, stream);
5982       if (stream->sparse) {
5983         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5984         gst_pad_push_event (stream->pad,
5985             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5986       }
5987     }
5988   }
5989 }
5990
5991 static void
5992 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
5993     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
5994 {
5995   GstClockTime ts, dur;
5996   GstEvent *gap;
5997
5998   ts = pos;
5999   dur =
6000       stream->segments[segment_index].duration - (pos -
6001       stream->segments[segment_index].time);
6002   gap = gst_event_new_gap (ts, dur);
6003   stream->time_position += dur;
6004
6005   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6006       "segment: %" GST_PTR_FORMAT, gap);
6007   gst_pad_push_event (stream->pad, gap);
6008 }
6009
6010 static void
6011 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6012     QtDemuxStream * stream)
6013 {
6014   gint i;
6015
6016   /* Push any initial gap segments before proceeding to the
6017    * 'real' data */
6018   for (i = 0; i < stream->n_segments; i++) {
6019     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6020
6021     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6022       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6023           stream->time_position);
6024     } else {
6025       /* Only support empty segment at the beginning followed by
6026        * one non-empty segment, this was checked when parsing the
6027        * edts atom, arriving here is unexpected */
6028       g_assert (i + 1 == stream->n_segments);
6029       break;
6030     }
6031   }
6032 }
6033
6034 static GstFlowReturn
6035 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6036 {
6037   GstQTDemux *demux;
6038
6039   demux = GST_QTDEMUX (parent);
6040
6041   GST_DEBUG_OBJECT (demux,
6042       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6043       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6044       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6045       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6046       gst_buffer_get_size (inbuf), demux->offset);
6047
6048   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6049     gboolean is_gap_input = FALSE;
6050     gint i;
6051
6052     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6053
6054     for (i = 0; i < demux->n_streams; i++) {
6055       demux->streams[i]->discont = TRUE;
6056     }
6057
6058     /* Check if we can land back on our feet in the case where upstream is
6059      * handling the seeking/pushing of samples with gaps in between (like
6060      * in the case of trick-mode DASH for example) */
6061     if (demux->upstream_format_is_time
6062         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6063       gint i;
6064       for (i = 0; i < demux->n_streams; i++) {
6065         guint32 res;
6066         GST_LOG_OBJECT (demux,
6067             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6068             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6069         res =
6070             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6071             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6072         if (res != -1) {
6073           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6074           GST_LOG_OBJECT (demux,
6075               "Checking if sample %d from stream %d is valid (offset:%"
6076               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6077               sample->offset, sample->size);
6078           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6079             GST_LOG_OBJECT (demux,
6080                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6081                 res);
6082             is_gap_input = TRUE;
6083             /* We can go back to standard playback mode */
6084             demux->state = QTDEMUX_STATE_MOVIE;
6085             /* Remember which sample this stream is at */
6086             demux->streams[i]->sample_index = res;
6087             /* Finally update all push-based values to the expected values */
6088             demux->neededbytes = demux->streams[i]->samples[res].size;
6089             demux->todrop = 0;
6090             demux->offset = GST_BUFFER_OFFSET (inbuf);
6091           }
6092         }
6093       }
6094       if (!is_gap_input) {
6095         /* Reset state if it's a real discont */
6096         demux->neededbytes = 16;
6097         demux->state = QTDEMUX_STATE_INITIAL;
6098       }
6099     }
6100     /* Reverse fragmented playback, need to flush all we have before
6101      * consuming a new fragment.
6102      * The samples array have the timestamps calculated by accumulating the
6103      * durations but this won't work for reverse playback of fragments as
6104      * the timestamps of a subsequent fragment should be smaller than the
6105      * previously received one. */
6106     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6107       gst_qtdemux_process_adapter (demux, TRUE);
6108       for (i = 0; i < demux->n_streams; i++)
6109         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6110     }
6111   }
6112
6113   gst_adapter_push (demux->adapter, inbuf);
6114
6115   GST_DEBUG_OBJECT (demux,
6116       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6117       demux->neededbytes, gst_adapter_available (demux->adapter));
6118
6119   return gst_qtdemux_process_adapter (demux, FALSE);
6120 }
6121
6122 static GstFlowReturn
6123 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6124 {
6125   GstFlowReturn ret = GST_FLOW_OK;
6126
6127   /* we never really mean to buffer that much */
6128   if (demux->neededbytes == -1) {
6129     goto eos;
6130   }
6131
6132   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6133       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6134
6135 #ifndef GST_DISABLE_GST_DEBUG
6136     {
6137       guint64 discont_offset, distance_from_discont;
6138
6139       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6140       distance_from_discont =
6141           gst_adapter_distance_from_discont (demux->adapter);
6142
6143       GST_DEBUG_OBJECT (demux,
6144           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6145           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6146           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6147           demux->offset, discont_offset, distance_from_discont);
6148     }
6149 #endif
6150
6151     switch (demux->state) {
6152       case QTDEMUX_STATE_INITIAL:{
6153         const guint8 *data;
6154         guint32 fourcc;
6155         guint64 size;
6156
6157         gst_qtdemux_check_seekability (demux);
6158
6159         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6160
6161         /* get fourcc/length, set neededbytes */
6162         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6163             &size, &fourcc);
6164         gst_adapter_unmap (demux->adapter);
6165         data = NULL;
6166         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6167             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6168         if (size == 0) {
6169           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6170               (_("This file is invalid and cannot be played.")),
6171               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6172                   GST_FOURCC_ARGS (fourcc)));
6173           ret = GST_FLOW_ERROR;
6174           break;
6175         }
6176         if (fourcc == FOURCC_mdat) {
6177           gint next_entry = next_entry_size (demux);
6178           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6179             /* we have the headers, start playback */
6180             demux->state = QTDEMUX_STATE_MOVIE;
6181             demux->neededbytes = next_entry;
6182             demux->mdatleft = size;
6183           } else {
6184             /* no headers yet, try to get them */
6185             guint bs;
6186             gboolean res;
6187             guint64 old, target;
6188
6189           buffer_data:
6190             old = demux->offset;
6191             target = old + size;
6192
6193             /* try to jump over the atom with a seek */
6194             /* only bother if it seems worth doing so,
6195              * and avoids possible upstream/server problems */
6196             if (demux->upstream_seekable &&
6197                 demux->upstream_size > 4 * (1 << 20)) {
6198               res = qtdemux_seek_offset (demux, target);
6199             } else {
6200               GST_DEBUG_OBJECT (demux, "skipping seek");
6201               res = FALSE;
6202             }
6203
6204             if (res) {
6205               GST_DEBUG_OBJECT (demux, "seek success");
6206               /* remember the offset fo the first mdat so we can seek back to it
6207                * after we have the headers */
6208               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6209                 demux->first_mdat = old;
6210                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6211                     demux->first_mdat);
6212               }
6213               /* seek worked, continue reading */
6214               demux->offset = target;
6215               demux->neededbytes = 16;
6216               demux->state = QTDEMUX_STATE_INITIAL;
6217             } else {
6218               /* seek failed, need to buffer */
6219               demux->offset = old;
6220               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6221               /* there may be multiple mdat (or alike) buffers */
6222               /* sanity check */
6223               if (demux->mdatbuffer)
6224                 bs = gst_buffer_get_size (demux->mdatbuffer);
6225               else
6226                 bs = 0;
6227               if (size + bs > 10 * (1 << 20))
6228                 goto no_moov;
6229               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6230               demux->neededbytes = size;
6231               if (!demux->mdatbuffer)
6232                 demux->mdatoffset = demux->offset;
6233             }
6234           }
6235         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6236           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6237               (_("This file is invalid and cannot be played.")),
6238               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6239                   GST_FOURCC_ARGS (fourcc), size));
6240           ret = GST_FLOW_ERROR;
6241           break;
6242         } else {
6243           /* this means we already started buffering and still no moov header,
6244            * let's continue buffering everything till we get moov */
6245           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6246                   || fourcc == FOURCC_moof))
6247             goto buffer_data;
6248           demux->neededbytes = size;
6249           demux->state = QTDEMUX_STATE_HEADER;
6250         }
6251         break;
6252       }
6253       case QTDEMUX_STATE_HEADER:{
6254         const guint8 *data;
6255         guint32 fourcc;
6256
6257         GST_DEBUG_OBJECT (demux, "In header");
6258
6259         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6260
6261         /* parse the header */
6262         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6263             &fourcc);
6264         if (fourcc == FOURCC_moov) {
6265           gint n;
6266
6267           /* in usual fragmented setup we could try to scan for more
6268            * and end up at the the moov (after mdat) again */
6269           if (demux->got_moov && demux->n_streams > 0 &&
6270               (!demux->fragmented
6271                   || demux->last_moov_offset == demux->offset)) {
6272             GST_DEBUG_OBJECT (demux,
6273                 "Skipping moov atom as we have (this) one already");
6274           } else {
6275             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6276
6277             if (demux->got_moov && demux->fragmented) {
6278               GST_DEBUG_OBJECT (demux,
6279                   "Got a second moov, clean up data from old one");
6280               if (demux->moov_node)
6281                 g_node_destroy (demux->moov_node);
6282               demux->moov_node = NULL;
6283               demux->moov_node_compressed = NULL;
6284             } else {
6285               /* prepare newsegment to send when streaming actually starts */
6286               if (!demux->pending_newsegment) {
6287                 demux->pending_newsegment =
6288                     gst_event_new_segment (&demux->segment);
6289                 if (demux->segment_seqnum)
6290                   gst_event_set_seqnum (demux->pending_newsegment,
6291                       demux->segment_seqnum);
6292               }
6293             }
6294
6295             demux->last_moov_offset = demux->offset;
6296
6297             qtdemux_parse_moov (demux, data, demux->neededbytes);
6298             qtdemux_node_dump (demux, demux->moov_node);
6299             qtdemux_parse_tree (demux);
6300             qtdemux_prepare_streams (demux);
6301             if (!demux->got_moov)
6302               qtdemux_expose_streams (demux);
6303             else {
6304
6305               for (n = 0; n < demux->n_streams; n++) {
6306                 QtDemuxStream *stream = demux->streams[n];
6307
6308                 gst_qtdemux_configure_stream (demux, stream);
6309               }
6310             }
6311
6312             demux->got_moov = TRUE;
6313             gst_qtdemux_check_send_pending_segment (demux);
6314
6315             /* fragmented streams headers shouldn't contain edts atoms */
6316             if (!demux->fragmented) {
6317               for (n = 0; n < demux->n_streams; n++) {
6318                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6319                     demux->streams[n]);
6320               }
6321             }
6322
6323             g_node_destroy (demux->moov_node);
6324             demux->moov_node = NULL;
6325             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6326           }
6327         } else if (fourcc == FOURCC_moof) {
6328           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6329             guint64 dist = 0;
6330             GstClockTime prev_pts;
6331             guint64 prev_offset;
6332             guint64 adapter_discont_offset, adapter_discont_dist;
6333
6334             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6335
6336             /*
6337              * The timestamp of the moof buffer is relevant as some scenarios
6338              * won't have the initial timestamp in the atoms. Whenever a new
6339              * buffer has started, we get that buffer's PTS and use it as a base
6340              * timestamp for the trun entries.
6341              *
6342              * To keep track of the current buffer timestamp and starting point
6343              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6344              * from the beggining of the buffer, with the distance and demux->offset
6345              * we know if it is still the same buffer or not.
6346              */
6347             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6348             prev_offset = demux->offset - dist;
6349             if (demux->fragment_start_offset == -1
6350                 || prev_offset > demux->fragment_start_offset) {
6351               demux->fragment_start_offset = prev_offset;
6352               demux->fragment_start = prev_pts;
6353               GST_DEBUG_OBJECT (demux,
6354                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6355                   GST_TIME_FORMAT, demux->fragment_start_offset,
6356                   GST_TIME_ARGS (demux->fragment_start));
6357             }
6358
6359             /* We can't use prev_offset() here because this would require
6360              * upstream to set consistent and correct offsets on all buffers
6361              * since the discont. Nothing ever did that in the past and we
6362              * would break backwards compatibility here then.
6363              * Instead take the offset we had at the last discont and count
6364              * the bytes from there. This works with old code as there would
6365              * be no discont between moov and moof, and also works with
6366              * adaptivedemux which correctly sets offset and will set the
6367              * DISCONT flag accordingly when needed.
6368              *
6369              * We also only do this for upstream TIME segments as otherwise
6370              * there are potential backwards compatibility problems with
6371              * seeking in PUSH mode and upstream providing inconsistent
6372              * timestamps. */
6373             adapter_discont_offset =
6374                 gst_adapter_offset_at_discont (demux->adapter);
6375             adapter_discont_dist =
6376                 gst_adapter_distance_from_discont (demux->adapter);
6377
6378             GST_DEBUG_OBJECT (demux,
6379                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6380                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6381                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6382
6383             if (demux->upstream_format_is_time) {
6384               demux->moof_offset = adapter_discont_offset;
6385               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6386                 demux->moof_offset += adapter_discont_dist;
6387               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6388                 demux->moof_offset = demux->offset;
6389             } else {
6390               demux->moof_offset = demux->offset;
6391             }
6392
6393             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6394                     demux->moof_offset, NULL)) {
6395               gst_adapter_unmap (demux->adapter);
6396               ret = GST_FLOW_ERROR;
6397               goto done;
6398             }
6399             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6400             if (demux->mss_mode && !demux->exposed) {
6401               if (!demux->pending_newsegment) {
6402                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6403                 demux->pending_newsegment =
6404                     gst_event_new_segment (&demux->segment);
6405                 if (demux->segment_seqnum)
6406                   gst_event_set_seqnum (demux->pending_newsegment,
6407                       demux->segment_seqnum);
6408               }
6409               qtdemux_expose_streams (demux);
6410             }
6411           } else {
6412             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6413           }
6414         } else if (fourcc == FOURCC_ftyp) {
6415           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6416           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6417         } else if (fourcc == FOURCC_uuid) {
6418           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6419           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6420         } else if (fourcc == FOURCC_sidx) {
6421           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6422           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6423         } else {
6424           GST_WARNING_OBJECT (demux,
6425               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6426               GST_FOURCC_ARGS (fourcc));
6427           /* Let's jump that one and go back to initial state */
6428         }
6429         gst_adapter_unmap (demux->adapter);
6430         data = NULL;
6431
6432         if (demux->mdatbuffer && demux->n_streams) {
6433           gsize remaining_data_size = 0;
6434
6435           /* the mdat was before the header */
6436           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6437               demux->n_streams, demux->mdatbuffer);
6438           /* restore our adapter/offset view of things with upstream;
6439            * put preceding buffered data ahead of current moov data.
6440            * This should also handle evil mdat, moov, mdat cases and alike */
6441           gst_adapter_flush (demux->adapter, demux->neededbytes);
6442
6443           /* Store any remaining data after the mdat for later usage */
6444           remaining_data_size = gst_adapter_available (demux->adapter);
6445           if (remaining_data_size > 0) {
6446             g_assert (demux->restoredata_buffer == NULL);
6447             demux->restoredata_buffer =
6448                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6449             demux->restoredata_offset = demux->offset + demux->neededbytes;
6450             GST_DEBUG_OBJECT (demux,
6451                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6452                 G_GUINT64_FORMAT, remaining_data_size,
6453                 demux->restoredata_offset);
6454           }
6455
6456           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6457           demux->mdatbuffer = NULL;
6458           demux->offset = demux->mdatoffset;
6459           demux->neededbytes = next_entry_size (demux);
6460           demux->state = QTDEMUX_STATE_MOVIE;
6461           demux->mdatleft = gst_adapter_available (demux->adapter);
6462         } else {
6463           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6464           gst_adapter_flush (demux->adapter, demux->neededbytes);
6465
6466           /* only go back to the mdat if there are samples to play */
6467           if (demux->got_moov && demux->first_mdat != -1
6468               && has_next_entry (demux)) {
6469             gboolean res;
6470
6471             /* we need to seek back */
6472             res = qtdemux_seek_offset (demux, demux->first_mdat);
6473             if (res) {
6474               demux->offset = demux->first_mdat;
6475             } else {
6476               GST_DEBUG_OBJECT (demux, "Seek back failed");
6477             }
6478           } else {
6479             demux->offset += demux->neededbytes;
6480           }
6481           demux->neededbytes = 16;
6482           demux->state = QTDEMUX_STATE_INITIAL;
6483         }
6484
6485         break;
6486       }
6487       case QTDEMUX_STATE_BUFFER_MDAT:{
6488         GstBuffer *buf;
6489         guint8 fourcc[4];
6490
6491         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6492             demux->offset);
6493         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6494         gst_buffer_extract (buf, 0, fourcc, 4);
6495         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6496             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6497         if (demux->mdatbuffer)
6498           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6499         else
6500           demux->mdatbuffer = buf;
6501         demux->offset += demux->neededbytes;
6502         demux->neededbytes = 16;
6503         demux->state = QTDEMUX_STATE_INITIAL;
6504         gst_qtdemux_post_progress (demux, 1, 1);
6505
6506         break;
6507       }
6508       case QTDEMUX_STATE_MOVIE:{
6509         QtDemuxStream *stream = NULL;
6510         QtDemuxSample *sample;
6511         int i = -1;
6512         GstClockTime dts, pts, duration;
6513         gboolean keyframe;
6514
6515         GST_DEBUG_OBJECT (demux,
6516             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6517
6518         if (demux->fragmented) {
6519           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6520               demux->mdatleft);
6521           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6522             /* if needed data starts within this atom,
6523              * then it should not exceed this atom */
6524             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6525               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6526                   (_("This file is invalid and cannot be played.")),
6527                   ("sample data crosses atom boundary"));
6528               ret = GST_FLOW_ERROR;
6529               break;
6530             }
6531             demux->mdatleft -= demux->neededbytes;
6532           } else {
6533             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6534             /* so we are dropping more than left in this atom */
6535             gst_qtdemux_drop_data (demux, demux->mdatleft);
6536             demux->mdatleft = 0;
6537
6538             /* need to resume atom parsing so we do not miss any other pieces */
6539             demux->state = QTDEMUX_STATE_INITIAL;
6540             demux->neededbytes = 16;
6541
6542             /* check if there was any stored post mdat data from previous buffers */
6543             if (demux->restoredata_buffer) {
6544               g_assert (gst_adapter_available (demux->adapter) == 0);
6545
6546               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6547               demux->restoredata_buffer = NULL;
6548               demux->offset = demux->restoredata_offset;
6549             }
6550
6551             break;
6552           }
6553         }
6554
6555         if (demux->todrop) {
6556           if (demux->cenc_aux_info_offset > 0) {
6557             GstByteReader br;
6558             const guint8 *data;
6559
6560             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6561             data = gst_adapter_map (demux->adapter, demux->todrop);
6562             gst_byte_reader_init (&br, data + 8, demux->todrop);
6563             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6564                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6565               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6566               ret = GST_FLOW_ERROR;
6567               gst_adapter_unmap (demux->adapter);
6568               g_free (demux->cenc_aux_info_sizes);
6569               demux->cenc_aux_info_sizes = NULL;
6570               goto done;
6571             }
6572             demux->cenc_aux_info_offset = 0;
6573             g_free (demux->cenc_aux_info_sizes);
6574             demux->cenc_aux_info_sizes = NULL;
6575             gst_adapter_unmap (demux->adapter);
6576           }
6577           gst_qtdemux_drop_data (demux, demux->todrop);
6578         }
6579
6580         /* first buffer? */
6581         /* initial newsegment sent here after having added pads,
6582          * possible others in sink_event */
6583         gst_qtdemux_check_send_pending_segment (demux);
6584
6585         /* Figure out which stream this packet belongs to */
6586         for (i = 0; i < demux->n_streams; i++) {
6587           stream = demux->streams[i];
6588           if (stream->sample_index >= stream->n_samples)
6589             continue;
6590           GST_LOG_OBJECT (demux,
6591               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6592               " / size:%d)", i, stream->sample_index,
6593               stream->samples[stream->sample_index].offset,
6594               stream->samples[stream->sample_index].size);
6595
6596           if (stream->samples[stream->sample_index].offset == demux->offset)
6597             break;
6598         }
6599
6600         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6601           goto unknown_stream;
6602
6603         if (stream->new_caps) {
6604           gst_qtdemux_configure_stream (demux, stream);
6605         }
6606
6607         /* Put data in a buffer, set timestamps, caps, ... */
6608         sample = &stream->samples[stream->sample_index];
6609
6610         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6611           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6612               GST_FOURCC_ARGS (stream->fourcc));
6613
6614           dts = QTSAMPLE_DTS (stream, sample);
6615           pts = QTSAMPLE_PTS (stream, sample);
6616           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6617           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6618
6619           /* check for segment end */
6620           if (G_UNLIKELY (demux->segment.stop != -1
6621                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6622             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6623             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6624
6625             /* skip this data, stream is EOS */
6626             gst_adapter_flush (demux->adapter, demux->neededbytes);
6627
6628             /* check if all streams are eos */
6629             ret = GST_FLOW_EOS;
6630             for (i = 0; i < demux->n_streams; i++) {
6631               if (!STREAM_IS_EOS (demux->streams[i])) {
6632                 ret = GST_FLOW_OK;
6633                 break;
6634               }
6635             }
6636
6637             if (ret == GST_FLOW_EOS) {
6638               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6639               goto eos;
6640             }
6641           } else {
6642             GstBuffer *outbuf;
6643
6644             outbuf =
6645                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6646
6647             /* FIXME: should either be an assert or a plain check */
6648             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6649
6650             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6651                 dts, pts, duration, keyframe, dts, demux->offset);
6652           }
6653
6654           /* combine flows */
6655           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6656           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6657             goto non_ok_unlinked_flow;
6658         } else {
6659           /* skip this data, stream is EOS */
6660           gst_adapter_flush (demux->adapter, demux->neededbytes);
6661         }
6662
6663         stream->sample_index++;
6664         stream->offset_in_sample = 0;
6665
6666         /* update current offset and figure out size of next buffer */
6667         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6668             demux->offset, demux->neededbytes);
6669         demux->offset += demux->neededbytes;
6670         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6671             demux->offset);
6672
6673         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6674           if (demux->fragmented) {
6675             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6676             /* there may be more to follow, only finish this atom */
6677             demux->todrop = demux->mdatleft;
6678             demux->neededbytes = demux->todrop;
6679             break;
6680           }
6681           goto eos;
6682         }
6683         break;
6684       }
6685       default:
6686         goto invalid_state;
6687     }
6688   }
6689
6690   /* when buffering movie data, at least show user something is happening */
6691   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6692       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6693     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6694         demux->neededbytes);
6695   }
6696 done:
6697
6698   return ret;
6699
6700   /* ERRORS */
6701 non_ok_unlinked_flow:
6702   {
6703     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6704         gst_flow_get_name (ret));
6705     return ret;
6706   }
6707 unknown_stream:
6708   {
6709     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6710     ret = GST_FLOW_ERROR;
6711     goto done;
6712   }
6713 eos:
6714   {
6715     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6716     ret = GST_FLOW_EOS;
6717     goto done;
6718   }
6719 invalid_state:
6720   {
6721     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6722         (NULL), ("qtdemuxer invalid state %d", demux->state));
6723     ret = GST_FLOW_ERROR;
6724     goto done;
6725   }
6726 no_moov:
6727   {
6728     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6729         (NULL), ("no 'moov' atom within the first 10 MB"));
6730     ret = GST_FLOW_ERROR;
6731     goto done;
6732   }
6733 }
6734
6735 static gboolean
6736 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6737 {
6738   GstQuery *query;
6739   gboolean pull_mode;
6740
6741   query = gst_query_new_scheduling ();
6742
6743   if (!gst_pad_peer_query (sinkpad, query)) {
6744     gst_query_unref (query);
6745     goto activate_push;
6746   }
6747
6748   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6749       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6750   gst_query_unref (query);
6751
6752   if (!pull_mode)
6753     goto activate_push;
6754
6755   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6756   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6757
6758 activate_push:
6759   {
6760     GST_DEBUG_OBJECT (sinkpad, "activating push");
6761     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6762   }
6763 }
6764
6765 static gboolean
6766 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6767     GstPadMode mode, gboolean active)
6768 {
6769   gboolean res;
6770   GstQTDemux *demux = GST_QTDEMUX (parent);
6771
6772   switch (mode) {
6773     case GST_PAD_MODE_PUSH:
6774       demux->pullbased = FALSE;
6775       res = TRUE;
6776       break;
6777     case GST_PAD_MODE_PULL:
6778       if (active) {
6779         demux->pullbased = TRUE;
6780         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6781             sinkpad, NULL);
6782       } else {
6783         res = gst_pad_stop_task (sinkpad);
6784       }
6785       break;
6786     default:
6787       res = FALSE;
6788       break;
6789   }
6790   return res;
6791 }
6792
6793 #ifdef HAVE_ZLIB
6794 static void *
6795 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6796 {
6797   return g_malloc (items * size);
6798 }
6799
6800 static void
6801 qtdemux_zfree (void *opaque, void *addr)
6802 {
6803   g_free (addr);
6804 }
6805
6806 static void *
6807 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6808 {
6809   guint8 *buffer;
6810   z_stream *z;
6811   int ret;
6812
6813   z = g_new0 (z_stream, 1);
6814   z->zalloc = qtdemux_zalloc;
6815   z->zfree = qtdemux_zfree;
6816   z->opaque = NULL;
6817
6818   z->next_in = z_buffer;
6819   z->avail_in = z_length;
6820
6821   buffer = (guint8 *) g_malloc (length);
6822   ret = inflateInit (z);
6823   while (z->avail_in > 0) {
6824     if (z->avail_out == 0) {
6825       length += 1024;
6826       buffer = (guint8 *) g_realloc (buffer, length);
6827       z->next_out = buffer + z->total_out;
6828       z->avail_out = 1024;
6829     }
6830     ret = inflate (z, Z_SYNC_FLUSH);
6831     if (ret != Z_OK)
6832       break;
6833   }
6834   if (ret != Z_STREAM_END) {
6835     g_warning ("inflate() returned %d", ret);
6836   }
6837
6838   g_free (z);
6839   return buffer;
6840 }
6841 #endif /* HAVE_ZLIB */
6842
6843 static gboolean
6844 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6845 {
6846   GNode *cmov;
6847
6848   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6849
6850   /* counts as header data */
6851   qtdemux->header_size += length;
6852
6853   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6854   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6855
6856   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6857   if (cmov) {
6858     guint32 method;
6859     GNode *dcom;
6860     GNode *cmvd;
6861
6862     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6863     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6864     if (dcom == NULL || cmvd == NULL)
6865       goto invalid_compression;
6866
6867     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6868     switch (method) {
6869 #ifdef HAVE_ZLIB
6870       case FOURCC_zlib:{
6871         guint uncompressed_length;
6872         guint compressed_length;
6873         guint8 *buf;
6874
6875         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6876         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6877         GST_LOG ("length = %u", uncompressed_length);
6878
6879         buf =
6880             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6881             compressed_length, uncompressed_length);
6882
6883         qtdemux->moov_node_compressed = qtdemux->moov_node;
6884         qtdemux->moov_node = g_node_new (buf);
6885
6886         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6887             uncompressed_length);
6888         break;
6889       }
6890 #endif /* HAVE_ZLIB */
6891       default:
6892         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6893             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6894         break;
6895     }
6896   }
6897   return TRUE;
6898
6899   /* ERRORS */
6900 invalid_compression:
6901   {
6902     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6903     return FALSE;
6904   }
6905 }
6906
6907 static gboolean
6908 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6909     const guint8 * end)
6910 {
6911   while (G_UNLIKELY (buf < end)) {
6912     GNode *child;
6913     guint32 len;
6914
6915     if (G_UNLIKELY (buf + 4 > end)) {
6916       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6917       break;
6918     }
6919     len = QT_UINT32 (buf);
6920     if (G_UNLIKELY (len == 0)) {
6921       GST_LOG_OBJECT (qtdemux, "empty container");
6922       break;
6923     }
6924     if (G_UNLIKELY (len < 8)) {
6925       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6926       break;
6927     }
6928     if (G_UNLIKELY (len > (end - buf))) {
6929       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6930           (gint) (end - buf));
6931       break;
6932     }
6933
6934     child = g_node_new ((guint8 *) buf);
6935     g_node_append (node, child);
6936     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6937     qtdemux_parse_node (qtdemux, child, buf, len);
6938
6939     buf += len;
6940   }
6941   return TRUE;
6942 }
6943
6944 static gboolean
6945 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6946     GNode * xdxt)
6947 {
6948   int len = QT_UINT32 (xdxt->data);
6949   guint8 *buf = xdxt->data;
6950   guint8 *end = buf + len;
6951   GstBuffer *buffer;
6952
6953   /* skip size and type */
6954   buf += 8;
6955   end -= 8;
6956
6957   while (buf < end) {
6958     gint size;
6959     guint32 type;
6960
6961     size = QT_UINT32 (buf);
6962     type = QT_FOURCC (buf + 4);
6963
6964     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6965
6966     if (buf + size > end || size <= 0)
6967       break;
6968
6969     buf += 8;
6970     size -= 8;
6971
6972     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6973         GST_FOURCC_ARGS (type));
6974
6975     switch (type) {
6976       case FOURCC_tCtH:
6977         buffer = gst_buffer_new_and_alloc (size);
6978         gst_buffer_fill (buffer, 0, buf, size);
6979         stream->buffers = g_slist_append (stream->buffers, buffer);
6980         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6981         break;
6982       case FOURCC_tCt_:
6983         buffer = gst_buffer_new_and_alloc (size);
6984         gst_buffer_fill (buffer, 0, buf, size);
6985         stream->buffers = g_slist_append (stream->buffers, buffer);
6986         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6987         break;
6988       case FOURCC_tCtC:
6989         buffer = gst_buffer_new_and_alloc (size);
6990         gst_buffer_fill (buffer, 0, buf, size);
6991         stream->buffers = g_slist_append (stream->buffers, buffer);
6992         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6993         break;
6994       default:
6995         GST_WARNING_OBJECT (qtdemux,
6996             "unknown theora cookie %" GST_FOURCC_FORMAT,
6997             GST_FOURCC_ARGS (type));
6998         break;
6999     }
7000     buf += size;
7001   }
7002   return TRUE;
7003 }
7004
7005 static gboolean
7006 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7007     guint length)
7008 {
7009   guint32 fourcc = 0;
7010   guint32 node_length = 0;
7011   const QtNodeType *type;
7012   const guint8 *end;
7013
7014   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7015
7016   if (G_UNLIKELY (length < 8))
7017     goto not_enough_data;
7018
7019   node_length = QT_UINT32 (buffer);
7020   fourcc = QT_FOURCC (buffer + 4);
7021
7022   /* ignore empty nodes */
7023   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7024     return TRUE;
7025
7026   type = qtdemux_type_get (fourcc);
7027
7028   end = buffer + length;
7029
7030   GST_LOG_OBJECT (qtdemux,
7031       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7032       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7033
7034   if (node_length > length)
7035     goto broken_atom_size;
7036
7037   if (type->flags & QT_FLAG_CONTAINER) {
7038     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7039   } else {
7040     switch (fourcc) {
7041       case FOURCC_stsd:
7042       {
7043         if (node_length < 20) {
7044           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7045           break;
7046         }
7047         GST_DEBUG_OBJECT (qtdemux,
7048             "parsing stsd (sample table, sample description) atom");
7049         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7050         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7051         break;
7052       }
7053       case FOURCC_mp4a:
7054       case FOURCC_alac:
7055       {
7056         guint32 version;
7057         guint32 offset;
7058         guint min_size;
7059
7060         /* also read alac (or whatever) in stead of mp4a in the following,
7061          * since a similar layout is used in other cases as well */
7062         if (fourcc == FOURCC_mp4a)
7063           min_size = 20;
7064         else
7065           min_size = 40;
7066
7067         /* There are two things we might encounter here: a true mp4a atom, and
7068            an mp4a entry in an stsd atom. The latter is what we're interested
7069            in, and it looks like an atom, but isn't really one. The true mp4a
7070            atom is short, so we detect it based on length here. */
7071         if (length < min_size) {
7072           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7073               GST_FOURCC_ARGS (fourcc));
7074           break;
7075         }
7076
7077         /* 'version' here is the sound sample description version. Types 0 and
7078            1 are documented in the QTFF reference, but type 2 is not: it's
7079            described in Apple header files instead (struct SoundDescriptionV2
7080            in Movies.h) */
7081         version = QT_UINT16 (buffer + 16);
7082
7083         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7084             GST_FOURCC_ARGS (fourcc), version);
7085
7086         /* parse any esds descriptors */
7087         switch (version) {
7088           case 0:
7089             offset = 0x24;
7090             break;
7091           case 1:
7092             offset = 0x34;
7093             break;
7094           case 2:
7095             offset = 0x48;
7096             break;
7097           default:
7098             GST_WARNING_OBJECT (qtdemux,
7099                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7100                 GST_FOURCC_ARGS (fourcc), version);
7101             offset = 0;
7102             break;
7103         }
7104         if (offset)
7105           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7106         break;
7107       }
7108       case FOURCC_mp4v:
7109       case FOURCC_MP4V:
7110       case FOURCC_fmp4:
7111       case FOURCC_FMP4:
7112       case FOURCC_apcs:
7113       case FOURCC_apch:
7114       case FOURCC_apcn:
7115       case FOURCC_apco:
7116       case FOURCC_ap4h:
7117       {
7118         const guint8 *buf;
7119         guint32 version;
7120         int tlen;
7121
7122         /* codec_data is contained inside these atoms, which all have
7123          * the same format. */
7124
7125         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7126             GST_FOURCC_ARGS (fourcc));
7127         version = QT_UINT32 (buffer + 16);
7128         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7129         if (1 || version == 0x00000000) {
7130           buf = buffer + 0x32;
7131
7132           /* FIXME Quicktime uses PASCAL string while
7133            * the iso format uses C strings. Check the file
7134            * type before attempting to parse the string here. */
7135           tlen = QT_UINT8 (buf);
7136           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7137           buf++;
7138           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7139           /* the string has a reserved space of 32 bytes so skip
7140            * the remaining 31 */
7141           buf += 31;
7142           buf += 4;             /* and 4 bytes reserved */
7143
7144           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7145
7146           qtdemux_parse_container (qtdemux, node, buf, end);
7147         }
7148         break;
7149       }
7150       case FOURCC_H264:
7151       {
7152         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7153         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7154         break;
7155       }
7156       case FOURCC_avc1:
7157       {
7158         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7159         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7160         break;
7161       }
7162       case FOURCC_avc3:
7163       {
7164         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7165         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7166         break;
7167       }
7168       case FOURCC_H265:
7169       {
7170         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7171         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7172         break;
7173       }
7174       case FOURCC_hvc1:
7175       {
7176         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7177         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7178         break;
7179       }
7180       case FOURCC_hev1:
7181       {
7182         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7183         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7184         break;
7185       }
7186       case FOURCC_mjp2:
7187       {
7188         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7189         break;
7190       }
7191       case FOURCC_meta:
7192       {
7193         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7194         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7195         break;
7196       }
7197       case FOURCC_mp4s:
7198       {
7199         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7200         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7201         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7202         break;
7203       }
7204       case FOURCC_XiTh:
7205       {
7206         guint32 version;
7207         guint32 offset;
7208
7209         version = QT_UINT32 (buffer + 12);
7210         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7211
7212         switch (version) {
7213           case 0x00000001:
7214             offset = 0x62;
7215             break;
7216           default:
7217             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7218             offset = 0;
7219             break;
7220         }
7221         if (offset)
7222           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7223         break;
7224       }
7225       case FOURCC_in24:
7226       {
7227         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7228         break;
7229       }
7230       case FOURCC_uuid:
7231       {
7232         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7233         break;
7234       }
7235       case FOURCC_encv:
7236       {
7237         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7238         break;
7239       }
7240       case FOURCC_enca:
7241       {
7242         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7243         break;
7244       }
7245       default:
7246         if (!strcmp (type->name, "unknown"))
7247           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7248         break;
7249     }
7250   }
7251   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7252       GST_FOURCC_ARGS (fourcc));
7253   return TRUE;
7254
7255 /* ERRORS */
7256 not_enough_data:
7257   {
7258     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7259         (_("This file is corrupt and cannot be played.")),
7260         ("Not enough data for an atom header, got only %u bytes", length));
7261     return FALSE;
7262   }
7263 broken_atom_size:
7264   {
7265     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7266         (_("This file is corrupt and cannot be played.")),
7267         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7268             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7269             length));
7270     return FALSE;
7271   }
7272 }
7273
7274 static GNode *
7275 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7276 {
7277   GNode *child;
7278   guint8 *buffer;
7279   guint32 child_fourcc;
7280
7281   for (child = g_node_first_child (node); child;
7282       child = g_node_next_sibling (child)) {
7283     buffer = (guint8 *) child->data;
7284
7285     child_fourcc = QT_FOURCC (buffer + 4);
7286
7287     if (G_UNLIKELY (child_fourcc == fourcc)) {
7288       return child;
7289     }
7290   }
7291   return NULL;
7292 }
7293
7294 static GNode *
7295 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7296     GstByteReader * parser)
7297 {
7298   GNode *child;
7299   guint8 *buffer;
7300   guint32 child_fourcc, child_len;
7301
7302   for (child = g_node_first_child (node); child;
7303       child = g_node_next_sibling (child)) {
7304     buffer = (guint8 *) child->data;
7305
7306     child_len = QT_UINT32 (buffer);
7307     child_fourcc = QT_FOURCC (buffer + 4);
7308
7309     if (G_UNLIKELY (child_fourcc == fourcc)) {
7310       if (G_UNLIKELY (child_len < (4 + 4)))
7311         return NULL;
7312       /* FIXME: must verify if atom length < parent atom length */
7313       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7314       return child;
7315     }
7316   }
7317   return NULL;
7318 }
7319
7320 static GNode *
7321 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7322     GstByteReader * parser)
7323 {
7324   GNode *child;
7325   guint8 *buffer;
7326   guint32 child_fourcc, child_len;
7327
7328   for (child = g_node_next_sibling (node); child;
7329       child = g_node_next_sibling (child)) {
7330     buffer = (guint8 *) child->data;
7331
7332     child_fourcc = QT_FOURCC (buffer + 4);
7333
7334     if (child_fourcc == fourcc) {
7335       if (parser) {
7336         child_len = QT_UINT32 (buffer);
7337         if (G_UNLIKELY (child_len < (4 + 4)))
7338           return NULL;
7339         /* FIXME: must verify if atom length < parent atom length */
7340         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7341       }
7342       return child;
7343     }
7344   }
7345   return NULL;
7346 }
7347
7348 static GNode *
7349 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7350 {
7351   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7352 }
7353
7354 static void
7355 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7356 {
7357 /* FIXME: This can only reliably work if demuxers have a
7358  * separate streaming thread per srcpad. This should be
7359  * done in a demuxer base class, which integrates parts
7360  * of multiqueue
7361  *
7362  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7363  */
7364 #if 0
7365   GstQuery *query;
7366
7367   query = gst_query_new_allocation (stream->caps, FALSE);
7368
7369   if (!gst_pad_peer_query (stream->pad, query)) {
7370     /* not a problem, just debug a little */
7371     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7372   }
7373
7374   if (stream->allocator)
7375     gst_object_unref (stream->allocator);
7376
7377   if (gst_query_get_n_allocation_params (query) > 0) {
7378     /* try the allocator */
7379     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7380         &stream->params);
7381     stream->use_allocator = TRUE;
7382   } else {
7383     stream->allocator = NULL;
7384     gst_allocation_params_init (&stream->params);
7385     stream->use_allocator = FALSE;
7386   }
7387   gst_query_unref (query);
7388 #endif
7389 }
7390
7391 static gboolean
7392 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7393     QtDemuxStream * stream)
7394 {
7395   GstStructure *s;
7396   const gchar *selected_system;
7397
7398   g_return_val_if_fail (qtdemux != NULL, FALSE);
7399   g_return_val_if_fail (stream != NULL, FALSE);
7400   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7401
7402   if (stream->protection_scheme_type != FOURCC_cenc) {
7403     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7404     return FALSE;
7405   }
7406   if (qtdemux->protection_system_ids == NULL) {
7407     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7408         "cenc protection system information has been found");
7409     return FALSE;
7410   }
7411   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7412   selected_system = gst_protection_select_system ((const gchar **)
7413       qtdemux->protection_system_ids->pdata);
7414   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7415       qtdemux->protection_system_ids->len - 1);
7416   if (!selected_system) {
7417     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7418         "suitable decryptor element has been found");
7419     return FALSE;
7420   }
7421
7422   s = gst_caps_get_structure (stream->caps, 0);
7423   if (!gst_structure_has_name (s, "application/x-cenc")) {
7424     gst_structure_set (s,
7425         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7426         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7427         NULL);
7428     gst_structure_set_name (s, "application/x-cenc");
7429   }
7430   return TRUE;
7431 }
7432
7433 static gboolean
7434 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7435 {
7436   if (stream->subtype == FOURCC_vide) {
7437     /* fps is calculated base on the duration of the average framerate since
7438      * qt does not have a fixed framerate. */
7439     gboolean fps_available = TRUE;
7440
7441     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7442       /* still frame */
7443       stream->fps_n = 0;
7444       stream->fps_d = 1;
7445     } else {
7446       if (stream->duration == 0 || stream->n_samples < 2) {
7447         stream->fps_n = stream->timescale;
7448         stream->fps_d = 1;
7449         fps_available = FALSE;
7450       } else {
7451         GstClockTime avg_duration;
7452         guint64 duration;
7453         guint32 n_samples;
7454
7455         /* duration and n_samples can be updated for fragmented format
7456          * so, framerate of fragmented format is calculated using data in a moof */
7457         if (qtdemux->fragmented && stream->n_samples_moof > 0
7458             && stream->duration_moof > 0) {
7459           n_samples = stream->n_samples_moof;
7460           duration = stream->duration_moof;
7461         } else {
7462           n_samples = stream->n_samples;
7463           duration = stream->duration;
7464         }
7465
7466         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7467         /* stream->duration is guint64, timescale, n_samples are guint32 */
7468         avg_duration =
7469             gst_util_uint64_scale_round (duration -
7470             stream->first_duration, GST_SECOND,
7471             (guint64) (stream->timescale) * (n_samples - 1));
7472
7473         GST_LOG_OBJECT (qtdemux,
7474             "Calculating avg sample duration based on stream (or moof) duration %"
7475             G_GUINT64_FORMAT
7476             " minus first sample %u, leaving %d samples gives %"
7477             GST_TIME_FORMAT, duration, stream->first_duration,
7478             n_samples - 1, GST_TIME_ARGS (avg_duration));
7479
7480         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7481             &stream->fps_d);
7482
7483         GST_DEBUG_OBJECT (qtdemux,
7484             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7485             stream->timescale, stream->fps_n, stream->fps_d);
7486       }
7487     }
7488
7489     if (stream->caps) {
7490       stream->caps = gst_caps_make_writable (stream->caps);
7491
7492       gst_caps_set_simple (stream->caps,
7493           "width", G_TYPE_INT, stream->width,
7494           "height", G_TYPE_INT, stream->height, NULL);
7495
7496       /* set framerate if calculated framerate is reliable */
7497       if (fps_available) {
7498         gst_caps_set_simple (stream->caps,
7499             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7500       }
7501
7502       /* calculate pixel-aspect-ratio using display width and height */
7503       GST_DEBUG_OBJECT (qtdemux,
7504           "video size %dx%d, target display size %dx%d", stream->width,
7505           stream->height, stream->display_width, stream->display_height);
7506       /* qt file might have pasp atom */
7507       if (stream->par_w > 0 && stream->par_h > 0) {
7508         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7509         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7510             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7511       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7512           stream->width > 0 && stream->height > 0) {
7513         gint n, d;
7514
7515         /* calculate the pixel aspect ratio using the display and pixel w/h */
7516         n = stream->display_width * stream->height;
7517         d = stream->display_height * stream->width;
7518         if (n == d)
7519           n = d = 1;
7520         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7521         stream->par_w = n;
7522         stream->par_h = d;
7523         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7524             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7525       }
7526
7527       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7528         guint par_w = 1, par_h = 1;
7529
7530         if (stream->par_w > 0 && stream->par_h > 0) {
7531           par_w = stream->par_w;
7532           par_h = stream->par_h;
7533         }
7534
7535         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7536                 stream->width, stream->height, par_w, par_h)) {
7537           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7538         }
7539
7540         gst_caps_set_simple (stream->caps,
7541             "multiview-mode", G_TYPE_STRING,
7542             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7543             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7544             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7545       }
7546     }
7547   }
7548
7549   else if (stream->subtype == FOURCC_soun) {
7550     if (stream->caps) {
7551       stream->caps = gst_caps_make_writable (stream->caps);
7552       if (stream->rate > 0)
7553         gst_caps_set_simple (stream->caps,
7554             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7555       if (stream->n_channels > 0)
7556         gst_caps_set_simple (stream->caps,
7557             "channels", G_TYPE_INT, stream->n_channels, NULL);
7558       if (stream->n_channels > 2) {
7559         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7560          * correctly; this is just the minimum we can do - assume
7561          * we don't actually have any channel positions. */
7562         gst_caps_set_simple (stream->caps,
7563             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7564       }
7565     }
7566   }
7567
7568   if (stream->pad) {
7569     GstCaps *prev_caps = NULL;
7570
7571     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7572     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7573     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7574     gst_pad_set_active (stream->pad, TRUE);
7575
7576     gst_pad_use_fixed_caps (stream->pad);
7577
7578     if (stream->protected) {
7579       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7580         GST_ERROR_OBJECT (qtdemux,
7581             "Failed to configure protected stream caps.");
7582         return FALSE;
7583       }
7584     }
7585
7586     if (stream->new_stream) {
7587       gchar *stream_id;
7588       GstEvent *event;
7589       GstStreamFlags stream_flags;
7590
7591       event =
7592           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7593           0);
7594       if (event) {
7595         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7596           qtdemux->have_group_id = TRUE;
7597         else
7598           qtdemux->have_group_id = FALSE;
7599         gst_event_unref (event);
7600       } else if (!qtdemux->have_group_id) {
7601         qtdemux->have_group_id = TRUE;
7602         qtdemux->group_id = gst_util_group_id_next ();
7603       }
7604
7605       stream->new_stream = FALSE;
7606       stream_id =
7607           gst_pad_create_stream_id_printf (stream->pad,
7608           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7609       event = gst_event_new_stream_start (stream_id);
7610       if (qtdemux->have_group_id)
7611         gst_event_set_group_id (event, qtdemux->group_id);
7612       stream_flags = GST_STREAM_FLAG_NONE;
7613       if (stream->disabled)
7614         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7615       if (stream->sparse)
7616         stream_flags |= GST_STREAM_FLAG_SPARSE;
7617       gst_event_set_stream_flags (event, stream_flags);
7618       gst_pad_push_event (stream->pad, event);
7619       g_free (stream_id);
7620     }
7621
7622     prev_caps = gst_pad_get_current_caps (stream->pad);
7623
7624     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7625       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7626       gst_pad_set_caps (stream->pad, stream->caps);
7627     } else {
7628       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7629     }
7630
7631     if (prev_caps)
7632       gst_caps_unref (prev_caps);
7633     stream->new_caps = FALSE;
7634   }
7635   return TRUE;
7636 }
7637
7638 static gboolean
7639 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7640     QtDemuxStream * stream, GstTagList * list)
7641 {
7642   gboolean ret = TRUE;
7643   /* consistent default for push based mode */
7644   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7645
7646   if (stream->subtype == FOURCC_vide) {
7647     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7648
7649     stream->pad =
7650         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7651     g_free (name);
7652
7653     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7654       gst_object_unref (stream->pad);
7655       stream->pad = NULL;
7656       ret = FALSE;
7657       goto done;
7658     }
7659
7660     qtdemux->n_video_streams++;
7661   } else if (stream->subtype == FOURCC_soun) {
7662     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7663
7664     stream->pad =
7665         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7666     g_free (name);
7667     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7668       gst_object_unref (stream->pad);
7669       stream->pad = NULL;
7670       ret = FALSE;
7671       goto done;
7672     }
7673     qtdemux->n_audio_streams++;
7674   } else if (stream->subtype == FOURCC_strm) {
7675     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7676   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7677       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7678     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7679
7680     stream->pad =
7681         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7682     g_free (name);
7683     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7684       gst_object_unref (stream->pad);
7685       stream->pad = NULL;
7686       ret = FALSE;
7687       goto done;
7688     }
7689     qtdemux->n_sub_streams++;
7690   } else if (stream->caps) {
7691     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7692
7693     stream->pad =
7694         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7695     g_free (name);
7696     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7697       gst_object_unref (stream->pad);
7698       stream->pad = NULL;
7699       ret = FALSE;
7700       goto done;
7701     }
7702     qtdemux->n_video_streams++;
7703   } else {
7704     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7705     goto done;
7706   }
7707
7708   if (stream->pad) {
7709     GList *l;
7710
7711     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7712         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7713     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7714     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7715
7716     if (stream->pending_tags)
7717       gst_tag_list_unref (stream->pending_tags);
7718     stream->pending_tags = list;
7719     list = NULL;
7720     /* global tags go on each pad anyway */
7721     stream->send_global_tags = TRUE;
7722     /* send upstream GST_EVENT_PROTECTION events that were received before
7723        this source pad was created */
7724     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7725       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7726   }
7727 done:
7728   if (list)
7729     gst_tag_list_unref (list);
7730   return ret;
7731 }
7732
7733 /* find next atom with @fourcc starting at @offset */
7734 static GstFlowReturn
7735 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7736     guint64 * length, guint32 fourcc)
7737 {
7738   GstFlowReturn ret;
7739   guint32 lfourcc;
7740   GstBuffer *buf;
7741
7742   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7743       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7744
7745   while (TRUE) {
7746     GstMapInfo map;
7747
7748     buf = NULL;
7749     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7750     if (G_UNLIKELY (ret != GST_FLOW_OK))
7751       goto locate_failed;
7752     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7753       /* likely EOF */
7754       ret = GST_FLOW_EOS;
7755       gst_buffer_unref (buf);
7756       goto locate_failed;
7757     }
7758     gst_buffer_map (buf, &map, GST_MAP_READ);
7759     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7760     gst_buffer_unmap (buf, &map);
7761     gst_buffer_unref (buf);
7762
7763     if (G_UNLIKELY (*length == 0)) {
7764       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7765       ret = GST_FLOW_ERROR;
7766       goto locate_failed;
7767     }
7768
7769     if (lfourcc == fourcc) {
7770       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7771           *offset);
7772       break;
7773     } else {
7774       GST_LOG_OBJECT (qtdemux,
7775           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7776           GST_FOURCC_ARGS (fourcc), *offset);
7777       *offset += *length;
7778     }
7779   }
7780
7781   return GST_FLOW_OK;
7782
7783 locate_failed:
7784   {
7785     /* might simply have had last one */
7786     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7787     return ret;
7788   }
7789 }
7790
7791 /* should only do something in pull mode */
7792 /* call with OBJECT lock */
7793 static GstFlowReturn
7794 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7795 {
7796   guint64 length, offset;
7797   GstBuffer *buf = NULL;
7798   GstFlowReturn ret = GST_FLOW_OK;
7799   GstFlowReturn res = GST_FLOW_OK;
7800   GstMapInfo map;
7801
7802   offset = qtdemux->moof_offset;
7803   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7804
7805   if (!offset) {
7806     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7807     return GST_FLOW_EOS;
7808   }
7809
7810   /* best not do pull etc with lock held */
7811   GST_OBJECT_UNLOCK (qtdemux);
7812
7813   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7814   if (ret != GST_FLOW_OK)
7815     goto flow_failed;
7816
7817   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7818   if (G_UNLIKELY (ret != GST_FLOW_OK))
7819     goto flow_failed;
7820   gst_buffer_map (buf, &map, GST_MAP_READ);
7821   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7822     gst_buffer_unmap (buf, &map);
7823     gst_buffer_unref (buf);
7824     buf = NULL;
7825     goto parse_failed;
7826   }
7827
7828   gst_buffer_unmap (buf, &map);
7829   gst_buffer_unref (buf);
7830   buf = NULL;
7831
7832   offset += length;
7833   /* look for next moof */
7834   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7835   if (G_UNLIKELY (ret != GST_FLOW_OK))
7836     goto flow_failed;
7837
7838 exit:
7839   GST_OBJECT_LOCK (qtdemux);
7840
7841   qtdemux->moof_offset = offset;
7842
7843   return res;
7844
7845 parse_failed:
7846   {
7847     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7848     offset = 0;
7849     res = GST_FLOW_ERROR;
7850     goto exit;
7851   }
7852 flow_failed:
7853   {
7854     /* maybe upstream temporarily flushing */
7855     if (ret != GST_FLOW_FLUSHING) {
7856       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7857       offset = 0;
7858     } else {
7859       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7860       /* resume at current position next time */
7861     }
7862     res = ret;
7863     goto exit;
7864   }
7865 }
7866
7867 /* initialise bytereaders for stbl sub-atoms */
7868 static gboolean
7869 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7870 {
7871   stream->stbl_index = -1;      /* no samples have yet been parsed */
7872   stream->sample_index = -1;
7873
7874   /* time-to-sample atom */
7875   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7876     goto corrupt_file;
7877
7878   /* copy atom data into a new buffer for later use */
7879   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7880
7881   /* skip version + flags */
7882   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7883       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7884     goto corrupt_file;
7885   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7886
7887   /* make sure there's enough data */
7888   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7889     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7890     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7891         stream->n_sample_times);
7892     if (!stream->n_sample_times)
7893       goto corrupt_file;
7894   }
7895
7896   /* sync sample atom */
7897   stream->stps_present = FALSE;
7898   if ((stream->stss_present =
7899           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7900               &stream->stss) ? TRUE : FALSE) == TRUE) {
7901     /* copy atom data into a new buffer for later use */
7902     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7903
7904     /* skip version + flags */
7905     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7906         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7907       goto corrupt_file;
7908
7909     if (stream->n_sample_syncs) {
7910       /* make sure there's enough data */
7911       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7912         goto corrupt_file;
7913     }
7914
7915     /* partial sync sample atom */
7916     if ((stream->stps_present =
7917             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7918                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7919       /* copy atom data into a new buffer for later use */
7920       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7921
7922       /* skip version + flags */
7923       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7924           !gst_byte_reader_get_uint32_be (&stream->stps,
7925               &stream->n_sample_partial_syncs))
7926         goto corrupt_file;
7927
7928       /* if there are no entries, the stss table contains the real
7929        * sync samples */
7930       if (stream->n_sample_partial_syncs) {
7931         /* make sure there's enough data */
7932         if (!qt_atom_parser_has_chunks (&stream->stps,
7933                 stream->n_sample_partial_syncs, 4))
7934           goto corrupt_file;
7935       }
7936     }
7937   }
7938
7939   /* sample size */
7940   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7941     goto no_samples;
7942
7943   /* copy atom data into a new buffer for later use */
7944   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7945
7946   /* skip version + flags */
7947   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7948       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7949     goto corrupt_file;
7950
7951   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7952     goto corrupt_file;
7953
7954   if (!stream->n_samples)
7955     goto no_samples;
7956
7957   /* sample-to-chunk atom */
7958   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7959     goto corrupt_file;
7960
7961   /* copy atom data into a new buffer for later use */
7962   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7963
7964   /* skip version + flags */
7965   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7966       !gst_byte_reader_get_uint32_be (&stream->stsc,
7967           &stream->n_samples_per_chunk))
7968     goto corrupt_file;
7969
7970   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7971       stream->n_samples_per_chunk);
7972
7973   /* make sure there's enough data */
7974   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7975           12))
7976     goto corrupt_file;
7977
7978
7979   /* chunk offset */
7980   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7981     stream->co_size = sizeof (guint32);
7982   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7983           &stream->stco))
7984     stream->co_size = sizeof (guint64);
7985   else
7986     goto corrupt_file;
7987
7988   /* copy atom data into a new buffer for later use */
7989   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7990
7991   /* skip version + flags */
7992   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7993     goto corrupt_file;
7994
7995   /* chunks_are_samples == TRUE means treat chunks as samples */
7996   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7997   if (stream->chunks_are_samples) {
7998     /* treat chunks as samples */
7999     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8000       goto corrupt_file;
8001   } else {
8002     /* skip number of entries */
8003     if (!gst_byte_reader_skip (&stream->stco, 4))
8004       goto corrupt_file;
8005
8006     /* make sure there are enough data in the stsz atom */
8007     if (!stream->sample_size) {
8008       /* different sizes for each sample */
8009       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8010         goto corrupt_file;
8011     }
8012   }
8013
8014   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8015       stream->n_samples, (guint) sizeof (QtDemuxSample),
8016       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8017
8018   if (stream->n_samples >=
8019       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8020     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8021         "be larger than %uMB (broken file?)", stream->n_samples,
8022         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8023     return FALSE;
8024   }
8025
8026   g_assert (stream->samples == NULL);
8027   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8028   if (!stream->samples) {
8029     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8030         stream->n_samples);
8031     return FALSE;
8032   }
8033
8034   /* composition time-to-sample */
8035   if ((stream->ctts_present =
8036           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8037               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8038     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8039
8040     /* copy atom data into a new buffer for later use */
8041     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8042
8043     /* skip version + flags */
8044     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8045         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8046             &stream->n_composition_times))
8047       goto corrupt_file;
8048
8049     /* make sure there's enough data */
8050     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8051             4 + 4))
8052       goto corrupt_file;
8053
8054     /* This is optional, if missing we iterate the ctts */
8055     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8056       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8057           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8058         g_free ((gpointer) cslg.data);
8059         goto corrupt_file;
8060       }
8061     } else {
8062       gint32 cslg_least = 0;
8063       guint num_entries, pos;
8064       gint i;
8065
8066       pos = gst_byte_reader_get_pos (&stream->ctts);
8067       num_entries = stream->n_composition_times;
8068
8069       stream->cslg_shift = 0;
8070
8071       for (i = 0; i < num_entries; i++) {
8072         gint32 offset;
8073
8074         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8075         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8076
8077         if (offset < cslg_least)
8078           cslg_least = offset;
8079       }
8080
8081       if (cslg_least < 0)
8082         stream->cslg_shift = ABS (cslg_least);
8083       else
8084         stream->cslg_shift = 0;
8085
8086       /* reset the reader so we can generate sample table */
8087       gst_byte_reader_set_pos (&stream->ctts, pos);
8088     }
8089   } else {
8090     /* Ensure the cslg_shift value is consistent so we can use it
8091      * unconditionnally to produce TS and Segment */
8092     stream->cslg_shift = 0;
8093   }
8094
8095   return TRUE;
8096
8097 corrupt_file:
8098   {
8099     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8100         (_("This file is corrupt and cannot be played.")), (NULL));
8101     return FALSE;
8102   }
8103 no_samples:
8104   {
8105     gst_qtdemux_stbl_free (stream);
8106     if (!qtdemux->fragmented) {
8107       /* not quite good */
8108       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8109       return FALSE;
8110     } else {
8111       /* may pick up samples elsewhere */
8112       return TRUE;
8113     }
8114   }
8115 }
8116
8117 /* collect samples from the next sample to be parsed up to sample @n for @stream
8118  * by reading the info from @stbl
8119  *
8120  * This code can be executed from both the streaming thread and the seeking
8121  * thread so it takes the object lock to protect itself
8122  */
8123 static gboolean
8124 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8125 {
8126   gint i, j, k;
8127   QtDemuxSample *samples, *first, *cur, *last;
8128   guint32 n_samples_per_chunk;
8129   guint32 n_samples;
8130
8131   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8132       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8133       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8134
8135   n_samples = stream->n_samples;
8136
8137   if (n >= n_samples)
8138     goto out_of_samples;
8139
8140   GST_OBJECT_LOCK (qtdemux);
8141   if (n <= stream->stbl_index)
8142     goto already_parsed;
8143
8144   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8145
8146   if (!stream->stsz.data) {
8147     /* so we already parsed and passed all the moov samples;
8148      * onto fragmented ones */
8149     g_assert (qtdemux->fragmented);
8150     goto done;
8151   }
8152
8153   /* pointer to the sample table */
8154   samples = stream->samples;
8155
8156   /* starts from -1, moves to the next sample index to parse */
8157   stream->stbl_index++;
8158
8159   /* keep track of the first and last sample to fill */
8160   first = &samples[stream->stbl_index];
8161   last = &samples[n];
8162
8163   if (!stream->chunks_are_samples) {
8164     /* set the sample sizes */
8165     if (stream->sample_size == 0) {
8166       /* different sizes for each sample */
8167       for (cur = first; cur <= last; cur++) {
8168         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8169         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8170             (guint) (cur - samples), cur->size);
8171       }
8172     } else {
8173       /* samples have the same size */
8174       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8175       for (cur = first; cur <= last; cur++)
8176         cur->size = stream->sample_size;
8177     }
8178   }
8179
8180   n_samples_per_chunk = stream->n_samples_per_chunk;
8181   cur = first;
8182
8183   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8184     guint32 last_chunk;
8185
8186     if (stream->stsc_chunk_index >= stream->last_chunk
8187         || stream->stsc_chunk_index < stream->first_chunk) {
8188       stream->first_chunk =
8189           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8190       stream->samples_per_chunk =
8191           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8192       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8193
8194       /* chunk numbers are counted from 1 it seems */
8195       if (G_UNLIKELY (stream->first_chunk == 0))
8196         goto corrupt_file;
8197
8198       --stream->first_chunk;
8199
8200       /* the last chunk of each entry is calculated by taking the first chunk
8201        * of the next entry; except if there is no next, where we fake it with
8202        * INT_MAX */
8203       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8204         stream->last_chunk = G_MAXUINT32;
8205       } else {
8206         stream->last_chunk =
8207             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8208         if (G_UNLIKELY (stream->last_chunk == 0))
8209           goto corrupt_file;
8210
8211         --stream->last_chunk;
8212       }
8213
8214       GST_LOG_OBJECT (qtdemux,
8215           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8216           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8217
8218       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8219         goto corrupt_file;
8220
8221       if (stream->last_chunk != G_MAXUINT32) {
8222         if (!qt_atom_parser_peek_sub (&stream->stco,
8223                 stream->first_chunk * stream->co_size,
8224                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8225                 &stream->co_chunk))
8226           goto corrupt_file;
8227
8228       } else {
8229         stream->co_chunk = stream->stco;
8230         if (!gst_byte_reader_skip (&stream->co_chunk,
8231                 stream->first_chunk * stream->co_size))
8232           goto corrupt_file;
8233       }
8234
8235       stream->stsc_chunk_index = stream->first_chunk;
8236     }
8237
8238     last_chunk = stream->last_chunk;
8239
8240     if (stream->chunks_are_samples) {
8241       cur = &samples[stream->stsc_chunk_index];
8242
8243       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8244         if (j > n) {
8245           /* save state */
8246           stream->stsc_chunk_index = j;
8247           goto done;
8248         }
8249
8250         cur->offset =
8251             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8252             stream->co_size);
8253
8254         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8255             "%" G_GUINT64_FORMAT, j, cur->offset);
8256
8257         if (stream->samples_per_frame * stream->bytes_per_frame) {
8258           cur->size =
8259               (stream->samples_per_chunk * stream->n_channels) /
8260               stream->samples_per_frame * stream->bytes_per_frame;
8261         } else {
8262           cur->size = stream->samples_per_chunk;
8263         }
8264
8265         GST_DEBUG_OBJECT (qtdemux,
8266             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8267             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8268                     stream->stco_sample_index)), cur->size);
8269
8270         cur->timestamp = stream->stco_sample_index;
8271         cur->duration = stream->samples_per_chunk;
8272         cur->keyframe = TRUE;
8273         cur++;
8274
8275         stream->stco_sample_index += stream->samples_per_chunk;
8276       }
8277       stream->stsc_chunk_index = j;
8278     } else {
8279       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8280         guint32 samples_per_chunk;
8281         guint64 chunk_offset;
8282
8283         if (!stream->stsc_sample_index
8284             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8285                 &stream->chunk_offset))
8286           goto corrupt_file;
8287
8288         samples_per_chunk = stream->samples_per_chunk;
8289         chunk_offset = stream->chunk_offset;
8290
8291         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8292           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8293               G_GUINT64_FORMAT " and size %d",
8294               (guint) (cur - samples), chunk_offset, cur->size);
8295
8296           cur->offset = chunk_offset;
8297           chunk_offset += cur->size;
8298           cur++;
8299
8300           if (G_UNLIKELY (cur > last)) {
8301             /* save state */
8302             stream->stsc_sample_index = k + 1;
8303             stream->chunk_offset = chunk_offset;
8304             stream->stsc_chunk_index = j;
8305             goto done2;
8306           }
8307         }
8308         stream->stsc_sample_index = 0;
8309       }
8310       stream->stsc_chunk_index = j;
8311     }
8312     stream->stsc_index++;
8313   }
8314
8315   if (stream->chunks_are_samples)
8316     goto ctts;
8317 done2:
8318   {
8319     guint32 n_sample_times;
8320
8321     n_sample_times = stream->n_sample_times;
8322     cur = first;
8323
8324     for (i = stream->stts_index; i < n_sample_times; i++) {
8325       guint32 stts_samples;
8326       gint32 stts_duration;
8327       gint64 stts_time;
8328
8329       if (stream->stts_sample_index >= stream->stts_samples
8330           || !stream->stts_sample_index) {
8331
8332         stream->stts_samples =
8333             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8334         stream->stts_duration =
8335             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8336
8337         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8338             i, stream->stts_samples, stream->stts_duration);
8339
8340         stream->stts_sample_index = 0;
8341       }
8342
8343       stts_samples = stream->stts_samples;
8344       stts_duration = stream->stts_duration;
8345       stts_time = stream->stts_time;
8346
8347       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8348         GST_DEBUG_OBJECT (qtdemux,
8349             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8350             (guint) (cur - samples), j,
8351             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8352
8353         cur->timestamp = stts_time;
8354         cur->duration = stts_duration;
8355
8356         /* avoid 32-bit wrap-around,
8357          * but still mind possible 'negative' duration */
8358         stts_time += (gint64) stts_duration;
8359         cur++;
8360
8361         if (G_UNLIKELY (cur > last)) {
8362           /* save values */
8363           stream->stts_time = stts_time;
8364           stream->stts_sample_index = j + 1;
8365           goto done3;
8366         }
8367       }
8368       stream->stts_sample_index = 0;
8369       stream->stts_time = stts_time;
8370       stream->stts_index++;
8371     }
8372     /* fill up empty timestamps with the last timestamp, this can happen when
8373      * the last samples do not decode and so we don't have timestamps for them.
8374      * We however look at the last timestamp to estimate the track length so we
8375      * need something in here. */
8376     for (; cur < last; cur++) {
8377       GST_DEBUG_OBJECT (qtdemux,
8378           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8379           (guint) (cur - samples),
8380           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8381       cur->timestamp = stream->stts_time;
8382       cur->duration = -1;
8383     }
8384   }
8385 done3:
8386   {
8387     /* sample sync, can be NULL */
8388     if (stream->stss_present == TRUE) {
8389       guint32 n_sample_syncs;
8390
8391       n_sample_syncs = stream->n_sample_syncs;
8392
8393       if (!n_sample_syncs) {
8394         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8395         stream->all_keyframe = TRUE;
8396       } else {
8397         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8398           /* note that the first sample is index 1, not 0 */
8399           guint32 index;
8400
8401           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8402
8403           if (G_LIKELY (index > 0 && index <= n_samples)) {
8404             index -= 1;
8405             samples[index].keyframe = TRUE;
8406             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8407             /* and exit if we have enough samples */
8408             if (G_UNLIKELY (index >= n)) {
8409               i++;
8410               break;
8411             }
8412           }
8413         }
8414         /* save state */
8415         stream->stss_index = i;
8416       }
8417
8418       /* stps marks partial sync frames like open GOP I-Frames */
8419       if (stream->stps_present == TRUE) {
8420         guint32 n_sample_partial_syncs;
8421
8422         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8423
8424         /* if there are no entries, the stss table contains the real
8425          * sync samples */
8426         if (n_sample_partial_syncs) {
8427           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8428             /* note that the first sample is index 1, not 0 */
8429             guint32 index;
8430
8431             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8432
8433             if (G_LIKELY (index > 0 && index <= n_samples)) {
8434               index -= 1;
8435               samples[index].keyframe = TRUE;
8436               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8437               /* and exit if we have enough samples */
8438               if (G_UNLIKELY (index >= n)) {
8439                 i++;
8440                 break;
8441               }
8442             }
8443           }
8444           /* save state */
8445           stream->stps_index = i;
8446         }
8447       }
8448     } else {
8449       /* no stss, all samples are keyframes */
8450       stream->all_keyframe = TRUE;
8451       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8452     }
8453   }
8454
8455 ctts:
8456   /* composition time to sample */
8457   if (stream->ctts_present == TRUE) {
8458     guint32 n_composition_times;
8459     guint32 ctts_count;
8460     gint32 ctts_soffset;
8461
8462     /* Fill in the pts_offsets */
8463     cur = first;
8464     n_composition_times = stream->n_composition_times;
8465
8466     for (i = stream->ctts_index; i < n_composition_times; i++) {
8467       if (stream->ctts_sample_index >= stream->ctts_count
8468           || !stream->ctts_sample_index) {
8469         stream->ctts_count =
8470             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8471         stream->ctts_soffset =
8472             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8473         stream->ctts_sample_index = 0;
8474       }
8475
8476       ctts_count = stream->ctts_count;
8477       ctts_soffset = stream->ctts_soffset;
8478
8479       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8480         cur->pts_offset = ctts_soffset;
8481         cur++;
8482
8483         if (G_UNLIKELY (cur > last)) {
8484           /* save state */
8485           stream->ctts_sample_index = j + 1;
8486           goto done;
8487         }
8488       }
8489       stream->ctts_sample_index = 0;
8490       stream->ctts_index++;
8491     }
8492   }
8493 done:
8494   stream->stbl_index = n;
8495   /* if index has been completely parsed, free data that is no-longer needed */
8496   if (n + 1 == stream->n_samples) {
8497     gst_qtdemux_stbl_free (stream);
8498     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8499     if (qtdemux->pullbased) {
8500       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8501       while (n + 1 == stream->n_samples)
8502         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8503           break;
8504     }
8505   }
8506   GST_OBJECT_UNLOCK (qtdemux);
8507
8508   return TRUE;
8509
8510   /* SUCCESS */
8511 already_parsed:
8512   {
8513     GST_LOG_OBJECT (qtdemux,
8514         "Tried to parse up to sample %u but this sample has already been parsed",
8515         n);
8516     /* if fragmented, there may be more */
8517     if (qtdemux->fragmented && n == stream->stbl_index)
8518       goto done;
8519     GST_OBJECT_UNLOCK (qtdemux);
8520     return TRUE;
8521   }
8522   /* ERRORS */
8523 out_of_samples:
8524   {
8525     GST_LOG_OBJECT (qtdemux,
8526         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8527         stream->n_samples);
8528     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8529         (_("This file is corrupt and cannot be played.")), (NULL));
8530     return FALSE;
8531   }
8532 corrupt_file:
8533   {
8534     GST_OBJECT_UNLOCK (qtdemux);
8535     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8536         (_("This file is corrupt and cannot be played.")), (NULL));
8537     return FALSE;
8538   }
8539 }
8540
8541 /* collect all segment info for @stream.
8542  */
8543 static gboolean
8544 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8545     GNode * trak)
8546 {
8547   GNode *edts;
8548   /* accept edts if they contain gaps at start and there is only
8549    * one media segment */
8550   gboolean allow_pushbased_edts = TRUE;
8551   gint media_segments_count = 0;
8552
8553   /* parse and prepare segment info from the edit list */
8554   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8555   stream->n_segments = 0;
8556   stream->segments = NULL;
8557   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8558     GNode *elst;
8559     gint n_segments;
8560     gint i, count, entry_size;
8561     guint64 time;
8562     GstClockTime stime;
8563     guint8 *buffer;
8564     guint8 version;
8565
8566     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8567     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8568       goto done;
8569
8570     buffer = elst->data;
8571
8572     version = QT_UINT8 (buffer + 8);
8573     entry_size = (version == 1) ? 20 : 12;
8574
8575     n_segments = QT_UINT32 (buffer + 12);
8576
8577     /* we might allocate a bit too much, at least allocate 1 segment */
8578     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8579
8580     /* segments always start from 0 */
8581     time = 0;
8582     stime = 0;
8583     count = 0;
8584     for (i = 0; i < n_segments; i++) {
8585       guint64 duration;
8586       guint64 media_time;
8587       gboolean time_valid = TRUE;
8588       QtDemuxSegment *segment;
8589       guint32 rate_int;
8590       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8591
8592       if (version == 1) {
8593         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8594         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8595         if (media_time == G_MAXUINT64)
8596           time_valid = FALSE;
8597       } else {
8598         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8599         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8600         if (media_time == G_MAXUINT32)
8601           time_valid = FALSE;
8602       }
8603
8604       if (time_valid)
8605         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8606
8607       segment = &stream->segments[count++];
8608
8609       /* time and duration expressed in global timescale */
8610       segment->time = stime;
8611       /* add non scaled values so we don't cause roundoff errors */
8612       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8613         time += duration;
8614         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8615         segment->duration = stime - segment->time;
8616       } else {
8617         /* zero duration does not imply media_start == media_stop
8618          * but, only specify media_start.*/
8619         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8620         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8621             && stime >= media_start) {
8622           segment->duration = stime - media_start;
8623         } else {
8624           segment->duration = GST_CLOCK_TIME_NONE;
8625         }
8626       }
8627       segment->stop_time = stime;
8628
8629       segment->trak_media_start = media_time;
8630       /* media_time expressed in stream timescale */
8631       if (time_valid) {
8632         segment->media_start = media_start;
8633         segment->media_stop = segment->media_start + segment->duration;
8634         media_segments_count++;
8635       } else {
8636         segment->media_start = GST_CLOCK_TIME_NONE;
8637         segment->media_stop = GST_CLOCK_TIME_NONE;
8638       }
8639       rate_int =
8640           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8641
8642       if (rate_int <= 1) {
8643         /* 0 is not allowed, some programs write 1 instead of the floating point
8644          * value */
8645         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8646             rate_int);
8647         segment->rate = 1;
8648       } else {
8649         segment->rate = rate_int / 65536.0;
8650       }
8651
8652       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8653           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8654           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8655           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8656           i, GST_TIME_ARGS (segment->time),
8657           GST_TIME_ARGS (segment->duration),
8658           GST_TIME_ARGS (segment->media_start), media_time,
8659           GST_TIME_ARGS (segment->media_stop),
8660           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8661           stream->timescale);
8662       if (segment->stop_time > qtdemux->segment.stop) {
8663         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8664             " extends to %" GST_TIME_FORMAT
8665             " past the end of the file duration %" GST_TIME_FORMAT
8666             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8667             GST_TIME_ARGS (qtdemux->segment.stop));
8668         qtdemux->segment.stop = segment->stop_time;
8669       }
8670     }
8671     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8672     stream->n_segments = count;
8673     if (media_segments_count != 1)
8674       allow_pushbased_edts = FALSE;
8675   }
8676 done:
8677
8678   /* push based does not handle segments, so act accordingly here,
8679    * and warn if applicable */
8680   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8681     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8682     /* remove and use default one below, we stream like it anyway */
8683     g_free (stream->segments);
8684     stream->segments = NULL;
8685     stream->n_segments = 0;
8686   }
8687
8688   /* no segments, create one to play the complete trak */
8689   if (stream->n_segments == 0) {
8690     GstClockTime stream_duration =
8691         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8692
8693     if (stream->segments == NULL)
8694       stream->segments = g_new (QtDemuxSegment, 1);
8695
8696     /* represent unknown our way */
8697     if (stream_duration == 0)
8698       stream_duration = GST_CLOCK_TIME_NONE;
8699
8700     stream->segments[0].time = 0;
8701     stream->segments[0].stop_time = stream_duration;
8702     stream->segments[0].duration = stream_duration;
8703     stream->segments[0].media_start = 0;
8704     stream->segments[0].media_stop = stream_duration;
8705     stream->segments[0].rate = 1.0;
8706     stream->segments[0].trak_media_start = 0;
8707
8708     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8709         GST_TIME_ARGS (stream_duration));
8710     stream->n_segments = 1;
8711     stream->dummy_segment = TRUE;
8712   }
8713   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8714
8715   return TRUE;
8716 }
8717
8718 /*
8719  * Parses the stsd atom of a svq3 trak looking for
8720  * the SMI and gama atoms.
8721  */
8722 static void
8723 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8724     guint8 ** gamma, GstBuffer ** seqh)
8725 {
8726   guint8 *_gamma = NULL;
8727   GstBuffer *_seqh = NULL;
8728   guint8 *stsd_data = stsd->data;
8729   guint32 length = QT_UINT32 (stsd_data);
8730   guint16 version;
8731
8732   if (length < 32) {
8733     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8734     goto end;
8735   }
8736
8737   stsd_data += 32;
8738   length -= 32;
8739   version = QT_UINT16 (stsd_data);
8740   if (version == 3) {
8741     if (length >= 70) {
8742       length -= 70;
8743       stsd_data += 70;
8744       while (length > 8) {
8745         guint32 fourcc, size;
8746         guint8 *data;
8747         size = QT_UINT32 (stsd_data);
8748         fourcc = QT_FOURCC (stsd_data + 4);
8749         data = stsd_data + 8;
8750
8751         if (size == 0) {
8752           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8753               "svq3 atom parsing");
8754           goto end;
8755         }
8756
8757         switch (fourcc) {
8758           case FOURCC_gama:{
8759             if (size == 12) {
8760               _gamma = data;
8761             } else {
8762               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8763                   " for gama atom, expected 12", size);
8764             }
8765             break;
8766           }
8767           case FOURCC_SMI_:{
8768             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8769               guint32 seqh_size;
8770               if (_seqh != NULL) {
8771                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8772                     " found, ignoring");
8773               } else {
8774                 seqh_size = QT_UINT32 (data + 4);
8775                 if (seqh_size > 0) {
8776                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8777                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8778                 }
8779               }
8780             }
8781             break;
8782           }
8783           default:{
8784             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8785                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8786           }
8787         }
8788
8789         if (size <= length) {
8790           length -= size;
8791           stsd_data += size;
8792         }
8793       }
8794     } else {
8795       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8796     }
8797   } else {
8798     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8799         G_GUINT16_FORMAT, version);
8800     goto end;
8801   }
8802
8803 end:
8804   if (gamma) {
8805     *gamma = _gamma;
8806   }
8807   if (seqh) {
8808     *seqh = _seqh;
8809   } else if (_seqh) {
8810     gst_buffer_unref (_seqh);
8811   }
8812 }
8813
8814 static gchar *
8815 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8816 {
8817   GNode *dinf;
8818   GstByteReader dref;
8819   gchar *uri = NULL;
8820
8821   /*
8822    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8823    * atom that might contain a 'data' atom with the rtsp uri.
8824    * This case was reported in bug #597497, some info about
8825    * the hndl atom can be found in TN1195
8826    */
8827   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8828   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8829
8830   if (dinf) {
8831     guint32 dref_num_entries = 0;
8832     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8833         gst_byte_reader_skip (&dref, 4) &&
8834         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8835       gint i;
8836
8837       /* search dref entries for hndl atom */
8838       for (i = 0; i < dref_num_entries; i++) {
8839         guint32 size = 0, type;
8840         guint8 string_len = 0;
8841         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8842             qt_atom_parser_get_fourcc (&dref, &type)) {
8843           if (type == FOURCC_hndl) {
8844             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8845
8846             /* skip data reference handle bytes and the
8847              * following pascal string and some extra 4
8848              * bytes I have no idea what are */
8849             if (!gst_byte_reader_skip (&dref, 4) ||
8850                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8851                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8852               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8853               break;
8854             }
8855
8856             /* iterate over the atoms to find the data atom */
8857             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8858               guint32 atom_size;
8859               guint32 atom_type;
8860
8861               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8862                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8863                 if (atom_type == FOURCC_data) {
8864                   const guint8 *uri_aux = NULL;
8865
8866                   /* found the data atom that might contain the rtsp uri */
8867                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8868                       "hndl atom, interpreting it as an URI");
8869                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8870                           &uri_aux)) {
8871                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8872                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8873                     else
8874                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8875                           "didn't contain a rtsp address");
8876                   } else {
8877                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8878                         "atom contents");
8879                   }
8880                   break;
8881                 }
8882                 /* skipping to the next entry */
8883                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8884                   break;
8885               } else {
8886                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8887                     "atom header");
8888                 break;
8889               }
8890             }
8891             break;
8892           }
8893           /* skip to the next entry */
8894           if (!gst_byte_reader_skip (&dref, size - 8))
8895             break;
8896         } else {
8897           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8898         }
8899       }
8900       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8901     }
8902   }
8903   return uri;
8904 }
8905
8906 #define AMR_NB_ALL_MODES        0x81ff
8907 #define AMR_WB_ALL_MODES        0x83ff
8908 static guint
8909 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8910 {
8911   /* The 'damr' atom is of the form:
8912    *
8913    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8914    *    32 b       8 b          16 b           8 b                 8 b
8915    *
8916    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8917    * represents the highest mode used in the stream (and thus the maximum
8918    * bitrate), with a couple of special cases as seen below.
8919    */
8920
8921   /* Map of frame type ID -> bitrate */
8922   static const guint nb_bitrates[] = {
8923     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8924   };
8925   static const guint wb_bitrates[] = {
8926     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8927   };
8928   GstMapInfo map;
8929   gsize max_mode;
8930   guint16 mode_set;
8931
8932   gst_buffer_map (buf, &map, GST_MAP_READ);
8933
8934   if (map.size != 0x11) {
8935     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8936     goto bad_data;
8937   }
8938
8939   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8940     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8941         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8942     goto bad_data;
8943   }
8944
8945   mode_set = QT_UINT16 (map.data + 13);
8946
8947   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8948     max_mode = 7 + (wb ? 1 : 0);
8949   else
8950     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8951     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8952
8953   if (max_mode == -1) {
8954     GST_DEBUG ("No mode indication was found (mode set) = %x",
8955         (guint) mode_set);
8956     goto bad_data;
8957   }
8958
8959   gst_buffer_unmap (buf, &map);
8960   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8961
8962 bad_data:
8963   gst_buffer_unmap (buf, &map);
8964   return 0;
8965 }
8966
8967 static gboolean
8968 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8969     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8970 {
8971   /*
8972    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8973    * [0 1 2]
8974    * [3 4 5]
8975    * [6 7 8]
8976    */
8977
8978   if (gst_byte_reader_get_remaining (reader) < 36)
8979     return FALSE;
8980
8981   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8982   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8983   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8984   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8985   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8986   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8987   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8988   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8989   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8990
8991   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8992   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8993       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8994       matrix[2] & 0xFF);
8995   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8996       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8997       matrix[5] & 0xFF);
8998   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8999       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9000       matrix[8] & 0xFF);
9001
9002   return TRUE;
9003 }
9004
9005 static void
9006 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9007     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9008 {
9009
9010 /* [a b c]
9011  * [d e f]
9012  * [g h i]
9013  *
9014  * This macro will only compare value abdegh, it expects cfi to have already
9015  * been checked
9016  */
9017 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9018                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9019
9020   /* only handle the cases where the last column has standard values */
9021   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9022     const gchar *rotation_tag = NULL;
9023
9024     /* no rotation needed */
9025     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9026       /* NOP */
9027     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9028       rotation_tag = "rotate-90";
9029     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9030       rotation_tag = "rotate-180";
9031     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9032       rotation_tag = "rotate-270";
9033     } else {
9034       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9035     }
9036
9037     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9038         rotation_tag);
9039     if (rotation_tag != NULL) {
9040       if (*taglist == NULL)
9041         *taglist = gst_tag_list_new_empty ();
9042       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9043           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9044     }
9045   } else {
9046     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9047   }
9048 }
9049
9050 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9051  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9052  * Common Encryption (cenc), the function will also parse the tenc box (defined
9053  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9054  * (typically an enc[v|a|t|s] sample entry); the function will set
9055  * @original_fmt to the fourcc of the original unencrypted stream format.
9056  * Returns TRUE if successful; FALSE otherwise. */
9057 static gboolean
9058 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9059     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9060 {
9061   GNode *sinf;
9062   GNode *frma;
9063   GNode *schm;
9064   GNode *schi;
9065
9066   g_return_val_if_fail (qtdemux != NULL, FALSE);
9067   g_return_val_if_fail (stream != NULL, FALSE);
9068   g_return_val_if_fail (container != NULL, FALSE);
9069   g_return_val_if_fail (original_fmt != NULL, FALSE);
9070
9071   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9072   if (G_UNLIKELY (!sinf)) {
9073     if (stream->protection_scheme_type == FOURCC_cenc) {
9074       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9075           "mandatory for Common Encryption");
9076       return FALSE;
9077     }
9078     return TRUE;
9079   }
9080
9081   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9082   if (G_UNLIKELY (!frma)) {
9083     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9084     return FALSE;
9085   }
9086
9087   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9088   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9089       GST_FOURCC_ARGS (*original_fmt));
9090
9091   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9092   if (!schm) {
9093     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9094     return FALSE;
9095   }
9096   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9097   stream->protection_scheme_version =
9098       QT_UINT32 ((const guint8 *) schm->data + 16);
9099
9100   GST_DEBUG_OBJECT (qtdemux,
9101       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9102       "protection_scheme_version: %#010x",
9103       GST_FOURCC_ARGS (stream->protection_scheme_type),
9104       stream->protection_scheme_version);
9105
9106   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9107   if (!schi) {
9108     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9109     return FALSE;
9110   }
9111   if (stream->protection_scheme_type == FOURCC_cenc) {
9112     QtDemuxCencSampleSetInfo *info;
9113     GNode *tenc;
9114     const guint8 *tenc_data;
9115     guint32 isEncrypted;
9116     guint8 iv_size;
9117     const guint8 *default_kid;
9118     GstBuffer *kid_buf;
9119
9120     if (G_UNLIKELY (!stream->protection_scheme_info))
9121       stream->protection_scheme_info =
9122           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9123
9124     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9125
9126     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9127     if (!tenc) {
9128       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9129           "which is mandatory for Common Encryption");
9130       return FALSE;
9131     }
9132     tenc_data = (const guint8 *) tenc->data + 12;
9133     isEncrypted = QT_UINT24 (tenc_data);
9134     iv_size = QT_UINT8 (tenc_data + 3);
9135     default_kid = (tenc_data + 4);
9136     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9137     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9138     if (info->default_properties)
9139       gst_structure_free (info->default_properties);
9140     info->default_properties =
9141         gst_structure_new ("application/x-cenc",
9142         "iv_size", G_TYPE_UINT, iv_size,
9143         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9144         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9145     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9146         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9147     gst_buffer_unref (kid_buf);
9148   }
9149   return TRUE;
9150 }
9151
9152 /* parse the traks.
9153  * With each track we associate a new QtDemuxStream that contains all the info
9154  * about the trak.
9155  * traks that do not decode to something (like strm traks) will not have a pad.
9156  */
9157 static gboolean
9158 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9159 {
9160   GstByteReader tkhd;
9161   int offset;
9162   GNode *mdia;
9163   GNode *mdhd;
9164   GNode *hdlr;
9165   GNode *minf;
9166   GNode *stbl;
9167   GNode *stsd;
9168   GNode *mp4a;
9169   GNode *mp4v;
9170   GNode *wave;
9171   GNode *esds;
9172   GNode *pasp;
9173   GNode *tref;
9174   GNode *udta;
9175   GNode *svmi;
9176
9177   QtDemuxStream *stream = NULL;
9178   gboolean new_stream = FALSE;
9179   gchar *codec = NULL;
9180   const guint8 *stsd_data;
9181   guint16 lang_code;            /* quicktime lang code or packed iso code */
9182   guint32 version;
9183   guint32 tkhd_flags = 0;
9184   guint8 tkhd_version = 0;
9185   guint32 fourcc;
9186   guint value_size, stsd_len, len;
9187   guint32 track_id;
9188   guint32 dummy;
9189
9190   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9191
9192   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9193       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9194       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9195     goto corrupt_file;
9196
9197   /* pick between 64 or 32 bits */
9198   value_size = tkhd_version == 1 ? 8 : 4;
9199   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9200       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9201     goto corrupt_file;
9202
9203   if (!qtdemux->got_moov) {
9204     if (qtdemux_find_stream (qtdemux, track_id))
9205       goto existing_stream;
9206     stream = _create_stream ();
9207     stream->track_id = track_id;
9208     new_stream = TRUE;
9209   } else {
9210     stream = qtdemux_find_stream (qtdemux, track_id);
9211     if (!stream) {
9212       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9213       goto skip_track;
9214     }
9215
9216     /* flush samples data from this track from previous moov */
9217     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9218     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9219   }
9220   /* need defaults for fragments */
9221   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9222
9223   if (stream->pending_tags == NULL)
9224     stream->pending_tags = gst_tag_list_new_empty ();
9225
9226   if ((tkhd_flags & 1) == 0)
9227     stream->disabled = TRUE;
9228
9229   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9230       tkhd_version, tkhd_flags, stream->track_id);
9231
9232   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9233     goto corrupt_file;
9234
9235   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9236     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9237     if (qtdemux->major_brand != FOURCC_mjp2 ||
9238         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9239       goto corrupt_file;
9240   }
9241
9242   len = QT_UINT32 ((guint8 *) mdhd->data);
9243   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9244   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9245   if (version == 0x01000000) {
9246     if (len < 38)
9247       goto corrupt_file;
9248     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9249     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9250     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9251   } else {
9252     if (len < 30)
9253       goto corrupt_file;
9254     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9255     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9256     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9257   }
9258
9259   if (lang_code < 0x400) {
9260     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9261   } else if (lang_code == 0x7fff) {
9262     stream->lang_id[0] = 0;     /* unspecified */
9263   } else {
9264     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9265     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9266     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9267     stream->lang_id[3] = 0;
9268   }
9269
9270   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9271       stream->timescale);
9272   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9273       stream->duration);
9274   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9275       lang_code, stream->lang_id);
9276
9277   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9278     goto corrupt_file;
9279
9280   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9281     /* chapters track reference */
9282     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9283     if (chap) {
9284       gsize length = GST_READ_UINT32_BE (chap->data);
9285       if (qtdemux->chapters_track_id)
9286         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9287
9288       if (length >= 12) {
9289         qtdemux->chapters_track_id =
9290             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9291       }
9292     }
9293   }
9294
9295   /* fragmented files may have bogus duration in moov */
9296   if (!qtdemux->fragmented &&
9297       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9298     guint64 tdur1, tdur2;
9299
9300     /* don't overflow */
9301     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9302     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9303
9304     /* HACK:
9305      * some of those trailers, nowadays, have prologue images that are
9306      * themselves video tracks as well. I haven't really found a way to
9307      * identify those yet, except for just looking at their duration. */
9308     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9309       GST_WARNING_OBJECT (qtdemux,
9310           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9311           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9312           "found, assuming preview image or something; skipping track",
9313           stream->duration, stream->timescale, qtdemux->duration,
9314           qtdemux->timescale);
9315       if (new_stream)
9316         gst_qtdemux_stream_free (qtdemux, stream);
9317       return TRUE;
9318     }
9319   }
9320
9321   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9322     goto corrupt_file;
9323
9324   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9325       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9326
9327   len = QT_UINT32 ((guint8 *) hdlr->data);
9328   if (len >= 20)
9329     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9330   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9331       GST_FOURCC_ARGS (stream->subtype));
9332
9333   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9334     goto corrupt_file;
9335
9336   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9337     goto corrupt_file;
9338
9339   /*parse svmi header if existing */
9340   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9341   if (svmi) {
9342     len = QT_UINT32 ((guint8 *) svmi->data);
9343     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9344     if (!version) {
9345       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9346       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9347       guint8 frame_type, frame_layout;
9348
9349       /* MPEG-A stereo video */
9350       if (qtdemux->major_brand == FOURCC_ss02)
9351         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9352
9353       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9354       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9355       switch (frame_type) {
9356         case 0:
9357           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9358           break;
9359         case 1:
9360           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9361           break;
9362         case 2:
9363           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9364           break;
9365         case 3:
9366           /* mode 3 is primary/secondary view sequence, ie
9367            * left/right views in separate tracks. See section 7.2
9368            * of ISO/IEC 23000-11:2009 */
9369           GST_FIXME_OBJECT (qtdemux,
9370               "Implement stereo video in separate streams");
9371       }
9372
9373       if ((frame_layout & 0x1) == 0)
9374         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9375
9376       GST_LOG_OBJECT (qtdemux,
9377           "StereoVideo: composition type: %u, is_left_first: %u",
9378           frame_type, frame_layout);
9379       stream->multiview_mode = mode;
9380       stream->multiview_flags = flags;
9381     }
9382   }
9383
9384   /* parse stsd */
9385   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9386     goto corrupt_file;
9387   stsd_data = (const guint8 *) stsd->data;
9388
9389   /* stsd should at least have one entry */
9390   stsd_len = QT_UINT32 (stsd_data);
9391   if (stsd_len < 24) {
9392     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9393     if (stream->subtype == FOURCC_vivo) {
9394       if (new_stream)
9395         gst_qtdemux_stream_free (qtdemux, stream);
9396       return TRUE;
9397     } else {
9398       goto corrupt_file;
9399     }
9400   }
9401
9402   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9403
9404   /* and that entry should fit within stsd */
9405   len = QT_UINT32 (stsd_data + 16);
9406   if (len > stsd_len + 16)
9407     goto corrupt_file;
9408
9409   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9410   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9411       GST_FOURCC_ARGS (stream->fourcc));
9412   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9413
9414   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9415     goto error_encrypted;
9416
9417   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9418     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9419     stream->protected = TRUE;
9420     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9421       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9422   }
9423
9424   if (stream->subtype == FOURCC_vide) {
9425     guint32 w = 0, h = 0;
9426     gboolean gray;
9427     gint depth, palette_size, palette_count;
9428     guint32 matrix[9];
9429     guint32 *palette_data = NULL;
9430
9431     stream->sampled = TRUE;
9432
9433     /* version 1 uses some 64-bit ints */
9434     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9435       goto corrupt_file;
9436
9437     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9438       goto corrupt_file;
9439
9440     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9441         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9442       goto corrupt_file;
9443
9444     stream->display_width = w >> 16;
9445     stream->display_height = h >> 16;
9446
9447     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9448         &stream->pending_tags);
9449
9450     offset = 16;
9451     if (len < 86)
9452       goto corrupt_file;
9453
9454     stream->width = QT_UINT16 (stsd_data + offset + 32);
9455     stream->height = QT_UINT16 (stsd_data + offset + 34);
9456     stream->fps_n = 0;          /* this is filled in later */
9457     stream->fps_d = 0;          /* this is filled in later */
9458     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9459     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9460
9461     /* if color_table_id is 0, ctab atom must follow; however some files
9462      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9463      * if color table is not present we'll correct the value */
9464     if (stream->color_table_id == 0 &&
9465         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9466       stream->color_table_id = -1;
9467     }
9468
9469     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9470         stream->width, stream->height, stream->bits_per_sample,
9471         stream->color_table_id);
9472
9473     depth = stream->bits_per_sample;
9474
9475     /* more than 32 bits means grayscale */
9476     gray = (depth > 32);
9477     /* low 32 bits specify the depth  */
9478     depth &= 0x1F;
9479
9480     /* different number of palette entries is determined by depth. */
9481     palette_count = 0;
9482     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9483       palette_count = (1 << depth);
9484     palette_size = palette_count * 4;
9485
9486     if (stream->color_table_id) {
9487       switch (palette_count) {
9488         case 0:
9489           break;
9490         case 2:
9491           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9492           break;
9493         case 4:
9494           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9495           break;
9496         case 16:
9497           if (gray)
9498             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9499           else
9500             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9501           break;
9502         case 256:
9503           if (gray)
9504             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9505           else
9506             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9507           break;
9508         default:
9509           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9510               (_("The video in this file might not play correctly.")),
9511               ("unsupported palette depth %d", depth));
9512           break;
9513       }
9514     } else {
9515       gint i, j, start, end;
9516
9517       if (len < 94)
9518         goto corrupt_file;
9519
9520       /* read table */
9521       start = QT_UINT32 (stsd_data + offset + 86);
9522       palette_count = QT_UINT16 (stsd_data + offset + 90);
9523       end = QT_UINT16 (stsd_data + offset + 92);
9524
9525       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9526           start, end, palette_count);
9527
9528       if (end > 255)
9529         end = 255;
9530       if (start > end)
9531         start = end;
9532
9533       if (len < 94 + (end - start) * 8)
9534         goto corrupt_file;
9535
9536       /* palette is always the same size */
9537       palette_data = g_malloc0 (256 * 4);
9538       palette_size = 256 * 4;
9539
9540       for (j = 0, i = start; i <= end; j++, i++) {
9541         guint32 a, r, g, b;
9542
9543         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9544         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9545         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9546         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9547
9548         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9549             (g & 0xff00) | (b >> 8);
9550       }
9551     }
9552
9553     if (stream->caps)
9554       gst_caps_unref (stream->caps);
9555
9556     stream->caps =
9557         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9558     if (G_UNLIKELY (!stream->caps)) {
9559       g_free (palette_data);
9560       goto unknown_stream;
9561     }
9562
9563     if (codec) {
9564       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9565           GST_TAG_VIDEO_CODEC, codec, NULL);
9566       g_free (codec);
9567       codec = NULL;
9568     }
9569
9570
9571     if (palette_data) {
9572       GstStructure *s;
9573
9574       if (stream->rgb8_palette)
9575         gst_memory_unref (stream->rgb8_palette);
9576       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9577           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9578
9579       s = gst_caps_get_structure (stream->caps, 0);
9580
9581       /* non-raw video has a palette_data property. raw video has the palette as
9582        * an extra plane that we append to the output buffers before we push
9583        * them*/
9584       if (!gst_structure_has_name (s, "video/x-raw")) {
9585         GstBuffer *palette;
9586
9587         palette = gst_buffer_new ();
9588         gst_buffer_append_memory (palette, stream->rgb8_palette);
9589         stream->rgb8_palette = NULL;
9590
9591         gst_caps_set_simple (stream->caps, "palette_data",
9592             GST_TYPE_BUFFER, palette, NULL);
9593         gst_buffer_unref (palette);
9594       }
9595     } else if (palette_count != 0) {
9596       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9597           (NULL), ("Unsupported palette depth %d", depth));
9598     }
9599
9600     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9601         QT_UINT16 (stsd_data + offset + 48));
9602
9603     esds = NULL;
9604     pasp = NULL;
9605     /* pick 'the' stsd child */
9606     if (!stream->protected)
9607       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9608     else
9609       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9610
9611     if (mp4v) {
9612       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9613       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9614     }
9615
9616     if (pasp) {
9617       const guint8 *pasp_data = (const guint8 *) pasp->data;
9618
9619       stream->par_w = QT_UINT32 (pasp_data + 8);
9620       stream->par_h = QT_UINT32 (pasp_data + 12);
9621     } else {
9622       stream->par_w = 0;
9623       stream->par_h = 0;
9624     }
9625
9626     if (esds) {
9627       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9628     } else {
9629       switch (fourcc) {
9630         case FOURCC_H264:
9631         case FOURCC_avc1:
9632         case FOURCC_avc3:
9633         {
9634           gint len = QT_UINT32 (stsd_data) - 0x66;
9635           const guint8 *avc_data = stsd_data + 0x66;
9636
9637           /* find avcC */
9638           while (len >= 0x8) {
9639             gint size;
9640
9641             if (QT_UINT32 (avc_data) <= len)
9642               size = QT_UINT32 (avc_data) - 0x8;
9643             else
9644               size = len - 0x8;
9645
9646             if (size < 1)
9647               /* No real data, so break out */
9648               break;
9649
9650             switch (QT_FOURCC (avc_data + 0x4)) {
9651               case FOURCC_avcC:
9652               {
9653                 /* parse, if found */
9654                 GstBuffer *buf;
9655
9656                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9657
9658                 /* First 4 bytes are the length of the atom, the next 4 bytes
9659                  * are the fourcc, the next 1 byte is the version, and the
9660                  * subsequent bytes are profile_tier_level structure like data. */
9661                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9662                     avc_data + 8 + 1, size - 1);
9663                 buf = gst_buffer_new_and_alloc (size);
9664                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9665                 gst_caps_set_simple (stream->caps,
9666                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9667                 gst_buffer_unref (buf);
9668
9669                 break;
9670               }
9671               case FOURCC_strf:
9672               {
9673                 GstBuffer *buf;
9674
9675                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9676
9677                 /* First 4 bytes are the length of the atom, the next 4 bytes
9678                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9679                  * next 1 byte is the version, and the
9680                  * subsequent bytes are sequence parameter set like data. */
9681
9682                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9683                 if (size > 1) {
9684                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9685                       avc_data + 8 + 40 + 1, size - 1);
9686
9687                   buf = gst_buffer_new_and_alloc (size);
9688                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9689                   gst_caps_set_simple (stream->caps,
9690                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9691                   gst_buffer_unref (buf);
9692                 }
9693                 break;
9694               }
9695               case FOURCC_btrt:
9696               {
9697                 guint avg_bitrate, max_bitrate;
9698
9699                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9700                 if (size < 12)
9701                   break;
9702
9703                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9704                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9705
9706                 if (!max_bitrate && !avg_bitrate)
9707                   break;
9708
9709                 /* Some muxers seem to swap the average and maximum bitrates
9710                  * (I'm looking at you, YouTube), so we swap for sanity. */
9711                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9712                   guint temp = avg_bitrate;
9713
9714                   avg_bitrate = max_bitrate;
9715                   max_bitrate = temp;
9716                 }
9717
9718                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9719                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9720                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9721                 }
9722                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9723                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9724                       GST_TAG_BITRATE, avg_bitrate, NULL);
9725                 }
9726
9727                 break;
9728               }
9729
9730               default:
9731                 break;
9732             }
9733
9734             len -= size + 8;
9735             avc_data += size + 8;
9736           }
9737
9738           break;
9739         }
9740         case FOURCC_H265:
9741         case FOURCC_hvc1:
9742         case FOURCC_hev1:
9743         {
9744           gint len = QT_UINT32 (stsd_data) - 0x66;
9745           const guint8 *hevc_data = stsd_data + 0x66;
9746
9747           /* find hevc */
9748           while (len >= 0x8) {
9749             gint size;
9750
9751             if (QT_UINT32 (hevc_data) <= len)
9752               size = QT_UINT32 (hevc_data) - 0x8;
9753             else
9754               size = len - 0x8;
9755
9756             if (size < 1)
9757               /* No real data, so break out */
9758               break;
9759
9760             switch (QT_FOURCC (hevc_data + 0x4)) {
9761               case FOURCC_hvcC:
9762               {
9763                 /* parse, if found */
9764                 GstBuffer *buf;
9765
9766                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9767
9768                 /* First 4 bytes are the length of the atom, the next 4 bytes
9769                  * are the fourcc, the next 1 byte is the version, and the
9770                  * subsequent bytes are sequence parameter set like data. */
9771                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9772                     (stream->caps, hevc_data + 8 + 1, size - 1);
9773
9774                 buf = gst_buffer_new_and_alloc (size);
9775                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9776                 gst_caps_set_simple (stream->caps,
9777                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9778                 gst_buffer_unref (buf);
9779                 break;
9780               }
9781               default:
9782                 break;
9783             }
9784             len -= size + 8;
9785             hevc_data += size + 8;
9786           }
9787           break;
9788         }
9789         case FOURCC_mp4v:
9790         case FOURCC_MP4V:
9791         case FOURCC_fmp4:
9792         case FOURCC_FMP4:
9793         {
9794           GNode *glbl;
9795
9796           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9797               GST_FOURCC_ARGS (fourcc));
9798
9799           /* codec data might be in glbl extension atom */
9800           glbl = mp4v ?
9801               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9802           if (glbl) {
9803             guint8 *data;
9804             GstBuffer *buf;
9805             gint len;
9806
9807             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9808             data = glbl->data;
9809             len = QT_UINT32 (data);
9810             if (len > 0x8) {
9811               len -= 0x8;
9812               buf = gst_buffer_new_and_alloc (len);
9813               gst_buffer_fill (buf, 0, data + 8, len);
9814               gst_caps_set_simple (stream->caps,
9815                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9816               gst_buffer_unref (buf);
9817             }
9818           }
9819           break;
9820         }
9821         case FOURCC_mjp2:
9822         {
9823           /* see annex I of the jpeg2000 spec */
9824           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9825           const guint8 *data;
9826           const gchar *colorspace = NULL;
9827           gint ncomp = 0;
9828           guint32 ncomp_map = 0;
9829           gint32 *comp_map = NULL;
9830           guint32 nchan_def = 0;
9831           gint32 *chan_def = NULL;
9832
9833           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9834           /* some required atoms */
9835           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9836           if (!mjp2)
9837             break;
9838           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9839           if (!jp2h)
9840             break;
9841
9842           /* number of components; redundant with info in codestream, but useful
9843              to a muxer */
9844           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9845           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9846             break;
9847           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9848
9849           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9850           if (!colr)
9851             break;
9852           GST_DEBUG_OBJECT (qtdemux, "found colr");
9853           /* extract colour space info */
9854           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9855             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9856               case 16:
9857                 colorspace = "sRGB";
9858                 break;
9859               case 17:
9860                 colorspace = "GRAY";
9861                 break;
9862               case 18:
9863                 colorspace = "sYUV";
9864                 break;
9865               default:
9866                 colorspace = NULL;
9867                 break;
9868             }
9869           }
9870           if (!colorspace)
9871             /* colr is required, and only values 16, 17, and 18 are specified,
9872                so error if we have no colorspace */
9873             break;
9874
9875           /* extract component mapping */
9876           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9877           if (cmap) {
9878             guint32 cmap_len = 0;
9879             int i;
9880             cmap_len = QT_UINT32 (cmap->data);
9881             if (cmap_len >= 8) {
9882               /* normal box, subtract off header */
9883               cmap_len -= 8;
9884               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9885               if (cmap_len % 4 == 0) {
9886                 ncomp_map = (cmap_len / 4);
9887                 comp_map = g_new0 (gint32, ncomp_map);
9888                 for (i = 0; i < ncomp_map; i++) {
9889                   guint16 cmp;
9890                   guint8 mtyp, pcol;
9891                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9892                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9893                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9894                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9895                 }
9896               }
9897             }
9898           }
9899           /* extract channel definitions */
9900           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9901           if (cdef) {
9902             guint32 cdef_len = 0;
9903             int i;
9904             cdef_len = QT_UINT32 (cdef->data);
9905             if (cdef_len >= 10) {
9906               /* normal box, subtract off header and len */
9907               cdef_len -= 10;
9908               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9909               if (cdef_len % 6 == 0) {
9910                 nchan_def = (cdef_len / 6);
9911                 chan_def = g_new0 (gint32, nchan_def);
9912                 for (i = 0; i < nchan_def; i++)
9913                   chan_def[i] = -1;
9914                 for (i = 0; i < nchan_def; i++) {
9915                   guint16 cn, typ, asoc;
9916                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9917                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9918                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9919                   if (cn < nchan_def) {
9920                     switch (typ) {
9921                       case 0:
9922                         chan_def[cn] = asoc;
9923                         break;
9924                       case 1:
9925                         chan_def[cn] = 0;       /* alpha */
9926                         break;
9927                       default:
9928                         chan_def[cn] = -typ;
9929                     }
9930                   }
9931                 }
9932               }
9933             }
9934           }
9935
9936           gst_caps_set_simple (stream->caps,
9937               "num-components", G_TYPE_INT, ncomp, NULL);
9938           gst_caps_set_simple (stream->caps,
9939               "colorspace", G_TYPE_STRING, colorspace, NULL);
9940
9941           if (comp_map) {
9942             GValue arr = { 0, };
9943             GValue elt = { 0, };
9944             int i;
9945             g_value_init (&arr, GST_TYPE_ARRAY);
9946             g_value_init (&elt, G_TYPE_INT);
9947             for (i = 0; i < ncomp_map; i++) {
9948               g_value_set_int (&elt, comp_map[i]);
9949               gst_value_array_append_value (&arr, &elt);
9950             }
9951             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9952                 "component-map", &arr);
9953             g_value_unset (&elt);
9954             g_value_unset (&arr);
9955             g_free (comp_map);
9956           }
9957
9958           if (chan_def) {
9959             GValue arr = { 0, };
9960             GValue elt = { 0, };
9961             int i;
9962             g_value_init (&arr, GST_TYPE_ARRAY);
9963             g_value_init (&elt, G_TYPE_INT);
9964             for (i = 0; i < nchan_def; i++) {
9965               g_value_set_int (&elt, chan_def[i]);
9966               gst_value_array_append_value (&arr, &elt);
9967             }
9968             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9969                 "channel-definitions", &arr);
9970             g_value_unset (&elt);
9971             g_value_unset (&arr);
9972             g_free (chan_def);
9973           }
9974
9975           /* some optional atoms */
9976           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9977           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9978
9979           /* indicate possible fields in caps */
9980           if (field) {
9981             data = (guint8 *) field->data + 8;
9982             if (*data != 1)
9983               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9984                   (gint) * data, NULL);
9985           }
9986           /* add codec_data if provided */
9987           if (prefix) {
9988             GstBuffer *buf;
9989             gint len;
9990
9991             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9992             data = prefix->data;
9993             len = QT_UINT32 (data);
9994             if (len > 0x8) {
9995               len -= 0x8;
9996               buf = gst_buffer_new_and_alloc (len);
9997               gst_buffer_fill (buf, 0, data + 8, len);
9998               gst_caps_set_simple (stream->caps,
9999                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10000               gst_buffer_unref (buf);
10001             }
10002           }
10003           break;
10004         }
10005         case FOURCC_SVQ3:
10006         case FOURCC_VP31:
10007         {
10008           GstBuffer *buf;
10009           GstBuffer *seqh = NULL;
10010           guint8 *gamma_data = NULL;
10011           gint len = QT_UINT32 (stsd_data);
10012
10013           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10014           if (gamma_data) {
10015             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10016                 QT_FP32 (gamma_data), NULL);
10017           }
10018           if (seqh) {
10019             /* sorry for the bad name, but we don't know what this is, other
10020              * than its own fourcc */
10021             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10022                 NULL);
10023           }
10024
10025           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10026           buf = gst_buffer_new_and_alloc (len);
10027           gst_buffer_fill (buf, 0, stsd_data, len);
10028           gst_caps_set_simple (stream->caps,
10029               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10030           gst_buffer_unref (buf);
10031           break;
10032         }
10033         case FOURCC_rle_:
10034         case FOURCC_WRLE:
10035         {
10036           gst_caps_set_simple (stream->caps,
10037               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10038           break;
10039         }
10040         case FOURCC_XiTh:
10041         {
10042           GNode *xith, *xdxt;
10043
10044           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10045           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
10046           if (!xith)
10047             break;
10048
10049           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10050           if (!xdxt)
10051             break;
10052
10053           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10054           /* collect the headers and store them in a stream list so that we can
10055            * send them out first */
10056           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10057           break;
10058         }
10059         case FOURCC_ovc1:
10060         {
10061           GNode *ovc1;
10062           guint8 *ovc1_data;
10063           guint ovc1_len;
10064           GstBuffer *buf;
10065
10066           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10067           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
10068           if (!ovc1)
10069             break;
10070           ovc1_data = ovc1->data;
10071           ovc1_len = QT_UINT32 (ovc1_data);
10072           if (ovc1_len <= 198) {
10073             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10074             break;
10075           }
10076           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10077           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10078           gst_caps_set_simple (stream->caps,
10079               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10080           gst_buffer_unref (buf);
10081           break;
10082         }
10083         case FOURCC_vc_1:
10084         {
10085           gint len = QT_UINT32 (stsd_data) - 0x66;
10086           const guint8 *vc1_data = stsd_data + 0x66;
10087
10088           /* find dvc1 */
10089           while (len >= 8) {
10090             gint size;
10091
10092             if (QT_UINT32 (vc1_data) <= len)
10093               size = QT_UINT32 (vc1_data) - 8;
10094             else
10095               size = len - 8;
10096
10097             if (size < 1)
10098               /* No real data, so break out */
10099               break;
10100
10101             switch (QT_FOURCC (vc1_data + 0x4)) {
10102               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10103               {
10104                 GstBuffer *buf;
10105
10106                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10107                 buf = gst_buffer_new_and_alloc (size);
10108                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10109                 gst_caps_set_simple (stream->caps,
10110                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10111                 gst_buffer_unref (buf);
10112                 break;
10113               }
10114               default:
10115                 break;
10116             }
10117             len -= size + 8;
10118             vc1_data += size + 8;
10119           }
10120           break;
10121         }
10122         default:
10123           break;
10124       }
10125     }
10126
10127     GST_INFO_OBJECT (qtdemux,
10128         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10129         GST_FOURCC_ARGS (fourcc), stream->caps);
10130
10131   } else if (stream->subtype == FOURCC_soun) {
10132     int version, samplesize;
10133     guint16 compression_id;
10134     gboolean amrwb = FALSE;
10135
10136     offset = 32;
10137     /* sample description entry (16) + sound sample description v0 (20) */
10138     if (len < 36)
10139       goto corrupt_file;
10140
10141     version = QT_UINT32 (stsd_data + offset);
10142     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10143     samplesize = QT_UINT16 (stsd_data + offset + 10);
10144     compression_id = QT_UINT16 (stsd_data + offset + 12);
10145     stream->rate = QT_FP32 (stsd_data + offset + 16);
10146
10147     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10148     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10149         QT_UINT32 (stsd_data + offset + 4));
10150     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10151     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10152     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10153     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10154         QT_UINT16 (stsd_data + offset + 14));
10155     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10156
10157     if (compression_id == 0xfffe)
10158       stream->sampled = TRUE;
10159
10160     /* first assume uncompressed audio */
10161     stream->bytes_per_sample = samplesize / 8;
10162     stream->samples_per_frame = stream->n_channels;
10163     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10164     stream->samples_per_packet = stream->samples_per_frame;
10165     stream->bytes_per_packet = stream->bytes_per_sample;
10166
10167     offset = 52;
10168     switch (fourcc) {
10169         /* Yes, these have to be hard-coded */
10170       case FOURCC_MAC6:
10171       {
10172         stream->samples_per_packet = 6;
10173         stream->bytes_per_packet = 1;
10174         stream->bytes_per_frame = 1 * stream->n_channels;
10175         stream->bytes_per_sample = 1;
10176         stream->samples_per_frame = 6 * stream->n_channels;
10177         break;
10178       }
10179       case FOURCC_MAC3:
10180       {
10181         stream->samples_per_packet = 3;
10182         stream->bytes_per_packet = 1;
10183         stream->bytes_per_frame = 1 * stream->n_channels;
10184         stream->bytes_per_sample = 1;
10185         stream->samples_per_frame = 3 * stream->n_channels;
10186         break;
10187       }
10188       case FOURCC_ima4:
10189       {
10190         stream->samples_per_packet = 64;
10191         stream->bytes_per_packet = 34;
10192         stream->bytes_per_frame = 34 * stream->n_channels;
10193         stream->bytes_per_sample = 2;
10194         stream->samples_per_frame = 64 * stream->n_channels;
10195         break;
10196       }
10197       case FOURCC_ulaw:
10198       case FOURCC_alaw:
10199       {
10200         stream->samples_per_packet = 1;
10201         stream->bytes_per_packet = 1;
10202         stream->bytes_per_frame = 1 * stream->n_channels;
10203         stream->bytes_per_sample = 1;
10204         stream->samples_per_frame = 1 * stream->n_channels;
10205         break;
10206       }
10207       case FOURCC_agsm:
10208       {
10209         stream->samples_per_packet = 160;
10210         stream->bytes_per_packet = 33;
10211         stream->bytes_per_frame = 33 * stream->n_channels;
10212         stream->bytes_per_sample = 2;
10213         stream->samples_per_frame = 160 * stream->n_channels;
10214         break;
10215       }
10216       default:
10217         break;
10218     }
10219
10220     if (version == 0x00010000) {
10221       /* sample description entry (16) + sound sample description v1 (20+16) */
10222       if (len < 52)
10223         goto corrupt_file;
10224
10225       switch (fourcc) {
10226         case FOURCC_twos:
10227         case FOURCC_sowt:
10228         case FOURCC_raw_:
10229           break;
10230         default:
10231         {
10232           /* only parse extra decoding config for non-pcm audio */
10233           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10234           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10235           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10236           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10237
10238           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10239               stream->samples_per_packet);
10240           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10241               stream->bytes_per_packet);
10242           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10243               stream->bytes_per_frame);
10244           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10245               stream->bytes_per_sample);
10246
10247           if (!stream->sampled && stream->bytes_per_packet) {
10248             stream->samples_per_frame = (stream->bytes_per_frame /
10249                 stream->bytes_per_packet) * stream->samples_per_packet;
10250             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10251                 stream->samples_per_frame);
10252           }
10253           break;
10254         }
10255       }
10256     } else if (version == 0x00020000) {
10257       union
10258       {
10259         gdouble fp;
10260         guint64 val;
10261       } qtfp;
10262
10263       /* sample description entry (16) + sound sample description v2 (56) */
10264       if (len < 72)
10265         goto corrupt_file;
10266
10267       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10268       stream->rate = qtfp.fp;
10269       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10270
10271       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10272       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10273       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10274       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10275           QT_UINT32 (stsd_data + offset + 20));
10276       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10277           QT_UINT32 (stsd_data + offset + 24));
10278       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10279           QT_UINT32 (stsd_data + offset + 28));
10280       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10281           QT_UINT32 (stsd_data + offset + 32));
10282     } else if (version != 0x00000) {
10283       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10284     }
10285
10286     if (stream->caps)
10287       gst_caps_unref (stream->caps);
10288
10289     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10290         stsd_data + 32, len - 16, &codec);
10291
10292     switch (fourcc) {
10293       case FOURCC_in24:
10294       {
10295         GNode *enda;
10296         GNode *in24;
10297
10298         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10299
10300         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10301         if (!enda) {
10302           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10303           if (wave)
10304             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10305         }
10306         if (enda) {
10307           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10308           gst_caps_set_simple (stream->caps,
10309               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10310         }
10311         break;
10312       }
10313       case FOURCC_owma:
10314       {
10315         GNode *owma;
10316         const guint8 *owma_data;
10317         const gchar *codec_name = NULL;
10318         guint owma_len;
10319         GstBuffer *buf;
10320         gint version = 1;
10321         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10322         /* FIXME this should also be gst_riff_strf_auds,
10323          * but the latter one is actually missing bits-per-sample :( */
10324         typedef struct
10325         {
10326           gint16 wFormatTag;
10327           gint16 nChannels;
10328           gint32 nSamplesPerSec;
10329           gint32 nAvgBytesPerSec;
10330           gint16 nBlockAlign;
10331           gint16 wBitsPerSample;
10332           gint16 cbSize;
10333         } WAVEFORMATEX;
10334         WAVEFORMATEX *wfex;
10335
10336         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10337         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10338         if (!owma)
10339           break;
10340         owma_data = owma->data;
10341         owma_len = QT_UINT32 (owma_data);
10342         if (owma_len <= 54) {
10343           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10344           break;
10345         }
10346         wfex = (WAVEFORMATEX *) (owma_data + 36);
10347         buf = gst_buffer_new_and_alloc (owma_len - 54);
10348         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10349         if (wfex->wFormatTag == 0x0161) {
10350           codec_name = "Windows Media Audio";
10351           version = 2;
10352         } else if (wfex->wFormatTag == 0x0162) {
10353           codec_name = "Windows Media Audio 9 Pro";
10354           version = 3;
10355         } else if (wfex->wFormatTag == 0x0163) {
10356           codec_name = "Windows Media Audio 9 Lossless";
10357           /* is that correct? gstffmpegcodecmap.c is missing it, but
10358            * fluendo codec seems to support it */
10359           version = 4;
10360         }
10361
10362         gst_caps_set_simple (stream->caps,
10363             "codec_data", GST_TYPE_BUFFER, buf,
10364             "wmaversion", G_TYPE_INT, version,
10365             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10366             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10367             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10368             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10369             NULL);
10370         gst_buffer_unref (buf);
10371
10372         if (codec_name) {
10373           g_free (codec);
10374           codec = g_strdup (codec_name);
10375         }
10376         break;
10377       }
10378       case FOURCC_wma_:
10379       {
10380         gint len = QT_UINT32 (stsd_data) - offset;
10381         const guint8 *wfex_data = stsd_data + offset;
10382         const gchar *codec_name = NULL;
10383         gint version = 1;
10384         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10385         /* FIXME this should also be gst_riff_strf_auds,
10386          * but the latter one is actually missing bits-per-sample :( */
10387         typedef struct
10388         {
10389           gint16 wFormatTag;
10390           gint16 nChannels;
10391           gint32 nSamplesPerSec;
10392           gint32 nAvgBytesPerSec;
10393           gint16 nBlockAlign;
10394           gint16 wBitsPerSample;
10395           gint16 cbSize;
10396         } WAVEFORMATEX;
10397         WAVEFORMATEX wfex;
10398
10399         /* FIXME: unify with similar wavformatex parsing code above */
10400         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10401
10402         /* find wfex */
10403         while (len >= 8) {
10404           gint size;
10405
10406           if (QT_UINT32 (wfex_data) <= len)
10407             size = QT_UINT32 (wfex_data) - 8;
10408           else
10409             size = len - 8;
10410
10411           if (size < 1)
10412             /* No real data, so break out */
10413             break;
10414
10415           switch (QT_FOURCC (wfex_data + 4)) {
10416             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10417             {
10418               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10419
10420               if (size < 8 + 18)
10421                 break;
10422
10423               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10424               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10425               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10426               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10427               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10428               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10429               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10430
10431               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10432               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10433                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10434                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10435                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10436                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10437
10438               if (wfex.wFormatTag == 0x0161) {
10439                 codec_name = "Windows Media Audio";
10440                 version = 2;
10441               } else if (wfex.wFormatTag == 0x0162) {
10442                 codec_name = "Windows Media Audio 9 Pro";
10443                 version = 3;
10444               } else if (wfex.wFormatTag == 0x0163) {
10445                 codec_name = "Windows Media Audio 9 Lossless";
10446                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10447                  * fluendo codec seems to support it */
10448                 version = 4;
10449               }
10450
10451               gst_caps_set_simple (stream->caps,
10452                   "wmaversion", G_TYPE_INT, version,
10453                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10454                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10455                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10456                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10457
10458               if (size > wfex.cbSize) {
10459                 GstBuffer *buf;
10460
10461                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10462                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10463                     size - wfex.cbSize);
10464                 gst_caps_set_simple (stream->caps,
10465                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10466                 gst_buffer_unref (buf);
10467               } else {
10468                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10469               }
10470
10471               if (codec_name) {
10472                 g_free (codec);
10473                 codec = g_strdup (codec_name);
10474               }
10475               break;
10476             }
10477             default:
10478               break;
10479           }
10480           len -= size + 8;
10481           wfex_data += size + 8;
10482         }
10483         break;
10484       }
10485       case FOURCC_opus:
10486       {
10487         GNode *opus;
10488         const guint8 *opus_data;
10489         guint8 *channel_mapping = NULL;
10490         guint32 rate;
10491         guint8 channels;
10492         guint8 channel_mapping_family;
10493         guint8 stream_count;
10494         guint8 coupled_count;
10495         guint8 i;
10496
10497         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10498         opus_data = opus->data;
10499
10500         channels = GST_READ_UINT8 (opus_data + 45);
10501         rate = GST_READ_UINT32_LE (opus_data + 48);
10502         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10503         stream_count = GST_READ_UINT8 (opus_data + 55);
10504         coupled_count = GST_READ_UINT8 (opus_data + 56);
10505
10506         if (channels > 0) {
10507           channel_mapping = g_malloc (channels * sizeof (guint8));
10508           for (i = 0; i < channels; i++)
10509             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10510         }
10511
10512         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10513             channel_mapping_family, stream_count, coupled_count,
10514             channel_mapping);
10515         break;
10516       }
10517       default:
10518         break;
10519     }
10520
10521     if (codec) {
10522       GstStructure *s;
10523       gint bitrate = 0;
10524
10525       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10526           GST_TAG_AUDIO_CODEC, codec, NULL);
10527       g_free (codec);
10528       codec = NULL;
10529
10530       /* some bitrate info may have ended up in caps */
10531       s = gst_caps_get_structure (stream->caps, 0);
10532       gst_structure_get_int (s, "bitrate", &bitrate);
10533       if (bitrate > 0)
10534         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10535             GST_TAG_BITRATE, bitrate, NULL);
10536     }
10537
10538     if (stream->protected && fourcc == FOURCC_mp4a)
10539       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10540     else
10541       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10542
10543     wave = NULL;
10544     esds = NULL;
10545     if (mp4a) {
10546       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10547       if (wave)
10548         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10549       if (!esds)
10550         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10551     }
10552
10553
10554     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10555        16 bits is a byte-swapped wave-style codec identifier,
10556        and we can find a WAVE header internally to a 'wave' atom here.
10557        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10558        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10559        is big-endian).
10560      */
10561     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10562       if (len < offset + 20) {
10563         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10564       } else {
10565         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10566         const guint8 *data = stsd_data + offset + 16;
10567         GNode *wavenode;
10568         GNode *waveheadernode;
10569
10570         wavenode = g_node_new ((guint8 *) data);
10571         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10572           const guint8 *waveheader;
10573           guint32 headerlen;
10574
10575           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10576           if (waveheadernode) {
10577             waveheader = (const guint8 *) waveheadernode->data;
10578             headerlen = QT_UINT32 (waveheader);
10579
10580             if (headerlen > 8) {
10581               gst_riff_strf_auds *header = NULL;
10582               GstBuffer *headerbuf;
10583               GstBuffer *extra;
10584
10585               waveheader += 8;
10586               headerlen -= 8;
10587
10588               headerbuf = gst_buffer_new_and_alloc (headerlen);
10589               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10590
10591               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10592                       headerbuf, &header, &extra)) {
10593                 gst_caps_unref (stream->caps);
10594                 /* FIXME: Need to do something with the channel reorder map */
10595                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10596                     header, extra, NULL, NULL, NULL);
10597
10598                 if (extra)
10599                   gst_buffer_unref (extra);
10600                 g_free (header);
10601               }
10602             }
10603           } else
10604             GST_DEBUG ("Didn't find waveheadernode for this codec");
10605         }
10606         g_node_destroy (wavenode);
10607       }
10608     } else if (esds) {
10609       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10610     } else {
10611       switch (fourcc) {
10612 #if 0
10613           /* FIXME: what is in the chunk? */
10614         case FOURCC_QDMC:
10615         {
10616           gint len = QT_UINT32 (stsd_data);
10617
10618           /* seems to be always = 116 = 0x74 */
10619           break;
10620         }
10621 #endif
10622         case FOURCC_QDM2:
10623         {
10624           gint len = QT_UINT32 (stsd_data);
10625
10626           if (len > 0x4C) {
10627             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10628
10629             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10630             gst_caps_set_simple (stream->caps,
10631                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10632             gst_buffer_unref (buf);
10633           }
10634           gst_caps_set_simple (stream->caps,
10635               "samplesize", G_TYPE_INT, samplesize, NULL);
10636           break;
10637         }
10638         case FOURCC_alac:
10639         {
10640           GNode *alac, *wave = NULL;
10641
10642           /* apparently, m4a has this atom appended directly in the stsd entry,
10643            * while mov has it in a wave atom */
10644           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10645           if (alac) {
10646             /* alac now refers to stsd entry atom */
10647             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10648             if (wave)
10649               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10650             else
10651               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10652           }
10653           if (alac) {
10654             const guint8 *alac_data = alac->data;
10655             gint len = QT_UINT32 (alac->data);
10656             GstBuffer *buf;
10657
10658             if (len < 36) {
10659               GST_DEBUG_OBJECT (qtdemux,
10660                   "discarding alac atom with unexpected len %d", len);
10661             } else {
10662               /* codec-data contains alac atom size and prefix,
10663                * ffmpeg likes it that way, not quite gst-ish though ...*/
10664               buf = gst_buffer_new_and_alloc (len);
10665               gst_buffer_fill (buf, 0, alac->data, len);
10666               gst_caps_set_simple (stream->caps,
10667                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10668               gst_buffer_unref (buf);
10669
10670               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10671               stream->n_channels = QT_UINT8 (alac_data + 21);
10672               stream->rate = QT_UINT32 (alac_data + 32);
10673             }
10674           }
10675           gst_caps_set_simple (stream->caps,
10676               "samplesize", G_TYPE_INT, samplesize, NULL);
10677           break;
10678         }
10679         case FOURCC_sawb:
10680           /* Fallthrough! */
10681           amrwb = TRUE;
10682         case FOURCC_samr:
10683         {
10684           gint len = QT_UINT32 (stsd_data);
10685
10686           if (len > 0x34) {
10687             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10688             guint bitrate;
10689
10690             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10691
10692             /* If we have enough data, let's try to get the 'damr' atom. See
10693              * the 3GPP container spec (26.244) for more details. */
10694             if ((len - 0x34) > 8 &&
10695                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10696               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10697                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10698             }
10699
10700             gst_caps_set_simple (stream->caps,
10701                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10702             gst_buffer_unref (buf);
10703           }
10704           break;
10705         }
10706         case FOURCC_mp4a:
10707         {
10708           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10709           gint len = QT_UINT32 (stsd_data);
10710
10711           if (len >= 50) {
10712             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10713
10714             if (sound_version == 1) {
10715               guint16 channels = QT_UINT16 (stsd_data + 40);
10716               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10717               guint8 codec_data[2];
10718               GstBuffer *buf;
10719               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10720
10721               gint sample_rate_index =
10722                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10723
10724               /* build AAC codec data */
10725               codec_data[0] = profile << 3;
10726               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10727               codec_data[1] = (sample_rate_index & 0x01) << 7;
10728               codec_data[1] |= (channels & 0xF) << 3;
10729
10730               buf = gst_buffer_new_and_alloc (2);
10731               gst_buffer_fill (buf, 0, codec_data, 2);
10732               gst_caps_set_simple (stream->caps,
10733                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10734               gst_buffer_unref (buf);
10735             }
10736           }
10737           break;
10738         }
10739         default:
10740           GST_INFO_OBJECT (qtdemux,
10741               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10742           break;
10743       }
10744     }
10745     GST_INFO_OBJECT (qtdemux,
10746         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10747         GST_FOURCC_ARGS (fourcc), stream->caps);
10748
10749   } else if (stream->subtype == FOURCC_strm) {
10750     if (fourcc == FOURCC_rtsp) {
10751       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10752     } else {
10753       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10754           GST_FOURCC_ARGS (fourcc));
10755       goto unknown_stream;
10756     }
10757     stream->sampled = TRUE;
10758   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10759       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10760
10761     stream->sampled = TRUE;
10762     stream->sparse = TRUE;
10763
10764     stream->caps =
10765         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10766     if (codec) {
10767       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10768           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10769       g_free (codec);
10770       codec = NULL;
10771     }
10772
10773     /* hunt for sort-of codec data */
10774     switch (fourcc) {
10775       case FOURCC_mp4s:
10776       {
10777         GNode *mp4s = NULL;
10778         GNode *esds = NULL;
10779
10780         /* look for palette in a stsd->mp4s->esds sub-atom */
10781         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10782         if (mp4s)
10783           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10784         if (esds == NULL) {
10785           /* Invalid STSD */
10786           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10787           break;
10788         }
10789
10790         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10791         break;
10792       }
10793       default:
10794         GST_INFO_OBJECT (qtdemux,
10795             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10796         break;
10797     }
10798     GST_INFO_OBJECT (qtdemux,
10799         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10800         GST_FOURCC_ARGS (fourcc), stream->caps);
10801   } else {
10802     /* everything in 1 sample */
10803     stream->sampled = TRUE;
10804
10805     stream->caps =
10806         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10807
10808     if (stream->caps == NULL)
10809       goto unknown_stream;
10810
10811     if (codec) {
10812       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10813           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10814       g_free (codec);
10815       codec = NULL;
10816     }
10817   }
10818
10819   /* promote to sampled format */
10820   if (stream->fourcc == FOURCC_samr) {
10821     /* force mono 8000 Hz for AMR */
10822     stream->sampled = TRUE;
10823     stream->n_channels = 1;
10824     stream->rate = 8000;
10825   } else if (stream->fourcc == FOURCC_sawb) {
10826     /* force mono 16000 Hz for AMR-WB */
10827     stream->sampled = TRUE;
10828     stream->n_channels = 1;
10829     stream->rate = 16000;
10830   } else if (stream->fourcc == FOURCC_mp4a) {
10831     stream->sampled = TRUE;
10832   }
10833
10834   /* collect sample information */
10835   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10836     goto samples_failed;
10837
10838   if (qtdemux->fragmented) {
10839     guint64 offset;
10840
10841     /* need all moov samples as basis; probably not many if any at all */
10842     /* prevent moof parsing taking of at this time */
10843     offset = qtdemux->moof_offset;
10844     qtdemux->moof_offset = 0;
10845     if (stream->n_samples &&
10846         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10847       qtdemux->moof_offset = offset;
10848       goto samples_failed;
10849     }
10850     qtdemux->moof_offset = 0;
10851     /* movie duration more reliable in this case (e.g. mehd) */
10852     if (qtdemux->segment.duration &&
10853         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10854       stream->duration =
10855           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10856   }
10857
10858   /* configure segments */
10859   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10860     goto segments_failed;
10861
10862   /* add some language tag, if useful */
10863   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10864       strcmp (stream->lang_id, "und")) {
10865     const gchar *lang_code;
10866
10867     /* convert ISO 639-2 code to ISO 639-1 */
10868     lang_code = gst_tag_get_language_code (stream->lang_id);
10869     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10870         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10871   }
10872
10873   /* Check for UDTA tags */
10874   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10875     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10876   }
10877
10878   /* now we are ready to add the stream */
10879   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10880     goto too_many_streams;
10881
10882   if (!qtdemux->got_moov) {
10883     qtdemux->streams[qtdemux->n_streams] = stream;
10884     qtdemux->n_streams++;
10885     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10886   }
10887
10888   return TRUE;
10889
10890 /* ERRORS */
10891 skip_track:
10892   {
10893     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10894     if (new_stream)
10895       gst_qtdemux_stream_free (qtdemux, stream);
10896     return TRUE;
10897   }
10898 corrupt_file:
10899   {
10900     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10901         (_("This file is corrupt and cannot be played.")), (NULL));
10902     if (new_stream)
10903       gst_qtdemux_stream_free (qtdemux, stream);
10904     return FALSE;
10905   }
10906 error_encrypted:
10907   {
10908     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10909     if (new_stream)
10910       gst_qtdemux_stream_free (qtdemux, stream);
10911     return FALSE;
10912   }
10913 samples_failed:
10914 segments_failed:
10915   {
10916     /* we posted an error already */
10917     /* free stbl sub-atoms */
10918     gst_qtdemux_stbl_free (stream);
10919     if (new_stream)
10920       gst_qtdemux_stream_free (qtdemux, stream);
10921     return FALSE;
10922   }
10923 existing_stream:
10924   {
10925     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10926         track_id);
10927     if (new_stream)
10928       gst_qtdemux_stream_free (qtdemux, stream);
10929     return TRUE;
10930   }
10931 unknown_stream:
10932   {
10933     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10934         GST_FOURCC_ARGS (stream->subtype));
10935     if (new_stream)
10936       gst_qtdemux_stream_free (qtdemux, stream);
10937     return TRUE;
10938   }
10939 too_many_streams:
10940   {
10941     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10942         (_("This file contains too many streams. Only playing first %d"),
10943             GST_QTDEMUX_MAX_STREAMS), (NULL));
10944     return TRUE;
10945   }
10946 }
10947
10948 /* If we can estimate the overall bitrate, and don't have information about the
10949  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10950  * the overall bitrate minus the sum of the bitrates of all other streams. This
10951  * should be useful for the common case where we have one audio and one video
10952  * stream and can estimate the bitrate of one, but not the other. */
10953 static void
10954 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10955 {
10956   QtDemuxStream *stream = NULL;
10957   gint64 size, sys_bitrate, sum_bitrate = 0;
10958   GstClockTime duration;
10959   gint i;
10960   guint bitrate;
10961
10962   if (qtdemux->fragmented)
10963     return;
10964
10965   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10966
10967   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10968       || size <= 0) {
10969     GST_DEBUG_OBJECT (qtdemux,
10970         "Size in bytes of the stream not known - bailing");
10971     return;
10972   }
10973
10974   /* Subtract the header size */
10975   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10976       size, qtdemux->header_size);
10977
10978   if (size < qtdemux->header_size)
10979     return;
10980
10981   size = size - qtdemux->header_size;
10982
10983   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
10984     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10985     return;
10986   }
10987
10988   for (i = 0; i < qtdemux->n_streams; i++) {
10989     switch (qtdemux->streams[i]->subtype) {
10990       case FOURCC_soun:
10991       case FOURCC_vide:
10992         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10993             qtdemux->streams[i]->caps);
10994         /* retrieve bitrate, prefer avg then max */
10995         bitrate = 0;
10996         if (qtdemux->streams[i]->pending_tags) {
10997           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10998               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10999           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11000           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11001               GST_TAG_NOMINAL_BITRATE, &bitrate);
11002           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11003           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11004               GST_TAG_BITRATE, &bitrate);
11005           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11006         }
11007         if (bitrate)
11008           sum_bitrate += bitrate;
11009         else {
11010           if (stream) {
11011             GST_DEBUG_OBJECT (qtdemux,
11012                 ">1 stream with unknown bitrate - bailing");
11013             return;
11014           } else
11015             stream = qtdemux->streams[i];
11016         }
11017
11018       default:
11019         /* For other subtypes, we assume no significant impact on bitrate */
11020         break;
11021     }
11022   }
11023
11024   if (!stream) {
11025     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11026     return;
11027   }
11028
11029   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11030
11031   if (sys_bitrate < sum_bitrate) {
11032     /* This can happen, since sum_bitrate might be derived from maximum
11033      * bitrates and not average bitrates */
11034     GST_DEBUG_OBJECT (qtdemux,
11035         "System bitrate less than sum bitrate - bailing");
11036     return;
11037   }
11038
11039   bitrate = sys_bitrate - sum_bitrate;
11040   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11041       ", Stream bitrate = %u", sys_bitrate, bitrate);
11042
11043   if (!stream->pending_tags)
11044     stream->pending_tags = gst_tag_list_new_empty ();
11045
11046   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11047       GST_TAG_BITRATE, bitrate, NULL);
11048 }
11049
11050 static GstFlowReturn
11051 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11052 {
11053   gint i;
11054   GstFlowReturn ret = GST_FLOW_OK;
11055
11056   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11057
11058   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11059     QtDemuxStream *stream = qtdemux->streams[i];
11060     guint32 sample_num = 0;
11061
11062     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11063         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11064
11065     if (qtdemux->fragmented) {
11066       /* need all moov samples first */
11067       GST_OBJECT_LOCK (qtdemux);
11068       while (stream->n_samples == 0)
11069         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11070           break;
11071       GST_OBJECT_UNLOCK (qtdemux);
11072     } else {
11073       /* discard any stray moof */
11074       qtdemux->moof_offset = 0;
11075     }
11076
11077     /* prepare braking */
11078     if (ret != GST_FLOW_ERROR)
11079       ret = GST_FLOW_OK;
11080
11081     /* in pull mode, we should have parsed some sample info by now;
11082      * and quite some code will not handle no samples.
11083      * in push mode, we'll just have to deal with it */
11084     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11085       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11086       gst_qtdemux_remove_stream (qtdemux, i);
11087       i--;
11088       continue;
11089     }
11090
11091     /* parse the initial sample for use in setting the frame rate cap */
11092     while (sample_num == 0 && sample_num < stream->n_samples) {
11093       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11094         break;
11095       ++sample_num;
11096     }
11097     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11098       stream->first_duration = stream->samples[0].duration;
11099       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11100           stream->track_id, stream->first_duration);
11101     }
11102   }
11103
11104   return ret;
11105 }
11106
11107 static GstFlowReturn
11108 qtdemux_expose_streams (GstQTDemux * qtdemux)
11109 {
11110   gint i;
11111   GstFlowReturn ret = GST_FLOW_OK;
11112   GSList *oldpads = NULL;
11113   GSList *iter;
11114
11115   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11116
11117   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11118     QtDemuxStream *stream = qtdemux->streams[i];
11119     GstPad *oldpad = stream->pad;
11120     GstTagList *list;
11121
11122     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11123         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11124
11125     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11126         stream->track_id == qtdemux->chapters_track_id) {
11127       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11128          so that it doesn't look like a subtitle track */
11129       gst_qtdemux_remove_stream (qtdemux, i);
11130       i--;
11131       continue;
11132     }
11133
11134     /* now we have all info and can expose */
11135     list = stream->pending_tags;
11136     stream->pending_tags = NULL;
11137     if (oldpad)
11138       oldpads = g_slist_prepend (oldpads, oldpad);
11139     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11140       return GST_FLOW_ERROR;
11141   }
11142
11143   gst_qtdemux_guess_bitrate (qtdemux);
11144
11145   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11146
11147   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11148     GstPad *oldpad = iter->data;
11149     GstEvent *event;
11150
11151     event = gst_event_new_eos ();
11152     if (qtdemux->segment_seqnum)
11153       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11154
11155     gst_pad_push_event (oldpad, event);
11156     gst_pad_set_active (oldpad, FALSE);
11157     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11158     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11159     gst_object_unref (oldpad);
11160   }
11161
11162   /* check if we should post a redirect in case there is a single trak
11163    * and it is a redirecting trak */
11164   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11165     GstMessage *m;
11166
11167     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11168         "an external content");
11169     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11170         gst_structure_new ("redirect",
11171             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11172             NULL));
11173     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11174     qtdemux->posted_redirect = TRUE;
11175   }
11176
11177   for (i = 0; i < qtdemux->n_streams; i++) {
11178     QtDemuxStream *stream = qtdemux->streams[i];
11179
11180     qtdemux_do_allocation (qtdemux, stream);
11181   }
11182
11183   qtdemux->exposed = TRUE;
11184   return ret;
11185 }
11186
11187 /* check if major or compatible brand is 3GP */
11188 static inline gboolean
11189 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11190 {
11191   if (major) {
11192     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11193         FOURCC_3g__);
11194   } else if (qtdemux->comp_brands != NULL) {
11195     GstMapInfo map;
11196     guint8 *data;
11197     gsize size;
11198     gboolean res = FALSE;
11199
11200     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11201     data = map.data;
11202     size = map.size;
11203     while (size >= 4) {
11204       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11205           FOURCC_3g__);
11206       data += 4;
11207       size -= 4;
11208     }
11209     gst_buffer_unmap (qtdemux->comp_brands, &map);
11210     return res;
11211   } else {
11212     return FALSE;
11213   }
11214 }
11215
11216 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11217 static inline gboolean
11218 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11219 {
11220   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11221       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11222       || fourcc == FOURCC_albm;
11223 }
11224
11225 static void
11226 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11227     const char *tag, const char *dummy, GNode * node)
11228 {
11229   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11230   int offset;
11231   char *name;
11232   gchar *data;
11233   gdouble longitude, latitude, altitude;
11234   gint len;
11235
11236   len = QT_UINT32 (node->data);
11237   if (len <= 14)
11238     goto short_read;
11239
11240   data = node->data;
11241   offset = 14;
11242
11243   /* TODO: language code skipped */
11244
11245   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11246
11247   if (!name) {
11248     /* do not alarm in trivial case, but bail out otherwise */
11249     if (*(data + offset) != 0) {
11250       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11251           "giving up", tag);
11252     }
11253   } else {
11254     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11255         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11256     offset += strlen (name);
11257     g_free (name);
11258   }
11259
11260   if (len < offset + 2 + 4 + 4 + 4)
11261     goto short_read;
11262
11263   /* +1 +1 = skip null-terminator and location role byte */
11264   offset += 1 + 1;
11265   /* table in spec says unsigned, semantics say negative has meaning ... */
11266   longitude = QT_SFP32 (data + offset);
11267
11268   offset += 4;
11269   latitude = QT_SFP32 (data + offset);
11270
11271   offset += 4;
11272   altitude = QT_SFP32 (data + offset);
11273
11274   /* one invalid means all are invalid */
11275   if (longitude >= -180.0 && longitude <= 180.0 &&
11276       latitude >= -90.0 && latitude <= 90.0) {
11277     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11278         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11279         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11280         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11281   }
11282
11283   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11284
11285   return;
11286
11287   /* ERRORS */
11288 short_read:
11289   {
11290     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11291     return;
11292   }
11293 }
11294
11295
11296 static void
11297 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11298     const char *tag, const char *dummy, GNode * node)
11299 {
11300   guint16 y;
11301   GDate *date;
11302   gint len;
11303
11304   len = QT_UINT32 (node->data);
11305   if (len < 14)
11306     return;
11307
11308   y = QT_UINT16 ((guint8 *) node->data + 12);
11309   if (y == 0) {
11310     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11311     return;
11312   }
11313   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11314
11315   date = g_date_new_dmy (1, 1, y);
11316   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11317   g_date_free (date);
11318 }
11319
11320 static void
11321 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11322     const char *tag, const char *dummy, GNode * node)
11323 {
11324   int offset;
11325   char *tag_str = NULL;
11326   guint8 *entity;
11327   guint16 table;
11328   gint len;
11329
11330   len = QT_UINT32 (node->data);
11331   if (len <= 20)
11332     goto short_read;
11333
11334   offset = 12;
11335   entity = (guint8 *) node->data + offset;
11336   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11337     GST_DEBUG_OBJECT (qtdemux,
11338         "classification info: %c%c%c%c invalid classification entity",
11339         entity[0], entity[1], entity[2], entity[3]);
11340     return;
11341   }
11342
11343   offset += 4;
11344   table = QT_UINT16 ((guint8 *) node->data + offset);
11345
11346   /* Language code skipped */
11347
11348   offset += 4;
11349
11350   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11351    * XXXX: classification entity, fixed length 4 chars.
11352    * Y[YYYY]: classification table, max 5 chars.
11353    */
11354   tag_str = g_strdup_printf ("----://%u/%s",
11355       table, (char *) node->data + offset);
11356
11357   /* memcpy To be sure we're preserving byte order */
11358   memcpy (tag_str, entity, 4);
11359   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11360
11361   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11362
11363   g_free (tag_str);
11364
11365   return;
11366
11367   /* ERRORS */
11368 short_read:
11369   {
11370     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11371     return;
11372   }
11373 }
11374
11375 static gboolean
11376 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11377     const char *tag, const char *dummy, GNode * node)
11378 {
11379   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11380   GNode *data;
11381   char *s;
11382   int len;
11383   guint32 type;
11384   int offset;
11385   gboolean ret = TRUE;
11386   const gchar *charset = NULL;
11387
11388   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11389   if (data) {
11390     len = QT_UINT32 (data->data);
11391     type = QT_UINT32 ((guint8 *) data->data + 8);
11392     if (type == 0x00000001 && len > 16) {
11393       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11394           env_vars);
11395       if (s) {
11396         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11397         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11398         g_free (s);
11399       } else {
11400         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11401       }
11402     }
11403   } else {
11404     len = QT_UINT32 (node->data);
11405     type = QT_UINT32 ((guint8 *) node->data + 4);
11406     if ((type >> 24) == 0xa9) {
11407       gint str_len;
11408       gint lang_code;
11409
11410       /* Type starts with the (C) symbol, so the next data is a list
11411        * of (string size(16), language code(16), string) */
11412
11413       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11414       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11415
11416       /* the string + fourcc + size + 2 16bit fields,
11417        * means that there are more tags in this atom */
11418       if (len > str_len + 8 + 4) {
11419         /* TODO how to represent the same tag in different languages? */
11420         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11421             "text alternatives, reading only first one");
11422       }
11423
11424       offset = 12;
11425       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11426       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11427
11428       if (lang_code < 0x800) {  /* MAC encoded string */
11429         charset = "mac";
11430       }
11431     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11432             QT_FOURCC ((guint8 *) node->data + 4))) {
11433       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11434
11435       /* we go for 3GP style encoding if major brands claims so,
11436        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11437       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11438           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11439               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11440         offset = 14;
11441         /* 16-bit Language code is ignored here as well */
11442         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11443       } else {
11444         goto normal;
11445       }
11446     } else {
11447     normal:
11448       offset = 8;
11449       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11450       ret = FALSE;              /* may have to fallback */
11451     }
11452     if (charset) {
11453       GError *err = NULL;
11454
11455       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11456           charset, NULL, NULL, &err);
11457       if (err) {
11458         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11459             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11460             err->message);
11461         g_error_free (err);
11462       }
11463     } else {
11464       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11465           len - offset, env_vars);
11466     }
11467     if (s) {
11468       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11469       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11470       g_free (s);
11471       ret = TRUE;
11472     } else {
11473       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11474     }
11475   }
11476   return ret;
11477 }
11478
11479 static void
11480 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11481     const char *tag, const char *dummy, GNode * node)
11482 {
11483   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11484 }
11485
11486 static void
11487 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11488     const char *tag, const char *dummy, GNode * node)
11489 {
11490   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11491   guint8 *data;
11492   char *s, *t, *k = NULL;
11493   int len;
11494   int offset;
11495   int count;
11496
11497   /* first try normal string tag if major brand not 3GP */
11498   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11499     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11500       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11501        * let's try it 3gpp way after minor safety check */
11502       data = node->data;
11503       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11504         return;
11505     } else
11506       return;
11507   }
11508
11509   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11510
11511   data = node->data;
11512
11513   len = QT_UINT32 (data);
11514   if (len < 15)
11515     goto short_read;
11516
11517   count = QT_UINT8 (data + 14);
11518   offset = 15;
11519   for (; count; count--) {
11520     gint slen;
11521
11522     if (offset + 1 > len)
11523       goto short_read;
11524     slen = QT_UINT8 (data + offset);
11525     offset += 1;
11526     if (offset + slen > len)
11527       goto short_read;
11528     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11529         slen, env_vars);
11530     if (s) {
11531       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11532       if (k) {
11533         t = g_strjoin (",", k, s, NULL);
11534         g_free (s);
11535         g_free (k);
11536         k = t;
11537       } else {
11538         k = s;
11539       }
11540     } else {
11541       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11542     }
11543     offset += slen;
11544   }
11545
11546 done:
11547   if (k) {
11548     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11549     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11550   }
11551   g_free (k);
11552
11553   return;
11554
11555   /* ERRORS */
11556 short_read:
11557   {
11558     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11559     goto done;
11560   }
11561 }
11562
11563 static void
11564 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11565     const char *tag1, const char *tag2, GNode * node)
11566 {
11567   GNode *data;
11568   int len;
11569   int type;
11570   int n1, n2;
11571
11572   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11573   if (data) {
11574     len = QT_UINT32 (data->data);
11575     type = QT_UINT32 ((guint8 *) data->data + 8);
11576     if (type == 0x00000000 && len >= 22) {
11577       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11578       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11579       if (n1 > 0) {
11580         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11581         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11582       }
11583       if (n2 > 0) {
11584         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11585         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11586       }
11587     }
11588   }
11589 }
11590
11591 static void
11592 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11593     const char *tag1, const char *dummy, GNode * node)
11594 {
11595   GNode *data;
11596   int len;
11597   int type;
11598   int n1;
11599
11600   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11601   if (data) {
11602     len = QT_UINT32 (data->data);
11603     type = QT_UINT32 ((guint8 *) data->data + 8);
11604     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11605     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11606     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11607       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11608       if (n1) {
11609         /* do not add bpm=0 */
11610         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11611         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11612             NULL);
11613       }
11614     }
11615   }
11616 }
11617
11618 static void
11619 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11620     const char *tag1, const char *dummy, GNode * node)
11621 {
11622   GNode *data;
11623   int len;
11624   int type;
11625   guint32 num;
11626
11627   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11628   if (data) {
11629     len = QT_UINT32 (data->data);
11630     type = QT_UINT32 ((guint8 *) data->data + 8);
11631     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11632     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11633     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11634       num = QT_UINT32 ((guint8 *) data->data + 16);
11635       if (num) {
11636         /* do not add num=0 */
11637         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11638         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11639       }
11640     }
11641   }
11642 }
11643
11644 static void
11645 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11646     const char *tag1, const char *dummy, GNode * node)
11647 {
11648   GNode *data;
11649   int len;
11650   int type;
11651   GstSample *sample;
11652
11653   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11654   if (data) {
11655     len = QT_UINT32 (data->data);
11656     type = QT_UINT32 ((guint8 *) data->data + 8);
11657     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11658     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11659       if ((sample =
11660               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11661                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11662         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11663         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11664         gst_sample_unref (sample);
11665       }
11666     }
11667   }
11668 }
11669
11670 static void
11671 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11672     const char *tag, const char *dummy, GNode * node)
11673 {
11674   GNode *data;
11675   char *s;
11676   int len;
11677   int type;
11678
11679   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11680   if (data) {
11681     len = QT_UINT32 (data->data);
11682     type = QT_UINT32 ((guint8 *) data->data + 8);
11683     if (type == 0x00000001 && len > 16) {
11684       guint y, m = 1, d = 1;
11685       gint ret;
11686
11687       s = g_strndup ((char *) data->data + 16, len - 16);
11688       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11689       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11690       if (ret >= 1 && y > 1500 && y < 3000) {
11691         GDate *date;
11692
11693         date = g_date_new_dmy (d, m, y);
11694         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11695         g_date_free (date);
11696       } else {
11697         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11698       }
11699       g_free (s);
11700     }
11701   }
11702 }
11703
11704 static void
11705 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11706     const char *tag, const char *dummy, GNode * node)
11707 {
11708   GNode *data;
11709
11710   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11711
11712   /* re-route to normal string tag if major brand says so
11713    * or no data atom and compatible brand suggests so */
11714   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11715       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11716     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11717     return;
11718   }
11719
11720   if (data) {
11721     guint len, type, n;
11722
11723     len = QT_UINT32 (data->data);
11724     type = QT_UINT32 ((guint8 *) data->data + 8);
11725     if (type == 0x00000000 && len >= 18) {
11726       n = QT_UINT16 ((guint8 *) data->data + 16);
11727       if (n > 0) {
11728         const gchar *genre;
11729
11730         genre = gst_tag_id3_genre_get (n - 1);
11731         if (genre != NULL) {
11732           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11733           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11734         }
11735       }
11736     }
11737   }
11738 }
11739
11740 static void
11741 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11742     const gchar * tag, guint8 * data, guint32 datasize)
11743 {
11744   gdouble value;
11745   gchar *datacopy;
11746
11747   /* make a copy to have \0 at the end */
11748   datacopy = g_strndup ((gchar *) data, datasize);
11749
11750   /* convert the str to double */
11751   if (sscanf (datacopy, "%lf", &value) == 1) {
11752     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11753     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11754   } else {
11755     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11756         datacopy);
11757   }
11758   g_free (datacopy);
11759 }
11760
11761
11762 static void
11763 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11764     const char *tag, const char *tag_bis, GNode * node)
11765 {
11766   GNode *mean;
11767   GNode *name;
11768   GNode *data;
11769   guint32 meansize;
11770   guint32 namesize;
11771   guint32 datatype;
11772   guint32 datasize;
11773   const gchar *meanstr;
11774   const gchar *namestr;
11775
11776   /* checking the whole ---- atom size for consistency */
11777   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11778     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11779     return;
11780   }
11781
11782   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11783   if (!mean) {
11784     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11785     return;
11786   }
11787
11788   meansize = QT_UINT32 (mean->data);
11789   if (meansize <= 12) {
11790     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11791     return;
11792   }
11793   meanstr = ((gchar *) mean->data) + 12;
11794   meansize -= 12;
11795
11796   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11797   if (!name) {
11798     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11799     return;
11800   }
11801
11802   namesize = QT_UINT32 (name->data);
11803   if (namesize <= 12) {
11804     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11805     return;
11806   }
11807   namestr = ((gchar *) name->data) + 12;
11808   namesize -= 12;
11809
11810   /*
11811    * Data atom is:
11812    * uint32 - size
11813    * uint32 - name
11814    * uint8  - version
11815    * uint24 - data type
11816    * uint32 - all 0
11817    * rest   - the data
11818    */
11819   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11820   if (!data) {
11821     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11822     return;
11823   }
11824   datasize = QT_UINT32 (data->data);
11825   if (datasize <= 16) {
11826     GST_WARNING_OBJECT (demux, "Data atom too small");
11827     return;
11828   }
11829   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11830
11831   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11832       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11833     static const struct
11834     {
11835       const gchar name[28];
11836       const gchar tag[28];
11837     } tags[] = {
11838       {
11839       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11840       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11841       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11842       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11843       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11844       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11845       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11846       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11847     };
11848     int i;
11849
11850     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11851       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11852         switch (gst_tag_get_type (tags[i].tag)) {
11853           case G_TYPE_DOUBLE:
11854             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11855                 ((guint8 *) data->data) + 16, datasize - 16);
11856             break;
11857           case G_TYPE_STRING:
11858             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11859             break;
11860           default:
11861             /* not reached */
11862             break;
11863         }
11864         break;
11865       }
11866     }
11867     if (i == G_N_ELEMENTS (tags))
11868       goto unknown_tag;
11869   } else {
11870     goto unknown_tag;
11871   }
11872
11873   return;
11874
11875 /* errors */
11876 unknown_tag:
11877 #ifndef GST_DISABLE_GST_DEBUG
11878   {
11879     gchar *namestr_dbg;
11880     gchar *meanstr_dbg;
11881
11882     meanstr_dbg = g_strndup (meanstr, meansize);
11883     namestr_dbg = g_strndup (namestr, namesize);
11884
11885     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11886         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11887
11888     g_free (namestr_dbg);
11889     g_free (meanstr_dbg);
11890   }
11891 #endif
11892   return;
11893 }
11894
11895 static void
11896 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11897     const char *tag_bis, GNode * node)
11898 {
11899   guint8 *data;
11900   GstBuffer *buf;
11901   guint len;
11902   GstTagList *id32_taglist = NULL;
11903
11904   GST_LOG_OBJECT (demux, "parsing ID32");
11905
11906   data = node->data;
11907   len = GST_READ_UINT32_BE (data);
11908
11909   /* need at least full box and language tag */
11910   if (len < 12 + 2)
11911     return;
11912
11913   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11914   gst_buffer_fill (buf, 0, data + 14, len - 14);
11915
11916   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11917   if (id32_taglist) {
11918     GST_LOG_OBJECT (demux, "parsing ok");
11919     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11920     gst_tag_list_unref (id32_taglist);
11921   } else {
11922     GST_LOG_OBJECT (demux, "parsing failed");
11923   }
11924
11925   gst_buffer_unref (buf);
11926 }
11927
11928 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11929     const char *tag, const char *tag_bis, GNode * node);
11930
11931 /* unmapped tags
11932 FOURCC_pcst -> if media is a podcast -> bool
11933 FOURCC_cpil -> if media is part of a compilation -> bool
11934 FOURCC_pgap -> if media is part of a gapless context -> bool
11935 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11936 */
11937
11938 static const struct
11939 {
11940   guint32 fourcc;
11941   const gchar *gst_tag;
11942   const gchar *gst_tag_bis;
11943   const GstQTDemuxAddTagFunc func;
11944 } add_funcs[] = {
11945   {
11946   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11947   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11948   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11949   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11950   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11951   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11952   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11953   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11954   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11955   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11956   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11957   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11958   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11959   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11960   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11961   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11962   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11963   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11964   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11965   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11966   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11967   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11968   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11969         qtdemux_tag_add_num}, {
11970   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11971         qtdemux_tag_add_num}, {
11972   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11973   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11974   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11975   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11976   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11977   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11978   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11979   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11980   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11981   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11982   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11983   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11984   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11985   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11986   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11987   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11988   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11989   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11990         qtdemux_tag_add_classification}, {
11991   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11992   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11993   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11994
11995     /* This is a special case, some tags are stored in this
11996      * 'reverse dns naming', according to:
11997      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11998      * bug #614471
11999      */
12000   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12001     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12002   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12003 };
12004
12005 struct _GstQtDemuxTagList
12006 {
12007   GstQTDemux *demux;
12008   GstTagList *taglist;
12009 };
12010 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12011
12012 static void
12013 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12014 {
12015   gint len;
12016   guint8 *data;
12017   GstBuffer *buf;
12018   gchar *media_type;
12019   const gchar *style;
12020   GstSample *sample;
12021   GstStructure *s;
12022   guint i;
12023   guint8 ndata[4];
12024   GstQTDemux *demux = qtdemuxtaglist->demux;
12025   GstTagList *taglist = qtdemuxtaglist->taglist;
12026
12027   data = node->data;
12028   len = QT_UINT32 (data);
12029   buf = gst_buffer_new_and_alloc (len);
12030   gst_buffer_fill (buf, 0, data, len);
12031
12032   /* heuristic to determine style of tag */
12033   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12034       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12035     style = "itunes";
12036   else if (demux->major_brand == FOURCC_qt__)
12037     style = "quicktime";
12038   /* fall back to assuming iso/3gp tag style */
12039   else
12040     style = "iso";
12041
12042   /* santize the name for the caps. */
12043   for (i = 0; i < 4; i++) {
12044     guint8 d = data[4 + i];
12045     if (g_ascii_isalnum (d))
12046       ndata[i] = g_ascii_tolower (d);
12047     else
12048       ndata[i] = '_';
12049   }
12050
12051   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12052       ndata[0], ndata[1], ndata[2], ndata[3]);
12053   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12054
12055   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12056   sample = gst_sample_new (buf, NULL, NULL, s);
12057   gst_buffer_unref (buf);
12058   g_free (media_type);
12059
12060   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12061       len, s);
12062
12063   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12064       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12065
12066   gst_sample_unref (sample);
12067 }
12068
12069 static void
12070 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12071 {
12072   GNode *meta;
12073   GNode *ilst;
12074   GNode *xmp_;
12075   GNode *node;
12076   gint i;
12077   GstQtDemuxTagList demuxtaglist;
12078
12079   demuxtaglist.demux = qtdemux;
12080   demuxtaglist.taglist = taglist;
12081
12082   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12083   if (meta != NULL) {
12084     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12085     if (ilst == NULL) {
12086       GST_LOG_OBJECT (qtdemux, "no ilst");
12087       return;
12088     }
12089   } else {
12090     ilst = udta;
12091     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12092   }
12093
12094   i = 0;
12095   while (i < G_N_ELEMENTS (add_funcs)) {
12096     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12097     if (node) {
12098       gint len;
12099
12100       len = QT_UINT32 (node->data);
12101       if (len < 12) {
12102         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12103             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12104       } else {
12105         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12106             add_funcs[i].gst_tag_bis, node);
12107       }
12108       g_node_destroy (node);
12109     } else {
12110       i++;
12111     }
12112   }
12113
12114   /* parsed nodes have been removed, pass along remainder as blob */
12115   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12116       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12117
12118   /* parse up XMP_ node if existing */
12119   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12120   if (xmp_ != NULL) {
12121     GstBuffer *buf;
12122     GstTagList *xmptaglist;
12123
12124     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12125         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12126     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12127     gst_buffer_unref (buf);
12128
12129     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12130   } else {
12131     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12132   }
12133 }
12134
12135 typedef struct
12136 {
12137   GstStructure *structure;      /* helper for sort function */
12138   gchar *location;
12139   guint min_req_bitrate;
12140   guint min_req_qt_version;
12141 } GstQtReference;
12142
12143 static gint
12144 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12145 {
12146   GstQtReference *ref_a = (GstQtReference *) a;
12147   GstQtReference *ref_b = (GstQtReference *) b;
12148
12149   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12150     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12151
12152   /* known bitrates go before unknown; higher bitrates go first */
12153   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12154 }
12155
12156 /* sort the redirects and post a message for the application.
12157  */
12158 static void
12159 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12160 {
12161   GstQtReference *best;
12162   GstStructure *s;
12163   GstMessage *msg;
12164   GValue list_val = { 0, };
12165   GList *l;
12166
12167   g_assert (references != NULL);
12168
12169   references = g_list_sort (references, qtdemux_redirects_sort_func);
12170
12171   best = (GstQtReference *) references->data;
12172
12173   g_value_init (&list_val, GST_TYPE_LIST);
12174
12175   for (l = references; l != NULL; l = l->next) {
12176     GstQtReference *ref = (GstQtReference *) l->data;
12177     GValue struct_val = { 0, };
12178
12179     ref->structure = gst_structure_new ("redirect",
12180         "new-location", G_TYPE_STRING, ref->location, NULL);
12181
12182     if (ref->min_req_bitrate > 0) {
12183       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12184           ref->min_req_bitrate, NULL);
12185     }
12186
12187     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12188     g_value_set_boxed (&struct_val, ref->structure);
12189     gst_value_list_append_value (&list_val, &struct_val);
12190     g_value_unset (&struct_val);
12191     /* don't free anything here yet, since we need best->structure below */
12192   }
12193
12194   g_assert (best != NULL);
12195   s = gst_structure_copy (best->structure);
12196
12197   if (g_list_length (references) > 1) {
12198     gst_structure_set_value (s, "locations", &list_val);
12199   }
12200
12201   g_value_unset (&list_val);
12202
12203   for (l = references; l != NULL; l = l->next) {
12204     GstQtReference *ref = (GstQtReference *) l->data;
12205
12206     gst_structure_free (ref->structure);
12207     g_free (ref->location);
12208     g_free (ref);
12209   }
12210   g_list_free (references);
12211
12212   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12213   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12214   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12215   qtdemux->posted_redirect = TRUE;
12216 }
12217
12218 /* look for redirect nodes, collect all redirect information and
12219  * process it.
12220  */
12221 static gboolean
12222 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12223 {
12224   GNode *rmra, *rmda, *rdrf;
12225
12226   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12227   if (rmra) {
12228     GList *redirects = NULL;
12229
12230     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12231     while (rmda) {
12232       GstQtReference ref = { NULL, NULL, 0, 0 };
12233       GNode *rmdr, *rmvc;
12234
12235       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12236         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12237         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12238             ref.min_req_bitrate);
12239       }
12240
12241       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12242         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12243         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12244
12245 #ifndef GST_DISABLE_GST_DEBUG
12246         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12247 #endif
12248         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12249
12250         GST_LOG_OBJECT (qtdemux,
12251             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12252             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12253             bitmask, check_type);
12254         if (package == FOURCC_qtim && check_type == 0) {
12255           ref.min_req_qt_version = version;
12256         }
12257       }
12258
12259       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12260       if (rdrf) {
12261         guint32 ref_type;
12262         guint8 *ref_data;
12263         guint ref_len;
12264
12265         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12266         if (ref_len > 20) {
12267           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12268           ref_data = (guint8 *) rdrf->data + 20;
12269           if (ref_type == FOURCC_alis) {
12270             guint record_len, record_version, fn_len;
12271
12272             if (ref_len > 70) {
12273               /* MacOSX alias record, google for alias-layout.txt */
12274               record_len = QT_UINT16 (ref_data + 4);
12275               record_version = QT_UINT16 (ref_data + 4 + 2);
12276               fn_len = QT_UINT8 (ref_data + 50);
12277               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12278                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12279               }
12280             } else {
12281               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12282                   ref_len);
12283             }
12284           } else if (ref_type == FOURCC_url_) {
12285             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12286           } else {
12287             GST_DEBUG_OBJECT (qtdemux,
12288                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12289                 GST_FOURCC_ARGS (ref_type));
12290           }
12291           if (ref.location != NULL) {
12292             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12293             redirects =
12294                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12295           } else {
12296             GST_WARNING_OBJECT (qtdemux,
12297                 "Failed to extract redirect location from rdrf atom");
12298           }
12299         } else {
12300           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12301         }
12302       }
12303
12304       /* look for others */
12305       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12306     }
12307
12308     if (redirects != NULL) {
12309       qtdemux_process_redirects (qtdemux, redirects);
12310     }
12311   }
12312   return TRUE;
12313 }
12314
12315 static GstTagList *
12316 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12317 {
12318   const gchar *fmt;
12319
12320   if (tags == NULL) {
12321     tags = gst_tag_list_new_empty ();
12322     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12323   }
12324
12325   if (qtdemux->major_brand == FOURCC_mjp2)
12326     fmt = "Motion JPEG 2000";
12327   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12328     fmt = "3GP";
12329   else if (qtdemux->major_brand == FOURCC_qt__)
12330     fmt = "Quicktime";
12331   else if (qtdemux->fragmented)
12332     fmt = "ISO fMP4";
12333   else
12334     fmt = "ISO MP4/M4A";
12335
12336   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12337       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12338
12339   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12340       fmt, NULL);
12341
12342   return tags;
12343 }
12344
12345 /* we have read the complete moov node now.
12346  * This function parses all of the relevant info, creates the traks and
12347  * prepares all data structures for playback
12348  */
12349 static gboolean
12350 qtdemux_parse_tree (GstQTDemux * qtdemux)
12351 {
12352   GNode *mvhd;
12353   GNode *trak;
12354   GNode *udta;
12355   GNode *mvex;
12356   GstClockTime duration;
12357   GNode *pssh;
12358   guint64 creation_time;
12359   GstDateTime *datetime = NULL;
12360   gint version;
12361
12362   /* make sure we have a usable taglist */
12363   if (!qtdemux->tag_list) {
12364     qtdemux->tag_list = gst_tag_list_new_empty ();
12365     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12366   } else {
12367     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12368   }
12369
12370   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12371   if (mvhd == NULL) {
12372     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12373     return qtdemux_parse_redirects (qtdemux);
12374   }
12375
12376   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12377   if (version == 1) {
12378     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12379     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12380     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12381   } else if (version == 0) {
12382     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12383     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12384     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12385   } else {
12386     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12387     return FALSE;
12388   }
12389
12390   /* Moving qt creation time (secs since 1904) to unix time */
12391   if (creation_time != 0) {
12392     /* Try to use epoch first as it should be faster and more commonly found */
12393     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12394       GTimeVal now;
12395
12396       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12397       /* some data cleansing sanity */
12398       g_get_current_time (&now);
12399       if (now.tv_sec + 24 * 3600 < creation_time) {
12400         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12401       } else {
12402         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12403       }
12404     } else {
12405       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12406       GDateTime *dt, *dt_local;
12407
12408       dt = g_date_time_add_seconds (base_dt, creation_time);
12409       dt_local = g_date_time_to_local (dt);
12410       datetime = gst_date_time_new_from_g_date_time (dt_local);
12411
12412       g_date_time_unref (base_dt);
12413       g_date_time_unref (dt);
12414     }
12415   }
12416   if (datetime) {
12417     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12418     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12419         datetime, NULL);
12420     gst_date_time_unref (datetime);
12421   }
12422
12423   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12424   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12425
12426   /* check for fragmented file and get some (default) data */
12427   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12428   if (mvex) {
12429     GNode *mehd;
12430     GstByteReader mehd_data;
12431
12432     /* let track parsing or anyone know weird stuff might happen ... */
12433     qtdemux->fragmented = TRUE;
12434
12435     /* compensate for total duration */
12436     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12437     if (mehd)
12438       qtdemux_parse_mehd (qtdemux, &mehd_data);
12439   }
12440
12441   /* set duration in the segment info */
12442   gst_qtdemux_get_duration (qtdemux, &duration);
12443   if (duration) {
12444     qtdemux->segment.duration = duration;
12445     /* also do not exceed duration; stop is set that way post seek anyway,
12446      * and segment activation falls back to duration,
12447      * whereas loop only checks stop, so let's align this here as well */
12448     qtdemux->segment.stop = duration;
12449   }
12450
12451   /* parse all traks */
12452   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12453   while (trak) {
12454     qtdemux_parse_trak (qtdemux, trak);
12455     /* iterate all siblings */
12456     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12457   }
12458
12459   if (!qtdemux->tag_list) {
12460     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12461     qtdemux->tag_list = gst_tag_list_new_empty ();
12462     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12463   } else {
12464     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12465   }
12466
12467   /* find tags */
12468   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12469   if (udta) {
12470     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12471   } else {
12472     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12473   }
12474
12475   /* maybe also some tags in meta box */
12476   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12477   if (udta) {
12478     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12479     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12480   } else {
12481     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12482   }
12483
12484   /* parse any protection system info */
12485   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12486   while (pssh) {
12487     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12488     qtdemux_parse_pssh (qtdemux, pssh);
12489     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12490   }
12491
12492   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12493
12494   return TRUE;
12495 }
12496
12497 /* taken from ffmpeg */
12498 static int
12499 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12500 {
12501   int count = 4;
12502   int len = 0;
12503
12504   while (count--) {
12505     int c;
12506
12507     if (ptr >= end)
12508       return -1;
12509
12510     c = *ptr++;
12511     len = (len << 7) | (c & 0x7f);
12512     if (!(c & 0x80))
12513       break;
12514   }
12515   *end_out = ptr;
12516   return len;
12517 }
12518
12519 /* this can change the codec originally present in @list */
12520 static void
12521 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12522     GNode * esds, GstTagList * list)
12523 {
12524   int len = QT_UINT32 (esds->data);
12525   guint8 *ptr = esds->data;
12526   guint8 *end = ptr + len;
12527   int tag;
12528   guint8 *data_ptr = NULL;
12529   int data_len = 0;
12530   guint8 object_type_id = 0;
12531   const char *codec_name = NULL;
12532   GstCaps *caps = NULL;
12533
12534   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12535   ptr += 8;
12536   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12537   ptr += 4;
12538   while (ptr + 1 < end) {
12539     tag = QT_UINT8 (ptr);
12540     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12541     ptr++;
12542     len = read_descr_size (ptr, end, &ptr);
12543     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12544
12545     /* Check the stated amount of data is available for reading */
12546     if (len < 0 || ptr + len > end)
12547       break;
12548
12549     switch (tag) {
12550       case ES_DESCRIPTOR_TAG:
12551         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12552         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12553         ptr += 3;
12554         break;
12555       case DECODER_CONFIG_DESC_TAG:{
12556         guint max_bitrate, avg_bitrate;
12557
12558         object_type_id = QT_UINT8 (ptr);
12559         max_bitrate = QT_UINT32 (ptr + 5);
12560         avg_bitrate = QT_UINT32 (ptr + 9);
12561         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12562         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12563         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12564         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12565         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12566         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12567           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12568               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12569         }
12570         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12571           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12572               avg_bitrate, NULL);
12573         }
12574         ptr += 13;
12575         break;
12576       }
12577       case DECODER_SPECIFIC_INFO_TAG:
12578         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12579         if (object_type_id == 0xe0 && len == 0x40) {
12580           guint8 *data;
12581           GstStructure *s;
12582           guint32 clut[16];
12583           gint i;
12584
12585           GST_DEBUG_OBJECT (qtdemux,
12586               "Have VOBSUB palette. Creating palette event");
12587           /* move to decConfigDescr data and read palette */
12588           data = ptr;
12589           for (i = 0; i < 16; i++) {
12590             clut[i] = QT_UINT32 (data);
12591             data += 4;
12592           }
12593
12594           s = gst_structure_new ("application/x-gst-dvd", "event",
12595               G_TYPE_STRING, "dvd-spu-clut-change",
12596               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12597               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12598               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12599               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12600               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12601               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12602               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12603               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12604               NULL);
12605
12606           /* store event and trigger custom processing */
12607           stream->pending_event =
12608               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12609         } else {
12610           /* Generic codec_data handler puts it on the caps */
12611           data_ptr = ptr;
12612           data_len = len;
12613         }
12614
12615         ptr += len;
12616         break;
12617       case SL_CONFIG_DESC_TAG:
12618         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12619         ptr += 1;
12620         break;
12621       default:
12622         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12623             tag);
12624         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12625         ptr += len;
12626         break;
12627     }
12628   }
12629
12630   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12631    * in use, and should also be used to override some other parameters for some
12632    * codecs. */
12633   switch (object_type_id) {
12634     case 0x20:                 /* MPEG-4 */
12635       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12636        * profile_and_level_indication */
12637       if (data_ptr != NULL && data_len >= 5 &&
12638           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12639         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12640             data_ptr + 4, data_len - 4);
12641       }
12642       break;                    /* Nothing special needed here */
12643     case 0x21:                 /* H.264 */
12644       codec_name = "H.264 / AVC";
12645       caps = gst_caps_new_simple ("video/x-h264",
12646           "stream-format", G_TYPE_STRING, "avc",
12647           "alignment", G_TYPE_STRING, "au", NULL);
12648       break;
12649     case 0x40:                 /* AAC (any) */
12650     case 0x66:                 /* AAC Main */
12651     case 0x67:                 /* AAC LC */
12652     case 0x68:                 /* AAC SSR */
12653       /* Override channels and rate based on the codec_data, as it's often
12654        * wrong. */
12655       /* Only do so for basic setup without HE-AAC extension */
12656       if (data_ptr && data_len == 2) {
12657         guint channels, rate;
12658
12659         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12660         if (channels > 0)
12661           stream->n_channels = channels;
12662
12663         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12664         if (rate > 0)
12665           stream->rate = rate;
12666       }
12667
12668       /* Set level and profile if possible */
12669       if (data_ptr != NULL && data_len >= 2) {
12670         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12671             data_ptr, data_len);
12672       } else {
12673         const gchar *profile_str = NULL;
12674         GstBuffer *buffer;
12675         GstMapInfo map;
12676         guint8 *codec_data;
12677         gint rate_idx, profile;
12678
12679         /* No codec_data, let's invent something.
12680          * FIXME: This is wrong for SBR! */
12681
12682         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
12683
12684         buffer = gst_buffer_new_and_alloc (2);
12685         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
12686         codec_data = map.data;
12687
12688         rate_idx =
12689             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
12690
12691         switch (object_type_id) {
12692           case 0x66:
12693             profile_str = "main";
12694             profile = 0;
12695             break;
12696           case 0x67:
12697             profile_str = "lc";
12698             profile = 1;
12699             break;
12700           case 0x68:
12701             profile_str = "ssr";
12702             profile = 2;
12703             break;
12704           default:
12705             profile = 3;
12706             break;
12707         }
12708
12709         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
12710         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
12711
12712         gst_buffer_unmap (buffer, &map);
12713         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12714             buffer, NULL);
12715         gst_buffer_unref (buffer);
12716
12717         if (profile_str) {
12718           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
12719               profile_str, NULL);
12720         }
12721       }
12722       break;
12723     case 0x60:                 /* MPEG-2, various profiles */
12724     case 0x61:
12725     case 0x62:
12726     case 0x63:
12727     case 0x64:
12728     case 0x65:
12729       codec_name = "MPEG-2 video";
12730       caps = gst_caps_new_simple ("video/mpeg",
12731           "mpegversion", G_TYPE_INT, 2,
12732           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12733       break;
12734     case 0x69:                 /* MPEG-2 BC audio */
12735     case 0x6B:                 /* MPEG-1 audio */
12736       caps = gst_caps_new_simple ("audio/mpeg",
12737           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12738       codec_name = "MPEG-1 audio";
12739       break;
12740     case 0x6A:                 /* MPEG-1 */
12741       codec_name = "MPEG-1 video";
12742       caps = gst_caps_new_simple ("video/mpeg",
12743           "mpegversion", G_TYPE_INT, 1,
12744           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12745       break;
12746     case 0x6C:                 /* MJPEG */
12747       caps =
12748           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12749           NULL);
12750       codec_name = "Motion-JPEG";
12751       break;
12752     case 0x6D:                 /* PNG */
12753       caps =
12754           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12755           NULL);
12756       codec_name = "PNG still images";
12757       break;
12758     case 0x6E:                 /* JPEG2000 */
12759       codec_name = "JPEG-2000";
12760       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12761       break;
12762     case 0xA4:                 /* Dirac */
12763       codec_name = "Dirac";
12764       caps = gst_caps_new_empty_simple ("video/x-dirac");
12765       break;
12766     case 0xA5:                 /* AC3 */
12767       codec_name = "AC-3 audio";
12768       caps = gst_caps_new_simple ("audio/x-ac3",
12769           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12770       break;
12771     case 0xA9:                 /* AC3 */
12772       codec_name = "DTS audio";
12773       caps = gst_caps_new_simple ("audio/x-dts",
12774           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12775       break;
12776     case 0xE1:                 /* QCELP */
12777       /* QCELP, the codec_data is a riff tag (little endian) with
12778        * 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). */
12779       caps = gst_caps_new_empty_simple ("audio/qcelp");
12780       codec_name = "QCELP";
12781       break;
12782     default:
12783       break;
12784   }
12785
12786   /* If we have a replacement caps, then change our caps for this stream */
12787   if (caps) {
12788     gst_caps_unref (stream->caps);
12789     stream->caps = caps;
12790   }
12791
12792   if (codec_name && list)
12793     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12794         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12795
12796   /* Add the codec_data attribute to caps, if we have it */
12797   if (data_ptr) {
12798     GstBuffer *buffer;
12799
12800     buffer = gst_buffer_new_and_alloc (data_len);
12801     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12802
12803     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12804     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12805
12806     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12807         buffer, NULL);
12808     gst_buffer_unref (buffer);
12809   }
12810
12811 }
12812
12813 #define _codec(name) \
12814   do { \
12815     if (codec_name) { \
12816       *codec_name = g_strdup (name); \
12817     } \
12818   } while (0)
12819
12820 static GstCaps *
12821 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12822     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12823 {
12824   GstCaps *caps = NULL;
12825   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12826
12827   switch (fourcc) {
12828     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12829       _codec ("PNG still images");
12830       caps = gst_caps_new_empty_simple ("image/png");
12831       break;
12832     case FOURCC_jpeg:
12833       _codec ("JPEG still images");
12834       caps =
12835           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12836           NULL);
12837       break;
12838     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12839     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12840     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12841     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12842       _codec ("Motion-JPEG");
12843       caps =
12844           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12845           NULL);
12846       break;
12847     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12848       _codec ("Motion-JPEG format B");
12849       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12850       break;
12851     case FOURCC_mjp2:
12852       _codec ("JPEG-2000");
12853       /* override to what it should be according to spec, avoid palette_data */
12854       stream->bits_per_sample = 24;
12855       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12856       break;
12857     case FOURCC_SVQ3:
12858       _codec ("Sorensen video v.3");
12859       caps = gst_caps_new_simple ("video/x-svq",
12860           "svqversion", G_TYPE_INT, 3, NULL);
12861       break;
12862     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12863     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12864       _codec ("Sorensen video v.1");
12865       caps = gst_caps_new_simple ("video/x-svq",
12866           "svqversion", G_TYPE_INT, 1, NULL);
12867       break;
12868     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12869       caps = gst_caps_new_empty_simple ("video/x-raw");
12870       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12871       _codec ("Windows Raw RGB");
12872       break;
12873     case FOURCC_raw_:
12874     {
12875       guint16 bps;
12876
12877       bps = QT_UINT16 (stsd_data + 98);
12878       switch (bps) {
12879         case 15:
12880           format = GST_VIDEO_FORMAT_RGB15;
12881           break;
12882         case 16:
12883           format = GST_VIDEO_FORMAT_RGB16;
12884           break;
12885         case 24:
12886           format = GST_VIDEO_FORMAT_RGB;
12887           break;
12888         case 32:
12889           format = GST_VIDEO_FORMAT_ARGB;
12890           break;
12891         default:
12892           /* unknown */
12893           break;
12894       }
12895       break;
12896     }
12897     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12898       format = GST_VIDEO_FORMAT_I420;
12899       break;
12900     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12901     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12902       format = GST_VIDEO_FORMAT_I420;
12903       break;
12904     case FOURCC_2vuy:
12905     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12906       format = GST_VIDEO_FORMAT_UYVY;
12907       break;
12908     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12909       format = GST_VIDEO_FORMAT_v308;
12910       break;
12911     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12912       format = GST_VIDEO_FORMAT_v216;
12913       break;
12914     case FOURCC_v210:
12915       format = GST_VIDEO_FORMAT_v210;
12916       break;
12917     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12918       format = GST_VIDEO_FORMAT_r210;
12919       break;
12920       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12921          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12922          format = GST_VIDEO_FORMAT_v410;
12923          break;
12924        */
12925       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12926        * but different order than AYUV
12927        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12928        format = GST_VIDEO_FORMAT_v408;
12929        break;
12930        */
12931     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12932     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12933       _codec ("MPEG-1 video");
12934       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12935           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12936       break;
12937     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12938     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12939     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12940     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12941     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12942     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12943     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12944     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12945     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12946     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12947     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12948     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12949     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12950     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12951     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12952     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12953     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12954     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12955     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12956     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12957     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12958     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12959     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12960     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12961     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12962     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12963     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12964     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12965     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12966     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12967     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12968     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12969     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12970     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12971     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12972     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12973     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12974     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12975     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12976     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12977     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12978     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12979     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12980     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12981     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12982     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12983       _codec ("MPEG-2 video");
12984       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12985           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12986       break;
12987     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12988       _codec ("GIF still images");
12989       caps = gst_caps_new_empty_simple ("image/gif");
12990       break;
12991     case FOURCC_h263:
12992     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12993     case FOURCC_s263:
12994     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12995       _codec ("H.263");
12996       /* ffmpeg uses the height/width props, don't know why */
12997       caps = gst_caps_new_simple ("video/x-h263",
12998           "variant", G_TYPE_STRING, "itu", NULL);
12999       break;
13000     case FOURCC_mp4v:
13001     case FOURCC_MP4V:
13002       _codec ("MPEG-4 video");
13003       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13004           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13005       break;
13006     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13007     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13008       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13009       caps = gst_caps_new_simple ("video/x-msmpeg",
13010           "msmpegversion", G_TYPE_INT, 43, NULL);
13011       break;
13012     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13013       _codec ("DivX 3");
13014       caps = gst_caps_new_simple ("video/x-divx",
13015           "divxversion", G_TYPE_INT, 3, NULL);
13016       break;
13017     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13018     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13019       _codec ("DivX 4");
13020       caps = gst_caps_new_simple ("video/x-divx",
13021           "divxversion", G_TYPE_INT, 4, NULL);
13022       break;
13023     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13024       _codec ("DivX 5");
13025       caps = gst_caps_new_simple ("video/x-divx",
13026           "divxversion", G_TYPE_INT, 5, NULL);
13027       break;
13028
13029     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13030       _codec ("FFV1");
13031       caps = gst_caps_new_simple ("video/x-ffv",
13032           "ffvversion", G_TYPE_INT, 1, NULL);
13033       break;
13034
13035     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13036     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13037     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
13038     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
13039     case FOURCC_FMP4:
13040     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13041       caps = gst_caps_new_simple ("video/mpeg",
13042           "mpegversion", G_TYPE_INT, 4, NULL);
13043       _codec ("MPEG-4");
13044       break;
13045
13046     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13047       _codec ("Cinepak");
13048       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13049       break;
13050     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13051       _codec ("Apple QuickDraw");
13052       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13053       break;
13054     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13055       _codec ("Apple video");
13056       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13057       break;
13058     case FOURCC_H264:
13059     case FOURCC_avc1:
13060       _codec ("H.264 / AVC");
13061       caps = gst_caps_new_simple ("video/x-h264",
13062           "stream-format", G_TYPE_STRING, "avc",
13063           "alignment", G_TYPE_STRING, "au", NULL);
13064       break;
13065     case FOURCC_avc3:
13066       _codec ("H.264 / AVC");
13067       caps = gst_caps_new_simple ("video/x-h264",
13068           "stream-format", G_TYPE_STRING, "avc3",
13069           "alignment", G_TYPE_STRING, "au", NULL);
13070       break;
13071     case FOURCC_H265:
13072     case FOURCC_hvc1:
13073       _codec ("H.265 / HEVC");
13074       caps = gst_caps_new_simple ("video/x-h265",
13075           "stream-format", G_TYPE_STRING, "hvc1",
13076           "alignment", G_TYPE_STRING, "au", NULL);
13077       break;
13078     case FOURCC_hev1:
13079       _codec ("H.265 / HEVC");
13080       caps = gst_caps_new_simple ("video/x-h265",
13081           "stream-format", G_TYPE_STRING, "hev1",
13082           "alignment", G_TYPE_STRING, "au", NULL);
13083       break;
13084     case FOURCC_rle_:
13085       _codec ("Run-length encoding");
13086       caps = gst_caps_new_simple ("video/x-rle",
13087           "layout", G_TYPE_STRING, "quicktime", NULL);
13088       break;
13089     case FOURCC_WRLE:
13090       _codec ("Run-length encoding");
13091       caps = gst_caps_new_simple ("video/x-rle",
13092           "layout", G_TYPE_STRING, "microsoft", NULL);
13093       break;
13094     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13095     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13096       _codec ("Indeo Video 3");
13097       caps = gst_caps_new_simple ("video/x-indeo",
13098           "indeoversion", G_TYPE_INT, 3, NULL);
13099       break;
13100     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13101     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13102       _codec ("Intel Video 4");
13103       caps = gst_caps_new_simple ("video/x-indeo",
13104           "indeoversion", G_TYPE_INT, 4, NULL);
13105       break;
13106     case FOURCC_dvcp:
13107     case FOURCC_dvc_:
13108     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13109     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13110     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13111     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13112     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13113     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13114       _codec ("DV Video");
13115       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13116           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13117       break;
13118     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13119     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13120       _codec ("DVCPro50 Video");
13121       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13122           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13123       break;
13124     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13125     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13126       _codec ("DVCProHD Video");
13127       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13128           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13129       break;
13130     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13131       _codec ("Apple Graphics (SMC)");
13132       caps = gst_caps_new_empty_simple ("video/x-smc");
13133       break;
13134     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13135       _codec ("VP3");
13136       caps = gst_caps_new_empty_simple ("video/x-vp3");
13137       break;
13138     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13139       _codec ("VP6 Flash");
13140       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13141       break;
13142     case FOURCC_XiTh:
13143       _codec ("Theora");
13144       caps = gst_caps_new_empty_simple ("video/x-theora");
13145       /* theora uses one byte of padding in the data stream because it does not
13146        * allow 0 sized packets while theora does */
13147       stream->padding = 1;
13148       break;
13149     case FOURCC_drac:
13150       _codec ("Dirac");
13151       caps = gst_caps_new_empty_simple ("video/x-dirac");
13152       break;
13153     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13154       _codec ("TIFF still images");
13155       caps = gst_caps_new_empty_simple ("image/tiff");
13156       break;
13157     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13158       _codec ("Apple Intermediate Codec");
13159       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13160       break;
13161     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13162       _codec ("AVID DNxHD");
13163       caps = gst_caps_from_string ("video/x-dnxhd");
13164       break;
13165     case FOURCC_VP80:
13166       _codec ("On2 VP8");
13167       caps = gst_caps_from_string ("video/x-vp8");
13168       break;
13169     case FOURCC_apcs:
13170       _codec ("Apple ProRes LT");
13171       caps =
13172           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13173           NULL);
13174       break;
13175     case FOURCC_apch:
13176       _codec ("Apple ProRes HQ");
13177       caps =
13178           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13179           NULL);
13180       break;
13181     case FOURCC_apcn:
13182       _codec ("Apple ProRes");
13183       caps =
13184           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13185           "standard", NULL);
13186       break;
13187     case FOURCC_apco:
13188       _codec ("Apple ProRes Proxy");
13189       caps =
13190           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13191           "proxy", NULL);
13192       break;
13193     case FOURCC_ap4h:
13194       _codec ("Apple ProRes 4444");
13195       caps =
13196           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13197           "4444", NULL);
13198       break;
13199     case FOURCC_vc_1:
13200     case FOURCC_ovc1:
13201       _codec ("VC-1");
13202       caps = gst_caps_new_simple ("video/x-wmv",
13203           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13204       break;
13205     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13206     default:
13207     {
13208       char *s, fourstr[5];
13209
13210       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13211       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13212       caps = gst_caps_new_empty_simple (s);
13213       g_free (s);
13214       break;
13215     }
13216   }
13217
13218   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13219     GstVideoInfo info;
13220
13221     gst_video_info_init (&info);
13222     gst_video_info_set_format (&info, format, stream->width, stream->height);
13223
13224     caps = gst_video_info_to_caps (&info);
13225     *codec_name = gst_pb_utils_get_codec_description (caps);
13226
13227     /* enable clipping for raw video streams */
13228     stream->need_clip = TRUE;
13229   }
13230
13231   return caps;
13232 }
13233
13234 static GstCaps *
13235 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13236     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13237 {
13238   GstCaps *caps;
13239   const GstStructure *s;
13240   const gchar *name;
13241   gint endian = 0;
13242   GstAudioFormat format = 0;
13243   gint depth;
13244
13245   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13246
13247   depth = stream->bytes_per_packet * 8;
13248
13249   switch (fourcc) {
13250     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13251     case FOURCC_raw_:
13252       /* 8-bit audio is unsigned */
13253       if (depth == 8)
13254         format = GST_AUDIO_FORMAT_U8;
13255       /* otherwise it's signed and big-endian just like 'twos' */
13256     case FOURCC_twos:
13257       endian = G_BIG_ENDIAN;
13258       /* fall-through */
13259     case FOURCC_sowt:
13260     {
13261       gchar *str;
13262
13263       if (!endian)
13264         endian = G_LITTLE_ENDIAN;
13265
13266       if (!format)
13267         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13268
13269       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13270       _codec (str);
13271       g_free (str);
13272
13273       caps = gst_caps_new_simple ("audio/x-raw",
13274           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13275           "layout", G_TYPE_STRING, "interleaved", NULL);
13276       break;
13277     }
13278     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13279       _codec ("Raw 64-bit floating-point audio");
13280       caps = gst_caps_new_simple ("audio/x-raw",
13281           "format", G_TYPE_STRING, "F64BE",
13282           "layout", G_TYPE_STRING, "interleaved", NULL);
13283       break;
13284     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13285       _codec ("Raw 32-bit floating-point audio");
13286       caps = gst_caps_new_simple ("audio/x-raw",
13287           "format", G_TYPE_STRING, "F32BE",
13288           "layout", G_TYPE_STRING, "interleaved", NULL);
13289       break;
13290     case FOURCC_in24:
13291       _codec ("Raw 24-bit PCM audio");
13292       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13293        * endian later */
13294       caps = gst_caps_new_simple ("audio/x-raw",
13295           "format", G_TYPE_STRING, "S24BE",
13296           "layout", G_TYPE_STRING, "interleaved", NULL);
13297       break;
13298     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13299       _codec ("Raw 32-bit PCM audio");
13300       caps = gst_caps_new_simple ("audio/x-raw",
13301           "format", G_TYPE_STRING, "S32BE",
13302           "layout", G_TYPE_STRING, "interleaved", NULL);
13303       break;
13304     case FOURCC_ulaw:
13305       _codec ("Mu-law audio");
13306       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13307       break;
13308     case FOURCC_alaw:
13309       _codec ("A-law audio");
13310       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13311       break;
13312     case 0x0200736d:
13313     case 0x6d730002:
13314       _codec ("Microsoft ADPCM");
13315       /* Microsoft ADPCM-ACM code 2 */
13316       caps = gst_caps_new_simple ("audio/x-adpcm",
13317           "layout", G_TYPE_STRING, "microsoft", NULL);
13318       break;
13319     case 0x1100736d:
13320     case 0x6d730011:
13321       _codec ("DVI/IMA ADPCM");
13322       caps = gst_caps_new_simple ("audio/x-adpcm",
13323           "layout", G_TYPE_STRING, "dvi", NULL);
13324       break;
13325     case 0x1700736d:
13326     case 0x6d730017:
13327       _codec ("DVI/Intel IMA ADPCM");
13328       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13329       caps = gst_caps_new_simple ("audio/x-adpcm",
13330           "layout", G_TYPE_STRING, "quicktime", NULL);
13331       break;
13332     case 0x5500736d:
13333     case 0x6d730055:
13334       /* MPEG layer 3, CBR only (pre QT4.1) */
13335     case FOURCC__mp3:
13336       _codec ("MPEG-1 layer 3");
13337       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13338       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13339           "mpegversion", G_TYPE_INT, 1, NULL);
13340       break;
13341     case 0x20736d:
13342     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13343       _codec ("EAC-3 audio");
13344       caps = gst_caps_new_simple ("audio/x-eac3",
13345           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13346       stream->sampled = TRUE;
13347       break;
13348     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13349     case FOURCC_ac_3:
13350       _codec ("AC-3 audio");
13351       caps = gst_caps_new_simple ("audio/x-ac3",
13352           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13353       stream->sampled = TRUE;
13354       break;
13355     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13356     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13357       _codec ("DTS audio");
13358       caps = gst_caps_new_simple ("audio/x-dts",
13359           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13360       stream->sampled = TRUE;
13361       break;
13362     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13363     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13364       _codec ("DTS-HD audio");
13365       caps = gst_caps_new_simple ("audio/x-dts",
13366           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13367       stream->sampled = TRUE;
13368       break;
13369     case FOURCC_MAC3:
13370       _codec ("MACE-3");
13371       caps = gst_caps_new_simple ("audio/x-mace",
13372           "maceversion", G_TYPE_INT, 3, NULL);
13373       break;
13374     case FOURCC_MAC6:
13375       _codec ("MACE-6");
13376       caps = gst_caps_new_simple ("audio/x-mace",
13377           "maceversion", G_TYPE_INT, 6, NULL);
13378       break;
13379     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13380       /* ogg/vorbis */
13381       caps = gst_caps_new_empty_simple ("application/ogg");
13382       break;
13383     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13384       _codec ("DV audio");
13385       caps = gst_caps_new_empty_simple ("audio/x-dv");
13386       break;
13387     case FOURCC_mp4a:
13388       _codec ("MPEG-4 AAC audio");
13389       caps = gst_caps_new_simple ("audio/mpeg",
13390           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13391           "stream-format", G_TYPE_STRING, "raw", NULL);
13392       break;
13393     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13394       _codec ("QDesign Music");
13395       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13396       break;
13397     case FOURCC_QDM2:
13398       _codec ("QDesign Music v.2");
13399       /* FIXME: QDesign music version 2 (no constant) */
13400       if (FALSE && data) {
13401         caps = gst_caps_new_simple ("audio/x-qdm2",
13402             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13403             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13404             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13405       } else {
13406         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13407       }
13408       break;
13409     case FOURCC_agsm:
13410       _codec ("GSM audio");
13411       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13412       break;
13413     case FOURCC_samr:
13414       _codec ("AMR audio");
13415       caps = gst_caps_new_empty_simple ("audio/AMR");
13416       break;
13417     case FOURCC_sawb:
13418       _codec ("AMR-WB audio");
13419       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13420       break;
13421     case FOURCC_ima4:
13422       _codec ("Quicktime IMA ADPCM");
13423       caps = gst_caps_new_simple ("audio/x-adpcm",
13424           "layout", G_TYPE_STRING, "quicktime", NULL);
13425       break;
13426     case FOURCC_alac:
13427       _codec ("Apple lossless audio");
13428       caps = gst_caps_new_empty_simple ("audio/x-alac");
13429       break;
13430     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13431       _codec ("QualComm PureVoice");
13432       caps = gst_caps_from_string ("audio/qcelp");
13433       break;
13434     case FOURCC_wma_:
13435     case FOURCC_owma:
13436       _codec ("WMA");
13437       caps = gst_caps_new_empty_simple ("audio/x-wma");
13438       break;
13439     case FOURCC_opus:
13440       _codec ("Opus");
13441       caps = gst_caps_new_empty_simple ("audio/x-opus");
13442       break;
13443     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13444     {
13445       guint32 flags = 0;
13446       guint32 depth = 0;
13447       guint32 width = 0;
13448       GstAudioFormat format;
13449       enum
13450       {
13451         FLAG_IS_FLOAT = 0x1,
13452         FLAG_IS_BIG_ENDIAN = 0x2,
13453         FLAG_IS_SIGNED = 0x4,
13454         FLAG_IS_PACKED = 0x8,
13455         FLAG_IS_ALIGNED_HIGH = 0x10,
13456         FLAG_IS_NON_INTERLEAVED = 0x20
13457       };
13458       _codec ("Raw LPCM audio");
13459
13460       if (data && len >= 56) {
13461         depth = QT_UINT32 (data + 40);
13462         flags = QT_UINT32 (data + 44);
13463         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13464       }
13465       if ((flags & FLAG_IS_FLOAT) == 0) {
13466         if (depth == 0)
13467           depth = 16;
13468         if (width == 0)
13469           width = 16;
13470         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13471             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13472             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13473         caps = gst_caps_new_simple ("audio/x-raw",
13474             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13475             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13476             "non-interleaved" : "interleaved", NULL);
13477       } else {
13478         if (width == 0)
13479           width = 32;
13480         if (width == 64) {
13481           if (flags & FLAG_IS_BIG_ENDIAN)
13482             format = GST_AUDIO_FORMAT_F64BE;
13483           else
13484             format = GST_AUDIO_FORMAT_F64LE;
13485         } else {
13486           if (flags & FLAG_IS_BIG_ENDIAN)
13487             format = GST_AUDIO_FORMAT_F32BE;
13488           else
13489             format = GST_AUDIO_FORMAT_F32LE;
13490         }
13491         caps = gst_caps_new_simple ("audio/x-raw",
13492             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13493             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13494             "non-interleaved" : "interleaved", NULL);
13495       }
13496       break;
13497     }
13498     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13499       /* ? */
13500     default:
13501     {
13502       char *s, fourstr[5];
13503
13504       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13505       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13506       caps = gst_caps_new_empty_simple (s);
13507       g_free (s);
13508       break;
13509     }
13510   }
13511
13512   if (caps) {
13513     GstCaps *templ_caps =
13514         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13515     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13516     gst_caps_unref (caps);
13517     gst_caps_unref (templ_caps);
13518     caps = intersection;
13519   }
13520
13521   /* enable clipping for raw audio streams */
13522   s = gst_caps_get_structure (caps, 0);
13523   name = gst_structure_get_name (s);
13524   if (g_str_has_prefix (name, "audio/x-raw")) {
13525     stream->need_clip = TRUE;
13526     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13527     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13528   }
13529   return caps;
13530 }
13531
13532 static GstCaps *
13533 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13534     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13535 {
13536   GstCaps *caps;
13537
13538   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13539
13540   switch (fourcc) {
13541     case FOURCC_mp4s:
13542       _codec ("DVD subtitle");
13543       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13544       stream->need_process = TRUE;
13545       break;
13546     case FOURCC_text:
13547       _codec ("Quicktime timed text");
13548       goto text;
13549     case FOURCC_tx3g:
13550       _codec ("3GPP timed text");
13551     text:
13552       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13553           "utf8", NULL);
13554       /* actual text piece needs to be extracted */
13555       stream->need_process = TRUE;
13556       break;
13557     case FOURCC_stpp:
13558       _codec ("XML subtitles");
13559       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13560       break;
13561     default:
13562     {
13563       char *s, fourstr[5];
13564
13565       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13566       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13567       caps = gst_caps_new_empty_simple (s);
13568       g_free (s);
13569       break;
13570     }
13571   }
13572   return caps;
13573 }
13574
13575 static GstCaps *
13576 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13577     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13578 {
13579   GstCaps *caps;
13580
13581   switch (fourcc) {
13582     case FOURCC_m1v:
13583       _codec ("MPEG 1 video");
13584       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13585           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13586       break;
13587     default:
13588       caps = NULL;
13589       break;
13590   }
13591   return caps;
13592 }
13593
13594 static void
13595 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13596     const gchar * system_id)
13597 {
13598   gint i;
13599
13600   if (!qtdemux->protection_system_ids)
13601     qtdemux->protection_system_ids =
13602         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13603   /* Check whether we already have an entry for this system ID. */
13604   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13605     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13606     if (g_ascii_strcasecmp (system_id, id) == 0) {
13607       return;
13608     }
13609   }
13610   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13611   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13612           -1));
13613 }