a45801105c578e249ba421b3d959eb880256a49b
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
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 _QtNode QtNode; */
101 typedef struct _QtDemuxSegment QtDemuxSegment;
102 typedef struct _QtDemuxSample QtDemuxSample;
103
104 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
105
106 /*struct _QtNode
107 {
108   guint32 type;
109   guint8 *data;
110   gint len;
111 };*/
112
113 struct _QtDemuxSample
114 {
115   guint32 size;
116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
117   guint64 offset;
118   guint64 timestamp;            /* DTS In mov time */
119   guint32 duration;             /* In mov time */
120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
121 };
122
123 /* Macros for converting to/from timescale */
124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
126
127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
129
130 /* timestamp is the DTS */
131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
132 /* timestamp + offset is the PTS */
133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 struct _QtDemuxStream
221 {
222   GstPad *pad;
223
224   /* stream type */
225   guint32 subtype;
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   gboolean new_caps;
231   gboolean new_stream;          /* signals that a stream_start is required */
232   gboolean on_keyframe;         /* if this stream last pushed buffer was a
233                                  * keyframe. This is important to identify
234                                  * where to stop pushing buffers after a
235                                  * segment stop time */
236
237   /* if the stream has a redirect URI in its headers, we store it here */
238   gchar *redirect_uri;
239
240   /* track id */
241   guint track_id;
242
243   /* duration/scale */
244   guint64 duration;             /* in timescale */
245   guint32 timescale;
246
247   /* language */
248   gchar lang_id[4];             /* ISO 639-2T language code */
249
250   /* our samples */
251   guint32 n_samples;
252   QtDemuxSample *samples;
253   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
254   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
255                                    the framerate, in timescale units */
256   guint32 n_samples_moof;       /* sample count in a moof */
257   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
258                                  * the framerate of fragmented format stream */
259   guint32 offset_in_sample;
260   guint32 max_buffer_size;
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   guint32 segment_seqnum;       /* segment event seqnum obtained from seek */
318
319   /* quicktime segments */
320   guint32 n_segments;
321   QtDemuxSegment *segments;
322   gboolean dummy_segment;
323   guint32 from_sample;
324   guint32 to_sample;
325
326   gboolean sent_eos;
327   GstTagList *pending_tags;
328   gboolean send_global_tags;
329
330   GstEvent *pending_event;
331
332   GstByteReader stco;
333   GstByteReader stsz;
334   GstByteReader stsc;
335   GstByteReader stts;
336   GstByteReader stss;
337   GstByteReader stps;
338   GstByteReader ctts;
339
340   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
341   gint64 stbl_index;
342   /* stco */
343   guint co_size;
344   GstByteReader co_chunk;
345   guint32 first_chunk;
346   guint32 current_chunk;
347   guint32 last_chunk;
348   guint32 samples_per_chunk;
349   guint32 stco_sample_index;
350   /* stsz */
351   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
352   /* stsc */
353   guint32 stsc_index;
354   guint32 n_samples_per_chunk;
355   guint32 stsc_chunk_index;
356   guint32 stsc_sample_index;
357   guint64 chunk_offset;
358   /* stts */
359   guint32 stts_index;
360   guint32 stts_samples;
361   guint32 n_sample_times;
362   guint32 stts_sample_index;
363   guint64 stts_time;
364   guint32 stts_duration;
365   /* stss */
366   gboolean stss_present;
367   guint32 n_sample_syncs;
368   guint32 stss_index;
369   /* stps */
370   gboolean stps_present;
371   guint32 n_sample_partial_syncs;
372   guint32 stps_index;
373   QtDemuxRandomAccessEntry *ra_entries;
374   guint n_ra_entries;
375
376   const QtDemuxRandomAccessEntry *pending_seek;
377
378   /* ctts */
379   gboolean ctts_present;
380   guint32 n_composition_times;
381   guint32 ctts_index;
382   guint32 ctts_sample_index;
383   guint32 ctts_count;
384   gint32 ctts_soffset;
385
386   /* cslg */
387   guint32 cslg_shift;
388
389   /* fragmented */
390   gboolean parsed_trex;
391   guint32 def_sample_duration;
392   guint32 def_sample_size;
393   guint32 def_sample_flags;
394
395   gboolean disabled;
396
397   /* stereoscopic video streams */
398   GstVideoMultiviewMode multiview_mode;
399   GstVideoMultiviewFlags multiview_flags;
400
401   /* protected streams */
402   gboolean protected;
403   guint32 protection_scheme_type;
404   guint32 protection_scheme_version;
405   gpointer protection_scheme_info;      /* specific to the protection scheme */
406   GQueue protection_scheme_event_queue;
407 };
408
409 /* Contains properties and cryptographic info for a set of samples from a
410  * track protected using Common Encryption (cenc) */
411 struct _QtDemuxCencSampleSetInfo
412 {
413   GstStructure *default_properties;
414
415   /* @crypto_info holds one GstStructure per sample */
416   GPtrArray *crypto_info;
417 };
418
419 enum QtDemuxState
420 {
421   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
422   QTDEMUX_STATE_HEADER,         /* Parsing the header */
423   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
424   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
425 };
426
427 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
428 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
429     guint32 fourcc, GstByteReader * parser);
430 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
431 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
432     guint32 fourcc, GstByteReader * parser);
433
434 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
435
436 static GstStaticPadTemplate gst_qtdemux_sink_template =
437     GST_STATIC_PAD_TEMPLATE ("sink",
438     GST_PAD_SINK,
439     GST_PAD_ALWAYS,
440     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
441         "application/x-3gp")
442     );
443
444 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
445 GST_STATIC_PAD_TEMPLATE ("video_%u",
446     GST_PAD_SRC,
447     GST_PAD_SOMETIMES,
448     GST_STATIC_CAPS_ANY);
449
450 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
451 GST_STATIC_PAD_TEMPLATE ("audio_%u",
452     GST_PAD_SRC,
453     GST_PAD_SOMETIMES,
454     GST_STATIC_CAPS_ANY);
455
456 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
457 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
458     GST_PAD_SRC,
459     GST_PAD_SOMETIMES,
460     GST_STATIC_CAPS_ANY);
461
462 #define gst_qtdemux_parent_class parent_class
463 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
464
465 static void gst_qtdemux_dispose (GObject * object);
466
467 static guint32
468 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
469     GstClockTime media_time);
470 static guint32
471 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
472     QtDemuxStream * str, gint64 media_offset);
473
474 #if 0
475 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
476 static GstIndex *gst_qtdemux_get_index (GstElement * element);
477 #endif
478 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
479     GstStateChange transition);
480 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
481 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
482     GstObject * parent, GstPadMode mode, gboolean active);
483
484 static void gst_qtdemux_loop (GstPad * pad);
485 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
486     GstBuffer * inbuf);
487 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
488     GstEvent * event);
489 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
490 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
491     QtDemuxStream * stream);
492 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
493     gboolean force);
494
495 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
496     const guint8 * buffer, guint length);
497 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
498     const guint8 * buffer, guint length);
499 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
500 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
501     GNode * udta);
502
503 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
504     QtDemuxStream * stream, GNode * esds, GstTagList * list);
505 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
506     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
507     gchar ** codec_name);
508 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
509     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
510     gchar ** codec_name);
511 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
513     gchar ** codec_name);
514 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
515     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
516     gchar ** codec_name);
517
518 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
519     QtDemuxStream * stream, guint32 n);
520 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
521 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
522     QtDemuxStream * stream);
523 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
524     QtDemuxStream * stream);
525 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
526 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
527 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
528     QtDemuxStream * stream);
529
530 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
531 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
532
533 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
534     const gchar * id);
535
536 static void
537 gst_qtdemux_class_init (GstQTDemuxClass * klass)
538 {
539   GObjectClass *gobject_class;
540   GstElementClass *gstelement_class;
541
542   gobject_class = (GObjectClass *) klass;
543   gstelement_class = (GstElementClass *) klass;
544
545   parent_class = g_type_class_peek_parent (klass);
546
547   gobject_class->dispose = gst_qtdemux_dispose;
548
549   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
550 #if 0
551   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
552   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
553 #endif
554
555   gst_tag_register_musicbrainz_tags ();
556
557   gst_element_class_add_pad_template (gstelement_class,
558       gst_static_pad_template_get (&gst_qtdemux_sink_template));
559   gst_element_class_add_pad_template (gstelement_class,
560       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
561   gst_element_class_add_pad_template (gstelement_class,
562       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
563   gst_element_class_add_pad_template (gstelement_class,
564       gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
565   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
566       "Codec/Demuxer",
567       "Demultiplex a QuickTime file into audio and video streams",
568       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
569
570   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
571
572 }
573
574 static void
575 gst_qtdemux_init (GstQTDemux * qtdemux)
576 {
577   qtdemux->sinkpad =
578       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
579   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
580   gst_pad_set_activatemode_function (qtdemux->sinkpad,
581       qtdemux_sink_activate_mode);
582   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
583   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
584   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
585
586   qtdemux->state = QTDEMUX_STATE_INITIAL;
587   qtdemux->pullbased = FALSE;
588   qtdemux->posted_redirect = FALSE;
589   qtdemux->pending_configure = FALSE;
590   qtdemux->neededbytes = 16;
591   qtdemux->todrop = 0;
592   qtdemux->adapter = gst_adapter_new ();
593   qtdemux->offset = 0;
594   qtdemux->first_mdat = -1;
595   qtdemux->got_moov = FALSE;
596   qtdemux->mdatoffset = -1;
597   qtdemux->mdatbuffer = NULL;
598   qtdemux->restoredata_buffer = NULL;
599   qtdemux->restoredata_offset = -1;
600   qtdemux->fragment_start = -1;
601   qtdemux->fragment_start_offset = -1;
602   qtdemux->media_caps = NULL;
603   qtdemux->exposed = FALSE;
604   qtdemux->mss_mode = FALSE;
605   qtdemux->pending_newsegment = NULL;
606   qtdemux->upstream_format_is_time = FALSE;
607   qtdemux->have_group_id = FALSE;
608   qtdemux->group_id = G_MAXUINT;
609   qtdemux->cenc_aux_info_offset = 0;
610   qtdemux->cenc_aux_info_sizes = NULL;
611   qtdemux->cenc_aux_sample_count = 0;
612   qtdemux->protection_system_ids = NULL;
613   g_queue_init (&qtdemux->protection_event_queue);
614   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
615   qtdemux->flowcombiner = gst_flow_combiner_new ();
616
617   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
618 }
619
620 static void
621 gst_qtdemux_dispose (GObject * object)
622 {
623   GstQTDemux *qtdemux = GST_QTDEMUX (object);
624
625   if (qtdemux->adapter) {
626     g_object_unref (G_OBJECT (qtdemux->adapter));
627     qtdemux->adapter = NULL;
628   }
629   gst_flow_combiner_free (qtdemux->flowcombiner);
630   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
631       NULL);
632   g_queue_clear (&qtdemux->protection_event_queue);
633
634   g_free (qtdemux->cenc_aux_info_sizes);
635   qtdemux->cenc_aux_info_sizes = NULL;
636
637   G_OBJECT_CLASS (parent_class)->dispose (object);
638 }
639
640 static void
641 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
642 {
643   if (qtdemux->posted_redirect) {
644     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
645         (_("This file contains no playable streams.")),
646         ("no known streams found, a redirect message has been posted"));
647   } else {
648     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
649         (_("This file contains no playable streams.")),
650         ("no known streams found"));
651   }
652 }
653
654 static GstBuffer *
655 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
656 {
657   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
658       mem, size, 0, size, mem, free_func);
659 }
660
661 static GstFlowReturn
662 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
663     GstBuffer ** buf)
664 {
665   GstFlowReturn flow;
666   GstMapInfo map;
667   gsize bsize;
668
669   if (G_UNLIKELY (size == 0)) {
670     GstFlowReturn ret;
671     GstBuffer *tmp = NULL;
672
673     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
674     if (ret != GST_FLOW_OK)
675       return ret;
676
677     gst_buffer_map (tmp, &map, GST_MAP_READ);
678     size = QT_UINT32 (map.data);
679     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
680
681     gst_buffer_unmap (tmp, &map);
682     gst_buffer_unref (tmp);
683   }
684
685   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
686   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
687     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
688       /* we're pulling header but already got most interesting bits,
689        * so never mind the rest (e.g. tags) (that much) */
690       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
691           size);
692       return GST_FLOW_EOS;
693     } else {
694       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
695           (_("This file is invalid and cannot be played.")),
696           ("atom has bogus size %" G_GUINT64_FORMAT, size));
697       return GST_FLOW_ERROR;
698     }
699   }
700
701   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
702
703   if (G_UNLIKELY (flow != GST_FLOW_OK))
704     return flow;
705
706   bsize = gst_buffer_get_size (*buf);
707   /* Catch short reads - we don't want any partial atoms */
708   if (G_UNLIKELY (bsize < size)) {
709     GST_WARNING_OBJECT (qtdemux,
710         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
711     gst_buffer_unref (*buf);
712     *buf = NULL;
713     return GST_FLOW_EOS;
714   }
715
716   return flow;
717 }
718
719 #if 1
720 static gboolean
721 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
722     GstFormat dest_format, gint64 * dest_value)
723 {
724   gboolean res = TRUE;
725   QtDemuxStream *stream = gst_pad_get_element_private (pad);
726   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
727   gint32 index;
728
729   if (stream->subtype != FOURCC_vide) {
730     res = FALSE;
731     goto done;
732   }
733
734   switch (src_format) {
735     case GST_FORMAT_TIME:
736       switch (dest_format) {
737         case GST_FORMAT_BYTES:{
738           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
739           if (-1 == index)
740             return FALSE;
741
742           *dest_value = stream->samples[index].offset;
743
744           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
745               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
746               GST_TIME_ARGS (src_value), *dest_value);
747           break;
748         }
749         default:
750           res = FALSE;
751           break;
752       }
753       break;
754     case GST_FORMAT_BYTES:
755       switch (dest_format) {
756         case GST_FORMAT_TIME:{
757           index =
758               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
759               stream, src_value);
760
761           if (-1 == index)
762             return FALSE;
763
764           *dest_value =
765               QTSTREAMTIME_TO_GSTTIME (stream,
766               stream->samples[index].timestamp);
767           GST_DEBUG_OBJECT (qtdemux,
768               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
769               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
770           break;
771         }
772         default:
773           res = FALSE;
774           break;
775       }
776       break;
777     default:
778       res = FALSE;
779   }
780
781 done:
782   gst_object_unref (qtdemux);
783
784   return res;
785 }
786 #endif
787
788 static gboolean
789 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
790 {
791   gboolean res = TRUE;
792
793   *duration = GST_CLOCK_TIME_NONE;
794
795   if (qtdemux->duration != 0) {
796     if (qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
797       *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
798     }
799   }
800   return res;
801 }
802
803 static gboolean
804 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
805     GstQuery * query)
806 {
807   gboolean res = FALSE;
808   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
809
810   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
811
812   switch (GST_QUERY_TYPE (query)) {
813     case GST_QUERY_POSITION:{
814       GstFormat fmt;
815
816       gst_query_parse_position (query, &fmt, NULL);
817       if (fmt == GST_FORMAT_TIME
818           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
819         gst_query_set_position (query, GST_FORMAT_TIME,
820             qtdemux->segment.position);
821         res = TRUE;
822       }
823     }
824       break;
825     case GST_QUERY_DURATION:{
826       GstFormat fmt;
827
828       gst_query_parse_duration (query, &fmt, NULL);
829       if (fmt == GST_FORMAT_TIME) {
830         /* First try to query upstream */
831         res = gst_pad_query_default (pad, parent, query);
832         if (!res) {
833           guint64 duration;
834           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
835             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
836             res = TRUE;
837           }
838         }
839       }
840       break;
841     }
842     case GST_QUERY_CONVERT:{
843       GstFormat src_fmt, dest_fmt;
844       gint64 src_value, dest_value = 0;
845
846       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
847
848       res = gst_qtdemux_src_convert (pad,
849           src_fmt, src_value, dest_fmt, &dest_value);
850       if (res) {
851         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
852         res = TRUE;
853       }
854       break;
855     }
856     case GST_QUERY_FORMATS:
857       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
858       res = TRUE;
859       break;
860     case GST_QUERY_SEEKING:{
861       GstFormat fmt;
862       gboolean seekable;
863
864       /* try upstream first */
865       res = gst_pad_query_default (pad, parent, query);
866
867       if (!res) {
868         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
869         if (fmt == GST_FORMAT_TIME) {
870           GstClockTime duration = GST_CLOCK_TIME_NONE;
871
872           gst_qtdemux_get_duration (qtdemux, &duration);
873           seekable = TRUE;
874           if (!qtdemux->pullbased) {
875             GstQuery *q;
876
877             /* we might be able with help from upstream */
878             seekable = FALSE;
879             q = gst_query_new_seeking (GST_FORMAT_BYTES);
880             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
881               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
882               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
883             }
884             gst_query_unref (q);
885           }
886           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
887           res = TRUE;
888         }
889       }
890       break;
891     }
892     case GST_QUERY_SEGMENT:
893     {
894       GstFormat format;
895       gint64 start, stop;
896
897       format = qtdemux->segment.format;
898
899       start =
900           gst_segment_to_stream_time (&qtdemux->segment, format,
901           qtdemux->segment.start);
902       if ((stop = qtdemux->segment.stop) == -1)
903         stop = qtdemux->segment.duration;
904       else
905         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
906
907       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
908       res = TRUE;
909       break;
910     }
911     default:
912       res = gst_pad_query_default (pad, parent, query);
913       break;
914   }
915
916   return res;
917 }
918
919 static void
920 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
921 {
922   if (G_LIKELY (stream->pad)) {
923     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
924         GST_DEBUG_PAD_NAME (stream->pad));
925
926     if (G_UNLIKELY (stream->pending_tags)) {
927       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
928           stream->pending_tags);
929       gst_pad_push_event (stream->pad,
930           gst_event_new_tag (stream->pending_tags));
931       stream->pending_tags = NULL;
932     }
933
934     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
935       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
936           qtdemux->tag_list);
937       gst_pad_push_event (stream->pad,
938           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
939       stream->send_global_tags = FALSE;
940     }
941   }
942 }
943
944 /* push event on all source pads; takes ownership of the event */
945 static void
946 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
947 {
948   guint n;
949   gboolean has_valid_stream = FALSE;
950   GstEventType etype = GST_EVENT_TYPE (event);
951
952   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
953       GST_EVENT_TYPE_NAME (event));
954
955   for (n = 0; n < qtdemux->n_streams; n++) {
956     GstPad *pad;
957     QtDemuxStream *stream = qtdemux->streams[n];
958     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
959
960     if ((pad = stream->pad)) {
961       has_valid_stream = TRUE;
962
963       if (etype == GST_EVENT_EOS) {
964         /* let's not send twice */
965         if (stream->sent_eos)
966           continue;
967         stream->sent_eos = TRUE;
968       }
969
970       gst_pad_push_event (pad, gst_event_ref (event));
971     }
972   }
973
974   gst_event_unref (event);
975
976   /* if it is EOS and there are no pads, post an error */
977   if (!has_valid_stream && etype == GST_EVENT_EOS) {
978     gst_qtdemux_post_no_playable_stream_error (qtdemux);
979   }
980 }
981
982 /* push a pending newsegment event, if any from the streaming thread */
983 static void
984 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
985 {
986   if (qtdemux->pending_newsegment) {
987     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
988     qtdemux->pending_newsegment = NULL;
989   }
990 }
991
992 typedef struct
993 {
994   guint64 media_time;
995 } FindData;
996
997 static gint
998 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
999 {
1000   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1001     return 1;
1002   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1003     return 0;
1004
1005   return -1;
1006 }
1007
1008 /* find the index of the sample that includes the data for @media_time using a
1009  * binary search.  Only to be called in optimized cases of linear search below.
1010  *
1011  * Returns the index of the sample.
1012  */
1013 static guint32
1014 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1015     guint64 media_time)
1016 {
1017   QtDemuxSample *result;
1018   guint32 index;
1019
1020   /* convert media_time to mov format */
1021   media_time =
1022       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1023
1024   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1025       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1026       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1027
1028   if (G_LIKELY (result))
1029     index = result - str->samples;
1030   else
1031     index = 0;
1032
1033   return index;
1034 }
1035
1036
1037
1038 /* find the index of the sample that includes the data for @media_offset using a
1039  * linear search
1040  *
1041  * Returns the index of the sample.
1042  */
1043 static guint32
1044 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1045     QtDemuxStream * str, gint64 media_offset)
1046 {
1047   QtDemuxSample *result = str->samples;
1048   guint32 index = 0;
1049
1050   if (result == NULL || str->n_samples == 0)
1051     return -1;
1052
1053   if (media_offset == result->offset)
1054     return index;
1055
1056   result++;
1057   while (index < str->n_samples - 1) {
1058     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1059       goto parse_failed;
1060
1061     if (media_offset < result->offset)
1062       break;
1063
1064     index++;
1065     result++;
1066   }
1067   return index;
1068
1069   /* ERRORS */
1070 parse_failed:
1071   {
1072     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1073     return -1;
1074   }
1075 }
1076
1077 /* find the index of the sample that includes the data for @media_time using a
1078  * linear search, and keeping in mind that not all samples may have been parsed
1079  * yet.  If possible, it will delegate to binary search.
1080  *
1081  * Returns the index of the sample.
1082  */
1083 static guint32
1084 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1085     GstClockTime media_time)
1086 {
1087   guint32 index = 0;
1088   guint64 mov_time;
1089   QtDemuxSample *sample;
1090
1091   /* convert media_time to mov format */
1092   mov_time =
1093       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1094
1095   sample = str->samples;
1096   if (mov_time == sample->timestamp + sample->pts_offset)
1097     return index;
1098
1099   /* use faster search if requested time in already parsed range */
1100   sample = str->samples + str->stbl_index;
1101   if (str->stbl_index >= 0 &&
1102       mov_time <= (sample->timestamp + sample->pts_offset))
1103     return gst_qtdemux_find_index (qtdemux, str, media_time);
1104
1105   while (index < str->n_samples - 1) {
1106     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1107       goto parse_failed;
1108
1109     sample = str->samples + index + 1;
1110     if (mov_time < (sample->timestamp + sample->pts_offset))
1111       break;
1112
1113     index++;
1114   }
1115   return index;
1116
1117   /* ERRORS */
1118 parse_failed:
1119   {
1120     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1121     return -1;
1122   }
1123 }
1124
1125 /* find the index of the keyframe needed to decode the sample at @index
1126  * of stream @str.
1127  *
1128  * Returns the index of the keyframe.
1129  */
1130 static guint32
1131 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1132     guint32 index)
1133 {
1134   guint32 new_index = index;
1135
1136   if (index >= str->n_samples) {
1137     new_index = str->n_samples;
1138     goto beach;
1139   }
1140
1141   /* all keyframes, return index */
1142   if (str->all_keyframe) {
1143     new_index = index;
1144     goto beach;
1145   }
1146
1147   /* else go back until we have a keyframe */
1148   while (TRUE) {
1149     if (str->samples[new_index].keyframe)
1150       break;
1151
1152     if (new_index == 0)
1153       break;
1154
1155     new_index--;
1156   }
1157
1158 beach:
1159   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1160       "gave %u", index, new_index);
1161
1162   return new_index;
1163 }
1164
1165 /* find the segment for @time_position for @stream
1166  *
1167  * Returns the index of the segment containing @time_position.
1168  * Returns the last segment and sets the @eos variable to TRUE
1169  * if the time is beyond the end. @eos may be NULL
1170  */
1171 static guint32
1172 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1173     GstClockTime time_position)
1174 {
1175   gint i;
1176   guint32 seg_idx;
1177
1178   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1179       GST_TIME_ARGS (time_position));
1180
1181   seg_idx = -1;
1182   for (i = 0; i < stream->n_segments; i++) {
1183     QtDemuxSegment *segment = &stream->segments[i];
1184
1185     GST_LOG_OBJECT (stream->pad,
1186         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1187         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1188
1189     /* For the last segment we include stop_time in the last segment */
1190     if (i < stream->n_segments - 1) {
1191       if (segment->time <= time_position && time_position < segment->stop_time) {
1192         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1193         seg_idx = i;
1194         break;
1195       }
1196     } else {
1197       /* Last segment always matches */
1198       seg_idx = i;
1199       break;
1200     }
1201   }
1202   return seg_idx;
1203 }
1204
1205 /* move the stream @str to the sample position @index.
1206  *
1207  * Updates @str->sample_index and marks discontinuity if needed.
1208  */
1209 static void
1210 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1211     guint32 index)
1212 {
1213   /* no change needed */
1214   if (index == str->sample_index)
1215     return;
1216
1217   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1218       str->n_samples);
1219
1220   /* position changed, we have a discont */
1221   str->sample_index = index;
1222   str->offset_in_sample = 0;
1223   /* Each time we move in the stream we store the position where we are
1224    * starting from */
1225   str->from_sample = index;
1226   str->discont = TRUE;
1227 }
1228
1229 static void
1230 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1231     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1232 {
1233   guint64 min_offset;
1234   gint64 min_byte_offset = -1;
1235   gint n;
1236
1237   min_offset = desired_time;
1238
1239   /* for each stream, find the index of the sample in the segment
1240    * and move back to the previous keyframe. */
1241   for (n = 0; n < qtdemux->n_streams; n++) {
1242     QtDemuxStream *str;
1243     guint32 index, kindex;
1244     guint32 seg_idx;
1245     GstClockTime media_start;
1246     GstClockTime media_time;
1247     GstClockTime seg_time;
1248     QtDemuxSegment *seg;
1249     gboolean empty_segment = FALSE;
1250
1251     str = qtdemux->streams[n];
1252
1253     if (str->sparse && !use_sparse)
1254       continue;
1255
1256     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1257     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1258
1259     /* get segment and time in the segment */
1260     seg = &str->segments[seg_idx];
1261     seg_time = desired_time - seg->time;
1262
1263     while (QTSEGMENT_IS_EMPTY (seg)) {
1264       seg_time = 0;
1265       empty_segment = TRUE;
1266       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1267           seg_idx);
1268       seg_idx++;
1269       if (seg_idx == str->n_segments)
1270         break;
1271       seg = &str->segments[seg_idx];
1272     }
1273
1274     if (seg_idx == str->n_segments) {
1275       /* FIXME track shouldn't have the last segment as empty, but if it
1276        * happens we better handle it */
1277       continue;
1278     }
1279
1280     /* get the media time in the segment */
1281     media_start = seg->media_start + seg_time;
1282
1283     /* get the index of the sample with media time */
1284     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1285     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1286         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1287         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1288         empty_segment);
1289
1290     if (!empty_segment) {
1291       /* find previous keyframe */
1292       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1293
1294       /* if the keyframe is at a different position, we need to update the
1295        * requested seek time */
1296       if (index != kindex) {
1297         index = kindex;
1298
1299         /* get timestamp of keyframe */
1300         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1301         GST_DEBUG_OBJECT (qtdemux,
1302             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1303             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1304             str->samples[kindex].offset);
1305
1306         /* keyframes in the segment get a chance to change the
1307          * desired_offset. keyframes out of the segment are
1308          * ignored. */
1309         if (media_time >= seg->media_start) {
1310           GstClockTime seg_time;
1311
1312           /* this keyframe is inside the segment, convert back to
1313            * segment time */
1314           seg_time = (media_time - seg->media_start) + seg->time;
1315           if (seg_time < min_offset)
1316             min_offset = seg_time;
1317         }
1318       }
1319     }
1320
1321     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1322       min_byte_offset = str->samples[index].offset;
1323   }
1324
1325   if (key_time)
1326     *key_time = min_offset;
1327   if (key_offset)
1328     *key_offset = min_byte_offset;
1329 }
1330
1331 static gboolean
1332 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1333     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1334 {
1335   gboolean res;
1336
1337   g_return_val_if_fail (format != NULL, FALSE);
1338   g_return_val_if_fail (cur != NULL, FALSE);
1339   g_return_val_if_fail (stop != NULL, FALSE);
1340
1341   if (*format == GST_FORMAT_TIME)
1342     return TRUE;
1343
1344   res = TRUE;
1345   if (cur_type != GST_SEEK_TYPE_NONE)
1346     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1347   if (res && stop_type != GST_SEEK_TYPE_NONE)
1348     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1349
1350   if (res)
1351     *format = GST_FORMAT_TIME;
1352
1353   return res;
1354 }
1355
1356 /* perform seek in push based mode:
1357    find BYTE position to move to based on time and delegate to upstream
1358 */
1359 static gboolean
1360 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1361 {
1362   gdouble rate;
1363   GstFormat format;
1364   GstSeekFlags flags;
1365   GstSeekType cur_type, stop_type;
1366   gint64 cur, stop, key_cur;
1367   gboolean res;
1368   gint64 byte_cur;
1369   gint64 original_stop;
1370   guint32 seqnum;
1371
1372   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1373
1374   gst_event_parse_seek (event, &rate, &format, &flags,
1375       &cur_type, &cur, &stop_type, &stop);
1376   seqnum = gst_event_get_seqnum (event);
1377
1378   /* only forward streaming and seeking is possible */
1379   if (rate <= 0)
1380     goto unsupported_seek;
1381
1382   /* convert to TIME if needed and possible */
1383   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1384           stop_type, &stop))
1385     goto no_format;
1386
1387   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1388    * the original stop position to use when upstream pushes the new segment
1389    * for this seek */
1390   original_stop = stop;
1391   stop = -1;
1392
1393   /* find reasonable corresponding BYTE position,
1394    * also try to mind about keyframes, since we can not go back a bit for them
1395    * later on */
1396   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1397
1398   if (byte_cur == -1)
1399     goto abort_seek;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1402       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1403       stop);
1404
1405   GST_OBJECT_LOCK (qtdemux);
1406   qtdemux->seek_offset = byte_cur;
1407   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1408     qtdemux->push_seek_start = cur;
1409   } else {
1410     qtdemux->push_seek_start = key_cur;
1411   }
1412
1413   if (stop_type == GST_SEEK_TYPE_NONE) {
1414     qtdemux->push_seek_stop = qtdemux->segment.stop;
1415   } else {
1416     qtdemux->push_seek_stop = original_stop;
1417   }
1418   GST_OBJECT_UNLOCK (qtdemux);
1419
1420   /* BYTE seek event */
1421   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1422       stop_type, stop);
1423   gst_event_set_seqnum (event, seqnum);
1424   res = gst_pad_push_event (qtdemux->sinkpad, event);
1425
1426   return res;
1427
1428   /* ERRORS */
1429 abort_seek:
1430   {
1431     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1432         "seek aborted.");
1433     return FALSE;
1434   }
1435 unsupported_seek:
1436   {
1437     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1438     return FALSE;
1439   }
1440 no_format:
1441   {
1442     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1443     return FALSE;
1444   }
1445 }
1446
1447 /* perform the seek.
1448  *
1449  * We set all segment_indexes in the streams to unknown and
1450  * adjust the time_position to the desired position. this is enough
1451  * to trigger a segment switch in the streaming thread to start
1452  * streaming from the desired position.
1453  *
1454  * Keyframe seeking is a little more complicated when dealing with
1455  * segments. Ideally we want to move to the previous keyframe in
1456  * the segment but there might not be a keyframe in the segment. In
1457  * fact, none of the segments could contain a keyframe. We take a
1458  * practical approach: seek to the previous keyframe in the segment,
1459  * if there is none, seek to the beginning of the segment.
1460  *
1461  * Called with STREAM_LOCK
1462  */
1463 static gboolean
1464 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1465     guint32 seqnum, GstSeekFlags flags)
1466 {
1467   gint64 desired_offset;
1468   gint n;
1469
1470   desired_offset = segment->position;
1471
1472   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1473       GST_TIME_ARGS (desired_offset));
1474
1475   /* may not have enough fragmented info to do this adjustment,
1476    * and we can't scan (and probably should not) at this time with
1477    * possibly flushing upstream */
1478   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1479     gint64 min_offset;
1480
1481     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1482     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1483         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1484     desired_offset = min_offset;
1485   }
1486
1487   /* and set all streams to the final position */
1488   gst_flow_combiner_reset (qtdemux->flowcombiner);
1489   for (n = 0; n < qtdemux->n_streams; n++) {
1490     QtDemuxStream *stream = qtdemux->streams[n];
1491
1492     stream->time_position = desired_offset;
1493     stream->accumulated_base = 0;
1494     stream->sample_index = -1;
1495     stream->offset_in_sample = 0;
1496     stream->segment_index = -1;
1497     stream->sent_eos = FALSE;
1498     stream->segment_seqnum = seqnum;
1499
1500     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1501       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1502   }
1503   segment->position = desired_offset;
1504   segment->time = desired_offset;
1505   if (segment->rate >= 0) {
1506     segment->start = desired_offset;
1507
1508     /* we stop at the end */
1509     if (segment->stop == -1)
1510       segment->stop = segment->duration;
1511   } else {
1512     segment->stop = desired_offset;
1513   }
1514
1515   if (qtdemux->fragmented)
1516     qtdemux->fragmented_seek_pending = TRUE;
1517
1518   return TRUE;
1519 }
1520
1521 /* do a seek in pull based mode */
1522 static gboolean
1523 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1524 {
1525   gdouble rate;
1526   GstFormat format;
1527   GstSeekFlags flags;
1528   GstSeekType cur_type, stop_type;
1529   gint64 cur, stop;
1530   gboolean flush;
1531   gboolean update;
1532   GstSegment seeksegment;
1533   guint32 seqnum = 0;
1534   GstEvent *flush_event;
1535
1536   if (event) {
1537     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1538
1539     gst_event_parse_seek (event, &rate, &format, &flags,
1540         &cur_type, &cur, &stop_type, &stop);
1541     seqnum = gst_event_get_seqnum (event);
1542
1543     /* we have to have a format as the segment format. Try to convert
1544      * if not. */
1545     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1546             stop_type, &stop))
1547       goto no_format;
1548
1549     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1550   } else {
1551     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1552     flags = 0;
1553   }
1554
1555   flush = flags & GST_SEEK_FLAG_FLUSH;
1556
1557   /* stop streaming, either by flushing or by pausing the task */
1558   if (flush) {
1559     flush_event = gst_event_new_flush_start ();
1560     if (seqnum)
1561       gst_event_set_seqnum (flush_event, seqnum);
1562     /* unlock upstream pull_range */
1563     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1564     /* make sure out loop function exits */
1565     gst_qtdemux_push_event (qtdemux, flush_event);
1566   } else {
1567     /* non flushing seek, pause the task */
1568     gst_pad_pause_task (qtdemux->sinkpad);
1569   }
1570
1571   /* wait for streaming to finish */
1572   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1573
1574   /* copy segment, we need this because we still need the old
1575    * segment when we close the current segment. */
1576   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1577
1578   if (event) {
1579     /* configure the segment with the seek variables */
1580     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1581     gst_segment_do_seek (&seeksegment, rate, format, flags,
1582         cur_type, cur, stop_type, stop, &update);
1583   }
1584
1585   /* now do the seek, this actually never returns FALSE */
1586   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1587
1588   /* prepare for streaming again */
1589   if (flush) {
1590     flush_event = gst_event_new_flush_stop (TRUE);
1591     if (seqnum)
1592       gst_event_set_seqnum (flush_event, seqnum);
1593
1594     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1595     gst_qtdemux_push_event (qtdemux, flush_event);
1596   }
1597
1598   /* commit the new segment */
1599   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1600
1601   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1602     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1603         qtdemux->segment.format, qtdemux->segment.position);
1604     if (seqnum)
1605       gst_message_set_seqnum (msg, seqnum);
1606     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1607   }
1608
1609   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1610   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1611       qtdemux->sinkpad, NULL);
1612
1613   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1614
1615   return TRUE;
1616
1617   /* ERRORS */
1618 no_format:
1619   {
1620     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1621     return FALSE;
1622   }
1623 }
1624
1625 static gboolean
1626 qtdemux_ensure_index (GstQTDemux * qtdemux)
1627 {
1628   guint i;
1629
1630   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1631
1632   /* Build complete index */
1633   for (i = 0; i < qtdemux->n_streams; i++) {
1634     QtDemuxStream *stream = qtdemux->streams[i];
1635
1636     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1637       goto parse_error;
1638   }
1639   return TRUE;
1640
1641   /* ERRORS */
1642 parse_error:
1643   {
1644     GST_LOG_OBJECT (qtdemux,
1645         "Building complete index of stream %u for seeking failed!", i);
1646     return FALSE;
1647   }
1648 }
1649
1650 static gboolean
1651 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1652     GstEvent * event)
1653 {
1654   gboolean res = TRUE;
1655   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1656
1657   switch (GST_EVENT_TYPE (event)) {
1658     case GST_EVENT_SEEK:
1659     {
1660 #ifndef GST_DISABLE_GST_DEBUG
1661       GstClockTime ts = gst_util_get_timestamp ();
1662 #endif
1663
1664       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1665         /* seek should be handled by upstream, we might need to re-download fragments */
1666         GST_DEBUG_OBJECT (qtdemux,
1667             "let upstream handle seek for fragmented playback");
1668         goto upstream;
1669       }
1670
1671       /* Build complete index for seeking;
1672        * if not a fragmented file at least */
1673       if (!qtdemux->fragmented)
1674         if (!qtdemux_ensure_index (qtdemux))
1675           goto index_failed;
1676 #ifndef GST_DISABLE_GST_DEBUG
1677       ts = gst_util_get_timestamp () - ts;
1678       GST_INFO_OBJECT (qtdemux,
1679           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1680 #endif
1681     }
1682       if (qtdemux->pullbased) {
1683         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1684       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1685         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1686         res = TRUE;
1687       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1688           && !qtdemux->fragmented) {
1689         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1690       } else {
1691         GST_DEBUG_OBJECT (qtdemux,
1692             "ignoring seek in push mode in current state");
1693         res = FALSE;
1694       }
1695       gst_event_unref (event);
1696       break;
1697     case GST_EVENT_QOS:
1698     case GST_EVENT_NAVIGATION:
1699       res = FALSE;
1700       gst_event_unref (event);
1701       break;
1702     default:
1703     upstream:
1704       res = gst_pad_event_default (pad, parent, event);
1705       break;
1706   }
1707
1708 done:
1709   return res;
1710
1711   /* ERRORS */
1712 index_failed:
1713   {
1714     GST_ERROR_OBJECT (qtdemux, "Index failed");
1715     gst_event_unref (event);
1716     res = FALSE;
1717     goto done;
1718   }
1719 }
1720
1721 /* stream/index return sample that is min/max w.r.t. byte position,
1722  * time is min/max w.r.t. time of samples,
1723  * the latter need not be time of the former sample */
1724 static void
1725 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1726     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1727 {
1728   gint i, n, index;
1729   gint64 time, min_time;
1730   QtDemuxStream *stream;
1731
1732   min_time = -1;
1733   stream = NULL;
1734   index = -1;
1735
1736   for (n = 0; n < qtdemux->n_streams; ++n) {
1737     QtDemuxStream *str;
1738     gint inc;
1739     gboolean set_sample;
1740
1741     str = qtdemux->streams[n];
1742     set_sample = !set;
1743
1744     if (fw) {
1745       i = 0;
1746       inc = 1;
1747     } else {
1748       i = str->n_samples - 1;
1749       inc = -1;
1750     }
1751
1752     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1753       if (str->samples[i].size == 0)
1754         continue;
1755
1756       if (fw && (str->samples[i].offset < byte_pos))
1757         continue;
1758
1759       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1760         continue;
1761
1762       /* move stream to first available sample */
1763       if (set) {
1764         gst_qtdemux_move_stream (qtdemux, str, i);
1765         set_sample = TRUE;
1766       }
1767
1768       /* avoid index from sparse streams since they might be far away */
1769       if (!str->sparse) {
1770         /* determine min/max time */
1771         time = QTSAMPLE_PTS (str, &str->samples[i]);
1772         if (min_time == -1 || (!fw && time > min_time) ||
1773             (fw && time < min_time)) {
1774           min_time = time;
1775         }
1776
1777         /* determine stream with leading sample, to get its position */
1778         if (!stream ||
1779             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1780             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1781           stream = str;
1782           index = i;
1783         }
1784       }
1785       break;
1786     }
1787
1788     /* no sample for this stream, mark eos */
1789     if (!set_sample)
1790       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1791   }
1792
1793   if (_time)
1794     *_time = min_time;
1795   if (_stream)
1796     *_stream = stream;
1797   if (_index)
1798     *_index = index;
1799 }
1800
1801 static QtDemuxStream *
1802 _create_stream (void)
1803 {
1804   QtDemuxStream *stream;
1805
1806   stream = g_new0 (QtDemuxStream, 1);
1807   /* new streams always need a discont */
1808   stream->discont = TRUE;
1809   /* we enable clipping for raw audio/video streams */
1810   stream->need_clip = FALSE;
1811   stream->need_process = FALSE;
1812   stream->segment_index = -1;
1813   stream->time_position = 0;
1814   stream->sample_index = -1;
1815   stream->offset_in_sample = 0;
1816   stream->new_stream = TRUE;
1817   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1818   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1819   stream->protected = FALSE;
1820   stream->protection_scheme_type = 0;
1821   stream->protection_scheme_version = 0;
1822   stream->protection_scheme_info = NULL;
1823   stream->n_samples_moof = 0;
1824   stream->duration_moof = 0;
1825   g_queue_init (&stream->protection_scheme_event_queue);
1826   return stream;
1827 }
1828
1829 static gboolean
1830 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1831 {
1832   GstStructure *structure;
1833   const gchar *variant;
1834   const GstCaps *mediacaps = NULL;
1835
1836   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1837
1838   structure = gst_caps_get_structure (caps, 0);
1839   variant = gst_structure_get_string (structure, "variant");
1840
1841   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1842     QtDemuxStream *stream;
1843     const GValue *value;
1844
1845     demux->fragmented = TRUE;
1846     demux->mss_mode = TRUE;
1847
1848     if (demux->n_streams > 1) {
1849       /* can't do this, we can only renegotiate for another mss format */
1850       return FALSE;
1851     }
1852
1853     value = gst_structure_get_value (structure, "media-caps");
1854     /* create stream */
1855     if (value) {
1856       const GValue *timescale_v;
1857
1858       /* TODO update when stream changes during playback */
1859
1860       if (demux->n_streams == 0) {
1861         stream = _create_stream ();
1862         demux->streams[demux->n_streams] = stream;
1863         demux->n_streams = 1;
1864       } else {
1865         stream = demux->streams[0];
1866       }
1867
1868       timescale_v = gst_structure_get_value (structure, "timescale");
1869       if (timescale_v) {
1870         stream->timescale = g_value_get_uint64 (timescale_v);
1871       } else {
1872         /* default mss timescale */
1873         stream->timescale = 10000000;
1874       }
1875       demux->timescale = stream->timescale;
1876
1877       mediacaps = gst_value_get_caps (value);
1878       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1879         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1880             mediacaps);
1881         stream->new_caps = TRUE;
1882       }
1883       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1884       structure = gst_caps_get_structure (mediacaps, 0);
1885       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1886         stream->subtype = FOURCC_vide;
1887
1888         gst_structure_get_int (structure, "width", &stream->width);
1889         gst_structure_get_int (structure, "height", &stream->height);
1890         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1891             &stream->fps_d);
1892       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1893         gint rate = 0;
1894         stream->subtype = FOURCC_soun;
1895         gst_structure_get_int (structure, "channels", &stream->n_channels);
1896         gst_structure_get_int (structure, "rate", &rate);
1897         stream->rate = rate;
1898       }
1899     }
1900     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1901   } else {
1902     demux->mss_mode = FALSE;
1903   }
1904
1905   return TRUE;
1906 }
1907
1908 static void
1909 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1910 {
1911   gint n;
1912
1913   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1914   gst_pad_stop_task (qtdemux->sinkpad);
1915
1916   if (hard || qtdemux->upstream_format_is_time) {
1917     qtdemux->state = QTDEMUX_STATE_INITIAL;
1918     qtdemux->neededbytes = 16;
1919     qtdemux->todrop = 0;
1920     qtdemux->pullbased = FALSE;
1921     qtdemux->posted_redirect = FALSE;
1922     qtdemux->first_mdat = -1;
1923     qtdemux->header_size = 0;
1924     qtdemux->mdatoffset = -1;
1925     qtdemux->restoredata_offset = -1;
1926     if (qtdemux->mdatbuffer)
1927       gst_buffer_unref (qtdemux->mdatbuffer);
1928     if (qtdemux->restoredata_buffer)
1929       gst_buffer_unref (qtdemux->restoredata_buffer);
1930     qtdemux->mdatbuffer = NULL;
1931     qtdemux->restoredata_buffer = NULL;
1932     qtdemux->mdatleft = 0;
1933     if (qtdemux->comp_brands)
1934       gst_buffer_unref (qtdemux->comp_brands);
1935     qtdemux->comp_brands = NULL;
1936     qtdemux->last_moov_offset = -1;
1937     if (qtdemux->moov_node)
1938       g_node_destroy (qtdemux->moov_node);
1939     qtdemux->moov_node = NULL;
1940     qtdemux->moov_node_compressed = NULL;
1941     if (qtdemux->tag_list)
1942       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1943     qtdemux->tag_list = NULL;
1944 #if 0
1945     if (qtdemux->element_index)
1946       gst_object_unref (qtdemux->element_index);
1947     qtdemux->element_index = NULL;
1948 #endif
1949     qtdemux->major_brand = 0;
1950     if (qtdemux->pending_newsegment)
1951       gst_event_unref (qtdemux->pending_newsegment);
1952     qtdemux->pending_newsegment = NULL;
1953     qtdemux->upstream_format_is_time = FALSE;
1954     qtdemux->upstream_seekable = FALSE;
1955     qtdemux->upstream_size = 0;
1956
1957     qtdemux->fragment_start = -1;
1958     qtdemux->fragment_start_offset = -1;
1959     qtdemux->duration = 0;
1960     qtdemux->moof_offset = 0;
1961     qtdemux->chapters_track_id = 0;
1962     qtdemux->have_group_id = FALSE;
1963     qtdemux->group_id = G_MAXUINT;
1964
1965     if (qtdemux->protection_system_ids) {
1966       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
1967       qtdemux->protection_system_ids = NULL;
1968     }
1969     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1970         NULL);
1971     g_queue_clear (&qtdemux->protection_event_queue);
1972   }
1973   qtdemux->offset = 0;
1974   gst_adapter_clear (qtdemux->adapter);
1975   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1976
1977   if (hard) {
1978     for (n = 0; n < qtdemux->n_streams; n++) {
1979       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1980       qtdemux->streams[n] = NULL;
1981     }
1982     qtdemux->n_streams = 0;
1983     qtdemux->n_video_streams = 0;
1984     qtdemux->n_audio_streams = 0;
1985     qtdemux->n_sub_streams = 0;
1986     qtdemux->exposed = FALSE;
1987     qtdemux->fragmented = FALSE;
1988     qtdemux->mss_mode = FALSE;
1989     gst_caps_replace (&qtdemux->media_caps, NULL);
1990     qtdemux->timescale = 0;
1991     qtdemux->got_moov = FALSE;
1992     qtdemux->pending_configure = FALSE;
1993   } else if (qtdemux->mss_mode) {
1994     gst_flow_combiner_reset (qtdemux->flowcombiner);
1995     for (n = 0; n < qtdemux->n_streams; n++)
1996       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
1997   } else {
1998     gst_flow_combiner_reset (qtdemux->flowcombiner);
1999     for (n = 0; n < qtdemux->n_streams; n++) {
2000       qtdemux->streams[n]->sent_eos = FALSE;
2001       qtdemux->streams[n]->segment_seqnum = 0;
2002       qtdemux->streams[n]->time_position = 0;
2003       qtdemux->streams[n]->accumulated_base = 0;
2004     }
2005     if (!qtdemux->pending_newsegment) {
2006       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2007     }
2008   }
2009 }
2010
2011 static gboolean
2012 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2013     GstEvent * event)
2014 {
2015   GstQTDemux *demux = GST_QTDEMUX (parent);
2016   gboolean res = TRUE;
2017
2018   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2019
2020   switch (GST_EVENT_TYPE (event)) {
2021     case GST_EVENT_SEGMENT:
2022     {
2023       gint64 offset = 0;
2024       QtDemuxStream *stream;
2025       gint idx;
2026       GstSegment segment;
2027       GstEvent *segment_event;
2028
2029       /* some debug output */
2030       gst_event_copy_segment (event, &segment);
2031       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2032           &segment);
2033
2034       if (segment.format == GST_FORMAT_TIME) {
2035         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2036         gst_event_replace (&demux->pending_newsegment, event);
2037         demux->upstream_format_is_time = TRUE;
2038       } else {
2039         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2040             "not in time format");
2041
2042         /* chain will send initial newsegment after pads have been added */
2043         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2044           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2045           goto exit;
2046         }
2047       }
2048
2049       /* check if this matches a time seek we received previously
2050        * FIXME for backwards compatibility reasons we use the
2051        * seek_offset here to compare. In the future we might want to
2052        * change this to use the seqnum as it uniquely should identify
2053        * the segment that corresponds to the seek. */
2054       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2055           ", received segment offset %" G_GINT64_FORMAT,
2056           demux->seek_offset, segment.start);
2057       if (segment.format == GST_FORMAT_BYTES
2058           && demux->seek_offset == segment.start) {
2059         GST_OBJECT_LOCK (demux);
2060         offset = segment.start;
2061
2062         segment.format = GST_FORMAT_TIME;
2063         segment.start = demux->push_seek_start;
2064         segment.stop = demux->push_seek_stop;
2065         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2066             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2067             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2068         GST_OBJECT_UNLOCK (demux);
2069       }
2070
2071       /* we only expect a BYTE segment, e.g. following a seek */
2072       if (segment.format == GST_FORMAT_BYTES) {
2073         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2074           offset = segment.start;
2075
2076           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2077               NULL, (gint64 *) & segment.start);
2078           if ((gint64) segment.start < 0)
2079             segment.start = 0;
2080         }
2081         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2082           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2083               NULL, (gint64 *) & segment.stop);
2084           /* keyframe seeking should already arrange for start >= stop,
2085            * but make sure in other rare cases */
2086           segment.stop = MAX (segment.stop, segment.start);
2087         }
2088       } else if (segment.format == GST_FORMAT_TIME) {
2089         /* push all data on the adapter before starting this
2090          * new segment */
2091         gst_qtdemux_process_adapter (demux, TRUE);
2092       } else {
2093         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2094         goto exit;
2095       }
2096
2097       /* accept upstream's notion of segment and distribute along */
2098       segment.format = GST_FORMAT_TIME;
2099       segment.position = segment.time = segment.start;
2100       segment.duration = demux->segment.duration;
2101       segment.base = gst_segment_to_running_time (&demux->segment,
2102           GST_FORMAT_TIME, demux->segment.position);
2103
2104       gst_segment_copy_into (&segment, &demux->segment);
2105       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2106       segment_event = gst_event_new_segment (&segment);
2107       gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2108       gst_qtdemux_push_event (demux, segment_event);
2109
2110       /* clear leftover in current segment, if any */
2111       gst_adapter_clear (demux->adapter);
2112
2113       /* set up streaming thread */
2114       demux->offset = offset;
2115       if (demux->upstream_format_is_time) {
2116         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2117             "set values to restart reading from a new atom");
2118         demux->neededbytes = 16;
2119         demux->todrop = 0;
2120       } else {
2121         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2122             NULL);
2123         if (stream) {
2124           demux->todrop = stream->samples[idx].offset - offset;
2125           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2126         } else {
2127           /* set up for EOS */
2128           demux->neededbytes = -1;
2129           demux->todrop = 0;
2130         }
2131       }
2132     exit:
2133       gst_event_unref (event);
2134       res = TRUE;
2135       goto drop;
2136     }
2137     case GST_EVENT_FLUSH_START:
2138     {
2139       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2140         gst_event_unref (event);
2141         goto drop;
2142       }
2143       break;
2144     }
2145     case GST_EVENT_FLUSH_STOP:
2146     {
2147       guint64 dur;
2148
2149       dur = demux->segment.duration;
2150       gst_qtdemux_reset (demux, FALSE);
2151       demux->segment.duration = dur;
2152
2153       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2154         gst_event_unref (event);
2155         goto drop;
2156       }
2157       break;
2158     }
2159     case GST_EVENT_EOS:
2160       /* If we are in push mode, and get an EOS before we've seen any streams,
2161        * then error out - we have nowhere to send the EOS */
2162       if (!demux->pullbased) {
2163         gint i;
2164         gboolean has_valid_stream = FALSE;
2165         for (i = 0; i < demux->n_streams; i++) {
2166           if (demux->streams[i]->pad != NULL) {
2167             has_valid_stream = TRUE;
2168             break;
2169           }
2170         }
2171         if (!has_valid_stream)
2172           gst_qtdemux_post_no_playable_stream_error (demux);
2173         else {
2174           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2175               (guint) gst_adapter_available (demux->adapter));
2176           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2177             res = FALSE;
2178           }
2179         }
2180       }
2181       break;
2182     case GST_EVENT_CAPS:{
2183       GstCaps *caps = NULL;
2184
2185       gst_event_parse_caps (event, &caps);
2186       gst_qtdemux_setcaps (demux, caps);
2187       res = TRUE;
2188       gst_event_unref (event);
2189       goto drop;
2190     }
2191     case GST_EVENT_PROTECTION:
2192     {
2193       const gchar *system_id = NULL;
2194
2195       gst_event_parse_protection (event, &system_id, NULL, NULL);
2196       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2197           system_id);
2198       gst_qtdemux_append_protection_system_id (demux, system_id);
2199       /* save the event for later, for source pads that have not been created */
2200       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2201       /* send it to all pads that already exist */
2202       gst_qtdemux_push_event (demux, event);
2203       res = TRUE;
2204       goto drop;
2205     }
2206     default:
2207       break;
2208   }
2209
2210   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2211
2212 drop:
2213   return res;
2214 }
2215
2216 #if 0
2217 static void
2218 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2219 {
2220   GstQTDemux *demux = GST_QTDEMUX (element);
2221
2222   GST_OBJECT_LOCK (demux);
2223   if (demux->element_index)
2224     gst_object_unref (demux->element_index);
2225   if (index) {
2226     demux->element_index = gst_object_ref (index);
2227   } else {
2228     demux->element_index = NULL;
2229   }
2230   GST_OBJECT_UNLOCK (demux);
2231   /* object lock might be taken again */
2232   if (index)
2233     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2234   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2235       demux->element_index, demux->index_id);
2236 }
2237
2238 static GstIndex *
2239 gst_qtdemux_get_index (GstElement * element)
2240 {
2241   GstIndex *result = NULL;
2242   GstQTDemux *demux = GST_QTDEMUX (element);
2243
2244   GST_OBJECT_LOCK (demux);
2245   if (demux->element_index)
2246     result = gst_object_ref (demux->element_index);
2247   GST_OBJECT_UNLOCK (demux);
2248
2249   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2250
2251   return result;
2252 }
2253 #endif
2254
2255 static void
2256 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2257 {
2258   g_free ((gpointer) stream->stco.data);
2259   stream->stco.data = NULL;
2260   g_free ((gpointer) stream->stsz.data);
2261   stream->stsz.data = NULL;
2262   g_free ((gpointer) stream->stsc.data);
2263   stream->stsc.data = NULL;
2264   g_free ((gpointer) stream->stts.data);
2265   stream->stts.data = NULL;
2266   g_free ((gpointer) stream->stss.data);
2267   stream->stss.data = NULL;
2268   g_free ((gpointer) stream->stps.data);
2269   stream->stps.data = NULL;
2270   g_free ((gpointer) stream->ctts.data);
2271   stream->ctts.data = NULL;
2272 }
2273
2274 static void
2275 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2276     QtDemuxStream * stream)
2277 {
2278   g_free (stream->segments);
2279   stream->segments = NULL;
2280   stream->segment_index = -1;
2281   stream->accumulated_base = 0;
2282 }
2283
2284 static void
2285 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2286     QtDemuxStream * stream)
2287 {
2288   g_free (stream->samples);
2289   stream->samples = NULL;
2290   gst_qtdemux_stbl_free (stream);
2291
2292   /* fragments */
2293   g_free (stream->ra_entries);
2294   stream->ra_entries = NULL;
2295   stream->n_ra_entries = 0;
2296
2297   stream->sample_index = -1;
2298   stream->stbl_index = -1;
2299   stream->n_samples = 0;
2300   stream->time_position = 0;
2301
2302   stream->n_samples_moof = 0;
2303   stream->duration_moof = 0;
2304 }
2305
2306 static void
2307 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2308 {
2309   if (stream->allocator)
2310     gst_object_unref (stream->allocator);
2311   while (stream->buffers) {
2312     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2313     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2314   }
2315   if (stream->rgb8_palette) {
2316     gst_memory_unref (stream->rgb8_palette);
2317     stream->rgb8_palette = NULL;
2318   }
2319
2320   if (stream->pending_tags)
2321     gst_tag_list_unref (stream->pending_tags);
2322   stream->pending_tags = NULL;
2323   g_free (stream->redirect_uri);
2324   stream->redirect_uri = NULL;
2325   stream->sent_eos = FALSE;
2326   stream->sparse = FALSE;
2327   stream->protected = FALSE;
2328   if (stream->protection_scheme_info) {
2329     if (stream->protection_scheme_type == FOURCC_cenc) {
2330       QtDemuxCencSampleSetInfo *info =
2331           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2332       if (info->default_properties)
2333         gst_structure_free (info->default_properties);
2334       if (info->crypto_info)
2335         g_ptr_array_free (info->crypto_info, TRUE);
2336     }
2337     g_free (stream->protection_scheme_info);
2338     stream->protection_scheme_info = NULL;
2339   }
2340   stream->protection_scheme_type = 0;
2341   stream->protection_scheme_version = 0;
2342   g_queue_foreach (&stream->protection_scheme_event_queue,
2343       (GFunc) gst_event_unref, NULL);
2344   g_queue_clear (&stream->protection_scheme_event_queue);
2345   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2346   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2347 }
2348
2349 static void
2350 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2351 {
2352   gst_qtdemux_stream_clear (qtdemux, stream);
2353   if (stream->caps)
2354     gst_caps_unref (stream->caps);
2355   stream->caps = NULL;
2356   if (stream->pad) {
2357     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2358     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2359   }
2360   g_free (stream);
2361 }
2362
2363 static void
2364 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2365 {
2366   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2367
2368   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2369   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2370   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2371   qtdemux->n_streams--;
2372 }
2373
2374 static GstStateChangeReturn
2375 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2376 {
2377   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2378   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2379
2380   switch (transition) {
2381     case GST_STATE_CHANGE_PAUSED_TO_READY:
2382       break;
2383     default:
2384       break;
2385   }
2386
2387   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2388
2389   switch (transition) {
2390     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2391       gst_qtdemux_reset (qtdemux, TRUE);
2392       break;
2393     }
2394     default:
2395       break;
2396   }
2397
2398   return result;
2399 }
2400
2401 static void
2402 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2403 {
2404   /* counts as header data */
2405   qtdemux->header_size += length;
2406
2407   /* only consider at least a sufficiently complete ftyp atom */
2408   if (length >= 20) {
2409     GstBuffer *buf;
2410
2411     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2412     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2413         GST_FOURCC_ARGS (qtdemux->major_brand));
2414     if (qtdemux->comp_brands)
2415       gst_buffer_unref (qtdemux->comp_brands);
2416     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2417     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2418   }
2419 }
2420
2421 static void
2422 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2423     GstTagList * xmptaglist)
2424 {
2425   /* Strip out bogus fields */
2426   if (xmptaglist) {
2427     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2428       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2429       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2430     } else {
2431       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2432     }
2433
2434     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2435
2436     /* prioritize native tags using _KEEP mode */
2437     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2438     gst_tag_list_unref (xmptaglist);
2439   }
2440 }
2441
2442 static void
2443 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2444 {
2445   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2446     0x97, 0xA9, 0x42, 0xE8,
2447     0x9C, 0x71, 0x99, 0x94,
2448     0x91, 0xE3, 0xAF, 0xAC
2449   };
2450   static const guint8 playready_uuid[] = {
2451     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2452     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2453   };
2454   guint offset;
2455
2456   /* counts as header data */
2457   qtdemux->header_size += length;
2458
2459   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2460
2461   if (length <= offset + 16) {
2462     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2463     return;
2464   }
2465
2466   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2467     GstBuffer *buf;
2468     GstTagList *taglist;
2469
2470     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2471         length - offset - 16, NULL);
2472     taglist = gst_tag_list_from_xmp_buffer (buf);
2473     gst_buffer_unref (buf);
2474
2475     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2476
2477   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2478     int len;
2479     const gunichar2 *s_utf16;
2480     char *contents;
2481
2482     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2483     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2484     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2485     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2486
2487     g_free (contents);
2488
2489     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2490         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2491         (NULL));
2492   } else {
2493     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2494         GST_READ_UINT32_LE (buffer + offset),
2495         GST_READ_UINT32_LE (buffer + offset + 4),
2496         GST_READ_UINT32_LE (buffer + offset + 8),
2497         GST_READ_UINT32_LE (buffer + offset + 12));
2498   }
2499 }
2500
2501 static void
2502 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2503 {
2504   GstSidxParser sidx_parser;
2505   GstIsoffParserResult res;
2506   guint consumed;
2507
2508   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2509
2510   res =
2511       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2512       &consumed);
2513   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2514   if (res == GST_ISOFF_QT_PARSER_DONE) {
2515     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2516   }
2517   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2518 }
2519
2520 /* caller verifies at least 8 bytes in buf */
2521 static void
2522 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2523     guint64 * plength, guint32 * pfourcc)
2524 {
2525   guint64 length;
2526   guint32 fourcc;
2527
2528   length = QT_UINT32 (data);
2529   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2530   fourcc = QT_FOURCC (data + 4);
2531   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2532
2533   if (length == 0) {
2534     length = G_MAXUINT64;
2535   } else if (length == 1 && size >= 16) {
2536     /* this means we have an extended size, which is the 64 bit value of
2537      * the next 8 bytes */
2538     length = QT_UINT64 (data + 8);
2539     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2540   }
2541
2542   if (plength)
2543     *plength = length;
2544   if (pfourcc)
2545     *pfourcc = fourcc;
2546 }
2547
2548 static gboolean
2549 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2550 {
2551   guint32 version = 0;
2552   GstClockTime duration = 0;
2553
2554   if (!gst_byte_reader_get_uint32_be (br, &version))
2555     goto failed;
2556
2557   version >>= 24;
2558   if (version == 1) {
2559     if (!gst_byte_reader_get_uint64_be (br, &duration))
2560       goto failed;
2561   } else {
2562     guint32 dur = 0;
2563
2564     if (!gst_byte_reader_get_uint32_be (br, &dur))
2565       goto failed;
2566     duration = dur;
2567   }
2568
2569   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2570   qtdemux->duration = duration;
2571
2572   return TRUE;
2573
2574 failed:
2575   {
2576     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2577     return FALSE;
2578   }
2579 }
2580
2581 static gboolean
2582 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2583     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2584 {
2585   if (!stream->parsed_trex && qtdemux->moov_node) {
2586     GNode *mvex, *trex;
2587     GstByteReader trex_data;
2588
2589     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2590     if (mvex) {
2591       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2592           &trex_data);
2593       while (trex) {
2594         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2595
2596         /* skip version/flags */
2597         if (!gst_byte_reader_skip (&trex_data, 4))
2598           goto next;
2599         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2600           goto next;
2601         if (id != stream->track_id)
2602           goto next;
2603         /* sample description index; ignore */
2604         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2605           goto next;
2606         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2607           goto next;
2608         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2609           goto next;
2610         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2611           goto next;
2612
2613         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2614             "duration %d,  size %d, flags 0x%x", stream->track_id,
2615             dur, size, flags);
2616
2617         stream->parsed_trex = TRUE;
2618         stream->def_sample_duration = dur;
2619         stream->def_sample_size = size;
2620         stream->def_sample_flags = flags;
2621
2622       next:
2623         /* iterate all siblings */
2624         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2625             &trex_data);
2626       }
2627     }
2628   }
2629
2630   *ds_duration = stream->def_sample_duration;
2631   *ds_size = stream->def_sample_size;
2632   *ds_flags = stream->def_sample_flags;
2633
2634   /* even then, above values are better than random ... */
2635   if (G_UNLIKELY (!stream->parsed_trex)) {
2636     GST_WARNING_OBJECT (qtdemux,
2637         "failed to find fragment defaults for stream %d", stream->track_id);
2638     return FALSE;
2639   }
2640
2641   return TRUE;
2642 }
2643
2644 /* This method should be called whenever a more accurate duration might
2645  * have been found. It will update all relevant variables if/where needed
2646  */
2647 static void
2648 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2649 {
2650   guint i;
2651   guint64 movdur;
2652   GstClockTime prevdur;
2653
2654   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2655
2656   if (movdur > qtdemux->duration) {
2657     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2658     GST_DEBUG_OBJECT (qtdemux,
2659         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2660         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2661     qtdemux->duration = movdur;
2662     GST_DEBUG_OBJECT (qtdemux,
2663         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2664         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2665         GST_TIME_ARGS (qtdemux->segment.stop));
2666     if (qtdemux->segment.duration == prevdur) {
2667       /* If the current segment has duration/stop identical to previous duration
2668        * update them also (because they were set at that point in time with
2669        * the wrong duration */
2670       /* We convert the value *from* the timescale version to avoid rounding errors */
2671       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2672       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2673       qtdemux->segment.duration = fixeddur;
2674       qtdemux->segment.stop = fixeddur;
2675     }
2676   }
2677   for (i = 0; i < qtdemux->n_streams; i++) {
2678     QtDemuxStream *stream = qtdemux->streams[i];
2679     if (stream) {
2680       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2681       if (movdur > stream->duration) {
2682         GST_DEBUG_OBJECT (qtdemux,
2683             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2684             GST_TIME_ARGS (duration));
2685         stream->duration = movdur;
2686         if (stream->dummy_segment) {
2687           /* Update all dummy values to new duration */
2688           stream->segments[0].stop_time = duration;
2689           stream->segments[0].duration = duration;
2690           stream->segments[0].media_stop = duration;
2691         }
2692       }
2693     }
2694   }
2695 }
2696
2697 static gboolean
2698 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2699     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2700     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2701     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2702 {
2703   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2704   guint64 timestamp;
2705   gint32 data_offset = 0;
2706   guint32 flags = 0, first_flags = 0, samples_count = 0;
2707   gint i;
2708   guint8 *data;
2709   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2710   QtDemuxSample *sample;
2711   gboolean ismv = FALSE;
2712
2713   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2714       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2715       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2716       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2717
2718   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2719     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2720     return TRUE;
2721   }
2722
2723   /* presence of stss or not can't really tell us much,
2724    * and flags and so on tend to be marginally reliable in these files */
2725   if (stream->subtype == FOURCC_soun) {
2726     GST_DEBUG_OBJECT (qtdemux,
2727         "sound track in fragmented file; marking all keyframes");
2728     stream->all_keyframe = TRUE;
2729   }
2730
2731   if (!gst_byte_reader_skip (trun, 1) ||
2732       !gst_byte_reader_get_uint24_be (trun, &flags))
2733     goto fail;
2734
2735   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2736     goto fail;
2737
2738   if (flags & TR_DATA_OFFSET) {
2739     /* note this is really signed */
2740     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2741       goto fail;
2742     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2743     /* default base offset = first byte of moof */
2744     if (*base_offset == -1) {
2745       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
2746       *base_offset = moof_offset;
2747     }
2748     *running_offset = *base_offset + data_offset;
2749   } else {
2750     /* if no offset at all, that would mean data starts at moof start,
2751      * which is a bit wrong and is ismv crappy way, so compensate
2752      * assuming data is in mdat following moof */
2753     if (*base_offset == -1) {
2754       *base_offset = moof_offset + moof_length + 8;
2755       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
2756       ismv = TRUE;
2757     }
2758     if (*running_offset == -1)
2759       *running_offset = *base_offset;
2760   }
2761
2762   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
2763       *running_offset);
2764   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
2765       data_offset, flags, samples_count);
2766
2767   if (flags & TR_FIRST_SAMPLE_FLAGS) {
2768     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
2769       GST_DEBUG_OBJECT (qtdemux,
2770           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
2771       flags ^= TR_FIRST_SAMPLE_FLAGS;
2772     } else {
2773       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
2774         goto fail;
2775       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
2776     }
2777   }
2778
2779   /* FIXME ? spec says other bits should also be checked to determine
2780    * entry size (and prefix size for that matter) */
2781   entry_size = 0;
2782   dur_offset = size_offset = 0;
2783   if (flags & TR_SAMPLE_DURATION) {
2784     GST_LOG_OBJECT (qtdemux, "entry duration present");
2785     dur_offset = entry_size;
2786     entry_size += 4;
2787   }
2788   if (flags & TR_SAMPLE_SIZE) {
2789     GST_LOG_OBJECT (qtdemux, "entry size present");
2790     size_offset = entry_size;
2791     entry_size += 4;
2792   }
2793   if (flags & TR_SAMPLE_FLAGS) {
2794     GST_LOG_OBJECT (qtdemux, "entry flags present");
2795     flags_offset = entry_size;
2796     entry_size += 4;
2797   }
2798   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2799     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
2800     ct_offset = entry_size;
2801     entry_size += 4;
2802   }
2803
2804   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
2805     goto fail;
2806   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
2807
2808   if (stream->n_samples + samples_count >=
2809       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
2810     goto index_too_big;
2811
2812   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
2813       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
2814       (stream->n_samples + samples_count) *
2815       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
2816
2817   /* create a new array of samples if it's the first sample parsed */
2818   if (stream->n_samples == 0) {
2819     g_assert (stream->samples == NULL);
2820     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
2821     /* or try to reallocate it with space enough to insert the new samples */
2822   } else
2823     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
2824         stream->n_samples + samples_count);
2825   if (stream->samples == NULL)
2826     goto out_of_memory;
2827
2828   if (qtdemux->fragment_start != -1) {
2829     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
2830     qtdemux->fragment_start = -1;
2831   } else {
2832     if (stream->n_samples == 0) {
2833       if (decode_ts > 0) {
2834         timestamp = decode_ts;
2835       } else if (stream->pending_seek != NULL) {
2836         /* if we don't have a timestamp from a tfdt box, we'll use the one
2837          * from the mfra seek table */
2838         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
2839             GST_TIME_ARGS (stream->pending_seek->ts));
2840
2841         /* FIXME: this is not fully correct, the timestamp refers to the random
2842          * access sample refered to in the tfra entry, which may not necessarily
2843          * be the first sample in the tfrag/trun (but hopefully/usually is) */
2844         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
2845       } else {
2846         timestamp = 0;
2847       }
2848
2849       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2850       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
2851           GST_TIME_ARGS (gst_ts));
2852     } else {
2853       /* subsequent fragments extend stream */
2854       timestamp =
2855           stream->samples[stream->n_samples - 1].timestamp +
2856           stream->samples[stream->n_samples - 1].duration;
2857
2858       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2859       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
2860           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
2861     }
2862   }
2863
2864   sample = stream->samples + stream->n_samples;
2865   for (i = 0; i < samples_count; i++) {
2866     guint32 dur, size, sflags, ct;
2867
2868     /* first read sample data */
2869     if (flags & TR_SAMPLE_DURATION) {
2870       dur = QT_UINT32 (data + dur_offset);
2871     } else {
2872       dur = d_sample_duration;
2873     }
2874     if (flags & TR_SAMPLE_SIZE) {
2875       size = QT_UINT32 (data + size_offset);
2876     } else {
2877       size = d_sample_size;
2878     }
2879     if (flags & TR_FIRST_SAMPLE_FLAGS) {
2880       if (i == 0) {
2881         sflags = first_flags;
2882       } else {
2883         sflags = d_sample_flags;
2884       }
2885     } else if (flags & TR_SAMPLE_FLAGS) {
2886       sflags = QT_UINT32 (data + flags_offset);
2887     } else {
2888       sflags = d_sample_flags;
2889     }
2890     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2891       ct = QT_UINT32 (data + ct_offset);
2892     } else {
2893       ct = 0;
2894     }
2895     data += entry_size;
2896
2897     /* fill the sample information */
2898     sample->offset = *running_offset;
2899     sample->pts_offset = ct;
2900     sample->size = size;
2901     sample->timestamp = timestamp;
2902     sample->duration = dur;
2903     /* sample-is-difference-sample */
2904     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
2905      * now idea how it relates to bitfield other than massive LE/BE confusion */
2906     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
2907     *running_offset += size;
2908     timestamp += dur;
2909     stream->duration_moof += dur;
2910     sample++;
2911   }
2912
2913   /* Update total duration if needed */
2914   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
2915
2916   stream->n_samples += samples_count;
2917   stream->n_samples_moof += samples_count;
2918
2919   if (stream->pending_seek != NULL)
2920     stream->pending_seek = NULL;
2921
2922   return TRUE;
2923
2924 fail:
2925   {
2926     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
2927     return FALSE;
2928   }
2929 out_of_memory:
2930   {
2931     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
2932         stream->n_samples);
2933     return FALSE;
2934   }
2935 index_too_big:
2936   {
2937     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
2938         "be larger than %uMB (broken file?)", stream->n_samples,
2939         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
2940     return FALSE;
2941   }
2942 }
2943
2944 /* find stream with @id */
2945 static inline QtDemuxStream *
2946 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
2947 {
2948   QtDemuxStream *stream;
2949   gint i;
2950
2951   /* check */
2952   if (G_UNLIKELY (!id)) {
2953     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
2954     return NULL;
2955   }
2956
2957   /* try to get it fast and simple */
2958   if (G_LIKELY (id <= qtdemux->n_streams)) {
2959     stream = qtdemux->streams[id - 1];
2960     if (G_LIKELY (stream->track_id == id))
2961       return stream;
2962   }
2963
2964   /* linear search otherwise */
2965   for (i = 0; i < qtdemux->n_streams; i++) {
2966     stream = qtdemux->streams[i];
2967     if (stream->track_id == id)
2968       return stream;
2969   }
2970   if (qtdemux->mss_mode) {
2971     /* mss should have only 1 stream anyway */
2972     return qtdemux->streams[0];
2973   }
2974
2975   return NULL;
2976 }
2977
2978 static gboolean
2979 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
2980     guint32 * fragment_number)
2981 {
2982   if (!gst_byte_reader_skip (mfhd, 4))
2983     goto fail;
2984   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
2985     goto fail;
2986   return TRUE;
2987 fail:
2988   {
2989     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
2990     return FALSE;
2991   }
2992 }
2993
2994 static gboolean
2995 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
2996     QtDemuxStream ** stream, guint32 * default_sample_duration,
2997     guint32 * default_sample_size, guint32 * default_sample_flags,
2998     gint64 * base_offset)
2999 {
3000   guint32 flags = 0;
3001   guint32 track_id = 0;
3002
3003   if (!gst_byte_reader_skip (tfhd, 1) ||
3004       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3005     goto invalid_track;
3006
3007   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3008     goto invalid_track;
3009
3010   *stream = qtdemux_find_stream (qtdemux, track_id);
3011   if (G_UNLIKELY (!*stream))
3012     goto unknown_stream;
3013
3014   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3015     *base_offset = qtdemux->moof_offset;
3016
3017   if (flags & TF_BASE_DATA_OFFSET)
3018     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3019       goto invalid_track;
3020
3021   /* obtain stream defaults */
3022   qtdemux_parse_trex (qtdemux, *stream,
3023       default_sample_duration, default_sample_size, default_sample_flags);
3024
3025   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3026   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3027     if (!gst_byte_reader_skip (tfhd, 4))
3028       goto invalid_track;
3029
3030   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3031     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3032       goto invalid_track;
3033
3034   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3035     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3036       goto invalid_track;
3037
3038   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3039     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3040       goto invalid_track;
3041
3042   return TRUE;
3043
3044 invalid_track:
3045   {
3046     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3047     return FALSE;
3048   }
3049 unknown_stream:
3050   {
3051     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3052     return TRUE;
3053   }
3054 }
3055
3056 static gboolean
3057 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3058     guint64 * decode_time)
3059 {
3060   guint32 version = 0;
3061
3062   if (!gst_byte_reader_get_uint32_be (br, &version))
3063     return FALSE;
3064
3065   version >>= 24;
3066   if (version == 1) {
3067     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3068       goto failed;
3069   } else {
3070     guint32 dec_time = 0;
3071     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3072       goto failed;
3073     *decode_time = dec_time;
3074   }
3075
3076   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3077       *decode_time);
3078
3079   return TRUE;
3080
3081 failed:
3082   {
3083     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3084     return FALSE;
3085   }
3086 }
3087
3088 /* Returns a pointer to a GstStructure containing the properties of
3089  * the stream sample identified by @sample_index. The caller must unref
3090  * the returned object after use. Returns NULL if unsuccessful. */
3091 static GstStructure *
3092 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3093     QtDemuxStream * stream, guint sample_index)
3094 {
3095   QtDemuxCencSampleSetInfo *info = NULL;
3096
3097   g_return_val_if_fail (stream != NULL, NULL);
3098   g_return_val_if_fail (stream->protected, NULL);
3099   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3100
3101   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3102
3103   /* Currently, cenc properties for groups of samples are not supported, so
3104    * simply return a copy of the default sample properties */
3105   return gst_structure_copy (info->default_properties);
3106 }
3107
3108 /* Parses the sizes of sample auxiliary information contained within a stream,
3109  * as given in a saiz box. Returns array of sample_count guint8 size values,
3110  * or NULL on failure */
3111 static guint8 *
3112 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3113     GstByteReader * br, guint32 * sample_count)
3114 {
3115   guint32 flags = 0;
3116   guint8 *info_sizes;
3117   guint8 default_info_size;
3118
3119   g_return_val_if_fail (qtdemux != NULL, NULL);
3120   g_return_val_if_fail (stream != NULL, NULL);
3121   g_return_val_if_fail (br != NULL, NULL);
3122   g_return_val_if_fail (sample_count != NULL, NULL);
3123
3124   if (!gst_byte_reader_get_uint32_be (br, &flags))
3125     return NULL;
3126
3127   if (flags & 0x1) {
3128     /* aux_info_type and aux_info_type_parameter are ignored */
3129     if (!gst_byte_reader_skip (br, 8))
3130       return NULL;
3131   }
3132
3133   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3134     return NULL;
3135   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3136
3137   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3138     return NULL;
3139   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3140
3141
3142   if (default_info_size == 0) {
3143     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3144       return NULL;
3145     }
3146   } else {
3147     info_sizes = g_new (guint8, *sample_count);
3148     memset (info_sizes, default_info_size, *sample_count);
3149   }
3150
3151   return info_sizes;
3152 }
3153
3154 /* Parses the offset of sample auxiliary information contained within a stream,
3155  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3156 static gboolean
3157 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3158     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3159     guint64 * offset)
3160 {
3161   guint8 version = 0;
3162   guint32 flags = 0;
3163   guint32 aux_info_type = 0;
3164   guint32 aux_info_type_parameter = 0;
3165   guint32 entry_count;
3166   guint32 off_32;
3167   guint64 off_64;
3168
3169   g_return_val_if_fail (qtdemux != NULL, FALSE);
3170   g_return_val_if_fail (stream != NULL, FALSE);
3171   g_return_val_if_fail (br != NULL, FALSE);
3172   g_return_val_if_fail (offset != NULL, FALSE);
3173
3174   if (!gst_byte_reader_get_uint8 (br, &version))
3175     return FALSE;
3176
3177   if (!gst_byte_reader_get_uint24_be (br, &flags))
3178     return FALSE;
3179
3180   if (flags & 0x1) {
3181     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type))
3182       return FALSE;
3183     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3184       return FALSE;
3185   } else if (stream->protected) {
3186     aux_info_type = stream->protection_scheme_type;
3187   } else {
3188     aux_info_type = stream->fourcc;
3189   }
3190
3191   if (info_type)
3192     *info_type = aux_info_type;
3193   if (info_type_parameter)
3194     *info_type_parameter = aux_info_type_parameter;
3195
3196   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3197       "aux_info_type_parameter:  %#06x",
3198       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3199
3200   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3201     return FALSE;
3202
3203   if (entry_count != 1) {
3204     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3205     return FALSE;
3206   }
3207
3208   if (version == 0) {
3209     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3210       return FALSE;
3211     *offset = (guint64) off_32;
3212   } else {
3213     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3214       return FALSE;
3215     *offset = off_64;
3216   }
3217
3218   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3219   return TRUE;
3220 }
3221
3222 static void
3223 qtdemux_gst_structure_free (GstStructure * gststructure)
3224 {
3225   if (gststructure) {
3226     gst_structure_free (gststructure);
3227   }
3228 }
3229
3230 /* Parses auxiliary information relating to samples protected using Common
3231  * Encryption (cenc); the format of this information is defined in
3232  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3233 static gboolean
3234 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3235     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3236 {
3237   QtDemuxCencSampleSetInfo *ss_info = NULL;
3238   guint8 size;
3239   gint i;
3240
3241   g_return_val_if_fail (qtdemux != NULL, FALSE);
3242   g_return_val_if_fail (stream != NULL, FALSE);
3243   g_return_val_if_fail (br != NULL, FALSE);
3244   g_return_val_if_fail (stream->protected, FALSE);
3245   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3246
3247   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3248
3249   if (ss_info->crypto_info) {
3250     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3251     g_ptr_array_free (ss_info->crypto_info, TRUE);
3252   }
3253
3254   ss_info->crypto_info =
3255       g_ptr_array_new_full (sample_count,
3256       (GDestroyNotify) qtdemux_gst_structure_free);
3257
3258   for (i = 0; i < sample_count; ++i) {
3259     GstStructure *properties;
3260     guint16 n_subsamples = 0;
3261     guint8 *data;
3262     guint iv_size;
3263     GstBuffer *buf;
3264
3265     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3266     if (properties == NULL) {
3267       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3268       return FALSE;
3269     }
3270     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3271       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3272       gst_structure_free (properties);
3273       return FALSE;
3274     }
3275     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3276       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3277       gst_structure_free (properties);
3278       return FALSE;
3279     }
3280     buf = gst_buffer_new_wrapped (data, iv_size);
3281     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3282     size = info_sizes[i];
3283     if (size > iv_size) {
3284       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3285           || !(n_subsamples > 0)) {
3286         gst_structure_free (properties);
3287         GST_ERROR_OBJECT (qtdemux,
3288             "failed to get subsample count for sample %u", i);
3289         return FALSE;
3290       }
3291       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3292       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3293         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3294             i);
3295         gst_structure_free (properties);
3296         return FALSE;
3297       }
3298       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3299       if (!buf) {
3300         gst_structure_free (properties);
3301         return FALSE;
3302       }
3303       gst_structure_set (properties,
3304           "subsample_count", G_TYPE_UINT, n_subsamples,
3305           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3306     } else {
3307       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3308     }
3309     g_ptr_array_add (ss_info->crypto_info, properties);
3310   }
3311   return TRUE;
3312 }
3313
3314 /* Converts a UUID in raw byte form to a string representation, as defined in
3315  * RFC 4122. The caller takes ownership of the returned string and is
3316  * responsible for freeing it after use. */
3317 static gchar *
3318 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3319 {
3320   const guint8 *uuid = (const guint8 *) uuid_bytes;
3321
3322   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3323       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3324       uuid[0], uuid[1], uuid[2], uuid[3],
3325       uuid[4], uuid[5], uuid[6], uuid[7],
3326       uuid[8], uuid[9], uuid[10], uuid[11],
3327       uuid[12], uuid[13], uuid[14], uuid[15]);
3328 }
3329
3330 /* Parses a Protection System Specific Header box (pssh), as defined in the
3331  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3332  * information needed by a specific content protection system in order to
3333  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3334  * otherwise. */
3335 static gboolean
3336 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3337 {
3338   gchar *sysid_string;
3339   guint32 pssh_size = QT_UINT32 (node->data);
3340   GstBuffer *pssh = NULL;
3341   GstEvent *event = NULL;
3342   guint32 parent_box_type;
3343   gint i;
3344
3345   if (G_UNLIKELY (pssh_size < 32U)) {
3346     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3347     return FALSE;
3348   }
3349
3350   sysid_string =
3351       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3352
3353   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3354
3355   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3356   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3357       gst_buffer_get_size (pssh));
3358
3359   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3360
3361   /* Push an event containing the pssh box onto the queues of all streams. */
3362   event = gst_event_new_protection (sysid_string, pssh,
3363       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3364   for (i = 0; i < qtdemux->n_streams; ++i) {
3365     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3366         gst_event_ref (event));
3367   }
3368   g_free (sysid_string);
3369   gst_event_unref (event);
3370   gst_buffer_unref (pssh);
3371   return TRUE;
3372 }
3373
3374 static gboolean
3375 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3376     guint64 moof_offset, QtDemuxStream * stream)
3377 {
3378   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3379   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3380   GNode *saiz_node, *saio_node, *pssh_node;
3381   GstByteReader saiz_data, saio_data;
3382   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3383   gint64 base_offset, running_offset;
3384   guint32 frag_num;
3385
3386   /* NOTE @stream ignored */
3387
3388   moof_node = g_node_new ((guint8 *) buffer);
3389   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3390   qtdemux_node_dump (qtdemux, moof_node);
3391
3392   /* Get fragment number from mfhd and check it's valid */
3393   mfhd_node =
3394       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3395   if (mfhd_node == NULL)
3396     goto missing_mfhd;
3397   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3398     goto fail;
3399   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3400
3401   /* unknown base_offset to start with */
3402   base_offset = running_offset = -1;
3403   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3404   while (traf_node) {
3405     guint64 decode_time = 0;
3406
3407     /* Fragment Header node */
3408     tfhd_node =
3409         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3410         &tfhd_data);
3411     if (!tfhd_node)
3412       goto missing_tfhd;
3413     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3414             &ds_size, &ds_flags, &base_offset))
3415       goto missing_tfhd;
3416
3417     /* The following code assumes at most a single set of sample auxiliary
3418      * data in the fragment (consisting of a saiz box and a corresponding saio
3419      * box); in theory, however, there could be multiple sets of sample
3420      * auxiliary data in a fragment. */
3421     saiz_node =
3422         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3423         &saiz_data);
3424     if (saiz_node) {
3425       guint32 info_type = 0;
3426       guint64 offset = 0;
3427       guint32 info_type_parameter = 0;
3428
3429       g_free (qtdemux->cenc_aux_info_sizes);
3430
3431       qtdemux->cenc_aux_info_sizes =
3432           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3433           &qtdemux->cenc_aux_sample_count);
3434       if (qtdemux->cenc_aux_info_sizes == NULL) {
3435         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3436         goto fail;
3437       }
3438       saio_node =
3439           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3440           &saio_data);
3441       if (!saio_node) {
3442         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3443         g_free (qtdemux->cenc_aux_info_sizes);
3444         qtdemux->cenc_aux_info_sizes = NULL;
3445         goto fail;
3446       }
3447
3448       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3449                   &info_type, &info_type_parameter, &offset))) {
3450         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3451         g_free (qtdemux->cenc_aux_info_sizes);
3452         qtdemux->cenc_aux_info_sizes = NULL;
3453         goto fail;
3454       }
3455       if (base_offset > qtdemux->moof_offset)
3456         offset += (guint64) (base_offset - qtdemux->moof_offset);
3457       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3458         GstByteReader br;
3459         if (offset > length) {
3460           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3461           qtdemux->cenc_aux_info_offset = offset;
3462         } else {
3463           gst_byte_reader_init (&br, buffer + offset, length - offset);
3464           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3465                   qtdemux->cenc_aux_info_sizes,
3466                   qtdemux->cenc_aux_sample_count)) {
3467             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3468             g_free (qtdemux->cenc_aux_info_sizes);
3469             qtdemux->cenc_aux_info_sizes = NULL;
3470             goto fail;
3471           }
3472         }
3473       }
3474     }
3475
3476     tfdt_node =
3477         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3478         &tfdt_data);
3479     if (tfdt_node) {
3480       GstClockTime decode_time_ts;
3481
3482       /* We'll use decode_time to interpolate timestamps
3483        * in case the input timestamps are missing */
3484       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3485
3486       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3487
3488       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3489           " (%" GST_TIME_FORMAT ")", decode_time,
3490           GST_TIME_ARGS (decode_time_ts));
3491
3492       /* Discard the fragment buffer timestamp info to avoid using it.
3493        * Rely on tfdt instead as it is more accurate than the timestamp
3494        * that is fetched from a manifest/playlist and is usually
3495        * less accurate. */
3496       qtdemux->fragment_start = -1;
3497     }
3498
3499     if (G_UNLIKELY (!stream)) {
3500       /* we lost track of offset, we'll need to regain it,
3501        * but can delay complaining until later or avoid doing so altogether */
3502       base_offset = -2;
3503       goto next;
3504     }
3505     if (G_UNLIKELY (base_offset < -1))
3506       goto lost_offset;
3507
3508     if (qtdemux->upstream_format_is_time)
3509       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3510
3511     /* initialise moof sample data */
3512     stream->n_samples_moof = 0;
3513     stream->duration_moof = 0;
3514
3515     /* Track Run node */
3516     trun_node =
3517         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3518         &trun_data);
3519     while (trun_node) {
3520       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3521           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3522           &running_offset, decode_time);
3523       /* iterate all siblings */
3524       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3525           &trun_data);
3526     }
3527     /* if no new base_offset provided for next traf,
3528      * base is end of current traf */
3529     base_offset = running_offset;
3530     running_offset = -1;
3531
3532     if (stream->n_samples_moof && stream->duration_moof)
3533       stream->new_caps = TRUE;
3534
3535   next:
3536     /* iterate all siblings */
3537     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3538   }
3539
3540   /* parse any protection system info */
3541   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3542   while (pssh_node) {
3543     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3544     qtdemux_parse_pssh (qtdemux, pssh_node);
3545     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3546   }
3547
3548   g_node_destroy (moof_node);
3549   return TRUE;
3550
3551 missing_tfhd:
3552   {
3553     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3554     goto fail;
3555   }
3556 missing_mfhd:
3557   {
3558     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3559     goto fail;
3560   }
3561 lost_offset:
3562   {
3563     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3564     goto fail;
3565   }
3566 fail:
3567   {
3568     g_node_destroy (moof_node);
3569     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3570         (_("This file is corrupt and cannot be played.")), (NULL));
3571     return FALSE;
3572   }
3573 }
3574
3575 #if 0
3576 /* might be used if some day we actually use mfra & co
3577  * for random access to fragments,
3578  * but that will require quite some modifications and much less relying
3579  * on a sample array */
3580 #endif
3581
3582 static gboolean
3583 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3584 {
3585   QtDemuxStream *stream;
3586   guint32 ver_flags, track_id, len, num_entries, i;
3587   guint value_size, traf_size, trun_size, sample_size;
3588   guint64 time = 0, moof_offset = 0;
3589 #if 0
3590   GstBuffer *buf = NULL;
3591   GstFlowReturn ret;
3592 #endif
3593   GstByteReader tfra;
3594
3595   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3596
3597   if (!gst_byte_reader_skip (&tfra, 8))
3598     return FALSE;
3599
3600   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3601     return FALSE;
3602
3603   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3604       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3605       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3606     return FALSE;
3607
3608   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3609
3610   stream = qtdemux_find_stream (qtdemux, track_id);
3611   if (stream == NULL)
3612     goto unknown_trackid;
3613
3614   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3615   sample_size = (len & 3) + 1;
3616   trun_size = ((len & 12) >> 2) + 1;
3617   traf_size = ((len & 48) >> 4) + 1;
3618
3619   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3620       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3621
3622   if (num_entries == 0)
3623     goto no_samples;
3624
3625   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3626           value_size + value_size + traf_size + trun_size + sample_size))
3627     goto corrupt_file;
3628
3629   g_free (stream->ra_entries);
3630   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3631   stream->n_ra_entries = num_entries;
3632
3633   for (i = 0; i < num_entries; i++) {
3634     qt_atom_parser_get_offset (&tfra, value_size, &time);
3635     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3636     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3637     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3638     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3639
3640     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3641
3642     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3643         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3644
3645     stream->ra_entries[i].ts = time;
3646     stream->ra_entries[i].moof_offset = moof_offset;
3647
3648     /* don't want to go through the entire file and read all moofs at startup */
3649 #if 0
3650     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3651     if (ret != GST_FLOW_OK)
3652       goto corrupt_file;
3653     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3654         moof_offset, stream);
3655     gst_buffer_unref (buf);
3656 #endif
3657   }
3658
3659   check_update_duration (qtdemux, time);
3660
3661   return TRUE;
3662
3663 /* ERRORS */
3664 unknown_trackid:
3665   {
3666     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3667     return FALSE;
3668   }
3669 corrupt_file:
3670   {
3671     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3672     return FALSE;
3673   }
3674 no_samples:
3675   {
3676     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3677     return FALSE;
3678   }
3679 }
3680
3681 static gboolean
3682 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3683 {
3684   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3685   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3686   GstBuffer *mfro = NULL, *mfra = NULL;
3687   GstFlowReturn flow;
3688   gboolean ret = FALSE;
3689   GNode *mfra_node, *tfra_node;
3690   guint64 mfra_offset = 0;
3691   guint32 fourcc, mfra_size;
3692   gint64 len;
3693
3694   /* query upstream size in bytes */
3695   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3696     goto size_query_failed;
3697
3698   /* mfro box should be at the very end of the file */
3699   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3700   if (flow != GST_FLOW_OK)
3701     goto exit;
3702
3703   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3704
3705   fourcc = QT_FOURCC (mfro_map.data + 4);
3706   if (fourcc != FOURCC_mfro)
3707     goto exit;
3708
3709   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3710   if (mfro_map.size < 16)
3711     goto invalid_mfro_size;
3712
3713   mfra_size = QT_UINT32 (mfro_map.data + 12);
3714   if (mfra_size >= len)
3715     goto invalid_mfra_size;
3716
3717   mfra_offset = len - mfra_size;
3718
3719   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3720       mfra_offset, mfra_size);
3721
3722   /* now get and parse mfra box */
3723   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3724   if (flow != GST_FLOW_OK)
3725     goto broken_file;
3726
3727   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3728
3729   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3730   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3731
3732   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3733
3734   while (tfra_node) {
3735     qtdemux_parse_tfra (qtdemux, tfra_node);
3736     /* iterate all siblings */
3737     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3738   }
3739   g_node_destroy (mfra_node);
3740
3741   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3742   ret = TRUE;
3743
3744 exit:
3745
3746   if (mfro) {
3747     if (mfro_map.memory != NULL)
3748       gst_buffer_unmap (mfro, &mfro_map);
3749     gst_buffer_unref (mfro);
3750   }
3751   if (mfra) {
3752     if (mfra_map.memory != NULL)
3753       gst_buffer_unmap (mfra, &mfra_map);
3754     gst_buffer_unref (mfra);
3755   }
3756   return ret;
3757
3758 /* ERRORS */
3759 size_query_failed:
3760   {
3761     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3762     goto exit;
3763   }
3764 invalid_mfro_size:
3765   {
3766     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3767     goto exit;
3768   }
3769 invalid_mfra_size:
3770   {
3771     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3772     goto exit;
3773   }
3774 broken_file:
3775   {
3776     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3777     goto exit;
3778   }
3779 }
3780
3781 static guint64
3782 add_offset (guint64 offset, guint64 advance)
3783 {
3784   /* Avoid 64-bit overflow by clamping */
3785   if (offset > G_MAXUINT64 - advance)
3786     return G_MAXUINT64;
3787   return offset + advance;
3788 }
3789
3790 static GstFlowReturn
3791 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
3792 {
3793   guint64 length = 0;
3794   guint32 fourcc = 0;
3795   GstBuffer *buf = NULL;
3796   GstFlowReturn ret = GST_FLOW_OK;
3797   guint64 cur_offset = qtdemux->offset;
3798   GstMapInfo map;
3799
3800   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
3801   if (G_UNLIKELY (ret != GST_FLOW_OK))
3802     goto beach;
3803   gst_buffer_map (buf, &map, GST_MAP_READ);
3804   if (G_LIKELY (map.size >= 8))
3805     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
3806   gst_buffer_unmap (buf, &map);
3807   gst_buffer_unref (buf);
3808
3809   /* maybe we already got most we needed, so only consider this eof */
3810   if (G_UNLIKELY (length == 0)) {
3811     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
3812         (_("Invalid atom size.")),
3813         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
3814             GST_FOURCC_ARGS (fourcc)));
3815     ret = GST_FLOW_EOS;
3816     goto beach;
3817   }
3818
3819   switch (fourcc) {
3820     case FOURCC_moof:
3821       /* record for later parsing when needed */
3822       if (!qtdemux->moof_offset) {
3823         qtdemux->moof_offset = qtdemux->offset;
3824       }
3825       if (qtdemux_pull_mfro_mfra (qtdemux)) {
3826         /* FIXME */
3827       } else {
3828         qtdemux->offset += length;      /* skip moof and keep going */
3829       }
3830       if (qtdemux->got_moov) {
3831         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3832         ret = GST_FLOW_EOS;
3833         goto beach;
3834       }
3835       break;
3836     case FOURCC_mdat:
3837     case FOURCC_free:
3838     case FOURCC_wide:
3839     case FOURCC_PICT:
3840     case FOURCC_pnot:
3841     {
3842       GST_LOG_OBJECT (qtdemux,
3843           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3844           GST_FOURCC_ARGS (fourcc), cur_offset);
3845       qtdemux->offset = add_offset (qtdemux->offset, length);
3846       break;
3847     }
3848     case FOURCC_moov:
3849     {
3850       GstBuffer *moov = NULL;
3851
3852       if (qtdemux->got_moov) {
3853         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3854         qtdemux->offset = add_offset (qtdemux->offset, length);
3855         goto beach;
3856       }
3857
3858       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3859       if (ret != GST_FLOW_OK)
3860         goto beach;
3861       gst_buffer_map (moov, &map, GST_MAP_READ);
3862
3863       if (length != map.size) {
3864         /* Some files have a 'moov' atom at the end of the file which contains
3865          * a terminal 'free' atom where the body of the atom is missing.
3866          * Check for, and permit, this special case.
3867          */
3868         if (map.size >= 8) {
3869           guint8 *final_data = map.data + (map.size - 8);
3870           guint32 final_length = QT_UINT32 (final_data);
3871           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3872
3873           if (final_fourcc == FOURCC_free
3874               && map.size + final_length - 8 == length) {
3875             /* Ok, we've found that special case. Allocate a new buffer with
3876              * that free atom actually present. */
3877             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3878             gst_buffer_fill (newmoov, 0, map.data, map.size);
3879             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3880             gst_buffer_unmap (moov, &map);
3881             gst_buffer_unref (moov);
3882             moov = newmoov;
3883             gst_buffer_map (moov, &map, GST_MAP_READ);
3884           }
3885         }
3886       }
3887
3888       if (length != map.size) {
3889         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3890             (_("This file is incomplete and cannot be played.")),
3891             ("We got less than expected (received %" G_GSIZE_FORMAT
3892                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3893                 (guint) length, cur_offset));
3894         gst_buffer_unmap (moov, &map);
3895         gst_buffer_unref (moov);
3896         ret = GST_FLOW_ERROR;
3897         goto beach;
3898       }
3899       qtdemux->offset += length;
3900
3901       qtdemux_parse_moov (qtdemux, map.data, length);
3902       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3903
3904       qtdemux_parse_tree (qtdemux);
3905       g_node_destroy (qtdemux->moov_node);
3906       gst_buffer_unmap (moov, &map);
3907       gst_buffer_unref (moov);
3908       qtdemux->moov_node = NULL;
3909       qtdemux->got_moov = TRUE;
3910
3911       break;
3912     }
3913     case FOURCC_ftyp:
3914     {
3915       GstBuffer *ftyp = NULL;
3916
3917       /* extract major brand; might come in handy for ISO vs QT issues */
3918       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3919       if (ret != GST_FLOW_OK)
3920         goto beach;
3921       qtdemux->offset += length;
3922       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3923       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3924       gst_buffer_unmap (ftyp, &map);
3925       gst_buffer_unref (ftyp);
3926       break;
3927     }
3928     case FOURCC_uuid:
3929     {
3930       GstBuffer *uuid = NULL;
3931
3932       /* uuid are extension atoms */
3933       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3934       if (ret != GST_FLOW_OK)
3935         goto beach;
3936       qtdemux->offset += length;
3937       gst_buffer_map (uuid, &map, GST_MAP_READ);
3938       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3939       gst_buffer_unmap (uuid, &map);
3940       gst_buffer_unref (uuid);
3941       break;
3942     }
3943     case FOURCC_sidx:
3944     {
3945       GstBuffer *sidx = NULL;
3946       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3947       if (ret != GST_FLOW_OK)
3948         goto beach;
3949       qtdemux->offset += length;
3950       gst_buffer_map (sidx, &map, GST_MAP_READ);
3951       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3952       gst_buffer_unmap (sidx, &map);
3953       gst_buffer_unref (sidx);
3954       break;
3955     }
3956     default:
3957     {
3958       GstBuffer *unknown = NULL;
3959
3960       GST_LOG_OBJECT (qtdemux,
3961           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3962           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3963           cur_offset);
3964       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3965       if (ret != GST_FLOW_OK)
3966         goto beach;
3967       gst_buffer_map (unknown, &map, GST_MAP_READ);
3968       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3969       gst_buffer_unmap (unknown, &map);
3970       gst_buffer_unref (unknown);
3971       qtdemux->offset += length;
3972       break;
3973     }
3974   }
3975
3976 beach:
3977   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3978     /* digested all data, show what we have */
3979     qtdemux_prepare_streams (qtdemux);
3980     ret = qtdemux_expose_streams (qtdemux);
3981
3982     qtdemux->state = QTDEMUX_STATE_MOVIE;
3983     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3984         qtdemux->state);
3985     return ret;
3986   }
3987   return ret;
3988 }
3989
3990 /* Seeks to the previous keyframe of the indexed stream and
3991  * aligns other streams with respect to the keyframe timestamp
3992  * of indexed stream. Only called in case of Reverse Playback
3993  */
3994 static GstFlowReturn
3995 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
3996 {
3997   guint8 n = 0;
3998   guint32 seg_idx = 0, k_index = 0;
3999   guint32 ref_seg_idx, ref_k_index;
4000   GstClockTime k_pos = 0, last_stop = 0;
4001   QtDemuxSegment *seg = NULL;
4002   QtDemuxStream *ref_str = NULL;
4003   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4004   guint64 target_ts;
4005
4006   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4007    * and finally align all the other streams on that timestamp with their
4008    * respective keyframes */
4009   for (n = 0; n < qtdemux->n_streams; n++) {
4010     QtDemuxStream *str = qtdemux->streams[n];
4011
4012     /* No candidate yet, take the first stream */
4013     if (!ref_str) {
4014       ref_str = str;
4015       continue;
4016     }
4017
4018     /* So that stream has a segment, we prefer video streams */
4019     if (str->subtype == FOURCC_vide) {
4020       ref_str = str;
4021       break;
4022     }
4023   }
4024
4025   if (G_UNLIKELY (!ref_str)) {
4026     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4027     goto eos;
4028   }
4029
4030   if (G_UNLIKELY (!ref_str->from_sample)) {
4031     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4032     goto eos;
4033   }
4034
4035   /* So that stream has been playing from from_sample to to_sample. We will
4036    * get the timestamp of the previous sample and search for a keyframe before
4037    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4038   if (ref_str->subtype == FOURCC_vide) {
4039     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4040         ref_str->from_sample - 1);
4041   } else {
4042     if (ref_str->from_sample >= 10)
4043       k_index = ref_str->from_sample - 10;
4044     else
4045       k_index = 0;
4046   }
4047
4048   target_ts =
4049       ref_str->samples[k_index].timestamp +
4050       ref_str->samples[k_index].pts_offset;
4051
4052   /* get current segment for that stream */
4053   seg = &ref_str->segments[ref_str->segment_index];
4054   /* Use segment start in original timescale for comparisons */
4055   seg_media_start_mov = seg->trak_media_start;
4056
4057   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4058       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4059       k_index, target_ts, seg_media_start_mov,
4060       GST_TIME_ARGS (seg->media_start));
4061
4062   /* Crawl back through segments to find the one containing this I frame */
4063   while (target_ts < seg_media_start_mov) {
4064     GST_DEBUG_OBJECT (qtdemux,
4065         "keyframe position (sample %u) is out of segment %u " " target %"
4066         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4067         ref_str->segment_index, target_ts, seg_media_start_mov);
4068
4069     if (G_UNLIKELY (!ref_str->segment_index)) {
4070       /* Reached first segment, let's consider it's EOS */
4071       goto eos;
4072     }
4073     ref_str->segment_index--;
4074     seg = &ref_str->segments[ref_str->segment_index];
4075     /* Use segment start in original timescale for comparisons */
4076     seg_media_start_mov = seg->trak_media_start;
4077   }
4078   /* Calculate time position of the keyframe and where we should stop */
4079   k_pos =
4080       QTSTREAMTIME_TO_GSTTIME (ref_str,
4081       target_ts - seg->trak_media_start) + seg->time;
4082   last_stop =
4083       QTSTREAMTIME_TO_GSTTIME (ref_str,
4084       ref_str->samples[ref_str->from_sample].timestamp -
4085       seg->trak_media_start) + seg->time;
4086
4087   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4088       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4089       k_index, GST_TIME_ARGS (k_pos));
4090
4091   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4092   qtdemux->segment.position = last_stop;
4093   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4094       GST_TIME_ARGS (last_stop));
4095
4096   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4097     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4098     goto eos;
4099   }
4100
4101   ref_seg_idx = ref_str->segment_index;
4102   ref_k_index = k_index;
4103
4104   /* Align them all on this */
4105   for (n = 0; n < qtdemux->n_streams; n++) {
4106     guint32 index = 0;
4107     GstClockTime seg_time = 0;
4108     QtDemuxStream *str = qtdemux->streams[n];
4109
4110     /* aligning reference stream again might lead to backing up to yet another
4111      * keyframe (due to timestamp rounding issues),
4112      * potentially putting more load on downstream; so let's try to avoid */
4113     if (str == ref_str) {
4114       seg_idx = ref_seg_idx;
4115       seg = &str->segments[seg_idx];
4116       k_index = ref_k_index;
4117       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4118           "sample at index %d", n, ref_str->segment_index, k_index);
4119     } else {
4120       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4121       GST_DEBUG_OBJECT (qtdemux,
4122           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4123           seg_idx, GST_TIME_ARGS (k_pos));
4124
4125       /* get segment and time in the segment */
4126       seg = &str->segments[seg_idx];
4127       seg_time = k_pos - seg->time;
4128
4129       /* get the media time in the segment.
4130        * No adjustment for empty "filler" segments */
4131       if (seg->media_start != GST_CLOCK_TIME_NONE)
4132         seg_time += seg->media_start;
4133
4134       /* get the index of the sample with media time */
4135       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4136       GST_DEBUG_OBJECT (qtdemux,
4137           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4138           GST_TIME_ARGS (seg_time), index);
4139
4140       /* find previous keyframe */
4141       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4142     }
4143
4144     /* Remember until where we want to go */
4145     str->to_sample = str->from_sample - 1;
4146     /* Define our time position */
4147     target_ts =
4148         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4149     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4150     if (seg->media_start != GST_CLOCK_TIME_NONE)
4151       str->time_position -= seg->media_start;
4152
4153     /* Now seek back in time */
4154     gst_qtdemux_move_stream (qtdemux, str, k_index);
4155     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4156         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4157         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4158   }
4159
4160   return GST_FLOW_OK;
4161
4162 eos:
4163   return GST_FLOW_EOS;
4164 }
4165
4166 /* activate the given segment number @seg_idx of @stream at time @offset.
4167  * @offset is an absolute global position over all the segments.
4168  *
4169  * This will push out a NEWSEGMENT event with the right values and
4170  * position the stream index to the first decodable sample before
4171  * @offset.
4172  */
4173 static gboolean
4174 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4175     guint32 seg_idx, GstClockTime offset)
4176 {
4177   GstEvent *event;
4178   QtDemuxSegment *segment;
4179   guint32 index, kf_index;
4180   GstClockTime seg_time;
4181   GstClockTime start, stop, time;
4182   gdouble rate;
4183
4184   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4185       seg_idx, GST_TIME_ARGS (offset));
4186
4187   /* update the current segment */
4188   stream->segment_index = seg_idx;
4189
4190   /* get the segment */
4191   segment = &stream->segments[seg_idx];
4192
4193   if (G_UNLIKELY (offset < segment->time)) {
4194     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4195         GST_TIME_ARGS (segment->time));
4196     return FALSE;
4197   }
4198
4199   /* segment lies beyond total indicated duration */
4200   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4201           segment->time > qtdemux->segment.duration)) {
4202     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4203         " < segment->time %" GST_TIME_FORMAT,
4204         GST_TIME_ARGS (qtdemux->segment.duration),
4205         GST_TIME_ARGS (segment->time));
4206     return FALSE;
4207   }
4208
4209   /* get time in this segment */
4210   seg_time = offset - segment->time;
4211
4212   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4213       GST_TIME_ARGS (seg_time));
4214
4215   if (G_UNLIKELY (seg_time > segment->duration)) {
4216     GST_LOG_OBJECT (stream->pad,
4217         "seg_time > segment->duration %" GST_TIME_FORMAT,
4218         GST_TIME_ARGS (segment->duration));
4219     seg_time = segment->duration;
4220   }
4221
4222   /* qtdemux->segment.stop is in outside-time-realm, whereas
4223    * segment->media_stop is in track-time-realm.
4224    *
4225    * In order to compare the two, we need to bring segment.stop
4226    * into the track-time-realm */
4227
4228   stop = qtdemux->segment.stop;
4229   if (stop == GST_CLOCK_TIME_NONE)
4230     stop = qtdemux->segment.duration;
4231   if (stop == GST_CLOCK_TIME_NONE)
4232     stop = segment->media_stop;
4233   else
4234     stop =
4235         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4236
4237   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4238     start = segment->time + seg_time;
4239     time = offset;
4240     stop = start - seg_time + segment->duration;
4241   } else if (qtdemux->segment.rate >= 0) {
4242     start = MIN (segment->media_start + seg_time, stop);
4243     time = offset;
4244   } else {
4245     if (segment->media_start >= qtdemux->segment.start) {
4246       time = segment->time;
4247     } else {
4248       time = segment->time + (qtdemux->segment.start - segment->media_start);
4249     }
4250
4251     start = MAX (segment->media_start, qtdemux->segment.start);
4252     stop = MIN (segment->media_start + seg_time, stop);
4253   }
4254
4255   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4256       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4257       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4258
4259   /* combine global rate with that of the segment */
4260   rate = segment->rate * qtdemux->segment.rate;
4261
4262   /* Copy flags from main segment */
4263   stream->segment.flags = qtdemux->segment.flags;
4264
4265   /* update the segment values used for clipping */
4266   stream->segment.offset = qtdemux->segment.offset;
4267   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4268   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4269   stream->segment.rate = rate;
4270   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4271       stream->cslg_shift);
4272   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4273       stream->cslg_shift);
4274   stream->segment.time = time;
4275   stream->segment.position = stream->segment.start;
4276
4277   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4278       &stream->segment);
4279
4280   /* now prepare and send the segment */
4281   if (stream->pad) {
4282     event = gst_event_new_segment (&stream->segment);
4283     if (stream->segment_seqnum) {
4284       gst_event_set_seqnum (event, stream->segment_seqnum);
4285     }
4286     gst_pad_push_event (stream->pad, event);
4287     /* assume we can send more data now */
4288     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4289     /* clear to send tags on this pad now */
4290     gst_qtdemux_push_tags (qtdemux, stream);
4291   }
4292
4293   /* in the fragmented case, we pick a fragment that starts before our
4294    * desired position and rely on downstream to wait for a keyframe
4295    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4296    * tfra entries tells us which trun/sample the key unit is in, but we don't
4297    * make use of this additional information at the moment) */
4298   if (qtdemux->fragmented) {
4299     stream->to_sample = G_MAXUINT32;
4300     return TRUE;
4301   }
4302
4303   /* We don't need to look for a sample in push-based */
4304   if (!qtdemux->pullbased)
4305     return TRUE;
4306
4307   /* and move to the keyframe before the indicated media time of the
4308    * segment */
4309   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4310     if (qtdemux->segment.rate >= 0) {
4311       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4312       stream->to_sample = G_MAXUINT32;
4313       GST_DEBUG_OBJECT (stream->pad,
4314           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4315           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4316           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4317     } else {
4318       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4319       stream->to_sample = index;
4320       GST_DEBUG_OBJECT (stream->pad,
4321           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4322           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4323           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4324     }
4325   } else {
4326     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4327         "this is an empty segment");
4328     return TRUE;
4329   }
4330
4331   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4332    * encountered an error and printed a message so we return appropriately */
4333   if (index == -1)
4334     return FALSE;
4335
4336   /* we're at the right spot */
4337   if (index == stream->sample_index) {
4338     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4339     return TRUE;
4340   }
4341
4342   /* find keyframe of the target index */
4343   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4344
4345 /* *INDENT-OFF* */
4346 /* indent does stupid stuff with stream->samples[].timestamp */
4347
4348   /* if we move forwards, we don't have to go back to the previous
4349    * keyframe since we already sent that. We can also just jump to
4350    * the keyframe right before the target index if there is one. */
4351   if (index > stream->sample_index) {
4352     /* moving forwards check if we move past a keyframe */
4353     if (kf_index > stream->sample_index) {
4354       GST_DEBUG_OBJECT (stream->pad,
4355            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4356            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4357            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4358       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4359     } else {
4360       GST_DEBUG_OBJECT (stream->pad,
4361           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4362           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4363           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4364     }
4365   } else {
4366     GST_DEBUG_OBJECT (stream->pad,
4367         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4368         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4369         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4370     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4371   }
4372
4373 /* *INDENT-ON* */
4374
4375   return TRUE;
4376 }
4377
4378 /* prepare to get the current sample of @stream, getting essential values.
4379  *
4380  * This function will also prepare and send the segment when needed.
4381  *
4382  * Return FALSE if the stream is EOS.
4383  *
4384  * PULL-BASED
4385  */
4386 static gboolean
4387 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4388     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4389     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4390     gboolean * keyframe)
4391 {
4392   QtDemuxSample *sample;
4393   GstClockTime time_position;
4394   guint32 seg_idx;
4395
4396   g_return_val_if_fail (stream != NULL, FALSE);
4397
4398   time_position = stream->time_position;
4399   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4400     goto eos;
4401
4402   seg_idx = stream->segment_index;
4403   if (G_UNLIKELY (seg_idx == -1)) {
4404     /* find segment corresponding to time_position if we are looking
4405      * for a segment. */
4406     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4407   }
4408
4409   /* different segment, activate it, sample_index will be set. */
4410   if (G_UNLIKELY (stream->segment_index != seg_idx))
4411     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4412
4413   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4414                   segment_index]))) {
4415     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4416
4417     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4418         " prepare empty sample");
4419
4420     *empty = TRUE;
4421     *pts = *dts = time_position;
4422     *duration = seg->duration - (time_position - seg->time);
4423
4424     return TRUE;
4425   }
4426
4427   *empty = FALSE;
4428
4429   if (stream->sample_index == -1)
4430     stream->sample_index = 0;
4431
4432   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4433       stream->sample_index, stream->n_samples);
4434
4435   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4436     if (!qtdemux->fragmented)
4437       goto eos;
4438
4439     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4440     do {
4441       GstFlowReturn flow;
4442
4443       GST_OBJECT_LOCK (qtdemux);
4444       flow = qtdemux_add_fragmented_samples (qtdemux);
4445       GST_OBJECT_UNLOCK (qtdemux);
4446
4447       if (flow != GST_FLOW_OK)
4448         goto eos;
4449     }
4450     while (stream->sample_index >= stream->n_samples);
4451   }
4452
4453   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4454     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4455         stream->sample_index);
4456     return FALSE;
4457   }
4458
4459   /* now get the info for the sample we're at */
4460   sample = &stream->samples[stream->sample_index];
4461
4462   *dts = QTSAMPLE_DTS (stream, sample);
4463   *pts = QTSAMPLE_PTS (stream, sample);
4464   *offset = sample->offset;
4465   *size = sample->size;
4466   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4467   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4468
4469   return TRUE;
4470
4471   /* special cases */
4472 eos:
4473   {
4474     stream->time_position = GST_CLOCK_TIME_NONE;
4475     return FALSE;
4476   }
4477 }
4478
4479 /* move to the next sample in @stream.
4480  *
4481  * Moves to the next segment when needed.
4482  */
4483 static void
4484 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4485 {
4486   QtDemuxSample *sample;
4487   QtDemuxSegment *segment;
4488
4489   /* get current segment */
4490   segment = &stream->segments[stream->segment_index];
4491
4492   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4493     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4494     goto next_segment;
4495   }
4496
4497   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4498     /* Mark the stream as EOS */
4499     GST_DEBUG_OBJECT (qtdemux,
4500         "reached max allowed sample %u, mark EOS", stream->to_sample);
4501     stream->time_position = GST_CLOCK_TIME_NONE;
4502     return;
4503   }
4504
4505   /* move to next sample */
4506   stream->sample_index++;
4507   stream->offset_in_sample = 0;
4508
4509   /* reached the last sample, we need the next segment */
4510   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4511     goto next_segment;
4512
4513   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4514     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4515         stream->sample_index);
4516     return;
4517   }
4518
4519   /* get next sample */
4520   sample = &stream->samples[stream->sample_index];
4521
4522   /* see if we are past the segment */
4523   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4524     goto next_segment;
4525
4526   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4527     /* inside the segment, update time_position, looks very familiar to
4528      * GStreamer segments, doesn't it? */
4529     stream->time_position =
4530         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4531   } else {
4532     /* not yet in segment, time does not yet increment. This means
4533      * that we are still prerolling keyframes to the decoder so it can
4534      * decode the first sample of the segment. */
4535     stream->time_position = segment->time;
4536   }
4537   return;
4538
4539   /* move to the next segment */
4540 next_segment:
4541   {
4542     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4543
4544     if (stream->segment_index == stream->n_segments - 1) {
4545       /* are we at the end of the last segment, we're EOS */
4546       stream->time_position = GST_CLOCK_TIME_NONE;
4547     } else {
4548       /* else we're only at the end of the current segment */
4549       stream->time_position = segment->stop_time;
4550     }
4551     /* make sure we select a new segment */
4552
4553     /* accumulate previous segments */
4554     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4555       stream->accumulated_base +=
4556           (stream->segment.stop -
4557           stream->segment.start) / ABS (stream->segment.rate);
4558
4559     stream->segment_index = -1;
4560   }
4561 }
4562
4563 static void
4564 gst_qtdemux_sync_streams (GstQTDemux * demux)
4565 {
4566   gint i;
4567
4568   if (demux->n_streams <= 1)
4569     return;
4570
4571   for (i = 0; i < demux->n_streams; i++) {
4572     QtDemuxStream *stream;
4573     GstClockTime end_time;
4574
4575     stream = demux->streams[i];
4576
4577     if (!stream->pad)
4578       continue;
4579
4580     /* TODO advance time on subtitle streams here, if any some day */
4581
4582     /* some clips/trailers may have unbalanced streams at the end,
4583      * so send EOS on shorter stream to prevent stalling others */
4584
4585     /* do not mess with EOS if SEGMENT seeking */
4586     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4587       continue;
4588
4589     if (demux->pullbased) {
4590       /* loop mode is sample time based */
4591       if (!STREAM_IS_EOS (stream))
4592         continue;
4593     } else {
4594       /* push mode is byte position based */
4595       if (stream->n_samples &&
4596           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4597         continue;
4598     }
4599
4600     if (stream->sent_eos)
4601       continue;
4602
4603     /* only act if some gap */
4604     end_time = stream->segments[stream->n_segments - 1].stop_time;
4605     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4606         ", stream end: %" GST_TIME_FORMAT,
4607         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4608     if (GST_CLOCK_TIME_IS_VALID (end_time)
4609         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4610       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4611           GST_PAD_NAME (stream->pad));
4612       stream->sent_eos = TRUE;
4613       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4614     }
4615   }
4616 }
4617
4618 /* EOS and NOT_LINKED need to be combined. This means that we return:
4619  *
4620  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4621  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4622  */
4623 static GstFlowReturn
4624 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4625     GstFlowReturn ret)
4626 {
4627   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4628
4629   if (stream->pad)
4630     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4631         ret);
4632   else
4633     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4634
4635   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4636   return ret;
4637 }
4638
4639 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4640  * completely clipped
4641  *
4642  * Should be used only with raw buffers */
4643 static GstBuffer *
4644 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4645     GstBuffer * buf)
4646 {
4647   guint64 start, stop, cstart, cstop, diff;
4648   GstClockTime pts, duration;
4649   gsize size, osize;
4650   gint num_rate, denom_rate;
4651   gint frame_size;
4652   gboolean clip_data;
4653   guint offset;
4654
4655   osize = size = gst_buffer_get_size (buf);
4656   offset = 0;
4657
4658   /* depending on the type, setup the clip parameters */
4659   if (stream->subtype == FOURCC_soun) {
4660     frame_size = stream->bytes_per_frame;
4661     num_rate = GST_SECOND;
4662     denom_rate = (gint) stream->rate;
4663     clip_data = TRUE;
4664   } else if (stream->subtype == FOURCC_vide) {
4665     frame_size = size;
4666     num_rate = stream->fps_n;
4667     denom_rate = stream->fps_d;
4668     clip_data = FALSE;
4669   } else
4670     goto wrong_type;
4671
4672   if (frame_size <= 0)
4673     goto bad_frame_size;
4674
4675   /* we can only clip if we have a valid pts */
4676   pts = GST_BUFFER_PTS (buf);
4677   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4678     goto no_pts;
4679
4680   duration = GST_BUFFER_DURATION (buf);
4681
4682   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4683     duration =
4684         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4685   }
4686
4687   start = pts;
4688   stop = start + duration;
4689
4690   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4691               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4692     goto clipped;
4693
4694   /* see if some clipping happened */
4695   diff = cstart - start;
4696   if (diff > 0) {
4697     pts += diff;
4698     duration -= diff;
4699
4700     if (clip_data) {
4701       /* bring clipped time to samples and to bytes */
4702       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4703       diff *= frame_size;
4704
4705       GST_DEBUG_OBJECT (qtdemux,
4706           "clipping start to %" GST_TIME_FORMAT " %"
4707           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4708
4709       offset = diff;
4710       size -= diff;
4711     }
4712   }
4713   diff = stop - cstop;
4714   if (diff > 0) {
4715     duration -= diff;
4716
4717     if (clip_data) {
4718       /* bring clipped time to samples and then to bytes */
4719       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4720       diff *= frame_size;
4721       GST_DEBUG_OBJECT (qtdemux,
4722           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4723           " bytes", GST_TIME_ARGS (cstop), diff);
4724       size -= diff;
4725     }
4726   }
4727
4728   if (offset != 0 || size != osize)
4729     gst_buffer_resize (buf, offset, size);
4730
4731   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4732   GST_BUFFER_PTS (buf) = pts;
4733   GST_BUFFER_DURATION (buf) = duration;
4734
4735   return buf;
4736
4737   /* dropped buffer */
4738 wrong_type:
4739   {
4740     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4741     return buf;
4742   }
4743 bad_frame_size:
4744   {
4745     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4746     return buf;
4747   }
4748 no_pts:
4749   {
4750     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4751     return buf;
4752   }
4753 clipped:
4754   {
4755     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4756     gst_buffer_unref (buf);
4757     return NULL;
4758   }
4759 }
4760
4761 /* the input buffer metadata must be writable,
4762  * but time/duration etc not yet set and need not be preserved */
4763 static GstBuffer *
4764 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4765     GstBuffer * buf)
4766 {
4767   GstMapInfo map;
4768   guint nsize = 0;
4769   gchar *str;
4770
4771   /* not many cases for now */
4772   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4773     /* send a one time dvd clut event */
4774     if (stream->pending_event && stream->pad)
4775       gst_pad_push_event (stream->pad, stream->pending_event);
4776     stream->pending_event = NULL;
4777   }
4778
4779   if (G_UNLIKELY (stream->subtype != FOURCC_text
4780           && stream->subtype != FOURCC_sbtl &&
4781           stream->subtype != FOURCC_subp)) {
4782     return buf;
4783   }
4784
4785   gst_buffer_map (buf, &map, GST_MAP_READ);
4786
4787   /* empty buffer is sent to terminate previous subtitle */
4788   if (map.size <= 2) {
4789     gst_buffer_unmap (buf, &map);
4790     gst_buffer_unref (buf);
4791     return NULL;
4792   }
4793   if (stream->subtype == FOURCC_subp) {
4794     /* That's all the processing needed for subpictures */
4795     gst_buffer_unmap (buf, &map);
4796     return buf;
4797   }
4798
4799   nsize = GST_READ_UINT16_BE (map.data);
4800   nsize = MIN (nsize, map.size - 2);
4801
4802   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4803       nsize, map.size);
4804
4805   /* takes care of UTF-8 validation or UTF-16 recognition,
4806    * no other encoding expected */
4807   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4808   gst_buffer_unmap (buf, &map);
4809   if (str) {
4810     gst_buffer_unref (buf);
4811     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4812   } else {
4813     /* this should not really happen unless the subtitle is corrupted */
4814     gst_buffer_unref (buf);
4815     buf = NULL;
4816   }
4817
4818   /* FIXME ? convert optional subsequent style info to markup */
4819
4820   return buf;
4821 }
4822
4823 /* Sets a buffer's attributes properly and pushes it downstream.
4824  * Also checks for additional actions and custom processing that may
4825  * need to be done first.
4826  */
4827 static GstFlowReturn
4828 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4829     QtDemuxStream * stream, GstBuffer * buf,
4830     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4831     gboolean keyframe, GstClockTime position, guint64 byte_position)
4832 {
4833   GstFlowReturn ret = GST_FLOW_OK;
4834
4835   /* offset the timestamps according to the edit list */
4836
4837   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4838     gchar *url;
4839     GstMapInfo map;
4840
4841     gst_buffer_map (buf, &map, GST_MAP_READ);
4842     url = g_strndup ((gchar *) map.data, map.size);
4843     gst_buffer_unmap (buf, &map);
4844     if (url != NULL && strlen (url) != 0) {
4845       /* we have RTSP redirect now */
4846       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4847           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4848               gst_structure_new ("redirect",
4849                   "new-location", G_TYPE_STRING, url, NULL)));
4850       qtdemux->posted_redirect = TRUE;
4851     } else {
4852       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4853           "posting");
4854     }
4855     g_free (url);
4856   }
4857
4858   /* position reporting */
4859   if (qtdemux->segment.rate >= 0) {
4860     qtdemux->segment.position = position;
4861     gst_qtdemux_sync_streams (qtdemux);
4862   }
4863
4864   if (G_UNLIKELY (!stream->pad)) {
4865     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4866     gst_buffer_unref (buf);
4867     goto exit;
4868   }
4869
4870   /* send out pending buffers */
4871   while (stream->buffers) {
4872     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4873
4874     if (G_UNLIKELY (stream->discont)) {
4875       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4876       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4877       stream->discont = FALSE;
4878     } else {
4879       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4880     }
4881
4882     gst_pad_push (stream->pad, buffer);
4883
4884     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4885   }
4886
4887   /* we're going to modify the metadata */
4888   buf = gst_buffer_make_writable (buf);
4889
4890   if (G_UNLIKELY (stream->need_process))
4891     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4892
4893   if (!buf) {
4894     goto exit;
4895   }
4896
4897   GST_BUFFER_DTS (buf) = dts;
4898   GST_BUFFER_PTS (buf) = pts;
4899   GST_BUFFER_DURATION (buf) = duration;
4900   GST_BUFFER_OFFSET (buf) = -1;
4901   GST_BUFFER_OFFSET_END (buf) = -1;
4902
4903   if (G_UNLIKELY (stream->rgb8_palette))
4904     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4905
4906   if (G_UNLIKELY (stream->padding)) {
4907     gst_buffer_resize (buf, stream->padding, -1);
4908   }
4909 #if 0
4910   if (G_UNLIKELY (qtdemux->element_index)) {
4911     GstClockTime stream_time;
4912
4913     stream_time =
4914         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4915         timestamp);
4916     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4917       GST_LOG_OBJECT (qtdemux,
4918           "adding association %" GST_TIME_FORMAT "-> %"
4919           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4920       gst_index_add_association (qtdemux->element_index,
4921           qtdemux->index_id,
4922           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4923           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4924           GST_FORMAT_BYTES, byte_position, NULL);
4925     }
4926   }
4927 #endif
4928
4929   if (stream->need_clip)
4930     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4931
4932   if (G_UNLIKELY (buf == NULL))
4933     goto exit;
4934
4935   if (G_UNLIKELY (stream->discont)) {
4936     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4937     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4938     stream->discont = FALSE;
4939   } else {
4940     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4941   }
4942
4943   if (!keyframe) {
4944     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4945     stream->on_keyframe = FALSE;
4946   } else {
4947     stream->on_keyframe = TRUE;
4948   }
4949
4950
4951   GST_LOG_OBJECT (qtdemux,
4952       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4953       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4954       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4955       GST_PAD_NAME (stream->pad));
4956
4957   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
4958     GstStructure *crypto_info;
4959     QtDemuxCencSampleSetInfo *info =
4960         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4961     gint index;
4962     GstEvent *event;
4963
4964     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
4965       gst_pad_push_event (stream->pad, event);
4966     }
4967
4968     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
4969     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
4970       /* steal structure from array */
4971       crypto_info = g_ptr_array_index (info->crypto_info, index);
4972       g_ptr_array_index (info->crypto_info, index) = NULL;
4973       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
4974       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
4975         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
4976     }
4977   }
4978
4979   ret = gst_pad_push (stream->pad, buf);
4980
4981   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4982     /* mark position in stream, we'll need this to know when to send GAP event */
4983     stream->segment.position = pts + duration;
4984   }
4985
4986 exit:
4987   return ret;
4988 }
4989
4990 static const QtDemuxRandomAccessEntry *
4991 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4992     GstClockTime pos, gboolean after)
4993 {
4994   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
4995   guint n_entries = stream->n_ra_entries;
4996   guint i;
4997
4998   /* we assume the table is sorted */
4999   for (i = 0; i < n_entries; ++i) {
5000     if (entries[i].ts > pos)
5001       break;
5002   }
5003
5004   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5005    * probably okay to assume that the index lists the very first fragment */
5006   if (i == 0)
5007     return &entries[0];
5008
5009   if (after)
5010     return &entries[i];
5011   else
5012     return &entries[i - 1];
5013 }
5014
5015 static gboolean
5016 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5017 {
5018   const QtDemuxRandomAccessEntry *best_entry = NULL;
5019   guint i;
5020
5021   GST_OBJECT_LOCK (qtdemux);
5022
5023   g_assert (qtdemux->n_streams > 0);
5024
5025   for (i = 0; i < qtdemux->n_streams; i++) {
5026     const QtDemuxRandomAccessEntry *entry;
5027     QtDemuxStream *stream;
5028     gboolean is_audio_or_video;
5029
5030     stream = qtdemux->streams[i];
5031
5032     g_free (stream->samples);
5033     stream->samples = NULL;
5034     stream->n_samples = 0;
5035     stream->stbl_index = -1;    /* no samples have yet been parsed */
5036     stream->sample_index = -1;
5037
5038     if (stream->ra_entries == NULL)
5039       continue;
5040
5041     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5042       is_audio_or_video = TRUE;
5043     else
5044       is_audio_or_video = FALSE;
5045
5046     entry =
5047         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5048         stream->time_position, !is_audio_or_video);
5049
5050     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5051         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5052
5053     stream->pending_seek = entry;
5054
5055     /* decide position to jump to just based on audio/video tracks, not subs */
5056     if (!is_audio_or_video)
5057       continue;
5058
5059     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5060       best_entry = entry;
5061   }
5062
5063   if (best_entry == NULL) {
5064     GST_OBJECT_UNLOCK (qtdemux);
5065     return FALSE;
5066   }
5067
5068   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5069       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5070       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5071       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5072
5073   qtdemux->moof_offset = best_entry->moof_offset;
5074
5075   qtdemux_add_fragmented_samples (qtdemux);
5076
5077   GST_OBJECT_UNLOCK (qtdemux);
5078   return TRUE;
5079 }
5080
5081 static GstFlowReturn
5082 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5083 {
5084   GstFlowReturn ret = GST_FLOW_OK;
5085   GstBuffer *buf = NULL;
5086   QtDemuxStream *stream;
5087   GstClockTime min_time;
5088   guint64 offset = 0;
5089   GstClockTime dts = GST_CLOCK_TIME_NONE;
5090   GstClockTime pts = GST_CLOCK_TIME_NONE;
5091   GstClockTime duration = 0;
5092   gboolean keyframe = FALSE;
5093   guint sample_size = 0;
5094   gboolean empty = 0;
5095   guint size;
5096   gint index;
5097   gint i;
5098
5099   gst_qtdemux_push_pending_newsegment (qtdemux);
5100
5101   if (qtdemux->fragmented_seek_pending) {
5102     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5103     gst_qtdemux_do_fragmented_seek (qtdemux);
5104     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5105     qtdemux->fragmented_seek_pending = FALSE;
5106   }
5107
5108   /* Figure out the next stream sample to output, min_time is expressed in
5109    * global time and runs over the edit list segments. */
5110   min_time = G_MAXUINT64;
5111   index = -1;
5112   for (i = 0; i < qtdemux->n_streams; i++) {
5113     GstClockTime position;
5114
5115     stream = qtdemux->streams[i];
5116     position = stream->time_position;
5117
5118     /* position of -1 is EOS */
5119     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5120       min_time = position;
5121       index = i;
5122     }
5123   }
5124   /* all are EOS */
5125   if (G_UNLIKELY (index == -1)) {
5126     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5127     goto eos;
5128   }
5129
5130   /* check for segment end */
5131   if (G_UNLIKELY (qtdemux->segment.stop != -1
5132           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5133               || (qtdemux->segment.rate < 0
5134                   && qtdemux->segment.start > min_time))
5135           && qtdemux->streams[index]->on_keyframe)) {
5136     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5137     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5138     goto eos_stream;
5139   }
5140
5141   /* gap events for subtitle streams */
5142   for (i = 0; i < qtdemux->n_streams; i++) {
5143     stream = qtdemux->streams[i];
5144     if (stream->pad && (stream->subtype == FOURCC_subp
5145             || stream->subtype == FOURCC_text
5146             || stream->subtype == FOURCC_sbtl)) {
5147       /* send one second gap events until the stream catches up */
5148       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5149       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5150           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5151           stream->segment.position + GST_SECOND < min_time) {
5152         GstEvent *gap =
5153             gst_event_new_gap (stream->segment.position, GST_SECOND);
5154         gst_pad_push_event (stream->pad, gap);
5155         stream->segment.position += GST_SECOND;
5156       }
5157     }
5158   }
5159
5160   stream = qtdemux->streams[index];
5161   if (stream->new_caps) {
5162     gst_qtdemux_configure_stream (qtdemux, stream);
5163     qtdemux_do_allocation (qtdemux, stream);
5164   }
5165
5166   /* fetch info for the current sample of this stream */
5167   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5168               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5169     goto eos_stream;
5170
5171   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5172   if (G_UNLIKELY (qtdemux->
5173           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5174     if (stream->subtype == FOURCC_vide && !keyframe) {
5175       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5176       goto next;
5177     }
5178   }
5179
5180   GST_DEBUG_OBJECT (qtdemux,
5181       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5182       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5183       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5184       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5185
5186   if (G_UNLIKELY (empty)) {
5187     /* empty segment, push a gap and move to the next one */
5188     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5189     stream->segment.position = pts + duration;
5190     goto next;
5191   }
5192
5193   /* hmm, empty sample, skip and move to next sample */
5194   if (G_UNLIKELY (sample_size <= 0))
5195     goto next;
5196
5197   /* last pushed sample was out of boundary, goto next sample */
5198   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5199     goto next;
5200
5201   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5202     size = sample_size;
5203   } else {
5204     GST_DEBUG_OBJECT (qtdemux,
5205         "size %d larger than stream max_buffer_size %d, trimming",
5206         sample_size, stream->max_buffer_size);
5207     size =
5208         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5209   }
5210
5211   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5212       offset);
5213
5214   if (stream->use_allocator) {
5215     /* if we have a per-stream allocator, use it */
5216     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5217   }
5218
5219   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5220       size, &buf);
5221   if (G_UNLIKELY (ret != GST_FLOW_OK))
5222     goto beach;
5223
5224   if (size != sample_size) {
5225     pts += gst_util_uint64_scale_int (GST_SECOND,
5226         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5227     dts += gst_util_uint64_scale_int (GST_SECOND,
5228         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5229     duration = gst_util_uint64_scale_int (GST_SECOND,
5230         size / stream->bytes_per_frame, stream->timescale);
5231   }
5232
5233   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5234       dts, pts, duration, keyframe, min_time, offset);
5235
5236   if (size != sample_size) {
5237     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5238     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5239
5240     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5241         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5242     if (time_position >= segment->media_start) {
5243       /* inside the segment, update time_position, looks very familiar to
5244        * GStreamer segments, doesn't it? */
5245       stream->time_position = (time_position - segment->media_start) +
5246           segment->time;
5247     } else {
5248       /* not yet in segment, time does not yet increment. This means
5249        * that we are still prerolling keyframes to the decoder so it can
5250        * decode the first sample of the segment. */
5251       stream->time_position = segment->time;
5252     }
5253   }
5254
5255   /* combine flows */
5256   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5257   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5258    * we have no more data for the pad to push */
5259   if (ret == GST_FLOW_EOS)
5260     ret = GST_FLOW_OK;
5261
5262   stream->offset_in_sample += size;
5263   if (stream->offset_in_sample >= sample_size) {
5264     gst_qtdemux_advance_sample (qtdemux, stream);
5265   }
5266   goto beach;
5267
5268 next:
5269   gst_qtdemux_advance_sample (qtdemux, stream);
5270
5271 beach:
5272   return ret;
5273
5274   /* special cases */
5275 eos:
5276   {
5277     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5278     ret = GST_FLOW_EOS;
5279     goto beach;
5280   }
5281 eos_stream:
5282   {
5283     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5284     /* EOS will be raised if all are EOS */
5285     ret = GST_FLOW_OK;
5286     goto beach;
5287   }
5288 }
5289
5290 static void
5291 gst_qtdemux_loop (GstPad * pad)
5292 {
5293   GstQTDemux *qtdemux;
5294   guint64 cur_offset;
5295   GstFlowReturn ret;
5296
5297   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5298
5299   cur_offset = qtdemux->offset;
5300   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5301       cur_offset, qtdemux->state);
5302
5303   switch (qtdemux->state) {
5304     case QTDEMUX_STATE_INITIAL:
5305     case QTDEMUX_STATE_HEADER:
5306       ret = gst_qtdemux_loop_state_header (qtdemux);
5307       break;
5308     case QTDEMUX_STATE_MOVIE:
5309       ret = gst_qtdemux_loop_state_movie (qtdemux);
5310       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5311         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5312       }
5313       break;
5314     default:
5315       /* ouch */
5316       goto invalid_state;
5317   }
5318
5319   /* if something went wrong, pause */
5320   if (ret != GST_FLOW_OK)
5321     goto pause;
5322
5323 done:
5324   gst_object_unref (qtdemux);
5325   return;
5326
5327   /* ERRORS */
5328 invalid_state:
5329   {
5330     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5331         (NULL), ("streaming stopped, invalid state"));
5332     gst_pad_pause_task (pad);
5333     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5334     goto done;
5335   }
5336 pause:
5337   {
5338     const gchar *reason = gst_flow_get_name (ret);
5339
5340     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5341
5342     gst_pad_pause_task (pad);
5343
5344     /* fatal errors need special actions */
5345     /* check EOS */
5346     if (ret == GST_FLOW_EOS) {
5347       if (qtdemux->n_streams == 0) {
5348         /* we have no streams, post an error */
5349         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5350       }
5351       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5352         gint64 stop;
5353
5354         if ((stop = qtdemux->segment.stop) == -1)
5355           stop = qtdemux->segment.duration;
5356
5357         if (qtdemux->segment.rate >= 0) {
5358           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5359           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5360               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5361                   GST_FORMAT_TIME, stop));
5362           gst_qtdemux_push_event (qtdemux,
5363               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
5364         } else {
5365           /*  For Reverse Playback */
5366           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5367           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5368               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5369                   GST_FORMAT_TIME, qtdemux->segment.start));
5370           gst_qtdemux_push_event (qtdemux,
5371               gst_event_new_segment_done (GST_FORMAT_TIME,
5372                   qtdemux->segment.start));
5373         }
5374       } else {
5375         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5376         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5377       }
5378     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5379       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5380           (NULL), ("streaming stopped, reason %s", reason));
5381       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5382     }
5383     goto done;
5384   }
5385 }
5386
5387 /*
5388  * has_next_entry
5389  *
5390  * Returns if there are samples to be played.
5391  */
5392 static gboolean
5393 has_next_entry (GstQTDemux * demux)
5394 {
5395   QtDemuxStream *stream;
5396   int i;
5397
5398   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5399
5400   for (i = 0; i < demux->n_streams; i++) {
5401     stream = demux->streams[i];
5402
5403     if (stream->sample_index == -1) {
5404       stream->sample_index = 0;
5405       stream->offset_in_sample = 0;
5406     }
5407
5408     if (stream->sample_index >= stream->n_samples) {
5409       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5410       continue;
5411     }
5412     GST_DEBUG_OBJECT (demux, "Found a sample");
5413     return TRUE;
5414   }
5415
5416   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5417   return FALSE;
5418 }
5419
5420 /*
5421  * next_entry_size
5422  *
5423  * Returns the size of the first entry at the current offset.
5424  * If -1, there are none (which means EOS or empty file).
5425  */
5426 static guint64
5427 next_entry_size (GstQTDemux * demux)
5428 {
5429   QtDemuxStream *stream;
5430   int i;
5431   int smallidx = -1;
5432   guint64 smalloffs = (guint64) - 1;
5433   QtDemuxSample *sample;
5434
5435   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5436       demux->offset);
5437
5438   for (i = 0; i < demux->n_streams; i++) {
5439     stream = demux->streams[i];
5440
5441     if (stream->sample_index == -1) {
5442       stream->sample_index = 0;
5443       stream->offset_in_sample = 0;
5444     }
5445
5446     if (stream->sample_index >= stream->n_samples) {
5447       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5448       continue;
5449     }
5450
5451     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5452       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5453           stream->sample_index);
5454       return -1;
5455     }
5456
5457     sample = &stream->samples[stream->sample_index];
5458
5459     GST_LOG_OBJECT (demux,
5460         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5461         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5462         sample->offset, sample->size);
5463
5464     if (((smalloffs == -1)
5465             || (sample->offset < smalloffs)) && (sample->size)) {
5466       smallidx = i;
5467       smalloffs = sample->offset;
5468     }
5469   }
5470
5471   GST_LOG_OBJECT (demux,
5472       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5473       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5474
5475   if (smallidx == -1)
5476     return -1;
5477
5478   stream = demux->streams[smallidx];
5479   sample = &stream->samples[stream->sample_index];
5480
5481   if (sample->offset >= demux->offset) {
5482     demux->todrop = sample->offset - demux->offset;
5483     return sample->size + demux->todrop;
5484   }
5485
5486   GST_DEBUG_OBJECT (demux,
5487       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5488   return -1;
5489 }
5490
5491 static void
5492 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5493 {
5494   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5495
5496   gst_element_post_message (GST_ELEMENT_CAST (demux),
5497       gst_message_new_element (GST_OBJECT_CAST (demux),
5498           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5499 }
5500
5501 static gboolean
5502 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5503 {
5504   GstEvent *event;
5505   gboolean res = 0;
5506
5507   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5508
5509   event =
5510       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5511       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5512       GST_SEEK_TYPE_NONE, -1);
5513
5514   /* store seqnum to drop flush events, they don't need to reach downstream */
5515   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5516   res = gst_pad_push_event (demux->sinkpad, event);
5517   demux->offset_seek_seqnum = 0;
5518
5519   return res;
5520 }
5521
5522 /* check for seekable upstream, above and beyond a mere query */
5523 static void
5524 gst_qtdemux_check_seekability (GstQTDemux * demux)
5525 {
5526   GstQuery *query;
5527   gboolean seekable = FALSE;
5528   gint64 start = -1, stop = -1;
5529
5530   if (demux->upstream_size)
5531     return;
5532
5533   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5534   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5535     GST_DEBUG_OBJECT (demux, "seeking query failed");
5536     goto done;
5537   }
5538
5539   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5540
5541   /* try harder to query upstream size if we didn't get it the first time */
5542   if (seekable && stop == -1) {
5543     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5544     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5545   }
5546
5547   /* if upstream doesn't know the size, it's likely that it's not seekable in
5548    * practice even if it technically may be seekable */
5549   if (seekable && (start != 0 || stop <= start)) {
5550     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5551     seekable = FALSE;
5552   }
5553
5554 done:
5555   gst_query_unref (query);
5556
5557   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5558       G_GUINT64_FORMAT ")", seekable, start, stop);
5559   demux->upstream_seekable = seekable;
5560   demux->upstream_size = seekable ? stop : -1;
5561 }
5562
5563 static void
5564 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5565 {
5566   g_return_if_fail (bytes <= demux->todrop);
5567
5568   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5569   gst_adapter_flush (demux->adapter, bytes);
5570   demux->neededbytes -= bytes;
5571   demux->offset += bytes;
5572   demux->todrop -= bytes;
5573 }
5574
5575 static void
5576 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5577 {
5578   if (G_UNLIKELY (demux->pending_newsegment)) {
5579     gint i;
5580
5581     gst_qtdemux_push_pending_newsegment (demux);
5582     /* clear to send tags on all streams */
5583     for (i = 0; i < demux->n_streams; i++) {
5584       QtDemuxStream *stream;
5585       stream = demux->streams[i];
5586       gst_qtdemux_push_tags (demux, stream);
5587       if (stream->sparse) {
5588         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5589         gst_pad_push_event (stream->pad,
5590             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5591       }
5592     }
5593   }
5594 }
5595
5596 static void
5597 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5598     QtDemuxStream * stream)
5599 {
5600   gint i;
5601
5602   /* Push any initial gap segments before proceeding to the
5603    * 'real' data */
5604   for (i = 0; i < stream->n_segments; i++) {
5605     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
5606
5607     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
5608       GstClockTime ts, dur;
5609       GstEvent *gap;
5610
5611       ts = stream->time_position;
5612       dur =
5613           stream->segments[i].duration - (stream->time_position -
5614           stream->segments[i].time);
5615       gap = gst_event_new_gap (ts, dur);
5616       stream->time_position += dur;
5617
5618       GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5619           "segment: %" GST_PTR_FORMAT, gap);
5620       gst_pad_push_event (stream->pad, gap);
5621     } else {
5622       /* Only support empty segment at the beginning followed by
5623        * one non-empty segment, this was checked when parsing the
5624        * edts atom, arriving here is unexpected */
5625       g_assert (i + 1 == stream->n_segments);
5626       break;
5627     }
5628   }
5629 }
5630
5631 static GstFlowReturn
5632 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5633 {
5634   GstQTDemux *demux;
5635
5636   demux = GST_QTDEMUX (parent);
5637
5638   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5639     gint i;
5640
5641     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5642
5643     for (i = 0; i < demux->n_streams; i++) {
5644       demux->streams[i]->discont = TRUE;
5645     }
5646
5647     /* Reverse fragmented playback, need to flush all we have before
5648      * consuming a new fragment.
5649      * The samples array have the timestamps calculated by accumulating the
5650      * durations but this won't work for reverse playback of fragments as
5651      * the timestamps of a subsequent fragment should be smaller than the
5652      * previously received one. */
5653     if (demux->fragmented && demux->segment.rate < 0) {
5654       gst_qtdemux_process_adapter (demux, TRUE);
5655       for (i = 0; i < demux->n_streams; i++)
5656         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5657     }
5658   }
5659
5660   gst_adapter_push (demux->adapter, inbuf);
5661
5662   GST_DEBUG_OBJECT (demux,
5663       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5664       demux->neededbytes, gst_adapter_available (demux->adapter));
5665
5666   return gst_qtdemux_process_adapter (demux, FALSE);
5667 }
5668
5669 static GstFlowReturn
5670 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5671 {
5672   GstFlowReturn ret = GST_FLOW_OK;
5673
5674   /* we never really mean to buffer that much */
5675   if (demux->neededbytes == -1) {
5676     goto eos;
5677   }
5678
5679   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5680       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5681
5682     GST_DEBUG_OBJECT (demux,
5683         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5684         demux->state, demux->neededbytes, demux->offset);
5685
5686     switch (demux->state) {
5687       case QTDEMUX_STATE_INITIAL:{
5688         const guint8 *data;
5689         guint32 fourcc;
5690         guint64 size;
5691
5692         gst_qtdemux_check_seekability (demux);
5693
5694         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5695
5696         /* get fourcc/length, set neededbytes */
5697         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5698             &size, &fourcc);
5699         gst_adapter_unmap (demux->adapter);
5700         data = NULL;
5701         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5702             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5703         if (size == 0) {
5704           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5705               (_("This file is invalid and cannot be played.")),
5706               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5707                   GST_FOURCC_ARGS (fourcc)));
5708           ret = GST_FLOW_ERROR;
5709           break;
5710         }
5711         if (fourcc == FOURCC_mdat) {
5712           gint next_entry = next_entry_size (demux);
5713           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5714             /* we have the headers, start playback */
5715             demux->state = QTDEMUX_STATE_MOVIE;
5716             demux->neededbytes = next_entry;
5717             demux->mdatleft = size;
5718           } else {
5719             /* no headers yet, try to get them */
5720             guint bs;
5721             gboolean res;
5722             guint64 old, target;
5723
5724           buffer_data:
5725             old = demux->offset;
5726             target = old + size;
5727
5728             /* try to jump over the atom with a seek */
5729             /* only bother if it seems worth doing so,
5730              * and avoids possible upstream/server problems */
5731             if (demux->upstream_seekable &&
5732                 demux->upstream_size > 4 * (1 << 20)) {
5733               res = qtdemux_seek_offset (demux, target);
5734             } else {
5735               GST_DEBUG_OBJECT (demux, "skipping seek");
5736               res = FALSE;
5737             }
5738
5739             if (res) {
5740               GST_DEBUG_OBJECT (demux, "seek success");
5741               /* remember the offset fo the first mdat so we can seek back to it
5742                * after we have the headers */
5743               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5744                 demux->first_mdat = old;
5745                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5746                     demux->first_mdat);
5747               }
5748               /* seek worked, continue reading */
5749               demux->offset = target;
5750               demux->neededbytes = 16;
5751               demux->state = QTDEMUX_STATE_INITIAL;
5752             } else {
5753               /* seek failed, need to buffer */
5754               demux->offset = old;
5755               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5756               /* there may be multiple mdat (or alike) buffers */
5757               /* sanity check */
5758               if (demux->mdatbuffer)
5759                 bs = gst_buffer_get_size (demux->mdatbuffer);
5760               else
5761                 bs = 0;
5762               if (size + bs > 10 * (1 << 20))
5763                 goto no_moov;
5764               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5765               demux->neededbytes = size;
5766               if (!demux->mdatbuffer)
5767                 demux->mdatoffset = demux->offset;
5768             }
5769           }
5770         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5771           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5772               (_("This file is invalid and cannot be played.")),
5773               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5774                   GST_FOURCC_ARGS (fourcc), size));
5775           ret = GST_FLOW_ERROR;
5776           break;
5777         } else {
5778           /* this means we already started buffering and still no moov header,
5779            * let's continue buffering everything till we get moov */
5780           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5781                   || fourcc == FOURCC_moof))
5782             goto buffer_data;
5783           demux->neededbytes = size;
5784           demux->state = QTDEMUX_STATE_HEADER;
5785         }
5786         break;
5787       }
5788       case QTDEMUX_STATE_HEADER:{
5789         const guint8 *data;
5790         guint32 fourcc;
5791
5792         GST_DEBUG_OBJECT (demux, "In header");
5793
5794         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5795
5796         /* parse the header */
5797         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5798             &fourcc);
5799         if (fourcc == FOURCC_moov) {
5800           gint n;
5801           gboolean got_samples = FALSE;
5802
5803           /* in usual fragmented setup we could try to scan for more
5804            * and end up at the the moov (after mdat) again */
5805           if (demux->got_moov && demux->n_streams > 0 &&
5806               (!demux->fragmented
5807                   || demux->last_moov_offset == demux->offset)) {
5808             GST_DEBUG_OBJECT (demux,
5809                 "Skipping moov atom as we have (this) one already");
5810           } else {
5811             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5812
5813             if (demux->got_moov && demux->fragmented) {
5814               GST_DEBUG_OBJECT (demux,
5815                   "Got a second moov, clean up data from old one");
5816               if (demux->moov_node)
5817                 g_node_destroy (demux->moov_node);
5818               demux->moov_node = NULL;
5819               demux->moov_node_compressed = NULL;
5820             } else {
5821               /* prepare newsegment to send when streaming actually starts */
5822               if (!demux->pending_newsegment)
5823                 demux->pending_newsegment =
5824                     gst_event_new_segment (&demux->segment);
5825             }
5826
5827             demux->last_moov_offset = demux->offset;
5828
5829             qtdemux_parse_moov (demux, data, demux->neededbytes);
5830             qtdemux_node_dump (demux, demux->moov_node);
5831             qtdemux_parse_tree (demux);
5832             qtdemux_prepare_streams (demux);
5833
5834             for (n = 0; n < demux->n_streams; n++) {
5835               QtDemuxStream *stream = demux->streams[n];
5836               got_samples |= stream->stbl_index >= 0;
5837             }
5838             if (!demux->fragmented || got_samples) {
5839               if (!demux->got_moov) {
5840                 qtdemux_expose_streams (demux);
5841               } else {
5842                 for (n = 0; n < demux->n_streams; n++) {
5843                   QtDemuxStream *stream = demux->streams[n];
5844                   gst_qtdemux_configure_stream (demux, stream);
5845                 }
5846               }
5847               gst_qtdemux_check_send_pending_segment (demux);
5848               demux->pending_configure = FALSE;
5849             } else {
5850               demux->pending_configure = TRUE;
5851             }
5852
5853             demux->got_moov = TRUE;
5854
5855             /* fragmented streams headers shouldn't contain edts atoms */
5856             if (!demux->fragmented) {
5857               for (n = 0; n < demux->n_streams; n++) {
5858                 gst_qtdemux_stream_send_initial_gap_segments (demux,
5859                     demux->streams[n]);
5860               }
5861             }
5862
5863             g_node_destroy (demux->moov_node);
5864             demux->moov_node = NULL;
5865             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5866           }
5867         } else if (fourcc == FOURCC_moof) {
5868           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5869             guint64 dist = 0;
5870             GstClockTime prev_pts;
5871             guint64 prev_offset;
5872             gint n;
5873
5874             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5875
5876             /*
5877              * The timestamp of the moof buffer is relevant as some scenarios
5878              * won't have the initial timestamp in the atoms. Whenever a new
5879              * buffer has started, we get that buffer's PTS and use it as a base
5880              * timestamp for the trun entries.
5881              *
5882              * To keep track of the current buffer timestamp and starting point
5883              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5884              * from the beggining of the buffer, with the distance and demux->offset
5885              * we know if it is still the same buffer or not.
5886              */
5887             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5888             prev_offset = demux->offset - dist;
5889             if (demux->fragment_start_offset == -1
5890                 || prev_offset > demux->fragment_start_offset) {
5891               demux->fragment_start_offset = prev_offset;
5892               demux->fragment_start = prev_pts;
5893               GST_DEBUG_OBJECT (demux,
5894                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5895                   GST_TIME_FORMAT, demux->fragment_start_offset,
5896                   GST_TIME_ARGS (demux->fragment_start));
5897             }
5898
5899             demux->moof_offset = demux->offset;
5900             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5901                     demux->offset, NULL)) {
5902               gst_adapter_unmap (demux->adapter);
5903               ret = GST_FLOW_ERROR;
5904               goto done;
5905             }
5906             /* in MSS we need to expose the pads after the first moof as we won't get a moov 
5907              * Also, fragmented format need to be exposed if a moov have no valid sample data */
5908             if (demux->mss_mode || demux->pending_configure) {
5909               if (!demux->exposed) {
5910                 if (!demux->pending_newsegment) {
5911                   GstSegment segment;
5912                   gst_segment_init (&segment, GST_FORMAT_TIME);
5913                   GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5914                   demux->pending_newsegment = gst_event_new_segment (&segment);
5915                 }
5916                 qtdemux_expose_streams (demux);
5917               } else {
5918                 for (n = 0; n < demux->n_streams; n++) {
5919                   QtDemuxStream *stream = demux->streams[n];
5920                   gst_qtdemux_configure_stream (demux, stream);
5921                 }
5922               }
5923               gst_qtdemux_check_send_pending_segment (demux);
5924               demux->pending_configure = FALSE;
5925             }
5926           } else {
5927             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5928           }
5929         } else if (fourcc == FOURCC_ftyp) {
5930           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5931           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5932         } else if (fourcc == FOURCC_uuid) {
5933           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5934           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5935         } else if (fourcc == FOURCC_sidx) {
5936           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5937           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5938         } else {
5939           GST_WARNING_OBJECT (demux,
5940               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5941               GST_FOURCC_ARGS (fourcc));
5942           /* Let's jump that one and go back to initial state */
5943         }
5944         gst_adapter_unmap (demux->adapter);
5945         data = NULL;
5946
5947         if (demux->mdatbuffer && demux->n_streams) {
5948           gsize remaining_data_size = 0;
5949
5950           /* the mdat was before the header */
5951           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5952               demux->n_streams, demux->mdatbuffer);
5953           /* restore our adapter/offset view of things with upstream;
5954            * put preceding buffered data ahead of current moov data.
5955            * This should also handle evil mdat, moov, mdat cases and alike */
5956           gst_adapter_flush (demux->adapter, demux->neededbytes);
5957
5958           /* Store any remaining data after the mdat for later usage */
5959           remaining_data_size = gst_adapter_available (demux->adapter);
5960           if (remaining_data_size > 0) {
5961             g_assert (demux->restoredata_buffer == NULL);
5962             demux->restoredata_buffer =
5963                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5964             demux->restoredata_offset = demux->offset + demux->neededbytes;
5965             GST_DEBUG_OBJECT (demux,
5966                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5967                 G_GUINT64_FORMAT, remaining_data_size,
5968                 demux->restoredata_offset);
5969           }
5970
5971           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5972           demux->mdatbuffer = NULL;
5973           demux->offset = demux->mdatoffset;
5974           demux->neededbytes = next_entry_size (demux);
5975           demux->state = QTDEMUX_STATE_MOVIE;
5976           demux->mdatleft = gst_adapter_available (demux->adapter);
5977         } else {
5978           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5979           gst_adapter_flush (demux->adapter, demux->neededbytes);
5980
5981           /* only go back to the mdat if there are samples to play */
5982           if (demux->got_moov && demux->first_mdat != -1
5983               && has_next_entry (demux)) {
5984             gboolean res;
5985
5986             /* we need to seek back */
5987             res = qtdemux_seek_offset (demux, demux->first_mdat);
5988             if (res) {
5989               demux->offset = demux->first_mdat;
5990             } else {
5991               GST_DEBUG_OBJECT (demux, "Seek back failed");
5992             }
5993           } else {
5994             demux->offset += demux->neededbytes;
5995           }
5996           demux->neededbytes = 16;
5997           demux->state = QTDEMUX_STATE_INITIAL;
5998         }
5999
6000         break;
6001       }
6002       case QTDEMUX_STATE_BUFFER_MDAT:{
6003         GstBuffer *buf;
6004         guint8 fourcc[4];
6005
6006         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6007             demux->offset);
6008         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6009         gst_buffer_extract (buf, 0, fourcc, 4);
6010         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6011             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6012         if (demux->mdatbuffer)
6013           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6014         else
6015           demux->mdatbuffer = buf;
6016         demux->offset += demux->neededbytes;
6017         demux->neededbytes = 16;
6018         demux->state = QTDEMUX_STATE_INITIAL;
6019         gst_qtdemux_post_progress (demux, 1, 1);
6020
6021         break;
6022       }
6023       case QTDEMUX_STATE_MOVIE:{
6024         QtDemuxStream *stream = NULL;
6025         QtDemuxSample *sample;
6026         int i = -1;
6027         GstClockTime dts, pts, duration;
6028         gboolean keyframe;
6029
6030         GST_DEBUG_OBJECT (demux,
6031             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6032
6033         if (demux->fragmented) {
6034           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6035               demux->mdatleft);
6036           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6037             /* if needed data starts within this atom,
6038              * then it should not exceed this atom */
6039             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6040               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6041                   (_("This file is invalid and cannot be played.")),
6042                   ("sample data crosses atom boundary"));
6043               ret = GST_FLOW_ERROR;
6044               break;
6045             }
6046             demux->mdatleft -= demux->neededbytes;
6047           } else {
6048             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6049             /* so we are dropping more than left in this atom */
6050             gst_qtdemux_drop_data (demux, demux->mdatleft);
6051             demux->mdatleft = 0;
6052
6053             /* need to resume atom parsing so we do not miss any other pieces */
6054             demux->state = QTDEMUX_STATE_INITIAL;
6055             demux->neededbytes = 16;
6056
6057             /* check if there was any stored post mdat data from previous buffers */
6058             if (demux->restoredata_buffer) {
6059               g_assert (gst_adapter_available (demux->adapter) == 0);
6060
6061               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6062               demux->restoredata_buffer = NULL;
6063               demux->offset = demux->restoredata_offset;
6064             }
6065
6066             break;
6067           }
6068         }
6069
6070         if (demux->todrop) {
6071           if (demux->cenc_aux_info_offset > 0) {
6072             GstByteReader br;
6073             const guint8 *data;
6074
6075             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6076             data = gst_adapter_map (demux->adapter, demux->todrop);
6077             gst_byte_reader_init (&br, data + 8, demux->todrop);
6078             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6079                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6080               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6081               ret = GST_FLOW_ERROR;
6082               gst_adapter_unmap (demux->adapter);
6083               g_free (demux->cenc_aux_info_sizes);
6084               demux->cenc_aux_info_sizes = NULL;
6085               goto done;
6086             }
6087             demux->cenc_aux_info_offset = 0;
6088             g_free (demux->cenc_aux_info_sizes);
6089             demux->cenc_aux_info_sizes = NULL;
6090             gst_adapter_unmap (demux->adapter);
6091           }
6092           gst_qtdemux_drop_data (demux, demux->todrop);
6093         }
6094
6095         /* first buffer? */
6096         /* initial newsegment sent here after having added pads,
6097          * possible others in sink_event */
6098         gst_qtdemux_check_send_pending_segment (demux);
6099
6100         /* Figure out which stream this packet belongs to */
6101         for (i = 0; i < demux->n_streams; i++) {
6102           stream = demux->streams[i];
6103           if (stream->sample_index >= stream->n_samples)
6104             continue;
6105           GST_LOG_OBJECT (demux,
6106               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6107               " / size:%d)", i, stream->sample_index,
6108               stream->samples[stream->sample_index].offset,
6109               stream->samples[stream->sample_index].size);
6110
6111           if (stream->samples[stream->sample_index].offset == demux->offset)
6112             break;
6113         }
6114
6115         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6116           goto unknown_stream;
6117
6118         if (stream->new_caps) {
6119           gst_qtdemux_configure_stream (demux, stream);
6120         }
6121
6122         /* Put data in a buffer, set timestamps, caps, ... */
6123         sample = &stream->samples[stream->sample_index];
6124
6125         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6126           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6127               GST_FOURCC_ARGS (stream->fourcc));
6128
6129           dts = QTSAMPLE_DTS (stream, sample);
6130           pts = QTSAMPLE_PTS (stream, sample);
6131           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6132           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6133
6134           /* check for segment end */
6135           if (G_UNLIKELY (demux->segment.stop != -1
6136                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6137             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6138             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6139
6140             /* skip this data, stream is EOS */
6141             gst_adapter_flush (demux->adapter, demux->neededbytes);
6142
6143             /* check if all streams are eos */
6144             ret = GST_FLOW_EOS;
6145             for (i = 0; i < demux->n_streams; i++) {
6146               if (!STREAM_IS_EOS (demux->streams[i])) {
6147                 ret = GST_FLOW_OK;
6148                 break;
6149               }
6150             }
6151
6152             if (ret == GST_FLOW_EOS) {
6153               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6154               goto eos;
6155             }
6156           } else {
6157             GstBuffer *outbuf;
6158
6159             outbuf =
6160                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6161
6162             /* FIXME: should either be an assert or a plain check */
6163             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6164
6165             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6166                 dts, pts, duration, keyframe, dts, demux->offset);
6167           }
6168
6169           /* combine flows */
6170           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6171           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6172             goto non_ok_unlinked_flow;
6173         } else {
6174           /* skip this data, stream is EOS */
6175           gst_adapter_flush (demux->adapter, demux->neededbytes);
6176         }
6177
6178         stream->sample_index++;
6179         stream->offset_in_sample = 0;
6180
6181         /* update current offset and figure out size of next buffer */
6182         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6183             demux->offset, demux->neededbytes);
6184         demux->offset += demux->neededbytes;
6185         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6186             demux->offset);
6187
6188         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6189           if (demux->fragmented) {
6190             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6191             /* there may be more to follow, only finish this atom */
6192             demux->todrop = demux->mdatleft;
6193             demux->neededbytes = demux->todrop;
6194             break;
6195           }
6196           goto eos;
6197         }
6198         break;
6199       }
6200       default:
6201         goto invalid_state;
6202     }
6203   }
6204
6205   /* when buffering movie data, at least show user something is happening */
6206   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6207       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6208     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6209         demux->neededbytes);
6210   }
6211 done:
6212
6213   return ret;
6214
6215   /* ERRORS */
6216 non_ok_unlinked_flow:
6217   {
6218     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6219         gst_flow_get_name (ret));
6220     return ret;
6221   }
6222 unknown_stream:
6223   {
6224     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6225     ret = GST_FLOW_ERROR;
6226     goto done;
6227   }
6228 eos:
6229   {
6230     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6231     ret = GST_FLOW_EOS;
6232     goto done;
6233   }
6234 invalid_state:
6235   {
6236     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6237         (NULL), ("qtdemuxer invalid state %d", demux->state));
6238     ret = GST_FLOW_ERROR;
6239     goto done;
6240   }
6241 no_moov:
6242   {
6243     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6244         (NULL), ("no 'moov' atom within the first 10 MB"));
6245     ret = GST_FLOW_ERROR;
6246     goto done;
6247   }
6248 }
6249
6250 static gboolean
6251 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6252 {
6253   GstQuery *query;
6254   gboolean pull_mode;
6255
6256   query = gst_query_new_scheduling ();
6257
6258   if (!gst_pad_peer_query (sinkpad, query)) {
6259     gst_query_unref (query);
6260     goto activate_push;
6261   }
6262
6263   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6264       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6265   gst_query_unref (query);
6266
6267   if (!pull_mode)
6268     goto activate_push;
6269
6270   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6271   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6272
6273 activate_push:
6274   {
6275     GST_DEBUG_OBJECT (sinkpad, "activating push");
6276     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6277   }
6278 }
6279
6280 static gboolean
6281 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6282     GstPadMode mode, gboolean active)
6283 {
6284   gboolean res;
6285   GstQTDemux *demux = GST_QTDEMUX (parent);
6286
6287   switch (mode) {
6288     case GST_PAD_MODE_PUSH:
6289       demux->pullbased = FALSE;
6290       res = TRUE;
6291       break;
6292     case GST_PAD_MODE_PULL:
6293       if (active) {
6294         demux->pullbased = TRUE;
6295         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6296             sinkpad, NULL);
6297       } else {
6298         res = gst_pad_stop_task (sinkpad);
6299       }
6300       break;
6301     default:
6302       res = FALSE;
6303       break;
6304   }
6305   return res;
6306 }
6307
6308 #ifdef HAVE_ZLIB
6309 static void *
6310 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6311 {
6312   return g_malloc (items * size);
6313 }
6314
6315 static void
6316 qtdemux_zfree (void *opaque, void *addr)
6317 {
6318   g_free (addr);
6319 }
6320
6321 static void *
6322 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6323 {
6324   guint8 *buffer;
6325   z_stream *z;
6326   int ret;
6327
6328   z = g_new0 (z_stream, 1);
6329   z->zalloc = qtdemux_zalloc;
6330   z->zfree = qtdemux_zfree;
6331   z->opaque = NULL;
6332
6333   z->next_in = z_buffer;
6334   z->avail_in = z_length;
6335
6336   buffer = (guint8 *) g_malloc (length);
6337   ret = inflateInit (z);
6338   while (z->avail_in > 0) {
6339     if (z->avail_out == 0) {
6340       length += 1024;
6341       buffer = (guint8 *) g_realloc (buffer, length);
6342       z->next_out = buffer + z->total_out;
6343       z->avail_out = 1024;
6344     }
6345     ret = inflate (z, Z_SYNC_FLUSH);
6346     if (ret != Z_OK)
6347       break;
6348   }
6349   if (ret != Z_STREAM_END) {
6350     g_warning ("inflate() returned %d", ret);
6351   }
6352
6353   g_free (z);
6354   return buffer;
6355 }
6356 #endif /* HAVE_ZLIB */
6357
6358 static gboolean
6359 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6360 {
6361   GNode *cmov;
6362
6363   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6364
6365   /* counts as header data */
6366   qtdemux->header_size += length;
6367
6368   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6369   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6370
6371   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6372   if (cmov) {
6373     guint32 method;
6374     GNode *dcom;
6375     GNode *cmvd;
6376
6377     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6378     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6379     if (dcom == NULL || cmvd == NULL)
6380       goto invalid_compression;
6381
6382     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6383     switch (method) {
6384 #ifdef HAVE_ZLIB
6385       case FOURCC_zlib:{
6386         guint uncompressed_length;
6387         guint compressed_length;
6388         guint8 *buf;
6389
6390         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6391         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6392         GST_LOG ("length = %u", uncompressed_length);
6393
6394         buf =
6395             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6396             compressed_length, uncompressed_length);
6397
6398         qtdemux->moov_node_compressed = qtdemux->moov_node;
6399         qtdemux->moov_node = g_node_new (buf);
6400
6401         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6402             uncompressed_length);
6403         break;
6404       }
6405 #endif /* HAVE_ZLIB */
6406       default:
6407         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6408             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6409         break;
6410     }
6411   }
6412   return TRUE;
6413
6414   /* ERRORS */
6415 invalid_compression:
6416   {
6417     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6418     return FALSE;
6419   }
6420 }
6421
6422 static gboolean
6423 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6424     const guint8 * end)
6425 {
6426   while (G_UNLIKELY (buf < end)) {
6427     GNode *child;
6428     guint32 len;
6429
6430     if (G_UNLIKELY (buf + 4 > end)) {
6431       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6432       break;
6433     }
6434     len = QT_UINT32 (buf);
6435     if (G_UNLIKELY (len == 0)) {
6436       GST_LOG_OBJECT (qtdemux, "empty container");
6437       break;
6438     }
6439     if (G_UNLIKELY (len < 8)) {
6440       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6441       break;
6442     }
6443     if (G_UNLIKELY (len > (end - buf))) {
6444       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6445           (gint) (end - buf));
6446       break;
6447     }
6448
6449     child = g_node_new ((guint8 *) buf);
6450     g_node_append (node, child);
6451     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6452     qtdemux_parse_node (qtdemux, child, buf, len);
6453
6454     buf += len;
6455   }
6456   return TRUE;
6457 }
6458
6459 static gboolean
6460 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6461     GNode * xdxt)
6462 {
6463   int len = QT_UINT32 (xdxt->data);
6464   guint8 *buf = xdxt->data;
6465   guint8 *end = buf + len;
6466   GstBuffer *buffer;
6467
6468   /* skip size and type */
6469   buf += 8;
6470   end -= 8;
6471
6472   while (buf < end) {
6473     gint size;
6474     guint32 type;
6475
6476     size = QT_UINT32 (buf);
6477     type = QT_FOURCC (buf + 4);
6478
6479     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6480
6481     if (buf + size > end || size <= 0)
6482       break;
6483
6484     buf += 8;
6485     size -= 8;
6486
6487     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6488         GST_FOURCC_ARGS (type));
6489
6490     switch (type) {
6491       case FOURCC_tCtH:
6492         buffer = gst_buffer_new_and_alloc (size);
6493         gst_buffer_fill (buffer, 0, buf, size);
6494         stream->buffers = g_slist_append (stream->buffers, buffer);
6495         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6496         break;
6497       case FOURCC_tCt_:
6498         buffer = gst_buffer_new_and_alloc (size);
6499         gst_buffer_fill (buffer, 0, buf, size);
6500         stream->buffers = g_slist_append (stream->buffers, buffer);
6501         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6502         break;
6503       case FOURCC_tCtC:
6504         buffer = gst_buffer_new_and_alloc (size);
6505         gst_buffer_fill (buffer, 0, buf, size);
6506         stream->buffers = g_slist_append (stream->buffers, buffer);
6507         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6508         break;
6509       default:
6510         GST_WARNING_OBJECT (qtdemux,
6511             "unknown theora cookie %" GST_FOURCC_FORMAT,
6512             GST_FOURCC_ARGS (type));
6513         break;
6514     }
6515     buf += size;
6516   }
6517   return TRUE;
6518 }
6519
6520 static gboolean
6521 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6522     guint length)
6523 {
6524   guint32 fourcc = 0;
6525   guint32 node_length = 0;
6526   const QtNodeType *type;
6527   const guint8 *end;
6528
6529   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6530
6531   if (G_UNLIKELY (length < 8))
6532     goto not_enough_data;
6533
6534   node_length = QT_UINT32 (buffer);
6535   fourcc = QT_FOURCC (buffer + 4);
6536
6537   /* ignore empty nodes */
6538   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6539     return TRUE;
6540
6541   type = qtdemux_type_get (fourcc);
6542
6543   end = buffer + length;
6544
6545   GST_LOG_OBJECT (qtdemux,
6546       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6547       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6548
6549   if (node_length > length)
6550     goto broken_atom_size;
6551
6552   if (type->flags & QT_FLAG_CONTAINER) {
6553     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6554   } else {
6555     switch (fourcc) {
6556       case FOURCC_stsd:
6557       {
6558         if (node_length < 20) {
6559           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6560           break;
6561         }
6562         GST_DEBUG_OBJECT (qtdemux,
6563             "parsing stsd (sample table, sample description) atom");
6564         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6565         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6566         break;
6567       }
6568       case FOURCC_mp4a:
6569       case FOURCC_alac:
6570       {
6571         guint32 version;
6572         guint32 offset;
6573         guint min_size;
6574
6575         /* also read alac (or whatever) in stead of mp4a in the following,
6576          * since a similar layout is used in other cases as well */
6577         if (fourcc == FOURCC_mp4a)
6578           min_size = 20;
6579         else
6580           min_size = 40;
6581
6582         /* There are two things we might encounter here: a true mp4a atom, and
6583            an mp4a entry in an stsd atom. The latter is what we're interested
6584            in, and it looks like an atom, but isn't really one. The true mp4a
6585            atom is short, so we detect it based on length here. */
6586         if (length < min_size) {
6587           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6588               GST_FOURCC_ARGS (fourcc));
6589           break;
6590         }
6591
6592         /* 'version' here is the sound sample description version. Types 0 and
6593            1 are documented in the QTFF reference, but type 2 is not: it's
6594            described in Apple header files instead (struct SoundDescriptionV2
6595            in Movies.h) */
6596         version = QT_UINT16 (buffer + 16);
6597
6598         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6599             GST_FOURCC_ARGS (fourcc), version);
6600
6601         /* parse any esds descriptors */
6602         switch (version) {
6603           case 0:
6604             offset = 0x24;
6605             break;
6606           case 1:
6607             offset = 0x34;
6608             break;
6609           case 2:
6610             offset = 0x48;
6611             break;
6612           default:
6613             GST_WARNING_OBJECT (qtdemux,
6614                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6615                 GST_FOURCC_ARGS (fourcc), version);
6616             offset = 0;
6617             break;
6618         }
6619         if (offset)
6620           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6621         break;
6622       }
6623       case FOURCC_mp4v:
6624       case FOURCC_MP4V:
6625       case FOURCC_fmp4:
6626       case FOURCC_FMP4:
6627       case FOURCC_apcs:
6628       case FOURCC_apch:
6629       case FOURCC_apcn:
6630       case FOURCC_apco:
6631       case FOURCC_ap4h:
6632       {
6633         const guint8 *buf;
6634         guint32 version;
6635         int tlen;
6636
6637         /* codec_data is contained inside these atoms, which all have
6638          * the same format. */
6639
6640         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6641             GST_FOURCC_ARGS (fourcc));
6642         version = QT_UINT32 (buffer + 16);
6643         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6644         if (1 || version == 0x00000000) {
6645           buf = buffer + 0x32;
6646
6647           /* FIXME Quicktime uses PASCAL string while
6648            * the iso format uses C strings. Check the file
6649            * type before attempting to parse the string here. */
6650           tlen = QT_UINT8 (buf);
6651           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6652           buf++;
6653           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6654           /* the string has a reserved space of 32 bytes so skip
6655            * the remaining 31 */
6656           buf += 31;
6657           buf += 4;             /* and 4 bytes reserved */
6658
6659           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6660
6661           qtdemux_parse_container (qtdemux, node, buf, end);
6662         }
6663         break;
6664       }
6665       case FOURCC_H264:
6666       {
6667         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6668         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6669         break;
6670       }
6671       case FOURCC_avc1:
6672       {
6673         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6674         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6675         break;
6676       }
6677       case FOURCC_avc3:
6678       {
6679         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6680         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6681         break;
6682       }
6683       case FOURCC_H265:
6684       {
6685         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6686         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6687         break;
6688       }
6689       case FOURCC_hvc1:
6690       {
6691         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6692         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6693         break;
6694       }
6695       case FOURCC_hev1:
6696       {
6697         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6698         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6699         break;
6700       }
6701       case FOURCC_mjp2:
6702       {
6703         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6704         break;
6705       }
6706       case FOURCC_meta:
6707       {
6708         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6709         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6710         break;
6711       }
6712       case FOURCC_mp4s:
6713       {
6714         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6715         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6716         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6717         break;
6718       }
6719       case FOURCC_XiTh:
6720       {
6721         guint32 version;
6722         guint32 offset;
6723
6724         version = QT_UINT32 (buffer + 12);
6725         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6726
6727         switch (version) {
6728           case 0x00000001:
6729             offset = 0x62;
6730             break;
6731           default:
6732             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6733             offset = 0;
6734             break;
6735         }
6736         if (offset)
6737           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6738         break;
6739       }
6740       case FOURCC_in24:
6741       {
6742         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6743         break;
6744       }
6745       case FOURCC_uuid:
6746       {
6747         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6748         break;
6749       }
6750       case FOURCC_encv:
6751       {
6752         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6753         break;
6754       }
6755       case FOURCC_enca:
6756       {
6757         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
6758         break;
6759       }
6760       default:
6761         if (!strcmp (type->name, "unknown"))
6762           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6763         break;
6764     }
6765   }
6766   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6767       GST_FOURCC_ARGS (fourcc));
6768   return TRUE;
6769
6770 /* ERRORS */
6771 not_enough_data:
6772   {
6773     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6774         (_("This file is corrupt and cannot be played.")),
6775         ("Not enough data for an atom header, got only %u bytes", length));
6776     return FALSE;
6777   }
6778 broken_atom_size:
6779   {
6780     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6781         (_("This file is corrupt and cannot be played.")),
6782         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6783             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6784             length));
6785     return FALSE;
6786   }
6787 }
6788
6789 static GNode *
6790 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6791 {
6792   GNode *child;
6793   guint8 *buffer;
6794   guint32 child_fourcc;
6795
6796   for (child = g_node_first_child (node); child;
6797       child = g_node_next_sibling (child)) {
6798     buffer = (guint8 *) child->data;
6799
6800     child_fourcc = QT_FOURCC (buffer + 4);
6801
6802     if (G_UNLIKELY (child_fourcc == fourcc)) {
6803       return child;
6804     }
6805   }
6806   return NULL;
6807 }
6808
6809 static GNode *
6810 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6811     GstByteReader * parser)
6812 {
6813   GNode *child;
6814   guint8 *buffer;
6815   guint32 child_fourcc, child_len;
6816
6817   for (child = g_node_first_child (node); child;
6818       child = g_node_next_sibling (child)) {
6819     buffer = (guint8 *) child->data;
6820
6821     child_len = QT_UINT32 (buffer);
6822     child_fourcc = QT_FOURCC (buffer + 4);
6823
6824     if (G_UNLIKELY (child_fourcc == fourcc)) {
6825       if (G_UNLIKELY (child_len < (4 + 4)))
6826         return NULL;
6827       /* FIXME: must verify if atom length < parent atom length */
6828       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6829       return child;
6830     }
6831   }
6832   return NULL;
6833 }
6834
6835 static GNode *
6836 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6837     GstByteReader * parser)
6838 {
6839   GNode *child;
6840   guint8 *buffer;
6841   guint32 child_fourcc, child_len;
6842
6843   for (child = g_node_next_sibling (node); child;
6844       child = g_node_next_sibling (child)) {
6845     buffer = (guint8 *) child->data;
6846
6847     child_fourcc = QT_FOURCC (buffer + 4);
6848
6849     if (child_fourcc == fourcc) {
6850       if (parser) {
6851         child_len = QT_UINT32 (buffer);
6852         if (G_UNLIKELY (child_len < (4 + 4)))
6853           return NULL;
6854         /* FIXME: must verify if atom length < parent atom length */
6855         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6856       }
6857       return child;
6858     }
6859   }
6860   return NULL;
6861 }
6862
6863 static GNode *
6864 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6865 {
6866   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6867 }
6868
6869 static void
6870 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6871 {
6872 /* FIXME: This can only reliably work if demuxers have a
6873  * separate streaming thread per srcpad. This should be
6874  * done in a demuxer base class, which integrates parts
6875  * of multiqueue
6876  *
6877  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6878  */
6879 #if 0
6880   GstQuery *query;
6881
6882   query = gst_query_new_allocation (stream->caps, FALSE);
6883
6884   if (!gst_pad_peer_query (stream->pad, query)) {
6885     /* not a problem, just debug a little */
6886     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6887   }
6888
6889   if (stream->allocator)
6890     gst_object_unref (stream->allocator);
6891
6892   if (gst_query_get_n_allocation_params (query) > 0) {
6893     /* try the allocator */
6894     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6895         &stream->params);
6896     stream->use_allocator = TRUE;
6897   } else {
6898     stream->allocator = NULL;
6899     gst_allocation_params_init (&stream->params);
6900     stream->use_allocator = FALSE;
6901   }
6902   gst_query_unref (query);
6903 #endif
6904 }
6905
6906 static gboolean
6907 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
6908     QtDemuxStream * stream)
6909 {
6910   GstStructure *s;
6911   const gchar *selected_system;
6912
6913   g_return_val_if_fail (qtdemux != NULL, FALSE);
6914   g_return_val_if_fail (stream != NULL, FALSE);
6915   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
6916
6917   if (stream->protection_scheme_type != FOURCC_cenc) {
6918     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
6919     return FALSE;
6920   }
6921   if (qtdemux->protection_system_ids == NULL) {
6922     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
6923         "cenc protection system information has been found");
6924     return FALSE;
6925   }
6926   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
6927   selected_system = gst_protection_select_system ((const gchar **)
6928       qtdemux->protection_system_ids->pdata);
6929   g_ptr_array_remove_index (qtdemux->protection_system_ids,
6930       qtdemux->protection_system_ids->len - 1);
6931   if (!selected_system) {
6932     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
6933         "suitable decryptor element has been found");
6934     return FALSE;
6935   }
6936
6937   s = gst_caps_get_structure (stream->caps, 0);
6938   if (!gst_structure_has_name (s, "application/x-cenc")) {
6939     gst_structure_set (s,
6940         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
6941         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
6942         NULL);
6943     gst_structure_set_name (s, "application/x-cenc");
6944   }
6945   return TRUE;
6946 }
6947
6948 static gboolean
6949 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6950 {
6951   if (stream->subtype == FOURCC_vide) {
6952     /* fps is calculated base on the duration of the average framerate since
6953      * qt does not have a fixed framerate. */
6954     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6955       /* still frame */
6956       stream->fps_n = 0;
6957       stream->fps_d = 1;
6958     } else {
6959       if (stream->duration == 0 || stream->n_samples < 2) {
6960         stream->fps_n = stream->timescale;
6961         stream->fps_d = 1;
6962       } else {
6963         GstClockTime avg_duration;
6964         guint64 duration;
6965         guint32 n_samples;
6966
6967         /* duration and n_samples can be updated for fragmented format
6968          * so, framerate of fragmented format is calculated using data in a moof */
6969         if (qtdemux->fragmented && stream->n_samples_moof > 0
6970             && stream->duration_moof > 0) {
6971           n_samples = stream->n_samples_moof;
6972           duration = stream->duration_moof;
6973         } else {
6974           n_samples = stream->n_samples;
6975           duration = stream->duration;
6976         }
6977
6978         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6979         /* stream->duration is guint64, timescale, n_samples are guint32 */
6980         avg_duration =
6981             gst_util_uint64_scale_round (duration -
6982             stream->first_duration, GST_SECOND,
6983             (guint64) (stream->timescale) * (n_samples - 1));
6984
6985         GST_LOG_OBJECT (qtdemux,
6986             "Calculating avg sample duration based on stream (or moof) duration %"
6987             G_GUINT64_FORMAT
6988             " minus first sample %u, leaving %d samples gives %"
6989             GST_TIME_FORMAT, duration, stream->first_duration,
6990             n_samples - 1, GST_TIME_ARGS (avg_duration));
6991
6992         gst_video_guess_framerate (avg_duration, &stream->fps_n,
6993             &stream->fps_d);
6994       }
6995       GST_DEBUG_OBJECT (qtdemux,
6996           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
6997           stream->timescale, stream->fps_n, stream->fps_d);
6998     }
6999
7000     if (stream->caps) {
7001       stream->caps = gst_caps_make_writable (stream->caps);
7002
7003       gst_caps_set_simple (stream->caps,
7004           "width", G_TYPE_INT, stream->width,
7005           "height", G_TYPE_INT, stream->height,
7006           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7007
7008       /* calculate pixel-aspect-ratio using display width and height */
7009       GST_DEBUG_OBJECT (qtdemux,
7010           "video size %dx%d, target display size %dx%d", stream->width,
7011           stream->height, stream->display_width, stream->display_height);
7012       /* qt file might have pasp atom */
7013       if (stream->par_w > 0 && stream->par_h > 0) {
7014         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7015         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7016             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7017       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7018           stream->width > 0 && stream->height > 0) {
7019         gint n, d;
7020
7021         /* calculate the pixel aspect ratio using the display and pixel w/h */
7022         n = stream->display_width * stream->height;
7023         d = stream->display_height * stream->width;
7024         if (n == d)
7025           n = d = 1;
7026         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7027         stream->par_w = n;
7028         stream->par_h = d;
7029         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7030             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7031       }
7032
7033       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7034         guint par_w = 1, par_h = 1;
7035
7036         if (stream->par_w > 0 && stream->par_h > 0) {
7037           par_w = stream->par_w;
7038           par_h = stream->par_h;
7039         }
7040
7041         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7042                 stream->width, stream->height, par_w, par_h)) {
7043           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7044         }
7045
7046         gst_caps_set_simple (stream->caps,
7047             "multiview-mode", G_TYPE_STRING,
7048             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7049             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7050             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7051       }
7052     }
7053   }
7054
7055   else if (stream->subtype == FOURCC_soun) {
7056     if (stream->caps) {
7057       stream->caps = gst_caps_make_writable (stream->caps);
7058       if (stream->rate > 0)
7059         gst_caps_set_simple (stream->caps,
7060             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7061       if (stream->n_channels > 0)
7062         gst_caps_set_simple (stream->caps,
7063             "channels", G_TYPE_INT, stream->n_channels, NULL);
7064       if (stream->n_channels > 2) {
7065         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7066          * correctly; this is just the minimum we can do - assume
7067          * we don't actually have any channel positions. */
7068         gst_caps_set_simple (stream->caps,
7069             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7070       }
7071     }
7072   }
7073
7074   if (stream->pad) {
7075     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7076     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7077     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7078     gst_pad_set_active (stream->pad, TRUE);
7079
7080     gst_pad_use_fixed_caps (stream->pad);
7081
7082     if (stream->protected) {
7083       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7084         GST_ERROR_OBJECT (qtdemux,
7085             "Failed to configure protected stream caps.");
7086         return FALSE;
7087       }
7088     }
7089
7090     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7091     if (stream->new_stream) {
7092       gchar *stream_id;
7093       GstEvent *event;
7094       GstStreamFlags stream_flags;
7095
7096       event =
7097           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7098           0);
7099       if (event) {
7100         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7101           qtdemux->have_group_id = TRUE;
7102         else
7103           qtdemux->have_group_id = FALSE;
7104         gst_event_unref (event);
7105       } else if (!qtdemux->have_group_id) {
7106         qtdemux->have_group_id = TRUE;
7107         qtdemux->group_id = gst_util_group_id_next ();
7108       }
7109
7110       stream->new_stream = FALSE;
7111       stream_id =
7112           gst_pad_create_stream_id_printf (stream->pad,
7113           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7114       event = gst_event_new_stream_start (stream_id);
7115       if (qtdemux->have_group_id)
7116         gst_event_set_group_id (event, qtdemux->group_id);
7117       stream_flags = GST_STREAM_FLAG_NONE;
7118       if (stream->disabled)
7119         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7120       if (stream->sparse)
7121         stream_flags |= GST_STREAM_FLAG_SPARSE;
7122       gst_event_set_stream_flags (event, stream_flags);
7123       gst_pad_push_event (stream->pad, event);
7124       g_free (stream_id);
7125     }
7126     gst_pad_set_caps (stream->pad, stream->caps);
7127     stream->new_caps = FALSE;
7128   }
7129   return TRUE;
7130 }
7131
7132 static gboolean
7133 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7134     QtDemuxStream * stream, GstTagList * list)
7135 {
7136   /* consistent default for push based mode */
7137   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7138
7139   if (stream->subtype == FOURCC_vide) {
7140     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7141
7142     stream->pad =
7143         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7144     g_free (name);
7145
7146     gst_qtdemux_configure_stream (qtdemux, stream);
7147     qtdemux->n_video_streams++;
7148   } else if (stream->subtype == FOURCC_soun) {
7149     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7150
7151     stream->pad =
7152         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7153     g_free (name);
7154     gst_qtdemux_configure_stream (qtdemux, stream);
7155     qtdemux->n_audio_streams++;
7156   } else if (stream->subtype == FOURCC_strm) {
7157     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7158   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7159       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7160     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7161
7162     stream->pad =
7163         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7164     g_free (name);
7165     gst_qtdemux_configure_stream (qtdemux, stream);
7166     qtdemux->n_sub_streams++;
7167   } else if (stream->caps) {
7168     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7169
7170     stream->pad =
7171         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7172     g_free (name);
7173     gst_qtdemux_configure_stream (qtdemux, stream);
7174     qtdemux->n_video_streams++;
7175   } else {
7176     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7177     goto done;
7178   }
7179
7180   if (stream->pad) {
7181     GList *l;
7182
7183     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7184         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7185     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7186     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7187
7188     if (stream->pending_tags)
7189       gst_tag_list_unref (stream->pending_tags);
7190     stream->pending_tags = list;
7191     list = NULL;
7192     /* global tags go on each pad anyway */
7193     stream->send_global_tags = TRUE;
7194     /* send upstream GST_EVENT_PROTECTION events that were received before
7195        this source pad was created */
7196     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7197       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7198   }
7199 done:
7200   if (list)
7201     gst_tag_list_unref (list);
7202   return TRUE;
7203 }
7204
7205 /* find next atom with @fourcc starting at @offset */
7206 static GstFlowReturn
7207 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7208     guint64 * length, guint32 fourcc)
7209 {
7210   GstFlowReturn ret;
7211   guint32 lfourcc;
7212   GstBuffer *buf;
7213
7214   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7215       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7216
7217   while (TRUE) {
7218     GstMapInfo map;
7219
7220     buf = NULL;
7221     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7222     if (G_UNLIKELY (ret != GST_FLOW_OK))
7223       goto locate_failed;
7224     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7225       /* likely EOF */
7226       ret = GST_FLOW_EOS;
7227       gst_buffer_unref (buf);
7228       goto locate_failed;
7229     }
7230     gst_buffer_map (buf, &map, GST_MAP_READ);
7231     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7232     gst_buffer_unmap (buf, &map);
7233     gst_buffer_unref (buf);
7234
7235     if (G_UNLIKELY (*length == 0)) {
7236       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7237       ret = GST_FLOW_ERROR;
7238       goto locate_failed;
7239     }
7240
7241     if (lfourcc == fourcc) {
7242       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7243           *offset);
7244       break;
7245     } else {
7246       GST_LOG_OBJECT (qtdemux,
7247           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7248           GST_FOURCC_ARGS (fourcc), *offset);
7249       *offset += *length;
7250     }
7251   }
7252
7253   return GST_FLOW_OK;
7254
7255 locate_failed:
7256   {
7257     /* might simply have had last one */
7258     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7259     return ret;
7260   }
7261 }
7262
7263 /* should only do something in pull mode */
7264 /* call with OBJECT lock */
7265 static GstFlowReturn
7266 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7267 {
7268   guint64 length, offset;
7269   GstBuffer *buf = NULL;
7270   GstFlowReturn ret = GST_FLOW_OK;
7271   GstFlowReturn res = GST_FLOW_OK;
7272   GstMapInfo map;
7273
7274   offset = qtdemux->moof_offset;
7275   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7276
7277   if (!offset) {
7278     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7279     return GST_FLOW_EOS;
7280   }
7281
7282   /* best not do pull etc with lock held */
7283   GST_OBJECT_UNLOCK (qtdemux);
7284
7285   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7286   if (ret != GST_FLOW_OK)
7287     goto flow_failed;
7288
7289   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7290   if (G_UNLIKELY (ret != GST_FLOW_OK))
7291     goto flow_failed;
7292   gst_buffer_map (buf, &map, GST_MAP_READ);
7293   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7294     gst_buffer_unmap (buf, &map);
7295     gst_buffer_unref (buf);
7296     buf = NULL;
7297     goto parse_failed;
7298   }
7299
7300   gst_buffer_unmap (buf, &map);
7301   gst_buffer_unref (buf);
7302   buf = NULL;
7303
7304   offset += length;
7305   /* look for next moof */
7306   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7307   if (G_UNLIKELY (ret != GST_FLOW_OK))
7308     goto flow_failed;
7309
7310 exit:
7311   GST_OBJECT_LOCK (qtdemux);
7312
7313   qtdemux->moof_offset = offset;
7314
7315   return res;
7316
7317 parse_failed:
7318   {
7319     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7320     offset = 0;
7321     res = GST_FLOW_ERROR;
7322     goto exit;
7323   }
7324 flow_failed:
7325   {
7326     /* maybe upstream temporarily flushing */
7327     if (ret != GST_FLOW_FLUSHING) {
7328       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7329       offset = 0;
7330     } else {
7331       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7332       /* resume at current position next time */
7333     }
7334     res = ret;
7335     goto exit;
7336   }
7337 }
7338
7339 /* initialise bytereaders for stbl sub-atoms */
7340 static gboolean
7341 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7342 {
7343   stream->stbl_index = -1;      /* no samples have yet been parsed */
7344   stream->sample_index = -1;
7345
7346   /* time-to-sample atom */
7347   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7348     goto corrupt_file;
7349
7350   /* copy atom data into a new buffer for later use */
7351   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7352
7353   /* skip version + flags */
7354   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7355       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7356     goto corrupt_file;
7357   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7358
7359   /* make sure there's enough data */
7360   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7361     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7362     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7363         stream->n_sample_times);
7364     if (!stream->n_sample_times)
7365       goto corrupt_file;
7366   }
7367
7368   /* sync sample atom */
7369   stream->stps_present = FALSE;
7370   if ((stream->stss_present =
7371           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7372               &stream->stss) ? TRUE : FALSE) == TRUE) {
7373     /* copy atom data into a new buffer for later use */
7374     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7375
7376     /* skip version + flags */
7377     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7378         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7379       goto corrupt_file;
7380
7381     if (stream->n_sample_syncs) {
7382       /* make sure there's enough data */
7383       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7384         goto corrupt_file;
7385     }
7386
7387     /* partial sync sample atom */
7388     if ((stream->stps_present =
7389             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7390                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7391       /* copy atom data into a new buffer for later use */
7392       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7393
7394       /* skip version + flags */
7395       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7396           !gst_byte_reader_get_uint32_be (&stream->stps,
7397               &stream->n_sample_partial_syncs))
7398         goto corrupt_file;
7399
7400       /* if there are no entries, the stss table contains the real
7401        * sync samples */
7402       if (stream->n_sample_partial_syncs) {
7403         /* make sure there's enough data */
7404         if (!qt_atom_parser_has_chunks (&stream->stps,
7405                 stream->n_sample_partial_syncs, 4))
7406           goto corrupt_file;
7407       }
7408     }
7409   }
7410
7411   /* sample size */
7412   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7413     goto no_samples;
7414
7415   /* copy atom data into a new buffer for later use */
7416   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7417
7418   /* skip version + flags */
7419   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7420       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7421     goto corrupt_file;
7422
7423   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7424     goto corrupt_file;
7425
7426   if (!stream->n_samples)
7427     goto no_samples;
7428
7429   /* sample-to-chunk atom */
7430   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7431     goto corrupt_file;
7432
7433   /* copy atom data into a new buffer for later use */
7434   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7435
7436   /* skip version + flags */
7437   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7438       !gst_byte_reader_get_uint32_be (&stream->stsc,
7439           &stream->n_samples_per_chunk))
7440     goto corrupt_file;
7441
7442   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7443       stream->n_samples_per_chunk);
7444
7445   /* make sure there's enough data */
7446   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7447           12))
7448     goto corrupt_file;
7449
7450
7451   /* chunk offset */
7452   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7453     stream->co_size = sizeof (guint32);
7454   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7455           &stream->stco))
7456     stream->co_size = sizeof (guint64);
7457   else
7458     goto corrupt_file;
7459
7460   /* copy atom data into a new buffer for later use */
7461   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7462
7463   /* skip version + flags */
7464   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7465     goto corrupt_file;
7466
7467   /* chunks_are_samples == TRUE means treat chunks as samples */
7468   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7469   if (stream->chunks_are_samples) {
7470     /* treat chunks as samples */
7471     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7472       goto corrupt_file;
7473   } else {
7474     /* skip number of entries */
7475     if (!gst_byte_reader_skip (&stream->stco, 4))
7476       goto corrupt_file;
7477
7478     /* make sure there are enough data in the stsz atom */
7479     if (!stream->sample_size) {
7480       /* different sizes for each sample */
7481       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7482         goto corrupt_file;
7483     }
7484   }
7485
7486   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7487       stream->n_samples, (guint) sizeof (QtDemuxSample),
7488       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7489
7490   if (stream->n_samples >=
7491       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7492     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7493         "be larger than %uMB (broken file?)", stream->n_samples,
7494         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7495     return FALSE;
7496   }
7497
7498   g_assert (stream->samples == NULL);
7499   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7500   if (!stream->samples) {
7501     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7502         stream->n_samples);
7503     return FALSE;
7504   }
7505
7506   /* composition time-to-sample */
7507   if ((stream->ctts_present =
7508           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7509               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7510     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7511
7512     /* copy atom data into a new buffer for later use */
7513     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7514
7515     /* skip version + flags */
7516     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7517         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7518             &stream->n_composition_times))
7519       goto corrupt_file;
7520
7521     /* make sure there's enough data */
7522     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7523             4 + 4))
7524       goto corrupt_file;
7525
7526     /* This is optional, if missing we iterate the ctts */
7527     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7528       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7529           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7530         g_free ((gpointer) cslg.data);
7531         goto corrupt_file;
7532       }
7533     } else {
7534       gint32 cslg_least = 0;
7535       guint num_entries, pos;
7536       gint i;
7537
7538       pos = gst_byte_reader_get_pos (&stream->ctts);
7539       num_entries = stream->n_composition_times;
7540
7541       stream->cslg_shift = 0;
7542
7543       for (i = 0; i < num_entries; i++) {
7544         gint32 offset;
7545
7546         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7547         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7548
7549         if (offset < cslg_least)
7550           cslg_least = offset;
7551       }
7552
7553       if (cslg_least < 0)
7554         stream->cslg_shift = ABS (cslg_least);
7555       else
7556         stream->cslg_shift = 0;
7557
7558       /* reset the reader so we can generate sample table */
7559       gst_byte_reader_set_pos (&stream->ctts, pos);
7560     }
7561   } else {
7562     /* Ensure the cslg_shift value is consistent so we can use it
7563      * unconditionnally to produce TS and Segment */
7564     stream->cslg_shift = 0;
7565   }
7566
7567   return TRUE;
7568
7569 corrupt_file:
7570   {
7571     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7572         (_("This file is corrupt and cannot be played.")), (NULL));
7573     return FALSE;
7574   }
7575 no_samples:
7576   {
7577     gst_qtdemux_stbl_free (stream);
7578     if (!qtdemux->fragmented) {
7579       /* not quite good */
7580       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7581       return FALSE;
7582     } else {
7583       /* may pick up samples elsewhere */
7584       return TRUE;
7585     }
7586   }
7587 }
7588
7589 /* collect samples from the next sample to be parsed up to sample @n for @stream
7590  * by reading the info from @stbl
7591  *
7592  * This code can be executed from both the streaming thread and the seeking
7593  * thread so it takes the object lock to protect itself
7594  */
7595 static gboolean
7596 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7597 {
7598   gint i, j, k;
7599   QtDemuxSample *samples, *first, *cur, *last;
7600   guint32 n_samples_per_chunk;
7601   guint32 n_samples;
7602
7603   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7604       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7605       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7606
7607   n_samples = stream->n_samples;
7608
7609   if (n >= n_samples)
7610     goto out_of_samples;
7611
7612   GST_OBJECT_LOCK (qtdemux);
7613   if (n <= stream->stbl_index)
7614     goto already_parsed;
7615
7616   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7617
7618   if (!stream->stsz.data) {
7619     /* so we already parsed and passed all the moov samples;
7620      * onto fragmented ones */
7621     g_assert (qtdemux->fragmented);
7622     goto done;
7623   }
7624
7625   /* pointer to the sample table */
7626   samples = stream->samples;
7627
7628   /* starts from -1, moves to the next sample index to parse */
7629   stream->stbl_index++;
7630
7631   /* keep track of the first and last sample to fill */
7632   first = &samples[stream->stbl_index];
7633   last = &samples[n];
7634
7635   if (!stream->chunks_are_samples) {
7636     /* set the sample sizes */
7637     if (stream->sample_size == 0) {
7638       /* different sizes for each sample */
7639       for (cur = first; cur <= last; cur++) {
7640         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7641         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7642             (guint) (cur - samples), cur->size);
7643       }
7644     } else {
7645       /* samples have the same size */
7646       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7647       for (cur = first; cur <= last; cur++)
7648         cur->size = stream->sample_size;
7649     }
7650   }
7651
7652   n_samples_per_chunk = stream->n_samples_per_chunk;
7653   cur = first;
7654
7655   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7656     guint32 last_chunk;
7657
7658     if (stream->stsc_chunk_index >= stream->last_chunk
7659         || stream->stsc_chunk_index < stream->first_chunk) {
7660       stream->first_chunk =
7661           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7662       stream->samples_per_chunk =
7663           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7664       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
7665
7666       /* chunk numbers are counted from 1 it seems */
7667       if (G_UNLIKELY (stream->first_chunk == 0))
7668         goto corrupt_file;
7669
7670       --stream->first_chunk;
7671
7672       /* the last chunk of each entry is calculated by taking the first chunk
7673        * of the next entry; except if there is no next, where we fake it with
7674        * INT_MAX */
7675       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
7676         stream->last_chunk = G_MAXUINT32;
7677       } else {
7678         stream->last_chunk =
7679             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
7680         if (G_UNLIKELY (stream->last_chunk == 0))
7681           goto corrupt_file;
7682
7683         --stream->last_chunk;
7684       }
7685
7686       GST_LOG_OBJECT (qtdemux,
7687           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
7688           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
7689
7690       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
7691         goto corrupt_file;
7692
7693       if (stream->last_chunk != G_MAXUINT32) {
7694         if (!qt_atom_parser_peek_sub (&stream->stco,
7695                 stream->first_chunk * stream->co_size,
7696                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
7697                 &stream->co_chunk))
7698           goto corrupt_file;
7699
7700       } else {
7701         stream->co_chunk = stream->stco;
7702         if (!gst_byte_reader_skip (&stream->co_chunk,
7703                 stream->first_chunk * stream->co_size))
7704           goto corrupt_file;
7705       }
7706
7707       stream->stsc_chunk_index = stream->first_chunk;
7708     }
7709
7710     last_chunk = stream->last_chunk;
7711
7712     if (stream->chunks_are_samples) {
7713       cur = &samples[stream->stsc_chunk_index];
7714
7715       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7716         if (j > n) {
7717           /* save state */
7718           stream->stsc_chunk_index = j;
7719           goto done;
7720         }
7721
7722         cur->offset =
7723             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
7724             stream->co_size);
7725
7726         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7727             "%" G_GUINT64_FORMAT, j, cur->offset);
7728
7729         if (stream->samples_per_frame * stream->bytes_per_frame) {
7730           cur->size =
7731               (stream->samples_per_chunk * stream->n_channels) /
7732               stream->samples_per_frame * stream->bytes_per_frame;
7733         } else {
7734           cur->size = stream->samples_per_chunk;
7735         }
7736
7737         GST_DEBUG_OBJECT (qtdemux,
7738             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7739             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7740                     stream->stco_sample_index)), cur->size);
7741
7742         cur->timestamp = stream->stco_sample_index;
7743         cur->duration = stream->samples_per_chunk;
7744         cur->keyframe = TRUE;
7745         cur++;
7746
7747         stream->stco_sample_index += stream->samples_per_chunk;
7748       }
7749       stream->stsc_chunk_index = j;
7750     } else {
7751       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7752         guint32 samples_per_chunk;
7753         guint64 chunk_offset;
7754
7755         if (!stream->stsc_sample_index
7756             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7757                 &stream->chunk_offset))
7758           goto corrupt_file;
7759
7760         samples_per_chunk = stream->samples_per_chunk;
7761         chunk_offset = stream->chunk_offset;
7762
7763         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7764           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7765               G_GUINT64_FORMAT " and size %d",
7766               (guint) (cur - samples), chunk_offset, cur->size);
7767
7768           cur->offset = chunk_offset;
7769           chunk_offset += cur->size;
7770           cur++;
7771
7772           if (G_UNLIKELY (cur > last)) {
7773             /* save state */
7774             stream->stsc_sample_index = k + 1;
7775             stream->chunk_offset = chunk_offset;
7776             stream->stsc_chunk_index = j;
7777             goto done2;
7778           }
7779         }
7780         stream->stsc_sample_index = 0;
7781       }
7782       stream->stsc_chunk_index = j;
7783     }
7784     stream->stsc_index++;
7785   }
7786
7787   if (stream->chunks_are_samples)
7788     goto ctts;
7789 done2:
7790   {
7791     guint32 n_sample_times;
7792
7793     n_sample_times = stream->n_sample_times;
7794     cur = first;
7795
7796     for (i = stream->stts_index; i < n_sample_times; i++) {
7797       guint32 stts_samples;
7798       gint32 stts_duration;
7799       gint64 stts_time;
7800
7801       if (stream->stts_sample_index >= stream->stts_samples
7802           || !stream->stts_sample_index) {
7803
7804         stream->stts_samples =
7805             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7806         stream->stts_duration =
7807             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7808
7809         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7810             i, stream->stts_samples, stream->stts_duration);
7811
7812         stream->stts_sample_index = 0;
7813       }
7814
7815       stts_samples = stream->stts_samples;
7816       stts_duration = stream->stts_duration;
7817       stts_time = stream->stts_time;
7818
7819       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7820         GST_DEBUG_OBJECT (qtdemux,
7821             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7822             (guint) (cur - samples), j,
7823             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7824
7825         cur->timestamp = stts_time;
7826         cur->duration = stts_duration;
7827
7828         /* avoid 32-bit wrap-around,
7829          * but still mind possible 'negative' duration */
7830         stts_time += (gint64) stts_duration;
7831         cur++;
7832
7833         if (G_UNLIKELY (cur > last)) {
7834           /* save values */
7835           stream->stts_time = stts_time;
7836           stream->stts_sample_index = j + 1;
7837           goto done3;
7838         }
7839       }
7840       stream->stts_sample_index = 0;
7841       stream->stts_time = stts_time;
7842       stream->stts_index++;
7843     }
7844     /* fill up empty timestamps with the last timestamp, this can happen when
7845      * the last samples do not decode and so we don't have timestamps for them.
7846      * We however look at the last timestamp to estimate the track length so we
7847      * need something in here. */
7848     for (; cur < last; cur++) {
7849       GST_DEBUG_OBJECT (qtdemux,
7850           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7851           (guint) (cur - samples),
7852           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7853       cur->timestamp = stream->stts_time;
7854       cur->duration = -1;
7855     }
7856   }
7857 done3:
7858   {
7859     /* sample sync, can be NULL */
7860     if (stream->stss_present == TRUE) {
7861       guint32 n_sample_syncs;
7862
7863       n_sample_syncs = stream->n_sample_syncs;
7864
7865       if (!n_sample_syncs) {
7866         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7867         stream->all_keyframe = TRUE;
7868       } else {
7869         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7870           /* note that the first sample is index 1, not 0 */
7871           guint32 index;
7872
7873           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7874
7875           if (G_LIKELY (index > 0 && index <= n_samples)) {
7876             index -= 1;
7877             samples[index].keyframe = TRUE;
7878             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7879             /* and exit if we have enough samples */
7880             if (G_UNLIKELY (index >= n)) {
7881               i++;
7882               break;
7883             }
7884           }
7885         }
7886         /* save state */
7887         stream->stss_index = i;
7888       }
7889
7890       /* stps marks partial sync frames like open GOP I-Frames */
7891       if (stream->stps_present == TRUE) {
7892         guint32 n_sample_partial_syncs;
7893
7894         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7895
7896         /* if there are no entries, the stss table contains the real
7897          * sync samples */
7898         if (n_sample_partial_syncs) {
7899           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7900             /* note that the first sample is index 1, not 0 */
7901             guint32 index;
7902
7903             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7904
7905             if (G_LIKELY (index > 0 && index <= n_samples)) {
7906               index -= 1;
7907               samples[index].keyframe = TRUE;
7908               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7909               /* and exit if we have enough samples */
7910               if (G_UNLIKELY (index >= n)) {
7911                 i++;
7912                 break;
7913               }
7914             }
7915           }
7916           /* save state */
7917           stream->stps_index = i;
7918         }
7919       }
7920     } else {
7921       /* no stss, all samples are keyframes */
7922       stream->all_keyframe = TRUE;
7923       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7924     }
7925   }
7926
7927 ctts:
7928   /* composition time to sample */
7929   if (stream->ctts_present == TRUE) {
7930     guint32 n_composition_times;
7931     guint32 ctts_count;
7932     gint32 ctts_soffset;
7933
7934     /* Fill in the pts_offsets */
7935     cur = first;
7936     n_composition_times = stream->n_composition_times;
7937
7938     for (i = stream->ctts_index; i < n_composition_times; i++) {
7939       if (stream->ctts_sample_index >= stream->ctts_count
7940           || !stream->ctts_sample_index) {
7941         stream->ctts_count =
7942             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7943         stream->ctts_soffset =
7944             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7945         stream->ctts_sample_index = 0;
7946       }
7947
7948       ctts_count = stream->ctts_count;
7949       ctts_soffset = stream->ctts_soffset;
7950
7951       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7952         cur->pts_offset = ctts_soffset;
7953         cur++;
7954
7955         if (G_UNLIKELY (cur > last)) {
7956           /* save state */
7957           stream->ctts_sample_index = j + 1;
7958           goto done;
7959         }
7960       }
7961       stream->ctts_sample_index = 0;
7962       stream->ctts_index++;
7963     }
7964   }
7965 done:
7966   stream->stbl_index = n;
7967   /* if index has been completely parsed, free data that is no-longer needed */
7968   if (n + 1 == stream->n_samples) {
7969     gst_qtdemux_stbl_free (stream);
7970     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
7971     if (qtdemux->pullbased) {
7972       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
7973       while (n + 1 == stream->n_samples)
7974         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7975           break;
7976     }
7977   }
7978   GST_OBJECT_UNLOCK (qtdemux);
7979
7980   return TRUE;
7981
7982   /* SUCCESS */
7983 already_parsed:
7984   {
7985     GST_LOG_OBJECT (qtdemux,
7986         "Tried to parse up to sample %u but this sample has already been parsed",
7987         n);
7988     /* if fragmented, there may be more */
7989     if (qtdemux->fragmented && n == stream->stbl_index)
7990       goto done;
7991     GST_OBJECT_UNLOCK (qtdemux);
7992     return TRUE;
7993   }
7994   /* ERRORS */
7995 out_of_samples:
7996   {
7997     GST_LOG_OBJECT (qtdemux,
7998         "Tried to parse up to sample %u but there are only %u samples", n + 1,
7999         stream->n_samples);
8000     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8001         (_("This file is corrupt and cannot be played.")), (NULL));
8002     return FALSE;
8003   }
8004 corrupt_file:
8005   {
8006     GST_OBJECT_UNLOCK (qtdemux);
8007     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8008         (_("This file is corrupt and cannot be played.")), (NULL));
8009     return FALSE;
8010   }
8011 }
8012
8013 /* collect all segment info for @stream.
8014  */
8015 static gboolean
8016 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8017     GNode * trak)
8018 {
8019   GNode *edts;
8020   /* accept edts if they contain gaps at start and there is only
8021    * one media segment */
8022   gboolean allow_pushbased_edts = TRUE;
8023   gint media_segments_count = 0;
8024
8025   /* parse and prepare segment info from the edit list */
8026   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8027   stream->n_segments = 0;
8028   stream->segments = NULL;
8029   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8030     GNode *elst;
8031     gint n_segments;
8032     gint i, count;
8033     guint64 time;
8034     GstClockTime stime;
8035     guint8 *buffer;
8036
8037     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8038     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8039       goto done;
8040
8041     buffer = elst->data;
8042
8043     n_segments = QT_UINT32 (buffer + 12);
8044
8045     /* we might allocate a bit too much, at least allocate 1 segment */
8046     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8047
8048     /* segments always start from 0 */
8049     time = 0;
8050     stime = 0;
8051     count = 0;
8052     for (i = 0; i < n_segments; i++) {
8053       guint64 duration;
8054       guint64 media_time;
8055       QtDemuxSegment *segment;
8056       guint32 rate_int;
8057       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8058
8059       media_time = QT_UINT32 (buffer + 20 + i * 12);
8060       duration = QT_UINT32 (buffer + 16 + i * 12);
8061
8062       if (media_time != G_MAXUINT32)
8063         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8064
8065       segment = &stream->segments[count++];
8066
8067       /* time and duration expressed in global timescale */
8068       segment->time = stime;
8069       /* add non scaled values so we don't cause roundoff errors */
8070       if (duration) {
8071         time += duration;
8072         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8073         segment->duration = stime - segment->time;
8074       } else {
8075         /* zero duration does not imply media_start == media_stop
8076          * but, only specify media_start.*/
8077         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8078         if (GST_CLOCK_TIME_IS_VALID (stime) && media_time != G_MAXUINT32
8079             && stime >= media_start) {
8080           segment->duration = stime - media_start;
8081         } else {
8082           segment->duration = GST_CLOCK_TIME_NONE;
8083         }
8084       }
8085       segment->stop_time = stime;
8086
8087       segment->trak_media_start = media_time;
8088       /* media_time expressed in stream timescale */
8089       if (media_time != G_MAXUINT32) {
8090         segment->media_start = media_start;
8091         segment->media_stop = segment->media_start + segment->duration;
8092         media_segments_count++;
8093       } else {
8094         segment->media_start = GST_CLOCK_TIME_NONE;
8095         segment->media_stop = GST_CLOCK_TIME_NONE;
8096       }
8097       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
8098
8099       if (rate_int <= 1) {
8100         /* 0 is not allowed, some programs write 1 instead of the floating point
8101          * value */
8102         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8103             rate_int);
8104         segment->rate = 1;
8105       } else {
8106         segment->rate = rate_int / 65536.0;
8107       }
8108
8109       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8110           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8111           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8112           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8113           i, GST_TIME_ARGS (segment->time),
8114           GST_TIME_ARGS (segment->duration),
8115           GST_TIME_ARGS (segment->media_start), media_time,
8116           GST_TIME_ARGS (segment->media_stop),
8117           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8118           stream->timescale);
8119       if (segment->stop_time > qtdemux->segment.stop) {
8120         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8121             " extends to %" GST_TIME_FORMAT
8122             " past the end of the file duration %" GST_TIME_FORMAT
8123             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8124             GST_TIME_ARGS (qtdemux->segment.stop));
8125         qtdemux->segment.stop = segment->stop_time;
8126       }
8127     }
8128     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8129     stream->n_segments = count;
8130     if (media_segments_count != 1)
8131       allow_pushbased_edts = FALSE;
8132   }
8133 done:
8134
8135   /* push based does not handle segments, so act accordingly here,
8136    * and warn if applicable */
8137   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8138     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8139     /* remove and use default one below, we stream like it anyway */
8140     g_free (stream->segments);
8141     stream->segments = NULL;
8142     stream->n_segments = 0;
8143   }
8144
8145   /* no segments, create one to play the complete trak */
8146   if (stream->n_segments == 0) {
8147     GstClockTime stream_duration =
8148         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8149
8150     if (stream->segments == NULL)
8151       stream->segments = g_new (QtDemuxSegment, 1);
8152
8153     /* represent unknown our way */
8154     if (stream_duration == 0)
8155       stream_duration = GST_CLOCK_TIME_NONE;
8156
8157     stream->segments[0].time = 0;
8158     stream->segments[0].stop_time = stream_duration;
8159     stream->segments[0].duration = stream_duration;
8160     stream->segments[0].media_start = 0;
8161     stream->segments[0].media_stop = stream_duration;
8162     stream->segments[0].rate = 1.0;
8163     stream->segments[0].trak_media_start = 0;
8164
8165     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8166         GST_TIME_ARGS (stream_duration));
8167     stream->n_segments = 1;
8168     stream->dummy_segment = TRUE;
8169   }
8170   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8171
8172   return TRUE;
8173 }
8174
8175 /*
8176  * Parses the stsd atom of a svq3 trak looking for
8177  * the SMI and gama atoms.
8178  */
8179 static void
8180 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8181     guint8 ** gamma, GstBuffer ** seqh)
8182 {
8183   guint8 *_gamma = NULL;
8184   GstBuffer *_seqh = NULL;
8185   guint8 *stsd_data = stsd->data;
8186   guint32 length = QT_UINT32 (stsd_data);
8187   guint16 version;
8188
8189   if (length < 32) {
8190     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8191     goto end;
8192   }
8193
8194   stsd_data += 32;
8195   length -= 32;
8196   version = QT_UINT16 (stsd_data);
8197   if (version == 3) {
8198     if (length >= 70) {
8199       length -= 70;
8200       stsd_data += 70;
8201       while (length > 8) {
8202         guint32 fourcc, size;
8203         guint8 *data;
8204         size = QT_UINT32 (stsd_data);
8205         fourcc = QT_FOURCC (stsd_data + 4);
8206         data = stsd_data + 8;
8207
8208         if (size == 0) {
8209           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8210               "svq3 atom parsing");
8211           goto end;
8212         }
8213
8214         switch (fourcc) {
8215           case FOURCC_gama:{
8216             if (size == 12) {
8217               _gamma = data;
8218             } else {
8219               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8220                   " for gama atom, expected 12", size);
8221             }
8222             break;
8223           }
8224           case FOURCC_SMI_:{
8225             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8226               guint32 seqh_size;
8227               if (_seqh != NULL) {
8228                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8229                     " found, ignoring");
8230               } else {
8231                 seqh_size = QT_UINT32 (data + 4);
8232                 if (seqh_size > 0) {
8233                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8234                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8235                 }
8236               }
8237             }
8238             break;
8239           }
8240           default:{
8241             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8242                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8243           }
8244         }
8245
8246         if (size <= length) {
8247           length -= size;
8248           stsd_data += size;
8249         }
8250       }
8251     } else {
8252       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8253     }
8254   } else {
8255     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8256         G_GUINT16_FORMAT, version);
8257     goto end;
8258   }
8259
8260 end:
8261   if (gamma) {
8262     *gamma = _gamma;
8263   }
8264   if (seqh) {
8265     *seqh = _seqh;
8266   } else if (_seqh) {
8267     gst_buffer_unref (_seqh);
8268   }
8269 }
8270
8271 static gchar *
8272 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8273 {
8274   GNode *dinf;
8275   GstByteReader dref;
8276   gchar *uri = NULL;
8277
8278   /*
8279    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8280    * atom that might contain a 'data' atom with the rtsp uri.
8281    * This case was reported in bug #597497, some info about
8282    * the hndl atom can be found in TN1195
8283    */
8284   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8285   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8286
8287   if (dinf) {
8288     guint32 dref_num_entries = 0;
8289     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8290         gst_byte_reader_skip (&dref, 4) &&
8291         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8292       gint i;
8293
8294       /* search dref entries for hndl atom */
8295       for (i = 0; i < dref_num_entries; i++) {
8296         guint32 size = 0, type;
8297         guint8 string_len = 0;
8298         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8299             qt_atom_parser_get_fourcc (&dref, &type)) {
8300           if (type == FOURCC_hndl) {
8301             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8302
8303             /* skip data reference handle bytes and the
8304              * following pascal string and some extra 4
8305              * bytes I have no idea what are */
8306             if (!gst_byte_reader_skip (&dref, 4) ||
8307                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8308                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8309               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8310               break;
8311             }
8312
8313             /* iterate over the atoms to find the data atom */
8314             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8315               guint32 atom_size;
8316               guint32 atom_type;
8317
8318               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8319                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8320                 if (atom_type == FOURCC_data) {
8321                   const guint8 *uri_aux = NULL;
8322
8323                   /* found the data atom that might contain the rtsp uri */
8324                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8325                       "hndl atom, interpreting it as an URI");
8326                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8327                           &uri_aux)) {
8328                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8329                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8330                     else
8331                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8332                           "didn't contain a rtsp address");
8333                   } else {
8334                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8335                         "atom contents");
8336                   }
8337                   break;
8338                 }
8339                 /* skipping to the next entry */
8340                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8341                   break;
8342               } else {
8343                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8344                     "atom header");
8345                 break;
8346               }
8347             }
8348             break;
8349           }
8350           /* skip to the next entry */
8351           if (!gst_byte_reader_skip (&dref, size - 8))
8352             break;
8353         } else {
8354           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8355         }
8356       }
8357       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8358     }
8359   }
8360   return uri;
8361 }
8362
8363 #define AMR_NB_ALL_MODES        0x81ff
8364 #define AMR_WB_ALL_MODES        0x83ff
8365 static guint
8366 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8367 {
8368   /* The 'damr' atom is of the form:
8369    *
8370    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8371    *    32 b       8 b          16 b           8 b                 8 b
8372    *
8373    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8374    * represents the highest mode used in the stream (and thus the maximum
8375    * bitrate), with a couple of special cases as seen below.
8376    */
8377
8378   /* Map of frame type ID -> bitrate */
8379   static const guint nb_bitrates[] = {
8380     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8381   };
8382   static const guint wb_bitrates[] = {
8383     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8384   };
8385   GstMapInfo map;
8386   gsize max_mode;
8387   guint16 mode_set;
8388
8389   gst_buffer_map (buf, &map, GST_MAP_READ);
8390
8391   if (map.size != 0x11) {
8392     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8393     goto bad_data;
8394   }
8395
8396   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8397     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8398         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8399     goto bad_data;
8400   }
8401
8402   mode_set = QT_UINT16 (map.data + 13);
8403
8404   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8405     max_mode = 7 + (wb ? 1 : 0);
8406   else
8407     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8408     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8409
8410   if (max_mode == -1) {
8411     GST_DEBUG ("No mode indication was found (mode set) = %x",
8412         (guint) mode_set);
8413     goto bad_data;
8414   }
8415
8416   gst_buffer_unmap (buf, &map);
8417   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8418
8419 bad_data:
8420   gst_buffer_unmap (buf, &map);
8421   return 0;
8422 }
8423
8424 static gboolean
8425 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8426     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8427 {
8428   /*
8429    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8430    * [0 1 2]
8431    * [3 4 5]
8432    * [6 7 8]
8433    */
8434
8435   if (gst_byte_reader_get_remaining (reader) < 36)
8436     return FALSE;
8437
8438   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8439   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8440   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8441   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8442   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8443   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8444   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8445   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8446   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8447
8448   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8449   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8450       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8451       matrix[2] & 0xFF);
8452   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8453       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8454       matrix[5] & 0xFF);
8455   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8456       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8457       matrix[8] & 0xFF);
8458
8459   return TRUE;
8460 }
8461
8462 static void
8463 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8464     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8465 {
8466
8467 /* [a b c]
8468  * [d e f]
8469  * [g h i]
8470  *
8471  * This macro will only compare value abdegh, it expects cfi to have already
8472  * been checked
8473  */
8474 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8475                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8476
8477   /* only handle the cases where the last column has standard values */
8478   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8479     const gchar *rotation_tag = NULL;
8480
8481     /* no rotation needed */
8482     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8483       /* NOP */
8484     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8485       rotation_tag = "rotate-90";
8486     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8487       rotation_tag = "rotate-180";
8488     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8489       rotation_tag = "rotate-270";
8490     } else {
8491       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8492     }
8493
8494     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8495         rotation_tag);
8496     if (rotation_tag != NULL) {
8497       if (*taglist == NULL)
8498         *taglist = gst_tag_list_new_empty ();
8499       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8500           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8501     }
8502   } else {
8503     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8504   }
8505 }
8506
8507 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8508  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8509  * Common Encryption (cenc), the function will also parse the tenc box (defined
8510  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8511  * (typically an enc[v|a|t|s] sample entry); the function will set
8512  * @original_fmt to the fourcc of the original unencrypted stream format.
8513  * Returns TRUE if successful; FALSE otherwise. */
8514 static gboolean
8515 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8516     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8517 {
8518   GNode *sinf;
8519   GNode *frma;
8520   GNode *schm;
8521   GNode *schi;
8522
8523   g_return_val_if_fail (qtdemux != NULL, FALSE);
8524   g_return_val_if_fail (stream != NULL, FALSE);
8525   g_return_val_if_fail (container != NULL, FALSE);
8526   g_return_val_if_fail (original_fmt != NULL, FALSE);
8527
8528   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8529   if (G_UNLIKELY (!sinf)) {
8530     if (stream->protection_scheme_type == FOURCC_cenc) {
8531       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8532           "mandatory for Common Encryption");
8533       return FALSE;
8534     }
8535     return TRUE;
8536   }
8537
8538   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8539   if (G_UNLIKELY (!frma)) {
8540     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8541     return FALSE;
8542   }
8543
8544   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8545   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8546       GST_FOURCC_ARGS (*original_fmt));
8547
8548   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8549   if (!schm) {
8550     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8551     return FALSE;
8552   }
8553   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8554   stream->protection_scheme_version =
8555       QT_UINT32 ((const guint8 *) schm->data + 16);
8556
8557   GST_DEBUG_OBJECT (qtdemux,
8558       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8559       "protection_scheme_version: %#010x",
8560       GST_FOURCC_ARGS (stream->protection_scheme_type),
8561       stream->protection_scheme_version);
8562
8563   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8564   if (!schi) {
8565     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8566     return FALSE;
8567   }
8568   if (stream->protection_scheme_type == FOURCC_cenc) {
8569     QtDemuxCencSampleSetInfo *info;
8570     GNode *tenc;
8571     const guint8 *tenc_data;
8572     guint32 isEncrypted;
8573     guint8 iv_size;
8574     const guint8 *default_kid;
8575     GstBuffer *kid_buf;
8576
8577     if (G_UNLIKELY (!stream->protection_scheme_info))
8578       stream->protection_scheme_info =
8579           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8580
8581     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8582
8583     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8584     if (!tenc) {
8585       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8586           "which is mandatory for Common Encryption");
8587       return FALSE;
8588     }
8589     tenc_data = (const guint8 *) tenc->data + 12;
8590     isEncrypted = QT_UINT24 (tenc_data);
8591     iv_size = QT_UINT8 (tenc_data + 3);
8592     default_kid = (tenc_data + 4);
8593     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8594     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8595     if (info->default_properties)
8596       gst_structure_free (info->default_properties);
8597     info->default_properties =
8598         gst_structure_new ("application/x-cenc",
8599         "iv_size", G_TYPE_UINT, iv_size,
8600         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8601         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8602     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8603         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8604     gst_buffer_unref (kid_buf);
8605   }
8606   return TRUE;
8607 }
8608
8609 /* parse the traks.
8610  * With each track we associate a new QtDemuxStream that contains all the info
8611  * about the trak.
8612  * traks that do not decode to something (like strm traks) will not have a pad.
8613  */
8614 static gboolean
8615 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8616 {
8617   GstByteReader tkhd;
8618   int offset;
8619   GNode *mdia;
8620   GNode *mdhd;
8621   GNode *hdlr;
8622   GNode *minf;
8623   GNode *stbl;
8624   GNode *stsd;
8625   GNode *mp4a;
8626   GNode *mp4v;
8627   GNode *wave;
8628   GNode *esds;
8629   GNode *pasp;
8630   GNode *tref;
8631   GNode *udta;
8632   GNode *svmi;
8633
8634   QtDemuxStream *stream = NULL;
8635   gboolean new_stream = FALSE;
8636   gchar *codec = NULL;
8637   const guint8 *stsd_data;
8638   guint16 lang_code;            /* quicktime lang code or packed iso code */
8639   guint32 version;
8640   guint32 tkhd_flags = 0;
8641   guint8 tkhd_version = 0;
8642   guint32 fourcc;
8643   guint value_size, stsd_len, len;
8644   guint32 track_id;
8645   guint32 dummy;
8646
8647   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8648
8649   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8650       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8651       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8652     goto corrupt_file;
8653
8654   /* pick between 64 or 32 bits */
8655   value_size = tkhd_version == 1 ? 8 : 4;
8656   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8657       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8658     goto corrupt_file;
8659
8660   if (!qtdemux->got_moov) {
8661     if (qtdemux_find_stream (qtdemux, track_id))
8662       goto existing_stream;
8663     stream = _create_stream ();
8664     stream->track_id = track_id;
8665     new_stream = TRUE;
8666   } else {
8667     stream = qtdemux_find_stream (qtdemux, track_id);
8668     if (!stream) {
8669       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
8670       goto skip_track;
8671     }
8672
8673     /* flush samples data from this track from previous moov */
8674     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
8675     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
8676   }
8677   /* need defaults for fragments */
8678   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
8679
8680   if (stream->pending_tags == NULL)
8681     stream->pending_tags = gst_tag_list_new_empty ();
8682
8683   if ((tkhd_flags & 1) == 0)
8684     stream->disabled = TRUE;
8685
8686   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
8687       tkhd_version, tkhd_flags, stream->track_id);
8688
8689   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
8690     goto corrupt_file;
8691
8692   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
8693     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
8694     if (qtdemux->major_brand != FOURCC_mjp2 ||
8695         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
8696       goto corrupt_file;
8697   }
8698
8699   len = QT_UINT32 ((guint8 *) mdhd->data);
8700   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
8701   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
8702   if (version == 0x01000000) {
8703     if (len < 38)
8704       goto corrupt_file;
8705     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
8706     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
8707     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
8708   } else {
8709     if (len < 30)
8710       goto corrupt_file;
8711     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
8712     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
8713     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
8714   }
8715
8716   if (lang_code < 0x400) {
8717     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
8718   } else if (lang_code == 0x7fff) {
8719     stream->lang_id[0] = 0;     /* unspecified */
8720   } else {
8721     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
8722     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
8723     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
8724     stream->lang_id[3] = 0;
8725   }
8726
8727   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
8728       stream->timescale);
8729   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
8730       stream->duration);
8731   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
8732       lang_code, stream->lang_id);
8733
8734   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
8735     goto corrupt_file;
8736
8737   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
8738     /* chapters track reference */
8739     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
8740     if (chap) {
8741       gsize length = GST_READ_UINT32_BE (chap->data);
8742       if (qtdemux->chapters_track_id)
8743         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
8744
8745       if (length >= 12) {
8746         qtdemux->chapters_track_id =
8747             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
8748       }
8749     }
8750   }
8751
8752   /* fragmented files may have bogus duration in moov */
8753   if (!qtdemux->fragmented &&
8754       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
8755     guint64 tdur1, tdur2;
8756
8757     /* don't overflow */
8758     tdur1 = stream->timescale * (guint64) qtdemux->duration;
8759     tdur2 = qtdemux->timescale * (guint64) stream->duration;
8760
8761     /* HACK:
8762      * some of those trailers, nowadays, have prologue images that are
8763      * themselves vide tracks as well. I haven't really found a way to
8764      * identify those yet, except for just looking at their duration. */
8765     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
8766       GST_WARNING_OBJECT (qtdemux,
8767           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
8768           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
8769           "found, assuming preview image or something; skipping track",
8770           stream->duration, stream->timescale, qtdemux->duration,
8771           qtdemux->timescale);
8772       if (new_stream)
8773         gst_qtdemux_stream_free (qtdemux, stream);
8774       return TRUE;
8775     }
8776   }
8777
8778   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
8779     goto corrupt_file;
8780
8781   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
8782       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
8783
8784   len = QT_UINT32 ((guint8 *) hdlr->data);
8785   if (len >= 20)
8786     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
8787   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
8788       GST_FOURCC_ARGS (stream->subtype));
8789
8790   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
8791     goto corrupt_file;
8792
8793   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
8794     goto corrupt_file;
8795
8796   /*parse svmi header if existing */
8797   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
8798   if (svmi) {
8799     len = QT_UINT32 ((guint8 *) svmi->data);
8800     version = QT_UINT32 ((guint8 *) svmi->data + 8);
8801     if (!version) {
8802       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
8803       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
8804       guint8 frame_type, frame_layout;
8805
8806       /* MPEG-A stereo video */
8807       if (qtdemux->major_brand == FOURCC_ss02)
8808         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
8809
8810       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
8811       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
8812       switch (frame_type) {
8813         case 0:
8814           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
8815           break;
8816         case 1:
8817           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
8818           break;
8819         case 2:
8820           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
8821           break;
8822         case 3:
8823           /* mode 3 is primary/secondary view sequence, ie
8824            * left/right views in separate tracks. See section 7.2
8825            * of ISO/IEC 23000-11:2009 */
8826           GST_FIXME_OBJECT (qtdemux,
8827               "Implement stereo video in separate streams");
8828       }
8829
8830       if ((frame_layout & 0x1) == 0)
8831         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
8832
8833       GST_LOG_OBJECT (qtdemux,
8834           "StereoVideo: composition type: %u, is_left_first: %u",
8835           frame_type, frame_layout);
8836       stream->multiview_mode = mode;
8837       stream->multiview_flags = flags;
8838     }
8839   }
8840
8841   /* parse stsd */
8842   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
8843     goto corrupt_file;
8844   stsd_data = (const guint8 *) stsd->data;
8845
8846   /* stsd should at least have one entry */
8847   stsd_len = QT_UINT32 (stsd_data);
8848   if (stsd_len < 24) {
8849     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
8850     if (stream->subtype == FOURCC_vivo) {
8851       if (new_stream)
8852         gst_qtdemux_stream_free (qtdemux, stream);
8853       return TRUE;
8854     } else {
8855       goto corrupt_file;
8856     }
8857   }
8858
8859   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
8860
8861   /* and that entry should fit within stsd */
8862   len = QT_UINT32 (stsd_data + 16);
8863   if (len > stsd_len + 16)
8864     goto corrupt_file;
8865
8866   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8867   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8868       GST_FOURCC_ARGS (stream->fourcc));
8869   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8870
8871   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
8872     goto error_encrypted;
8873
8874   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
8875     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
8876     stream->protected = TRUE;
8877     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
8878       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
8879   }
8880
8881   if (stream->subtype == FOURCC_vide) {
8882     guint32 w = 0, h = 0;
8883     gboolean gray;
8884     gint depth, palette_size, palette_count;
8885     guint32 matrix[9];
8886     guint32 *palette_data = NULL;
8887
8888     stream->sampled = TRUE;
8889
8890     /* version 1 uses some 64-bit ints */
8891     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8892       goto corrupt_file;
8893
8894     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8895       goto corrupt_file;
8896
8897     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8898         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8899       goto corrupt_file;
8900
8901     stream->display_width = w >> 16;
8902     stream->display_height = h >> 16;
8903
8904     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8905         &stream->pending_tags);
8906
8907     offset = 16;
8908     if (len < 86)
8909       goto corrupt_file;
8910
8911     stream->width = QT_UINT16 (stsd_data + offset + 32);
8912     stream->height = QT_UINT16 (stsd_data + offset + 34);
8913     stream->fps_n = 0;          /* this is filled in later */
8914     stream->fps_d = 0;          /* this is filled in later */
8915     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8916     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8917
8918     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8919         stream->width, stream->height, stream->bits_per_sample,
8920         stream->color_table_id);
8921
8922     depth = stream->bits_per_sample;
8923
8924     /* more than 32 bits means grayscale */
8925     gray = (depth > 32);
8926     /* low 32 bits specify the depth  */
8927     depth &= 0x1F;
8928
8929     /* different number of palette entries is determined by depth. */
8930     palette_count = 0;
8931     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8932       palette_count = (1 << depth);
8933     palette_size = palette_count * 4;
8934
8935     if (stream->color_table_id) {
8936       switch (palette_count) {
8937         case 0:
8938           break;
8939         case 2:
8940           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8941           break;
8942         case 4:
8943           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8944           break;
8945         case 16:
8946           if (gray)
8947             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8948           else
8949             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8950           break;
8951         case 256:
8952           if (gray)
8953             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8954           else
8955             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8956           break;
8957         default:
8958           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8959               (_("The video in this file might not play correctly.")),
8960               ("unsupported palette depth %d", depth));
8961           break;
8962       }
8963     } else {
8964       gint i, j, start, end;
8965
8966       if (len < 94)
8967         goto corrupt_file;
8968
8969       /* read table */
8970       start = QT_UINT32 (stsd_data + offset + 86);
8971       palette_count = QT_UINT16 (stsd_data + offset + 90);
8972       end = QT_UINT16 (stsd_data + offset + 92);
8973
8974       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8975           start, end, palette_count);
8976
8977       if (end > 255)
8978         end = 255;
8979       if (start > end)
8980         start = end;
8981
8982       if (len < 94 + (end - start) * 8)
8983         goto corrupt_file;
8984
8985       /* palette is always the same size */
8986       palette_data = g_malloc0 (256 * 4);
8987       palette_size = 256 * 4;
8988
8989       for (j = 0, i = start; i <= end; j++, i++) {
8990         guint32 a, r, g, b;
8991
8992         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
8993         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
8994         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
8995         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
8996
8997         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
8998             (g & 0xff00) | (b >> 8);
8999       }
9000     }
9001
9002     if (stream->caps)
9003       gst_caps_unref (stream->caps);
9004
9005     stream->caps =
9006         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9007     if (G_UNLIKELY (!stream->caps)) {
9008       g_free (palette_data);
9009       goto unknown_stream;
9010     }
9011
9012     if (codec) {
9013       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9014           GST_TAG_VIDEO_CODEC, codec, NULL);
9015       g_free (codec);
9016       codec = NULL;
9017     }
9018
9019
9020     if (palette_data) {
9021       GstStructure *s;
9022
9023       if (stream->rgb8_palette)
9024         gst_memory_unref (stream->rgb8_palette);
9025       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9026           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9027
9028       s = gst_caps_get_structure (stream->caps, 0);
9029
9030       /* non-raw video has a palette_data property. raw video has the palette as
9031        * an extra plane that we append to the output buffers before we push
9032        * them*/
9033       if (!gst_structure_has_name (s, "video/x-raw")) {
9034         GstBuffer *palette;
9035
9036         palette = gst_buffer_new ();
9037         gst_buffer_append_memory (palette, stream->rgb8_palette);
9038         stream->rgb8_palette = NULL;
9039
9040         gst_caps_set_simple (stream->caps, "palette_data",
9041             GST_TYPE_BUFFER, palette, NULL);
9042         gst_buffer_unref (palette);
9043       }
9044     } else if (palette_count != 0) {
9045       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9046           (NULL), ("Unsupported palette depth %d", depth));
9047     }
9048
9049     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9050         QT_UINT16 (stsd_data + offset + 48));
9051
9052     esds = NULL;
9053     pasp = NULL;
9054     /* pick 'the' stsd child */
9055     if (!stream->protected)
9056       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9057     else
9058       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9059
9060     if (mp4v) {
9061       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9062       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9063     }
9064
9065     if (pasp) {
9066       const guint8 *pasp_data = (const guint8 *) pasp->data;
9067
9068       stream->par_w = QT_UINT32 (pasp_data + 8);
9069       stream->par_h = QT_UINT32 (pasp_data + 12);
9070     } else {
9071       stream->par_w = 0;
9072       stream->par_h = 0;
9073     }
9074
9075     if (esds) {
9076       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9077     } else {
9078       switch (fourcc) {
9079         case FOURCC_H264:
9080         case FOURCC_avc1:
9081         case FOURCC_avc3:
9082         {
9083           gint len = QT_UINT32 (stsd_data) - 0x66;
9084           const guint8 *avc_data = stsd_data + 0x66;
9085
9086           /* find avcC */
9087           while (len >= 0x8) {
9088             gint size;
9089
9090             if (QT_UINT32 (avc_data) <= len)
9091               size = QT_UINT32 (avc_data) - 0x8;
9092             else
9093               size = len - 0x8;
9094
9095             if (size < 1)
9096               /* No real data, so break out */
9097               break;
9098
9099             switch (QT_FOURCC (avc_data + 0x4)) {
9100               case FOURCC_avcC:
9101               {
9102                 /* parse, if found */
9103                 GstBuffer *buf;
9104
9105                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9106
9107                 /* First 4 bytes are the length of the atom, the next 4 bytes
9108                  * are the fourcc, the next 1 byte is the version, and the
9109                  * subsequent bytes are profile_tier_level structure like data. */
9110                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9111                     avc_data + 8 + 1, size - 1);
9112                 buf = gst_buffer_new_and_alloc (size);
9113                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9114                 gst_caps_set_simple (stream->caps,
9115                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9116                 gst_buffer_unref (buf);
9117
9118                 break;
9119               }
9120               case FOURCC_strf:
9121               {
9122                 GstBuffer *buf;
9123
9124                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9125
9126                 /* First 4 bytes are the length of the atom, the next 4 bytes
9127                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9128                  * next 1 byte is the version, and the
9129                  * subsequent bytes are sequence parameter set like data. */
9130
9131                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9132                 if (size > 1) {
9133                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9134                       avc_data + 8 + 40 + 1, size - 1);
9135
9136                   buf = gst_buffer_new_and_alloc (size);
9137                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9138                   gst_caps_set_simple (stream->caps,
9139                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9140                   gst_buffer_unref (buf);
9141                 }
9142                 break;
9143               }
9144               case FOURCC_btrt:
9145               {
9146                 guint avg_bitrate, max_bitrate;
9147
9148                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9149                 if (size < 12)
9150                   break;
9151
9152                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9153                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9154
9155                 if (!max_bitrate && !avg_bitrate)
9156                   break;
9157
9158                 /* Some muxers seem to swap the average and maximum bitrates
9159                  * (I'm looking at you, YouTube), so we swap for sanity. */
9160                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9161                   guint temp = avg_bitrate;
9162
9163                   avg_bitrate = max_bitrate;
9164                   max_bitrate = temp;
9165                 }
9166
9167                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9168                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9169                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9170                 }
9171                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9172                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9173                       GST_TAG_BITRATE, avg_bitrate, NULL);
9174                 }
9175
9176                 break;
9177               }
9178
9179               default:
9180                 break;
9181             }
9182
9183             len -= size + 8;
9184             avc_data += size + 8;
9185           }
9186
9187           break;
9188         }
9189         case FOURCC_H265:
9190         case FOURCC_hvc1:
9191         case FOURCC_hev1:
9192         {
9193           gint len = QT_UINT32 (stsd_data) - 0x66;
9194           const guint8 *hevc_data = stsd_data + 0x66;
9195
9196           /* find hevc */
9197           while (len >= 0x8) {
9198             gint size;
9199
9200             if (QT_UINT32 (hevc_data) <= len)
9201               size = QT_UINT32 (hevc_data) - 0x8;
9202             else
9203               size = len - 0x8;
9204
9205             if (size < 1)
9206               /* No real data, so break out */
9207               break;
9208
9209             switch (QT_FOURCC (hevc_data + 0x4)) {
9210               case FOURCC_hvcC:
9211               {
9212                 /* parse, if found */
9213                 GstBuffer *buf;
9214
9215                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9216
9217                 /* First 4 bytes are the length of the atom, the next 4 bytes
9218                  * are the fourcc, the next 1 byte is the version, and the
9219                  * subsequent bytes are sequence parameter set like data. */
9220                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9221                     (stream->caps, hevc_data + 8 + 1, size - 1);
9222
9223                 buf = gst_buffer_new_and_alloc (size);
9224                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9225                 gst_caps_set_simple (stream->caps,
9226                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9227                 gst_buffer_unref (buf);
9228                 break;
9229               }
9230               default:
9231                 break;
9232             }
9233             len -= size + 8;
9234             hevc_data += size + 8;
9235           }
9236           break;
9237         }
9238         case FOURCC_mp4v:
9239         case FOURCC_MP4V:
9240         case FOURCC_fmp4:
9241         case FOURCC_FMP4:
9242         {
9243           GNode *glbl;
9244
9245           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9246               GST_FOURCC_ARGS (fourcc));
9247
9248           /* codec data might be in glbl extension atom */
9249           glbl = mp4v ?
9250               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9251           if (glbl) {
9252             guint8 *data;
9253             GstBuffer *buf;
9254             gint len;
9255
9256             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9257             data = glbl->data;
9258             len = QT_UINT32 (data);
9259             if (len > 0x8) {
9260               len -= 0x8;
9261               buf = gst_buffer_new_and_alloc (len);
9262               gst_buffer_fill (buf, 0, data + 8, len);
9263               gst_caps_set_simple (stream->caps,
9264                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9265               gst_buffer_unref (buf);
9266             }
9267           }
9268           break;
9269         }
9270         case FOURCC_mjp2:
9271         {
9272           /* see annex I of the jpeg2000 spec */
9273           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9274           const guint8 *data;
9275           const gchar *colorspace = NULL;
9276           gint ncomp = 0;
9277           guint32 ncomp_map = 0;
9278           gint32 *comp_map = NULL;
9279           guint32 nchan_def = 0;
9280           gint32 *chan_def = NULL;
9281
9282           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9283           /* some required atoms */
9284           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9285           if (!mjp2)
9286             break;
9287           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9288           if (!jp2h)
9289             break;
9290
9291           /* number of components; redundant with info in codestream, but useful
9292              to a muxer */
9293           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9294           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9295             break;
9296           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9297
9298           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9299           if (!colr)
9300             break;
9301           GST_DEBUG_OBJECT (qtdemux, "found colr");
9302           /* extract colour space info */
9303           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9304             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9305               case 16:
9306                 colorspace = "sRGB";
9307                 break;
9308               case 17:
9309                 colorspace = "GRAY";
9310                 break;
9311               case 18:
9312                 colorspace = "sYUV";
9313                 break;
9314               default:
9315                 colorspace = NULL;
9316                 break;
9317             }
9318           }
9319           if (!colorspace)
9320             /* colr is required, and only values 16, 17, and 18 are specified,
9321                so error if we have no colorspace */
9322             break;
9323
9324           /* extract component mapping */
9325           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9326           if (cmap) {
9327             guint32 cmap_len = 0;
9328             int i;
9329             cmap_len = QT_UINT32 (cmap->data);
9330             if (cmap_len >= 8) {
9331               /* normal box, subtract off header */
9332               cmap_len -= 8;
9333               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9334               if (cmap_len % 4 == 0) {
9335                 ncomp_map = (cmap_len / 4);
9336                 comp_map = g_new0 (gint32, ncomp_map);
9337                 for (i = 0; i < ncomp_map; i++) {
9338                   guint16 cmp;
9339                   guint8 mtyp, pcol;
9340                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9341                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9342                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9343                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9344                 }
9345               }
9346             }
9347           }
9348           /* extract channel definitions */
9349           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9350           if (cdef) {
9351             guint32 cdef_len = 0;
9352             int i;
9353             cdef_len = QT_UINT32 (cdef->data);
9354             if (cdef_len >= 10) {
9355               /* normal box, subtract off header and len */
9356               cdef_len -= 10;
9357               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9358               if (cdef_len % 6 == 0) {
9359                 nchan_def = (cdef_len / 6);
9360                 chan_def = g_new0 (gint32, nchan_def);
9361                 for (i = 0; i < nchan_def; i++)
9362                   chan_def[i] = -1;
9363                 for (i = 0; i < nchan_def; i++) {
9364                   guint16 cn, typ, asoc;
9365                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9366                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9367                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9368                   if (cn < nchan_def) {
9369                     switch (typ) {
9370                       case 0:
9371                         chan_def[cn] = asoc;
9372                         break;
9373                       case 1:
9374                         chan_def[cn] = 0;       /* alpha */
9375                         break;
9376                       default:
9377                         chan_def[cn] = -typ;
9378                     }
9379                   }
9380                 }
9381               }
9382             }
9383           }
9384
9385           gst_caps_set_simple (stream->caps,
9386               "num-components", G_TYPE_INT, ncomp, NULL);
9387           gst_caps_set_simple (stream->caps,
9388               "colorspace", G_TYPE_STRING, colorspace, NULL);
9389
9390           if (comp_map) {
9391             GValue arr = { 0, };
9392             GValue elt = { 0, };
9393             int i;
9394             g_value_init (&arr, GST_TYPE_ARRAY);
9395             g_value_init (&elt, G_TYPE_INT);
9396             for (i = 0; i < ncomp_map; i++) {
9397               g_value_set_int (&elt, comp_map[i]);
9398               gst_value_array_append_value (&arr, &elt);
9399             }
9400             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9401                 "component-map", &arr);
9402             g_value_unset (&elt);
9403             g_value_unset (&arr);
9404             g_free (comp_map);
9405           }
9406
9407           if (chan_def) {
9408             GValue arr = { 0, };
9409             GValue elt = { 0, };
9410             int i;
9411             g_value_init (&arr, GST_TYPE_ARRAY);
9412             g_value_init (&elt, G_TYPE_INT);
9413             for (i = 0; i < nchan_def; i++) {
9414               g_value_set_int (&elt, chan_def[i]);
9415               gst_value_array_append_value (&arr, &elt);
9416             }
9417             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9418                 "channel-definitions", &arr);
9419             g_value_unset (&elt);
9420             g_value_unset (&arr);
9421             g_free (chan_def);
9422           }
9423
9424           /* some optional atoms */
9425           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9426           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9427
9428           /* indicate possible fields in caps */
9429           if (field) {
9430             data = (guint8 *) field->data + 8;
9431             if (*data != 1)
9432               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9433                   (gint) * data, NULL);
9434           }
9435           /* add codec_data if provided */
9436           if (prefix) {
9437             GstBuffer *buf;
9438             gint len;
9439
9440             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9441             data = prefix->data;
9442             len = QT_UINT32 (data);
9443             if (len > 0x8) {
9444               len -= 0x8;
9445               buf = gst_buffer_new_and_alloc (len);
9446               gst_buffer_fill (buf, 0, data + 8, len);
9447               gst_caps_set_simple (stream->caps,
9448                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9449               gst_buffer_unref (buf);
9450             }
9451           }
9452           break;
9453         }
9454         case FOURCC_SVQ3:
9455         case FOURCC_VP31:
9456         {
9457           GstBuffer *buf;
9458           GstBuffer *seqh = NULL;
9459           guint8 *gamma_data = NULL;
9460           gint len = QT_UINT32 (stsd_data);
9461
9462           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9463           if (gamma_data) {
9464             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9465                 QT_FP32 (gamma_data), NULL);
9466           }
9467           if (seqh) {
9468             /* sorry for the bad name, but we don't know what this is, other
9469              * than its own fourcc */
9470             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9471                 NULL);
9472           }
9473
9474           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9475           buf = gst_buffer_new_and_alloc (len);
9476           gst_buffer_fill (buf, 0, stsd_data, len);
9477           gst_caps_set_simple (stream->caps,
9478               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9479           gst_buffer_unref (buf);
9480           break;
9481         }
9482         case FOURCC_rle_:
9483         case FOURCC_WRLE:
9484         {
9485           gst_caps_set_simple (stream->caps,
9486               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9487           break;
9488         }
9489         case FOURCC_XiTh:
9490         {
9491           GNode *xith, *xdxt;
9492
9493           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9494           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9495           if (!xith)
9496             break;
9497
9498           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9499           if (!xdxt)
9500             break;
9501
9502           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9503           /* collect the headers and store them in a stream list so that we can
9504            * send them out first */
9505           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9506           break;
9507         }
9508         case FOURCC_ovc1:
9509         {
9510           GNode *ovc1;
9511           guint8 *ovc1_data;
9512           guint ovc1_len;
9513           GstBuffer *buf;
9514
9515           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9516           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9517           if (!ovc1)
9518             break;
9519           ovc1_data = ovc1->data;
9520           ovc1_len = QT_UINT32 (ovc1_data);
9521           if (ovc1_len <= 198) {
9522             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9523             break;
9524           }
9525           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9526           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9527           gst_caps_set_simple (stream->caps,
9528               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9529           gst_buffer_unref (buf);
9530           break;
9531         }
9532         case FOURCC_vc_1:
9533         {
9534           gint len = QT_UINT32 (stsd_data) - 0x66;
9535           const guint8 *vc1_data = stsd_data + 0x66;
9536
9537           /* find dvc1 */
9538           while (len >= 8) {
9539             gint size;
9540
9541             if (QT_UINT32 (vc1_data) <= len)
9542               size = QT_UINT32 (vc1_data) - 8;
9543             else
9544               size = len - 8;
9545
9546             if (size < 1)
9547               /* No real data, so break out */
9548               break;
9549
9550             switch (QT_FOURCC (vc1_data + 0x4)) {
9551               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9552               {
9553                 GstBuffer *buf;
9554
9555                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9556                 buf = gst_buffer_new_and_alloc (size);
9557                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9558                 gst_caps_set_simple (stream->caps,
9559                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9560                 gst_buffer_unref (buf);
9561                 break;
9562               }
9563               default:
9564                 break;
9565             }
9566             len -= size + 8;
9567             vc1_data += size + 8;
9568           }
9569           break;
9570         }
9571         default:
9572           break;
9573       }
9574     }
9575
9576     GST_INFO_OBJECT (qtdemux,
9577         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9578         GST_FOURCC_ARGS (fourcc), stream->caps);
9579
9580   } else if (stream->subtype == FOURCC_soun) {
9581     int version, samplesize;
9582     guint16 compression_id;
9583     gboolean amrwb = FALSE;
9584
9585     offset = 32;
9586     /* sample description entry (16) + sound sample description v0 (20) */
9587     if (len < 36)
9588       goto corrupt_file;
9589
9590     version = QT_UINT32 (stsd_data + offset);
9591     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9592     samplesize = QT_UINT16 (stsd_data + offset + 10);
9593     compression_id = QT_UINT16 (stsd_data + offset + 12);
9594     stream->rate = QT_FP32 (stsd_data + offset + 16);
9595
9596     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9597     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9598         QT_UINT32 (stsd_data + offset + 4));
9599     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9600     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9601     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9602     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9603         QT_UINT16 (stsd_data + offset + 14));
9604     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9605
9606     if (compression_id == 0xfffe)
9607       stream->sampled = TRUE;
9608
9609     /* first assume uncompressed audio */
9610     stream->bytes_per_sample = samplesize / 8;
9611     stream->samples_per_frame = stream->n_channels;
9612     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9613     stream->samples_per_packet = stream->samples_per_frame;
9614     stream->bytes_per_packet = stream->bytes_per_sample;
9615
9616     offset = 52;
9617     switch (fourcc) {
9618         /* Yes, these have to be hard-coded */
9619       case FOURCC_MAC6:
9620       {
9621         stream->samples_per_packet = 6;
9622         stream->bytes_per_packet = 1;
9623         stream->bytes_per_frame = 1 * stream->n_channels;
9624         stream->bytes_per_sample = 1;
9625         stream->samples_per_frame = 6 * stream->n_channels;
9626         break;
9627       }
9628       case FOURCC_MAC3:
9629       {
9630         stream->samples_per_packet = 3;
9631         stream->bytes_per_packet = 1;
9632         stream->bytes_per_frame = 1 * stream->n_channels;
9633         stream->bytes_per_sample = 1;
9634         stream->samples_per_frame = 3 * stream->n_channels;
9635         break;
9636       }
9637       case FOURCC_ima4:
9638       {
9639         stream->samples_per_packet = 64;
9640         stream->bytes_per_packet = 34;
9641         stream->bytes_per_frame = 34 * stream->n_channels;
9642         stream->bytes_per_sample = 2;
9643         stream->samples_per_frame = 64 * stream->n_channels;
9644         break;
9645       }
9646       case FOURCC_ulaw:
9647       case FOURCC_alaw:
9648       {
9649         stream->samples_per_packet = 1;
9650         stream->bytes_per_packet = 1;
9651         stream->bytes_per_frame = 1 * stream->n_channels;
9652         stream->bytes_per_sample = 1;
9653         stream->samples_per_frame = 1 * stream->n_channels;
9654         break;
9655       }
9656       case FOURCC_agsm:
9657       {
9658         stream->samples_per_packet = 160;
9659         stream->bytes_per_packet = 33;
9660         stream->bytes_per_frame = 33 * stream->n_channels;
9661         stream->bytes_per_sample = 2;
9662         stream->samples_per_frame = 160 * stream->n_channels;
9663         break;
9664       }
9665       default:
9666         break;
9667     }
9668
9669     if (version == 0x00010000) {
9670       /* sample description entry (16) + sound sample description v1 (20+16) */
9671       if (len < 52)
9672         goto corrupt_file;
9673
9674       switch (fourcc) {
9675         case FOURCC_twos:
9676         case FOURCC_sowt:
9677         case FOURCC_raw_:
9678           break;
9679         default:
9680         {
9681           /* only parse extra decoding config for non-pcm audio */
9682           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
9683           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
9684           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
9685           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
9686
9687           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
9688               stream->samples_per_packet);
9689           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
9690               stream->bytes_per_packet);
9691           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
9692               stream->bytes_per_frame);
9693           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
9694               stream->bytes_per_sample);
9695
9696           if (!stream->sampled && stream->bytes_per_packet) {
9697             stream->samples_per_frame = (stream->bytes_per_frame /
9698                 stream->bytes_per_packet) * stream->samples_per_packet;
9699             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
9700                 stream->samples_per_frame);
9701           }
9702           break;
9703         }
9704       }
9705     } else if (version == 0x00020000) {
9706       union
9707       {
9708         gdouble fp;
9709         guint64 val;
9710       } qtfp;
9711
9712       /* sample description entry (16) + sound sample description v2 (56) */
9713       if (len < 72)
9714         goto corrupt_file;
9715
9716       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
9717       stream->rate = qtfp.fp;
9718       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
9719
9720       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
9721       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
9722       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
9723       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
9724           QT_UINT32 (stsd_data + offset + 20));
9725       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
9726           QT_UINT32 (stsd_data + offset + 24));
9727       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
9728           QT_UINT32 (stsd_data + offset + 28));
9729       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
9730           QT_UINT32 (stsd_data + offset + 32));
9731     } else if (version != 0x00000) {
9732       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
9733     }
9734
9735     if (stream->caps)
9736       gst_caps_unref (stream->caps);
9737
9738     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
9739         stsd_data + 32, len - 16, &codec);
9740
9741     switch (fourcc) {
9742       case FOURCC_in24:
9743       {
9744         GNode *enda;
9745         GNode *in24;
9746
9747         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
9748
9749         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
9750         if (!enda) {
9751           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
9752           if (wave)
9753             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
9754         }
9755         if (enda) {
9756           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
9757           gst_caps_set_simple (stream->caps,
9758               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
9759         }
9760         break;
9761       }
9762       case FOURCC_owma:
9763       {
9764         GNode *owma;
9765         const guint8 *owma_data;
9766         const gchar *codec_name = NULL;
9767         guint owma_len;
9768         GstBuffer *buf;
9769         gint version = 1;
9770         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9771         /* FIXME this should also be gst_riff_strf_auds,
9772          * but the latter one is actually missing bits-per-sample :( */
9773         typedef struct
9774         {
9775           gint16 wFormatTag;
9776           gint16 nChannels;
9777           gint32 nSamplesPerSec;
9778           gint32 nAvgBytesPerSec;
9779           gint16 nBlockAlign;
9780           gint16 wBitsPerSample;
9781           gint16 cbSize;
9782         } WAVEFORMATEX;
9783         WAVEFORMATEX *wfex;
9784
9785         GST_DEBUG_OBJECT (qtdemux, "parse owma");
9786         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
9787         if (!owma)
9788           break;
9789         owma_data = owma->data;
9790         owma_len = QT_UINT32 (owma_data);
9791         if (owma_len <= 54) {
9792           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
9793           break;
9794         }
9795         wfex = (WAVEFORMATEX *) (owma_data + 36);
9796         buf = gst_buffer_new_and_alloc (owma_len - 54);
9797         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
9798         if (wfex->wFormatTag == 0x0161) {
9799           codec_name = "Windows Media Audio";
9800           version = 2;
9801         } else if (wfex->wFormatTag == 0x0162) {
9802           codec_name = "Windows Media Audio 9 Pro";
9803           version = 3;
9804         } else if (wfex->wFormatTag == 0x0163) {
9805           codec_name = "Windows Media Audio 9 Lossless";
9806           /* is that correct? gstffmpegcodecmap.c is missing it, but
9807            * fluendo codec seems to support it */
9808           version = 4;
9809         }
9810
9811         gst_caps_set_simple (stream->caps,
9812             "codec_data", GST_TYPE_BUFFER, buf,
9813             "wmaversion", G_TYPE_INT, version,
9814             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
9815             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
9816             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9817             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9818             NULL);
9819         gst_buffer_unref (buf);
9820
9821         if (codec_name) {
9822           g_free (codec);
9823           codec = g_strdup (codec_name);
9824         }
9825         break;
9826       }
9827       case FOURCC_wma_:
9828       {
9829         gint len = QT_UINT32 (stsd_data) - offset;
9830         const guint8 *wfex_data = stsd_data + offset;
9831         const gchar *codec_name = NULL;
9832         gint version = 1;
9833         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9834         /* FIXME this should also be gst_riff_strf_auds,
9835          * but the latter one is actually missing bits-per-sample :( */
9836         typedef struct
9837         {
9838           gint16 wFormatTag;
9839           gint16 nChannels;
9840           gint32 nSamplesPerSec;
9841           gint32 nAvgBytesPerSec;
9842           gint16 nBlockAlign;
9843           gint16 wBitsPerSample;
9844           gint16 cbSize;
9845         } WAVEFORMATEX;
9846         WAVEFORMATEX wfex;
9847
9848         /* FIXME: unify with similar wavformatex parsing code above */
9849         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
9850
9851         /* find wfex */
9852         while (len >= 8) {
9853           gint size;
9854
9855           if (QT_UINT32 (wfex_data) <= len)
9856             size = QT_UINT32 (wfex_data) - 8;
9857           else
9858             size = len - 8;
9859
9860           if (size < 1)
9861             /* No real data, so break out */
9862             break;
9863
9864           switch (QT_FOURCC (wfex_data + 4)) {
9865             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
9866             {
9867               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
9868
9869               if (size < 8 + 18)
9870                 break;
9871
9872               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
9873               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
9874               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
9875               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
9876               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9877               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9878               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9879
9880               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9881               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9882                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9883                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9884                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9885                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9886
9887               if (wfex.wFormatTag == 0x0161) {
9888                 codec_name = "Windows Media Audio";
9889                 version = 2;
9890               } else if (wfex.wFormatTag == 0x0162) {
9891                 codec_name = "Windows Media Audio 9 Pro";
9892                 version = 3;
9893               } else if (wfex.wFormatTag == 0x0163) {
9894                 codec_name = "Windows Media Audio 9 Lossless";
9895                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9896                  * fluendo codec seems to support it */
9897                 version = 4;
9898               }
9899
9900               gst_caps_set_simple (stream->caps,
9901                   "wmaversion", G_TYPE_INT, version,
9902                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9903                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9904                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9905                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9906
9907               if (size > wfex.cbSize) {
9908                 GstBuffer *buf;
9909
9910                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9911                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9912                     size - wfex.cbSize);
9913                 gst_caps_set_simple (stream->caps,
9914                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9915                 gst_buffer_unref (buf);
9916               } else {
9917                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9918               }
9919
9920               if (codec_name) {
9921                 g_free (codec);
9922                 codec = g_strdup (codec_name);
9923               }
9924               break;
9925             }
9926             default:
9927               break;
9928           }
9929           len -= size + 8;
9930           wfex_data += size + 8;
9931         }
9932         break;
9933       }
9934       case FOURCC_opus:
9935       {
9936         GNode *opus;
9937         const guint8 *opus_data;
9938         guint8 *channel_mapping = NULL;
9939         guint32 rate;
9940         guint8 channels;
9941         guint8 channel_mapping_family;
9942         guint8 stream_count;
9943         guint8 coupled_count;
9944         guint8 i;
9945
9946         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
9947         opus_data = opus->data;
9948
9949         channels = GST_READ_UINT8 (opus_data + 45);
9950         rate = GST_READ_UINT32_LE (opus_data + 48);
9951         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
9952         stream_count = GST_READ_UINT8 (opus_data + 55);
9953         coupled_count = GST_READ_UINT8 (opus_data + 56);
9954
9955         if (channels > 0) {
9956           channel_mapping = g_malloc (channels * sizeof (guint8));
9957           for (i = 0; i < channels; i++)
9958             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
9959         }
9960
9961         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
9962             channel_mapping_family, stream_count, coupled_count,
9963             channel_mapping);
9964         break;
9965       }
9966       default:
9967         break;
9968     }
9969
9970     if (codec) {
9971       GstStructure *s;
9972       gint bitrate = 0;
9973
9974       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9975           GST_TAG_AUDIO_CODEC, codec, NULL);
9976       g_free (codec);
9977       codec = NULL;
9978
9979       /* some bitrate info may have ended up in caps */
9980       s = gst_caps_get_structure (stream->caps, 0);
9981       gst_structure_get_int (s, "bitrate", &bitrate);
9982       if (bitrate > 0)
9983         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9984             GST_TAG_BITRATE, bitrate, NULL);
9985     }
9986
9987     if (stream->protected && fourcc == FOURCC_mp4a)
9988       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
9989     else
9990       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
9991
9992     wave = NULL;
9993     esds = NULL;
9994     if (mp4a) {
9995       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
9996       if (wave)
9997         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
9998       if (!esds)
9999         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10000     }
10001
10002
10003     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10004        16 bits is a byte-swapped wave-style codec identifier,
10005        and we can find a WAVE header internally to a 'wave' atom here.
10006        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10007        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10008        is big-endian).
10009      */
10010     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10011       if (len < offset + 20) {
10012         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10013       } else {
10014         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10015         const guint8 *data = stsd_data + offset + 16;
10016         GNode *wavenode;
10017         GNode *waveheadernode;
10018
10019         wavenode = g_node_new ((guint8 *) data);
10020         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10021           const guint8 *waveheader;
10022           guint32 headerlen;
10023
10024           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10025           if (waveheadernode) {
10026             waveheader = (const guint8 *) waveheadernode->data;
10027             headerlen = QT_UINT32 (waveheader);
10028
10029             if (headerlen > 8) {
10030               gst_riff_strf_auds *header = NULL;
10031               GstBuffer *headerbuf;
10032               GstBuffer *extra;
10033
10034               waveheader += 8;
10035               headerlen -= 8;
10036
10037               headerbuf = gst_buffer_new_and_alloc (headerlen);
10038               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10039
10040               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10041                       headerbuf, &header, &extra)) {
10042                 gst_caps_unref (stream->caps);
10043                 /* FIXME: Need to do something with the channel reorder map */
10044                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10045                     header, extra, NULL, NULL, NULL);
10046
10047                 if (extra)
10048                   gst_buffer_unref (extra);
10049                 g_free (header);
10050               }
10051             }
10052           } else
10053             GST_DEBUG ("Didn't find waveheadernode for this codec");
10054         }
10055         g_node_destroy (wavenode);
10056       }
10057     } else if (esds) {
10058       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10059     } else {
10060       switch (fourcc) {
10061 #if 0
10062           /* FIXME: what is in the chunk? */
10063         case FOURCC_QDMC:
10064         {
10065           gint len = QT_UINT32 (stsd_data);
10066
10067           /* seems to be always = 116 = 0x74 */
10068           break;
10069         }
10070 #endif
10071         case FOURCC_QDM2:
10072         {
10073           gint len = QT_UINT32 (stsd_data);
10074
10075           if (len > 0x4C) {
10076             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10077
10078             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10079             gst_caps_set_simple (stream->caps,
10080                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10081             gst_buffer_unref (buf);
10082           }
10083           gst_caps_set_simple (stream->caps,
10084               "samplesize", G_TYPE_INT, samplesize, NULL);
10085           break;
10086         }
10087         case FOURCC_alac:
10088         {
10089           GNode *alac, *wave = NULL;
10090
10091           /* apparently, m4a has this atom appended directly in the stsd entry,
10092            * while mov has it in a wave atom */
10093           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10094           if (alac) {
10095             /* alac now refers to stsd entry atom */
10096             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10097             if (wave)
10098               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10099             else
10100               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10101           }
10102           if (alac) {
10103             const guint8 *alac_data = alac->data;
10104             gint len = QT_UINT32 (alac->data);
10105             GstBuffer *buf;
10106
10107             if (len < 36) {
10108               GST_DEBUG_OBJECT (qtdemux,
10109                   "discarding alac atom with unexpected len %d", len);
10110             } else {
10111               /* codec-data contains alac atom size and prefix,
10112                * ffmpeg likes it that way, not quite gst-ish though ...*/
10113               buf = gst_buffer_new_and_alloc (len);
10114               gst_buffer_fill (buf, 0, alac->data, len);
10115               gst_caps_set_simple (stream->caps,
10116                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10117               gst_buffer_unref (buf);
10118
10119               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10120               stream->n_channels = QT_UINT8 (alac_data + 21);
10121               stream->rate = QT_UINT32 (alac_data + 32);
10122             }
10123           }
10124           gst_caps_set_simple (stream->caps,
10125               "samplesize", G_TYPE_INT, samplesize, NULL);
10126           break;
10127         }
10128         case FOURCC_sawb:
10129           /* Fallthrough! */
10130           amrwb = TRUE;
10131         case FOURCC_samr:
10132         {
10133           gint len = QT_UINT32 (stsd_data);
10134
10135           if (len > 0x34) {
10136             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10137             guint bitrate;
10138
10139             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10140
10141             /* If we have enough data, let's try to get the 'damr' atom. See
10142              * the 3GPP container spec (26.244) for more details. */
10143             if ((len - 0x34) > 8 &&
10144                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10145               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10146                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10147             }
10148
10149             gst_caps_set_simple (stream->caps,
10150                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10151             gst_buffer_unref (buf);
10152           }
10153           break;
10154         }
10155         case FOURCC_mp4a:
10156         {
10157           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10158           gint len = QT_UINT32 (stsd_data);
10159
10160           if (len >= 50) {
10161             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10162
10163             if (sound_version == 1) {
10164               guint16 channels = QT_UINT16 (stsd_data + 40);
10165               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10166               guint8 codec_data[2];
10167               GstBuffer *buf;
10168               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10169
10170               gint sample_rate_index =
10171                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10172
10173               /* build AAC codec data */
10174               codec_data[0] = profile << 3;
10175               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10176               codec_data[1] = (sample_rate_index & 0x01) << 7;
10177               codec_data[1] |= (channels & 0xF) << 3;
10178
10179               buf = gst_buffer_new_and_alloc (2);
10180               gst_buffer_fill (buf, 0, codec_data, 2);
10181               gst_caps_set_simple (stream->caps,
10182                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10183               gst_buffer_unref (buf);
10184             }
10185           }
10186           break;
10187         }
10188         default:
10189           GST_INFO_OBJECT (qtdemux,
10190               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10191           break;
10192       }
10193     }
10194     GST_INFO_OBJECT (qtdemux,
10195         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10196         GST_FOURCC_ARGS (fourcc), stream->caps);
10197
10198   } else if (stream->subtype == FOURCC_strm) {
10199     if (fourcc == FOURCC_rtsp) {
10200       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10201     } else {
10202       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10203           GST_FOURCC_ARGS (fourcc));
10204       goto unknown_stream;
10205     }
10206     stream->sampled = TRUE;
10207   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10208       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10209
10210     stream->sampled = TRUE;
10211     stream->sparse = TRUE;
10212
10213     stream->caps =
10214         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10215     if (codec) {
10216       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10217           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10218       g_free (codec);
10219       codec = NULL;
10220     }
10221
10222     /* hunt for sort-of codec data */
10223     switch (fourcc) {
10224       case FOURCC_mp4s:
10225       {
10226         GNode *mp4s = NULL;
10227         GNode *esds = NULL;
10228
10229         /* look for palette in a stsd->mp4s->esds sub-atom */
10230         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10231         if (mp4s)
10232           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10233         if (esds == NULL) {
10234           /* Invalid STSD */
10235           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10236           break;
10237         }
10238
10239         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10240         break;
10241       }
10242       default:
10243         GST_INFO_OBJECT (qtdemux,
10244             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10245         break;
10246     }
10247     GST_INFO_OBJECT (qtdemux,
10248         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10249         GST_FOURCC_ARGS (fourcc), stream->caps);
10250   } else {
10251     /* everything in 1 sample */
10252     stream->sampled = TRUE;
10253
10254     stream->caps =
10255         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10256
10257     if (stream->caps == NULL)
10258       goto unknown_stream;
10259
10260     if (codec) {
10261       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10262           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10263       g_free (codec);
10264       codec = NULL;
10265     }
10266   }
10267
10268   /* promote to sampled format */
10269   if (stream->fourcc == FOURCC_samr) {
10270     /* force mono 8000 Hz for AMR */
10271     stream->sampled = TRUE;
10272     stream->n_channels = 1;
10273     stream->rate = 8000;
10274   } else if (stream->fourcc == FOURCC_sawb) {
10275     /* force mono 16000 Hz for AMR-WB */
10276     stream->sampled = TRUE;
10277     stream->n_channels = 1;
10278     stream->rate = 16000;
10279   } else if (stream->fourcc == FOURCC_mp4a) {
10280     stream->sampled = TRUE;
10281   }
10282
10283   /* collect sample information */
10284   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10285     goto samples_failed;
10286
10287   if (qtdemux->fragmented) {
10288     guint64 offset;
10289
10290     /* need all moov samples as basis; probably not many if any at all */
10291     /* prevent moof parsing taking of at this time */
10292     offset = qtdemux->moof_offset;
10293     qtdemux->moof_offset = 0;
10294     if (stream->n_samples &&
10295         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10296       qtdemux->moof_offset = offset;
10297       goto samples_failed;
10298     }
10299     qtdemux->moof_offset = 0;
10300     /* movie duration more reliable in this case (e.g. mehd) */
10301     if (qtdemux->segment.duration &&
10302         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10303       stream->duration =
10304           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10305   }
10306
10307   /* configure segments */
10308   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10309     goto segments_failed;
10310
10311   /* add some language tag, if useful */
10312   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10313       strcmp (stream->lang_id, "und")) {
10314     const gchar *lang_code;
10315
10316     /* convert ISO 639-2 code to ISO 639-1 */
10317     lang_code = gst_tag_get_language_code (stream->lang_id);
10318     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10319         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10320   }
10321
10322   /* Check for UDTA tags */
10323   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10324     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10325   }
10326
10327   /* now we are ready to add the stream */
10328   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10329     goto too_many_streams;
10330
10331   if (!qtdemux->got_moov) {
10332     qtdemux->streams[qtdemux->n_streams] = stream;
10333     qtdemux->n_streams++;
10334     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10335   }
10336
10337   return TRUE;
10338
10339 /* ERRORS */
10340 skip_track:
10341   {
10342     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10343     if (new_stream)
10344       gst_qtdemux_stream_free (qtdemux, stream);
10345     return TRUE;
10346   }
10347 corrupt_file:
10348   {
10349     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10350         (_("This file is corrupt and cannot be played.")), (NULL));
10351     if (new_stream)
10352       gst_qtdemux_stream_free (qtdemux, stream);
10353     return FALSE;
10354   }
10355 error_encrypted:
10356   {
10357     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10358     if (new_stream)
10359       gst_qtdemux_stream_free (qtdemux, stream);
10360     return FALSE;
10361   }
10362 samples_failed:
10363 segments_failed:
10364   {
10365     /* we posted an error already */
10366     /* free stbl sub-atoms */
10367     gst_qtdemux_stbl_free (stream);
10368     if (new_stream)
10369       gst_qtdemux_stream_free (qtdemux, stream);
10370     return FALSE;
10371   }
10372 existing_stream:
10373   {
10374     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10375         track_id);
10376     if (new_stream)
10377       gst_qtdemux_stream_free (qtdemux, stream);
10378     return TRUE;
10379   }
10380 unknown_stream:
10381   {
10382     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10383         GST_FOURCC_ARGS (stream->subtype));
10384     if (new_stream)
10385       gst_qtdemux_stream_free (qtdemux, stream);
10386     return TRUE;
10387   }
10388 too_many_streams:
10389   {
10390     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10391         (_("This file contains too many streams. Only playing first %d"),
10392             GST_QTDEMUX_MAX_STREAMS), (NULL));
10393     return TRUE;
10394   }
10395 }
10396
10397 /* If we can estimate the overall bitrate, and don't have information about the
10398  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10399  * the overall bitrate minus the sum of the bitrates of all other streams. This
10400  * should be useful for the common case where we have one audio and one video
10401  * stream and can estimate the bitrate of one, but not the other. */
10402 static void
10403 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10404 {
10405   QtDemuxStream *stream = NULL;
10406   gint64 size, sys_bitrate, sum_bitrate = 0;
10407   GstClockTime duration;
10408   gint i;
10409   guint bitrate;
10410
10411   if (qtdemux->fragmented)
10412     return;
10413
10414   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10415
10416   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10417       || size <= 0) {
10418     GST_DEBUG_OBJECT (qtdemux,
10419         "Size in bytes of the stream not known - bailing");
10420     return;
10421   }
10422
10423   /* Subtract the header size */
10424   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10425       size, qtdemux->header_size);
10426
10427   if (size < qtdemux->header_size)
10428     return;
10429
10430   size = size - qtdemux->header_size;
10431
10432   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
10433       duration == GST_CLOCK_TIME_NONE) {
10434     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10435     return;
10436   }
10437
10438   for (i = 0; i < qtdemux->n_streams; i++) {
10439     switch (qtdemux->streams[i]->subtype) {
10440       case FOURCC_soun:
10441       case FOURCC_vide:
10442         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10443             qtdemux->streams[i]->caps);
10444         /* retrieve bitrate, prefer avg then max */
10445         bitrate = 0;
10446         if (qtdemux->streams[i]->pending_tags) {
10447           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10448               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10449           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10450           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10451               GST_TAG_NOMINAL_BITRATE, &bitrate);
10452           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10453           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10454               GST_TAG_BITRATE, &bitrate);
10455           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10456         }
10457         if (bitrate)
10458           sum_bitrate += bitrate;
10459         else {
10460           if (stream) {
10461             GST_DEBUG_OBJECT (qtdemux,
10462                 ">1 stream with unknown bitrate - bailing");
10463             return;
10464           } else
10465             stream = qtdemux->streams[i];
10466         }
10467
10468       default:
10469         /* For other subtypes, we assume no significant impact on bitrate */
10470         break;
10471     }
10472   }
10473
10474   if (!stream) {
10475     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10476     return;
10477   }
10478
10479   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10480
10481   if (sys_bitrate < sum_bitrate) {
10482     /* This can happen, since sum_bitrate might be derived from maximum
10483      * bitrates and not average bitrates */
10484     GST_DEBUG_OBJECT (qtdemux,
10485         "System bitrate less than sum bitrate - bailing");
10486     return;
10487   }
10488
10489   bitrate = sys_bitrate - sum_bitrate;
10490   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10491       ", Stream bitrate = %u", sys_bitrate, bitrate);
10492
10493   if (!stream->pending_tags)
10494     stream->pending_tags = gst_tag_list_new_empty ();
10495
10496   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10497       GST_TAG_BITRATE, bitrate, NULL);
10498 }
10499
10500 static GstFlowReturn
10501 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10502 {
10503   gint i;
10504   GstFlowReturn ret = GST_FLOW_OK;
10505
10506   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10507
10508   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10509     QtDemuxStream *stream = qtdemux->streams[i];
10510     guint32 sample_num = 0;
10511
10512     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10513         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10514
10515     if (qtdemux->fragmented) {
10516       /* need all moov samples first */
10517       GST_OBJECT_LOCK (qtdemux);
10518       while (stream->n_samples == 0)
10519         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10520           break;
10521       GST_OBJECT_UNLOCK (qtdemux);
10522     } else {
10523       /* discard any stray moof */
10524       qtdemux->moof_offset = 0;
10525     }
10526
10527     /* prepare braking */
10528     if (ret != GST_FLOW_ERROR)
10529       ret = GST_FLOW_OK;
10530
10531     /* in pull mode, we should have parsed some sample info by now;
10532      * and quite some code will not handle no samples.
10533      * in push mode, we'll just have to deal with it */
10534     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10535       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10536       gst_qtdemux_remove_stream (qtdemux, i);
10537       i--;
10538       continue;
10539     }
10540
10541     /* parse the initial sample for use in setting the frame rate cap */
10542     while (sample_num == 0 && sample_num < stream->n_samples) {
10543       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10544         break;
10545       ++sample_num;
10546     }
10547     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10548       stream->first_duration = stream->samples[0].duration;
10549       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10550           stream->track_id, stream->first_duration);
10551     }
10552   }
10553
10554   return ret;
10555 }
10556
10557 static GstFlowReturn
10558 qtdemux_expose_streams (GstQTDemux * qtdemux)
10559 {
10560   gint i;
10561   GstFlowReturn ret = GST_FLOW_OK;
10562   GSList *oldpads = NULL;
10563   GSList *iter;
10564
10565   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10566
10567   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10568     QtDemuxStream *stream = qtdemux->streams[i];
10569     GstPad *oldpad = stream->pad;
10570     GstTagList *list;
10571
10572     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10573         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10574
10575     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10576         stream->track_id == qtdemux->chapters_track_id) {
10577       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10578          so that it doesn't look like a subtitle track */
10579       gst_qtdemux_remove_stream (qtdemux, i);
10580       i--;
10581       continue;
10582     }
10583
10584     /* now we have all info and can expose */
10585     list = stream->pending_tags;
10586     stream->pending_tags = NULL;
10587     if (oldpad)
10588       oldpads = g_slist_prepend (oldpads, oldpad);
10589     gst_qtdemux_add_stream (qtdemux, stream, list);
10590   }
10591
10592   gst_qtdemux_guess_bitrate (qtdemux);
10593
10594   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10595
10596   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10597     GstPad *oldpad = iter->data;
10598
10599     gst_pad_push_event (oldpad, gst_event_new_eos ());
10600     gst_pad_set_active (oldpad, FALSE);
10601     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10602     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10603     gst_object_unref (oldpad);
10604   }
10605
10606   /* check if we should post a redirect in case there is a single trak
10607    * and it is a redirecting trak */
10608   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10609     GstMessage *m;
10610
10611     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10612         "an external content");
10613     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10614         gst_structure_new ("redirect",
10615             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10616             NULL));
10617     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10618     qtdemux->posted_redirect = TRUE;
10619   }
10620
10621   for (i = 0; i < qtdemux->n_streams; i++) {
10622     QtDemuxStream *stream = qtdemux->streams[i];
10623
10624     qtdemux_do_allocation (qtdemux, stream);
10625   }
10626
10627   qtdemux->exposed = TRUE;
10628   return ret;
10629 }
10630
10631 /* check if major or compatible brand is 3GP */
10632 static inline gboolean
10633 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10634 {
10635   if (major) {
10636     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10637         FOURCC_3g__);
10638   } else if (qtdemux->comp_brands != NULL) {
10639     GstMapInfo map;
10640     guint8 *data;
10641     gsize size;
10642     gboolean res = FALSE;
10643
10644     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10645     data = map.data;
10646     size = map.size;
10647     while (size >= 4) {
10648       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10649           FOURCC_3g__);
10650       data += 4;
10651       size -= 4;
10652     }
10653     gst_buffer_unmap (qtdemux->comp_brands, &map);
10654     return res;
10655   } else {
10656     return FALSE;
10657   }
10658 }
10659
10660 /* check if tag is a spec'ed 3GP tag keyword storing a string */
10661 static inline gboolean
10662 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
10663 {
10664   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
10665       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
10666       || fourcc == FOURCC_albm;
10667 }
10668
10669 static void
10670 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
10671     const char *tag, const char *dummy, GNode * node)
10672 {
10673   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10674   int offset;
10675   char *name;
10676   gchar *data;
10677   gdouble longitude, latitude, altitude;
10678   gint len;
10679
10680   len = QT_UINT32 (node->data);
10681   if (len <= 14)
10682     goto short_read;
10683
10684   data = node->data;
10685   offset = 14;
10686
10687   /* TODO: language code skipped */
10688
10689   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
10690
10691   if (!name) {
10692     /* do not alarm in trivial case, but bail out otherwise */
10693     if (*(data + offset) != 0) {
10694       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
10695           "giving up", tag);
10696     }
10697   } else {
10698     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10699         GST_TAG_GEO_LOCATION_NAME, name, NULL);
10700     offset += strlen (name);
10701     g_free (name);
10702   }
10703
10704   if (len < offset + 2 + 4 + 4 + 4)
10705     goto short_read;
10706
10707   /* +1 +1 = skip null-terminator and location role byte */
10708   offset += 1 + 1;
10709   /* table in spec says unsigned, semantics say negative has meaning ... */
10710   longitude = QT_SFP32 (data + offset);
10711
10712   offset += 4;
10713   latitude = QT_SFP32 (data + offset);
10714
10715   offset += 4;
10716   altitude = QT_SFP32 (data + offset);
10717
10718   /* one invalid means all are invalid */
10719   if (longitude >= -180.0 && longitude <= 180.0 &&
10720       latitude >= -90.0 && latitude <= 90.0) {
10721     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10722         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
10723         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
10724         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
10725   }
10726
10727   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
10728
10729   return;
10730
10731   /* ERRORS */
10732 short_read:
10733   {
10734     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
10735     return;
10736   }
10737 }
10738
10739
10740 static void
10741 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
10742     const char *tag, const char *dummy, GNode * node)
10743 {
10744   guint16 y;
10745   GDate *date;
10746   gint len;
10747
10748   len = QT_UINT32 (node->data);
10749   if (len < 14)
10750     return;
10751
10752   y = QT_UINT16 ((guint8 *) node->data + 12);
10753   if (y == 0) {
10754     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
10755     return;
10756   }
10757   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
10758
10759   date = g_date_new_dmy (1, 1, y);
10760   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10761   g_date_free (date);
10762 }
10763
10764 static void
10765 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
10766     const char *tag, const char *dummy, GNode * node)
10767 {
10768   int offset;
10769   char *tag_str = NULL;
10770   guint8 *entity;
10771   guint16 table;
10772   gint len;
10773
10774   len = QT_UINT32 (node->data);
10775   if (len <= 20)
10776     goto short_read;
10777
10778   offset = 12;
10779   entity = (guint8 *) node->data + offset;
10780   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
10781     GST_DEBUG_OBJECT (qtdemux,
10782         "classification info: %c%c%c%c invalid classification entity",
10783         entity[0], entity[1], entity[2], entity[3]);
10784     return;
10785   }
10786
10787   offset += 4;
10788   table = QT_UINT16 ((guint8 *) node->data + offset);
10789
10790   /* Language code skipped */
10791
10792   offset += 4;
10793
10794   /* Tag format: "XXXX://Y[YYYY]/classification info string"
10795    * XXXX: classification entity, fixed length 4 chars.
10796    * Y[YYYY]: classification table, max 5 chars.
10797    */
10798   tag_str = g_strdup_printf ("----://%u/%s",
10799       table, (char *) node->data + offset);
10800
10801   /* memcpy To be sure we're preserving byte order */
10802   memcpy (tag_str, entity, 4);
10803   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
10804
10805   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
10806
10807   g_free (tag_str);
10808
10809   return;
10810
10811   /* ERRORS */
10812 short_read:
10813   {
10814     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
10815     return;
10816   }
10817 }
10818
10819 static gboolean
10820 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
10821     const char *tag, const char *dummy, GNode * node)
10822 {
10823   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10824   GNode *data;
10825   char *s;
10826   int len;
10827   guint32 type;
10828   int offset;
10829   gboolean ret = TRUE;
10830   const gchar *charset = NULL;
10831
10832   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10833   if (data) {
10834     len = QT_UINT32 (data->data);
10835     type = QT_UINT32 ((guint8 *) data->data + 8);
10836     if (type == 0x00000001 && len > 16) {
10837       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
10838           env_vars);
10839       if (s) {
10840         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10841         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10842         g_free (s);
10843       } else {
10844         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10845       }
10846     }
10847   } else {
10848     len = QT_UINT32 (node->data);
10849     type = QT_UINT32 ((guint8 *) node->data + 4);
10850     if ((type >> 24) == 0xa9) {
10851       gint str_len;
10852       gint lang_code;
10853
10854       /* Type starts with the (C) symbol, so the next data is a list
10855        * of (string size(16), language code(16), string) */
10856
10857       str_len = QT_UINT16 ((guint8 *) node->data + 8);
10858       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
10859
10860       /* the string + fourcc + size + 2 16bit fields,
10861        * means that there are more tags in this atom */
10862       if (len > str_len + 8 + 4) {
10863         /* TODO how to represent the same tag in different languages? */
10864         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
10865             "text alternatives, reading only first one");
10866       }
10867
10868       offset = 12;
10869       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
10870       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
10871
10872       if (lang_code < 0x800) {  /* MAC encoded string */
10873         charset = "mac";
10874       }
10875     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
10876             QT_FOURCC ((guint8 *) node->data + 4))) {
10877       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
10878
10879       /* we go for 3GP style encoding if major brands claims so,
10880        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
10881       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10882           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
10883               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
10884         offset = 14;
10885         /* 16-bit Language code is ignored here as well */
10886         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
10887       } else {
10888         goto normal;
10889       }
10890     } else {
10891     normal:
10892       offset = 8;
10893       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
10894       ret = FALSE;              /* may have to fallback */
10895     }
10896     if (charset) {
10897       GError *err = NULL;
10898
10899       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
10900           charset, NULL, NULL, &err);
10901       if (err) {
10902         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
10903             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
10904             err->message);
10905         g_error_free (err);
10906       }
10907     } else {
10908       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10909           len - offset, env_vars);
10910     }
10911     if (s) {
10912       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10913       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10914       g_free (s);
10915       ret = TRUE;
10916     } else {
10917       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10918     }
10919   }
10920   return ret;
10921 }
10922
10923 static void
10924 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10925     const char *tag, const char *dummy, GNode * node)
10926 {
10927   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10928 }
10929
10930 static void
10931 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10932     const char *tag, const char *dummy, GNode * node)
10933 {
10934   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10935   guint8 *data;
10936   char *s, *t, *k = NULL;
10937   int len;
10938   int offset;
10939   int count;
10940
10941   /* first try normal string tag if major brand not 3GP */
10942   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10943     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10944       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10945        * let's try it 3gpp way after minor safety check */
10946       data = node->data;
10947       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10948         return;
10949     } else
10950       return;
10951   }
10952
10953   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10954
10955   data = node->data;
10956
10957   len = QT_UINT32 (data);
10958   if (len < 15)
10959     goto short_read;
10960
10961   count = QT_UINT8 (data + 14);
10962   offset = 15;
10963   for (; count; count--) {
10964     gint slen;
10965
10966     if (offset + 1 > len)
10967       goto short_read;
10968     slen = QT_UINT8 (data + offset);
10969     offset += 1;
10970     if (offset + slen > len)
10971       goto short_read;
10972     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10973         slen, env_vars);
10974     if (s) {
10975       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10976       if (k) {
10977         t = g_strjoin (",", k, s, NULL);
10978         g_free (s);
10979         g_free (k);
10980         k = t;
10981       } else {
10982         k = s;
10983       }
10984     } else {
10985       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
10986     }
10987     offset += slen;
10988   }
10989
10990 done:
10991   if (k) {
10992     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
10993     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
10994   }
10995   g_free (k);
10996
10997   return;
10998
10999   /* ERRORS */
11000 short_read:
11001   {
11002     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11003     goto done;
11004   }
11005 }
11006
11007 static void
11008 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11009     const char *tag1, const char *tag2, GNode * node)
11010 {
11011   GNode *data;
11012   int len;
11013   int type;
11014   int n1, n2;
11015
11016   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11017   if (data) {
11018     len = QT_UINT32 (data->data);
11019     type = QT_UINT32 ((guint8 *) data->data + 8);
11020     if (type == 0x00000000 && len >= 22) {
11021       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11022       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11023       if (n1 > 0) {
11024         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11025         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11026       }
11027       if (n2 > 0) {
11028         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11029         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11030       }
11031     }
11032   }
11033 }
11034
11035 static void
11036 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11037     const char *tag1, const char *dummy, GNode * node)
11038 {
11039   GNode *data;
11040   int len;
11041   int type;
11042   int n1;
11043
11044   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11045   if (data) {
11046     len = QT_UINT32 (data->data);
11047     type = QT_UINT32 ((guint8 *) data->data + 8);
11048     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11049     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11050     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11051       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11052       if (n1) {
11053         /* do not add bpm=0 */
11054         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11055         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11056             NULL);
11057       }
11058     }
11059   }
11060 }
11061
11062 static void
11063 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11064     const char *tag1, const char *dummy, GNode * node)
11065 {
11066   GNode *data;
11067   int len;
11068   int type;
11069   guint32 num;
11070
11071   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11072   if (data) {
11073     len = QT_UINT32 (data->data);
11074     type = QT_UINT32 ((guint8 *) data->data + 8);
11075     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11076     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11077     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11078       num = QT_UINT32 ((guint8 *) data->data + 16);
11079       if (num) {
11080         /* do not add num=0 */
11081         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11082         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11083       }
11084     }
11085   }
11086 }
11087
11088 static void
11089 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11090     const char *tag1, const char *dummy, GNode * node)
11091 {
11092   GNode *data;
11093   int len;
11094   int type;
11095   GstSample *sample;
11096
11097   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11098   if (data) {
11099     len = QT_UINT32 (data->data);
11100     type = QT_UINT32 ((guint8 *) data->data + 8);
11101     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11102     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11103       if ((sample =
11104               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11105                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11106         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11107         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11108         gst_sample_unref (sample);
11109       }
11110     }
11111   }
11112 }
11113
11114 static void
11115 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11116     const char *tag, const char *dummy, GNode * node)
11117 {
11118   GNode *data;
11119   char *s;
11120   int len;
11121   int type;
11122
11123   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11124   if (data) {
11125     len = QT_UINT32 (data->data);
11126     type = QT_UINT32 ((guint8 *) data->data + 8);
11127     if (type == 0x00000001 && len > 16) {
11128       guint y, m = 1, d = 1;
11129       gint ret;
11130
11131       s = g_strndup ((char *) data->data + 16, len - 16);
11132       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11133       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11134       if (ret >= 1 && y > 1500 && y < 3000) {
11135         GDate *date;
11136
11137         date = g_date_new_dmy (d, m, y);
11138         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11139         g_date_free (date);
11140       } else {
11141         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11142       }
11143       g_free (s);
11144     }
11145   }
11146 }
11147
11148 static void
11149 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11150     const char *tag, const char *dummy, GNode * node)
11151 {
11152   GNode *data;
11153
11154   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11155
11156   /* re-route to normal string tag if major brand says so
11157    * or no data atom and compatible brand suggests so */
11158   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11159       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11160     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11161     return;
11162   }
11163
11164   if (data) {
11165     guint len, type, n;
11166
11167     len = QT_UINT32 (data->data);
11168     type = QT_UINT32 ((guint8 *) data->data + 8);
11169     if (type == 0x00000000 && len >= 18) {
11170       n = QT_UINT16 ((guint8 *) data->data + 16);
11171       if (n > 0) {
11172         const gchar *genre;
11173
11174         genre = gst_tag_id3_genre_get (n - 1);
11175         if (genre != NULL) {
11176           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11177           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11178         }
11179       }
11180     }
11181   }
11182 }
11183
11184 static void
11185 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11186     const gchar * tag, guint8 * data, guint32 datasize)
11187 {
11188   gdouble value;
11189   gchar *datacopy;
11190
11191   /* make a copy to have \0 at the end */
11192   datacopy = g_strndup ((gchar *) data, datasize);
11193
11194   /* convert the str to double */
11195   if (sscanf (datacopy, "%lf", &value) == 1) {
11196     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11197     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11198   } else {
11199     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11200         datacopy);
11201   }
11202   g_free (datacopy);
11203 }
11204
11205
11206 static void
11207 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11208     const char *tag, const char *tag_bis, GNode * node)
11209 {
11210   GNode *mean;
11211   GNode *name;
11212   GNode *data;
11213   guint32 meansize;
11214   guint32 namesize;
11215   guint32 datatype;
11216   guint32 datasize;
11217   const gchar *meanstr;
11218   const gchar *namestr;
11219
11220   /* checking the whole ---- atom size for consistency */
11221   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11222     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11223     return;
11224   }
11225
11226   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11227   if (!mean) {
11228     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11229     return;
11230   }
11231
11232   meansize = QT_UINT32 (mean->data);
11233   if (meansize <= 12) {
11234     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11235     return;
11236   }
11237   meanstr = ((gchar *) mean->data) + 12;
11238   meansize -= 12;
11239
11240   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11241   if (!name) {
11242     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11243     return;
11244   }
11245
11246   namesize = QT_UINT32 (name->data);
11247   if (namesize <= 12) {
11248     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11249     return;
11250   }
11251   namestr = ((gchar *) name->data) + 12;
11252   namesize -= 12;
11253
11254   /*
11255    * Data atom is:
11256    * uint32 - size
11257    * uint32 - name
11258    * uint8  - version
11259    * uint24 - data type
11260    * uint32 - all 0
11261    * rest   - the data
11262    */
11263   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11264   if (!data) {
11265     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11266     return;
11267   }
11268   datasize = QT_UINT32 (data->data);
11269   if (datasize <= 16) {
11270     GST_WARNING_OBJECT (demux, "Data atom too small");
11271     return;
11272   }
11273   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11274
11275   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11276       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11277     static const struct
11278     {
11279       const gchar name[28];
11280       const gchar tag[28];
11281     } tags[] = {
11282       {
11283       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11284       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11285       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11286       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11287       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11288       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11289       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11290       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11291     };
11292     int i;
11293
11294     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11295       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11296         switch (gst_tag_get_type (tags[i].tag)) {
11297           case G_TYPE_DOUBLE:
11298             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11299                 ((guint8 *) data->data) + 16, datasize - 16);
11300             break;
11301           case G_TYPE_STRING:
11302             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11303             break;
11304           default:
11305             /* not reached */
11306             break;
11307         }
11308         break;
11309       }
11310     }
11311     if (i == G_N_ELEMENTS (tags))
11312       goto unknown_tag;
11313   } else {
11314     goto unknown_tag;
11315   }
11316
11317   return;
11318
11319 /* errors */
11320 unknown_tag:
11321 #ifndef GST_DISABLE_GST_DEBUG
11322   {
11323     gchar *namestr_dbg;
11324     gchar *meanstr_dbg;
11325
11326     meanstr_dbg = g_strndup (meanstr, meansize);
11327     namestr_dbg = g_strndup (namestr, namesize);
11328
11329     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11330         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11331
11332     g_free (namestr_dbg);
11333     g_free (meanstr_dbg);
11334   }
11335 #endif
11336   return;
11337 }
11338
11339 static void
11340 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11341     const char *tag_bis, GNode * node)
11342 {
11343   guint8 *data;
11344   GstBuffer *buf;
11345   guint len;
11346   GstTagList *id32_taglist = NULL;
11347
11348   GST_LOG_OBJECT (demux, "parsing ID32");
11349
11350   data = node->data;
11351   len = GST_READ_UINT32_BE (data);
11352
11353   /* need at least full box and language tag */
11354   if (len < 12 + 2)
11355     return;
11356
11357   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11358   gst_buffer_fill (buf, 0, data + 14, len - 14);
11359
11360   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11361   if (id32_taglist) {
11362     GST_LOG_OBJECT (demux, "parsing ok");
11363     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11364     gst_tag_list_unref (id32_taglist);
11365   } else {
11366     GST_LOG_OBJECT (demux, "parsing failed");
11367   }
11368
11369   gst_buffer_unref (buf);
11370 }
11371
11372 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11373     const char *tag, const char *tag_bis, GNode * node);
11374
11375 /* unmapped tags
11376 FOURCC_pcst -> if media is a podcast -> bool
11377 FOURCC_cpil -> if media is part of a compilation -> bool
11378 FOURCC_pgap -> if media is part of a gapless context -> bool
11379 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11380 */
11381
11382 static const struct
11383 {
11384   guint32 fourcc;
11385   const gchar *gst_tag;
11386   const gchar *gst_tag_bis;
11387   const GstQTDemuxAddTagFunc func;
11388 } add_funcs[] = {
11389   {
11390   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11391   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11392   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11393   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11394   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11395   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11396   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11397   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11398   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11399   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11400   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11401   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11402   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11403   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11404   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11405   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11406   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11407   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11408   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11409   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11410   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11411   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11412   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11413         qtdemux_tag_add_num}, {
11414   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11415         qtdemux_tag_add_num}, {
11416   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11417   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11418   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11419   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11420   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11421   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11422   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11423   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11424   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11425   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11426   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11427   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11428   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11429   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11430   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11431   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11432   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11433   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11434         qtdemux_tag_add_classification}, {
11435   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11436   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11437   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11438
11439     /* This is a special case, some tags are stored in this
11440      * 'reverse dns naming', according to:
11441      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11442      * bug #614471
11443      */
11444   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11445     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11446   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11447 };
11448
11449 struct _GstQtDemuxTagList
11450 {
11451   GstQTDemux *demux;
11452   GstTagList *taglist;
11453 };
11454 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11455
11456 static void
11457 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11458 {
11459   gint len;
11460   guint8 *data;
11461   GstBuffer *buf;
11462   gchar *media_type;
11463   const gchar *style;
11464   GstSample *sample;
11465   GstStructure *s;
11466   guint i;
11467   guint8 ndata[4];
11468   GstQTDemux *demux = qtdemuxtaglist->demux;
11469   GstTagList *taglist = qtdemuxtaglist->taglist;
11470
11471   data = node->data;
11472   len = QT_UINT32 (data);
11473   buf = gst_buffer_new_and_alloc (len);
11474   gst_buffer_fill (buf, 0, data, len);
11475
11476   /* heuristic to determine style of tag */
11477   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11478       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11479     style = "itunes";
11480   else if (demux->major_brand == FOURCC_qt__)
11481     style = "quicktime";
11482   /* fall back to assuming iso/3gp tag style */
11483   else
11484     style = "iso";
11485
11486   /* santize the name for the caps. */
11487   for (i = 0; i < 4; i++) {
11488     guint8 d = data[4 + i];
11489     if (g_ascii_isalnum (d))
11490       ndata[i] = g_ascii_tolower (d);
11491     else
11492       ndata[i] = '_';
11493   }
11494
11495   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11496       ndata[0], ndata[1], ndata[2], ndata[3]);
11497   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11498
11499   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11500   sample = gst_sample_new (buf, NULL, NULL, s);
11501   gst_buffer_unref (buf);
11502   g_free (media_type);
11503
11504   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11505       len, s);
11506
11507   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11508       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11509
11510   gst_sample_unref (sample);
11511 }
11512
11513 static void
11514 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11515 {
11516   GNode *meta;
11517   GNode *ilst;
11518   GNode *xmp_;
11519   GNode *node;
11520   gint i;
11521   GstQtDemuxTagList demuxtaglist;
11522
11523   demuxtaglist.demux = qtdemux;
11524   demuxtaglist.taglist = taglist;
11525
11526   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11527   if (meta != NULL) {
11528     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11529     if (ilst == NULL) {
11530       GST_LOG_OBJECT (qtdemux, "no ilst");
11531       return;
11532     }
11533   } else {
11534     ilst = udta;
11535     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11536   }
11537
11538   i = 0;
11539   while (i < G_N_ELEMENTS (add_funcs)) {
11540     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11541     if (node) {
11542       gint len;
11543
11544       len = QT_UINT32 (node->data);
11545       if (len < 12) {
11546         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11547             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11548       } else {
11549         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11550             add_funcs[i].gst_tag_bis, node);
11551       }
11552       g_node_destroy (node);
11553     } else {
11554       i++;
11555     }
11556   }
11557
11558   /* parsed nodes have been removed, pass along remainder as blob */
11559   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11560       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11561
11562   /* parse up XMP_ node if existing */
11563   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11564   if (xmp_ != NULL) {
11565     GstBuffer *buf;
11566     GstTagList *xmptaglist;
11567
11568     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11569         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11570     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11571     gst_buffer_unref (buf);
11572
11573     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11574   } else {
11575     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11576   }
11577 }
11578
11579 typedef struct
11580 {
11581   GstStructure *structure;      /* helper for sort function */
11582   gchar *location;
11583   guint min_req_bitrate;
11584   guint min_req_qt_version;
11585 } GstQtReference;
11586
11587 static gint
11588 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11589 {
11590   GstQtReference *ref_a = (GstQtReference *) a;
11591   GstQtReference *ref_b = (GstQtReference *) b;
11592
11593   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11594     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11595
11596   /* known bitrates go before unknown; higher bitrates go first */
11597   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11598 }
11599
11600 /* sort the redirects and post a message for the application.
11601  */
11602 static void
11603 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11604 {
11605   GstQtReference *best;
11606   GstStructure *s;
11607   GstMessage *msg;
11608   GValue list_val = { 0, };
11609   GList *l;
11610
11611   g_assert (references != NULL);
11612
11613   references = g_list_sort (references, qtdemux_redirects_sort_func);
11614
11615   best = (GstQtReference *) references->data;
11616
11617   g_value_init (&list_val, GST_TYPE_LIST);
11618
11619   for (l = references; l != NULL; l = l->next) {
11620     GstQtReference *ref = (GstQtReference *) l->data;
11621     GValue struct_val = { 0, };
11622
11623     ref->structure = gst_structure_new ("redirect",
11624         "new-location", G_TYPE_STRING, ref->location, NULL);
11625
11626     if (ref->min_req_bitrate > 0) {
11627       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11628           ref->min_req_bitrate, NULL);
11629     }
11630
11631     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11632     g_value_set_boxed (&struct_val, ref->structure);
11633     gst_value_list_append_value (&list_val, &struct_val);
11634     g_value_unset (&struct_val);
11635     /* don't free anything here yet, since we need best->structure below */
11636   }
11637
11638   g_assert (best != NULL);
11639   s = gst_structure_copy (best->structure);
11640
11641   if (g_list_length (references) > 1) {
11642     gst_structure_set_value (s, "locations", &list_val);
11643   }
11644
11645   g_value_unset (&list_val);
11646
11647   for (l = references; l != NULL; l = l->next) {
11648     GstQtReference *ref = (GstQtReference *) l->data;
11649
11650     gst_structure_free (ref->structure);
11651     g_free (ref->location);
11652     g_free (ref);
11653   }
11654   g_list_free (references);
11655
11656   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
11657   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
11658   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
11659   qtdemux->posted_redirect = TRUE;
11660 }
11661
11662 /* look for redirect nodes, collect all redirect information and
11663  * process it.
11664  */
11665 static gboolean
11666 qtdemux_parse_redirects (GstQTDemux * qtdemux)
11667 {
11668   GNode *rmra, *rmda, *rdrf;
11669
11670   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
11671   if (rmra) {
11672     GList *redirects = NULL;
11673
11674     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
11675     while (rmda) {
11676       GstQtReference ref = { NULL, NULL, 0, 0 };
11677       GNode *rmdr, *rmvc;
11678
11679       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
11680         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
11681         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
11682             ref.min_req_bitrate);
11683       }
11684
11685       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
11686         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
11687         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
11688
11689 #ifndef GST_DISABLE_GST_DEBUG
11690         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
11691 #endif
11692         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
11693
11694         GST_LOG_OBJECT (qtdemux,
11695             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
11696             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
11697             bitmask, check_type);
11698         if (package == FOURCC_qtim && check_type == 0) {
11699           ref.min_req_qt_version = version;
11700         }
11701       }
11702
11703       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
11704       if (rdrf) {
11705         guint32 ref_type;
11706         guint8 *ref_data;
11707         guint ref_len;
11708
11709         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
11710         if (ref_len > 20) {
11711           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
11712           ref_data = (guint8 *) rdrf->data + 20;
11713           if (ref_type == FOURCC_alis) {
11714             guint record_len, record_version, fn_len;
11715
11716             if (ref_len > 70) {
11717               /* MacOSX alias record, google for alias-layout.txt */
11718               record_len = QT_UINT16 (ref_data + 4);
11719               record_version = QT_UINT16 (ref_data + 4 + 2);
11720               fn_len = QT_UINT8 (ref_data + 50);
11721               if (record_len > 50 && record_version == 2 && fn_len > 0) {
11722                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
11723               }
11724             } else {
11725               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
11726                   ref_len);
11727             }
11728           } else if (ref_type == FOURCC_url_) {
11729             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
11730           } else {
11731             GST_DEBUG_OBJECT (qtdemux,
11732                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
11733                 GST_FOURCC_ARGS (ref_type));
11734           }
11735           if (ref.location != NULL) {
11736             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
11737             redirects =
11738                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
11739           } else {
11740             GST_WARNING_OBJECT (qtdemux,
11741                 "Failed to extract redirect location from rdrf atom");
11742           }
11743         } else {
11744           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
11745         }
11746       }
11747
11748       /* look for others */
11749       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
11750     }
11751
11752     if (redirects != NULL) {
11753       qtdemux_process_redirects (qtdemux, redirects);
11754     }
11755   }
11756   return TRUE;
11757 }
11758
11759 static GstTagList *
11760 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
11761 {
11762   const gchar *fmt;
11763
11764   if (tags == NULL) {
11765     tags = gst_tag_list_new_empty ();
11766     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
11767   }
11768
11769   if (qtdemux->major_brand == FOURCC_mjp2)
11770     fmt = "Motion JPEG 2000";
11771   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
11772     fmt = "3GP";
11773   else if (qtdemux->major_brand == FOURCC_qt__)
11774     fmt = "Quicktime";
11775   else if (qtdemux->fragmented)
11776     fmt = "ISO fMP4";
11777   else
11778     fmt = "ISO MP4/M4A";
11779
11780   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
11781       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
11782
11783   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
11784       fmt, NULL);
11785
11786   return tags;
11787 }
11788
11789 /* we have read th complete moov node now.
11790  * This function parses all of the relevant info, creates the traks and
11791  * prepares all data structures for playback
11792  */
11793 static gboolean
11794 qtdemux_parse_tree (GstQTDemux * qtdemux)
11795 {
11796   GNode *mvhd;
11797   GNode *trak;
11798   GNode *udta;
11799   GNode *mvex;
11800   GstClockTime duration;
11801   GNode *pssh;
11802   guint64 creation_time;
11803   GstDateTime *datetime = NULL;
11804   gint version;
11805
11806   /* make sure we have a usable taglist */
11807   if (!qtdemux->tag_list) {
11808     qtdemux->tag_list = gst_tag_list_new_empty ();
11809     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11810   } else {
11811     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11812   }
11813
11814   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
11815   if (mvhd == NULL) {
11816     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
11817     return qtdemux_parse_redirects (qtdemux);
11818   }
11819
11820   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
11821   if (version == 1) {
11822     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
11823     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
11824     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
11825   } else if (version == 0) {
11826     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
11827     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
11828     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
11829   } else {
11830     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
11831     return FALSE;
11832   }
11833
11834   /* Moving qt creation time (secs since 1904) to unix time */
11835   if (creation_time != 0) {
11836     /* Try to use epoch first as it should be faster and more commonly found */
11837     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
11838       GTimeVal now;
11839
11840       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
11841       /* some data cleansing sanity */
11842       g_get_current_time (&now);
11843       if (now.tv_sec + 24 * 3600 < creation_time) {
11844         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
11845       } else {
11846         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
11847       }
11848     } else {
11849       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
11850       GDateTime *dt, *dt_local;
11851
11852       dt = g_date_time_add_seconds (base_dt, creation_time);
11853       dt_local = g_date_time_to_local (dt);
11854       datetime = gst_date_time_new_from_g_date_time (dt_local);
11855
11856       g_date_time_unref (base_dt);
11857       g_date_time_unref (dt);
11858     }
11859   }
11860   if (datetime) {
11861     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
11862     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
11863         datetime, NULL);
11864     gst_date_time_unref (datetime);
11865   }
11866
11867   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
11868   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
11869
11870   /* check for fragmented file and get some (default) data */
11871   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
11872   if (mvex) {
11873     GNode *mehd;
11874     GstByteReader mehd_data;
11875
11876     /* let track parsing or anyone know weird stuff might happen ... */
11877     qtdemux->fragmented = TRUE;
11878
11879     /* compensate for total duration */
11880     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
11881     if (mehd)
11882       qtdemux_parse_mehd (qtdemux, &mehd_data);
11883   }
11884
11885   /* set duration in the segment info */
11886   gst_qtdemux_get_duration (qtdemux, &duration);
11887   if (duration) {
11888     qtdemux->segment.duration = duration;
11889     /* also do not exceed duration; stop is set that way post seek anyway,
11890      * and segment activation falls back to duration,
11891      * whereas loop only checks stop, so let's align this here as well */
11892     qtdemux->segment.stop = duration;
11893   }
11894
11895   /* parse all traks */
11896   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
11897   while (trak) {
11898     qtdemux_parse_trak (qtdemux, trak);
11899     /* iterate all siblings */
11900     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
11901   }
11902
11903   if (!qtdemux->tag_list) {
11904     GST_DEBUG_OBJECT (qtdemux, "new tag list");
11905     qtdemux->tag_list = gst_tag_list_new_empty ();
11906     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11907   } else {
11908     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11909   }
11910
11911   /* find tags */
11912   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11913   if (udta) {
11914     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11915   } else {
11916     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11917   }
11918
11919   /* maybe also some tags in meta box */
11920   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11921   if (udta) {
11922     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11923     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11924   } else {
11925     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11926   }
11927
11928   /* parse any protection system info */
11929   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
11930   while (pssh) {
11931     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
11932     qtdemux_parse_pssh (qtdemux, pssh);
11933     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
11934   }
11935
11936   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11937
11938   return TRUE;
11939 }
11940
11941 /* taken from ffmpeg */
11942 static int
11943 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11944 {
11945   int count = 4;
11946   int len = 0;
11947
11948   while (count--) {
11949     int c;
11950
11951     if (ptr >= end)
11952       return -1;
11953
11954     c = *ptr++;
11955     len = (len << 7) | (c & 0x7f);
11956     if (!(c & 0x80))
11957       break;
11958   }
11959   *end_out = ptr;
11960   return len;
11961 }
11962
11963 /* this can change the codec originally present in @list */
11964 static void
11965 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11966     GNode * esds, GstTagList * list)
11967 {
11968   int len = QT_UINT32 (esds->data);
11969   guint8 *ptr = esds->data;
11970   guint8 *end = ptr + len;
11971   int tag;
11972   guint8 *data_ptr = NULL;
11973   int data_len = 0;
11974   guint8 object_type_id = 0;
11975   const char *codec_name = NULL;
11976   GstCaps *caps = NULL;
11977
11978   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11979   ptr += 8;
11980   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
11981   ptr += 4;
11982   while (ptr + 1 < end) {
11983     tag = QT_UINT8 (ptr);
11984     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
11985     ptr++;
11986     len = read_descr_size (ptr, end, &ptr);
11987     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
11988
11989     /* Check the stated amount of data is available for reading */
11990     if (len < 0 || ptr + len > end)
11991       break;
11992
11993     switch (tag) {
11994       case ES_DESCRIPTOR_TAG:
11995         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
11996         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
11997         ptr += 3;
11998         break;
11999       case DECODER_CONFIG_DESC_TAG:{
12000         guint max_bitrate, avg_bitrate;
12001
12002         object_type_id = QT_UINT8 (ptr);
12003         max_bitrate = QT_UINT32 (ptr + 5);
12004         avg_bitrate = QT_UINT32 (ptr + 9);
12005         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12006         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12007         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12008         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12009         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12010         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12011           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12012               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12013         }
12014         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12015           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12016               avg_bitrate, NULL);
12017         }
12018         ptr += 13;
12019         break;
12020       }
12021       case DECODER_SPECIFIC_INFO_TAG:
12022         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12023         if (object_type_id == 0xe0 && len == 0x40) {
12024           guint8 *data;
12025           GstStructure *s;
12026           guint32 clut[16];
12027           gint i;
12028
12029           GST_DEBUG_OBJECT (qtdemux,
12030               "Have VOBSUB palette. Creating palette event");
12031           /* move to decConfigDescr data and read palette */
12032           data = ptr;
12033           for (i = 0; i < 16; i++) {
12034             clut[i] = QT_UINT32 (data);
12035             data += 4;
12036           }
12037
12038           s = gst_structure_new ("application/x-gst-dvd", "event",
12039               G_TYPE_STRING, "dvd-spu-clut-change",
12040               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12041               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12042               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12043               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12044               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12045               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12046               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12047               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12048               NULL);
12049
12050           /* store event and trigger custom processing */
12051           stream->pending_event =
12052               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12053         } else {
12054           /* Generic codec_data handler puts it on the caps */
12055           data_ptr = ptr;
12056           data_len = len;
12057         }
12058
12059         ptr += len;
12060         break;
12061       case SL_CONFIG_DESC_TAG:
12062         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12063         ptr += 1;
12064         break;
12065       default:
12066         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12067             tag);
12068         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12069         ptr += len;
12070         break;
12071     }
12072   }
12073
12074   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12075    * in use, and should also be used to override some other parameters for some
12076    * codecs. */
12077   switch (object_type_id) {
12078     case 0x20:                 /* MPEG-4 */
12079       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12080        * profile_and_level_indication */
12081       if (data_ptr != NULL && data_len >= 5 &&
12082           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12083         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12084             data_ptr + 4, data_len - 4);
12085       }
12086       break;                    /* Nothing special needed here */
12087     case 0x21:                 /* H.264 */
12088       codec_name = "H.264 / AVC";
12089       caps = gst_caps_new_simple ("video/x-h264",
12090           "stream-format", G_TYPE_STRING, "avc",
12091           "alignment", G_TYPE_STRING, "au", NULL);
12092       break;
12093     case 0x40:                 /* AAC (any) */
12094     case 0x66:                 /* AAC Main */
12095     case 0x67:                 /* AAC LC */
12096     case 0x68:                 /* AAC SSR */
12097       /* Override channels and rate based on the codec_data, as it's often
12098        * wrong. */
12099       /* Only do so for basic setup without HE-AAC extension */
12100       if (data_ptr && data_len == 2) {
12101         guint channels, rateindex, rate;
12102
12103         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
12104         channels = (data_ptr[1] & 0x7f) >> 3;
12105         if (channels > 0 && channels < 7) {
12106           stream->n_channels = channels;
12107         } else if (channels == 7) {
12108           stream->n_channels = 8;
12109         }
12110
12111         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
12112         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
12113         if (rate > 0)
12114           stream->rate = rate;
12115       }
12116
12117       /* Set level and profile if possible */
12118       if (data_ptr != NULL && data_len >= 2) {
12119         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12120             data_ptr, data_len);
12121       }
12122       break;
12123     case 0x60:                 /* MPEG-2, various profiles */
12124     case 0x61:
12125     case 0x62:
12126     case 0x63:
12127     case 0x64:
12128     case 0x65:
12129       codec_name = "MPEG-2 video";
12130       caps = gst_caps_new_simple ("video/mpeg",
12131           "mpegversion", G_TYPE_INT, 2,
12132           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12133       break;
12134     case 0x69:                 /* MPEG-2 BC audio */
12135     case 0x6B:                 /* MPEG-1 audio */
12136       caps = gst_caps_new_simple ("audio/mpeg",
12137           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12138       codec_name = "MPEG-1 audio";
12139       break;
12140     case 0x6A:                 /* MPEG-1 */
12141       codec_name = "MPEG-1 video";
12142       caps = gst_caps_new_simple ("video/mpeg",
12143           "mpegversion", G_TYPE_INT, 1,
12144           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12145       break;
12146     case 0x6C:                 /* MJPEG */
12147       caps =
12148           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12149           NULL);
12150       codec_name = "Motion-JPEG";
12151       break;
12152     case 0x6D:                 /* PNG */
12153       caps =
12154           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12155           NULL);
12156       codec_name = "PNG still images";
12157       break;
12158     case 0x6E:                 /* JPEG2000 */
12159       codec_name = "JPEG-2000";
12160       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12161       break;
12162     case 0xA4:                 /* Dirac */
12163       codec_name = "Dirac";
12164       caps = gst_caps_new_empty_simple ("video/x-dirac");
12165       break;
12166     case 0xA5:                 /* AC3 */
12167       codec_name = "AC-3 audio";
12168       caps = gst_caps_new_simple ("audio/x-ac3",
12169           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12170       break;
12171     case 0xA9:                 /* AC3 */
12172       codec_name = "DTS audio";
12173       caps = gst_caps_new_simple ("audio/x-dts",
12174           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12175       break;
12176     case 0xE1:                 /* QCELP */
12177       /* QCELP, the codec_data is a riff tag (little endian) with
12178        * 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). */
12179       caps = gst_caps_new_empty_simple ("audio/qcelp");
12180       codec_name = "QCELP";
12181       break;
12182     default:
12183       break;
12184   }
12185
12186   /* If we have a replacement caps, then change our caps for this stream */
12187   if (caps) {
12188     gst_caps_unref (stream->caps);
12189     stream->caps = caps;
12190   }
12191
12192   if (codec_name && list)
12193     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12194         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12195
12196   /* Add the codec_data attribute to caps, if we have it */
12197   if (data_ptr) {
12198     GstBuffer *buffer;
12199
12200     buffer = gst_buffer_new_and_alloc (data_len);
12201     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12202
12203     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12204     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12205
12206     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12207         buffer, NULL);
12208     gst_buffer_unref (buffer);
12209   }
12210
12211 }
12212
12213 #define _codec(name) \
12214   do { \
12215     if (codec_name) { \
12216       *codec_name = g_strdup (name); \
12217     } \
12218   } while (0)
12219
12220 static GstCaps *
12221 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12222     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12223 {
12224   GstCaps *caps = NULL;
12225   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12226
12227   switch (fourcc) {
12228     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12229       _codec ("PNG still images");
12230       caps = gst_caps_new_empty_simple ("image/png");
12231       break;
12232     case FOURCC_jpeg:
12233       _codec ("JPEG still images");
12234       caps =
12235           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12236           NULL);
12237       break;
12238     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12239     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12240     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12241     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12242       _codec ("Motion-JPEG");
12243       caps =
12244           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12245           NULL);
12246       break;
12247     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12248       _codec ("Motion-JPEG format B");
12249       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12250       break;
12251     case FOURCC_mjp2:
12252       _codec ("JPEG-2000");
12253       /* override to what it should be according to spec, avoid palette_data */
12254       stream->bits_per_sample = 24;
12255       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12256       break;
12257     case FOURCC_SVQ3:
12258       _codec ("Sorensen video v.3");
12259       caps = gst_caps_new_simple ("video/x-svq",
12260           "svqversion", G_TYPE_INT, 3, NULL);
12261       break;
12262     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12263     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12264       _codec ("Sorensen video v.1");
12265       caps = gst_caps_new_simple ("video/x-svq",
12266           "svqversion", G_TYPE_INT, 1, NULL);
12267       break;
12268     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12269       caps = gst_caps_new_empty_simple ("video/x-raw");
12270       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12271       _codec ("Windows Raw RGB");
12272       break;
12273     case FOURCC_raw_:
12274     {
12275       guint16 bps;
12276
12277       bps = QT_UINT16 (stsd_data + 98);
12278       switch (bps) {
12279         case 15:
12280           format = GST_VIDEO_FORMAT_RGB15;
12281           break;
12282         case 16:
12283           format = GST_VIDEO_FORMAT_RGB16;
12284           break;
12285         case 24:
12286           format = GST_VIDEO_FORMAT_RGB;
12287           break;
12288         case 32:
12289           format = GST_VIDEO_FORMAT_ARGB;
12290           break;
12291         default:
12292           /* unknown */
12293           break;
12294       }
12295       break;
12296     }
12297     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12298       format = GST_VIDEO_FORMAT_I420;
12299       break;
12300     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12301     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12302       format = GST_VIDEO_FORMAT_I420;
12303       break;
12304     case FOURCC_2vuy:
12305     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12306       format = GST_VIDEO_FORMAT_UYVY;
12307       break;
12308     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12309       format = GST_VIDEO_FORMAT_v308;
12310       break;
12311     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12312       format = GST_VIDEO_FORMAT_v216;
12313       break;
12314     case FOURCC_v210:
12315       format = GST_VIDEO_FORMAT_v210;
12316       break;
12317     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12318       format = GST_VIDEO_FORMAT_r210;
12319       break;
12320       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12321          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12322          format = GST_VIDEO_FORMAT_v410;
12323          break;
12324        */
12325       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12326        * but different order than AYUV
12327        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12328        format = GST_VIDEO_FORMAT_v408;
12329        break;
12330        */
12331     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12332     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12333       _codec ("MPEG-1 video");
12334       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12335           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12336       break;
12337     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12338     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12339     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12340     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12341     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12342     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12343     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12344     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12345     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12346     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12347     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12348     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12349     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12350     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12351     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12352     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12353     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12354     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12355     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12356     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12357     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12358     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12359     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12360     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12361     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12362     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12363     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12364     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12365     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12366     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12367     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12368     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12369     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12370     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12371     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12372     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12373     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12374     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12375     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12376     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12377     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12378     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12379     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12380     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12381     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12382     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12383       _codec ("MPEG-2 video");
12384       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12385           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12386       break;
12387     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12388       _codec ("GIF still images");
12389       caps = gst_caps_new_empty_simple ("image/gif");
12390       break;
12391     case FOURCC_h263:
12392     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12393     case FOURCC_s263:
12394     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12395       _codec ("H.263");
12396       /* ffmpeg uses the height/width props, don't know why */
12397       caps = gst_caps_new_simple ("video/x-h263",
12398           "variant", G_TYPE_STRING, "itu", NULL);
12399       break;
12400     case FOURCC_mp4v:
12401     case FOURCC_MP4V:
12402       _codec ("MPEG-4 video");
12403       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12404           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12405       break;
12406     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12407     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12408       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12409       caps = gst_caps_new_simple ("video/x-msmpeg",
12410           "msmpegversion", G_TYPE_INT, 43, NULL);
12411       break;
12412     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12413       _codec ("DivX 3");
12414       caps = gst_caps_new_simple ("video/x-divx",
12415           "divxversion", G_TYPE_INT, 3, NULL);
12416       break;
12417     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12418     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12419       _codec ("DivX 4");
12420       caps = gst_caps_new_simple ("video/x-divx",
12421           "divxversion", G_TYPE_INT, 4, NULL);
12422       break;
12423     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12424       _codec ("DivX 5");
12425       caps = gst_caps_new_simple ("video/x-divx",
12426           "divxversion", G_TYPE_INT, 5, NULL);
12427       break;
12428
12429     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12430       _codec ("FFV1");
12431       caps = gst_caps_new_simple ("video/x-ffv",
12432           "ffvversion", G_TYPE_INT, 1, NULL);
12433       break;
12434
12435     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12436     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12437     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12438     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12439     case FOURCC_FMP4:
12440     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12441       caps = gst_caps_new_simple ("video/mpeg",
12442           "mpegversion", G_TYPE_INT, 4, NULL);
12443       _codec ("MPEG-4");
12444       break;
12445
12446     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12447       _codec ("Cinepak");
12448       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12449       break;
12450     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12451       _codec ("Apple QuickDraw");
12452       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12453       break;
12454     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12455       _codec ("Apple video");
12456       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12457       break;
12458     case FOURCC_H264:
12459     case FOURCC_avc1:
12460       _codec ("H.264 / AVC");
12461       caps = gst_caps_new_simple ("video/x-h264",
12462           "stream-format", G_TYPE_STRING, "avc",
12463           "alignment", G_TYPE_STRING, "au", NULL);
12464       break;
12465     case FOURCC_avc3:
12466       _codec ("H.264 / AVC");
12467       caps = gst_caps_new_simple ("video/x-h264",
12468           "stream-format", G_TYPE_STRING, "avc3",
12469           "alignment", G_TYPE_STRING, "au", NULL);
12470       break;
12471     case FOURCC_H265:
12472     case FOURCC_hvc1:
12473       _codec ("H.265 / HEVC");
12474       caps = gst_caps_new_simple ("video/x-h265",
12475           "stream-format", G_TYPE_STRING, "hvc1",
12476           "alignment", G_TYPE_STRING, "au", NULL);
12477       break;
12478     case FOURCC_hev1:
12479       _codec ("H.265 / HEVC");
12480       caps = gst_caps_new_simple ("video/x-h265",
12481           "stream-format", G_TYPE_STRING, "hev1",
12482           "alignment", G_TYPE_STRING, "au", NULL);
12483       break;
12484     case FOURCC_rle_:
12485       _codec ("Run-length encoding");
12486       caps = gst_caps_new_simple ("video/x-rle",
12487           "layout", G_TYPE_STRING, "quicktime", NULL);
12488       break;
12489     case FOURCC_WRLE:
12490       _codec ("Run-length encoding");
12491       caps = gst_caps_new_simple ("video/x-rle",
12492           "layout", G_TYPE_STRING, "microsoft", NULL);
12493       break;
12494     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12495     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12496       _codec ("Indeo Video 3");
12497       caps = gst_caps_new_simple ("video/x-indeo",
12498           "indeoversion", G_TYPE_INT, 3, NULL);
12499       break;
12500     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12501     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12502       _codec ("Intel Video 4");
12503       caps = gst_caps_new_simple ("video/x-indeo",
12504           "indeoversion", G_TYPE_INT, 4, NULL);
12505       break;
12506     case FOURCC_dvcp:
12507     case FOURCC_dvc_:
12508     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12509     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12510     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12511     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12512     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12513     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12514       _codec ("DV Video");
12515       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12516           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12517       break;
12518     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12519     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12520       _codec ("DVCPro50 Video");
12521       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12522           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12523       break;
12524     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12525     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12526       _codec ("DVCProHD Video");
12527       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12528           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12529       break;
12530     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12531       _codec ("Apple Graphics (SMC)");
12532       caps = gst_caps_new_empty_simple ("video/x-smc");
12533       break;
12534     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12535       _codec ("VP3");
12536       caps = gst_caps_new_empty_simple ("video/x-vp3");
12537       break;
12538     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12539       _codec ("VP6 Flash");
12540       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12541       break;
12542     case FOURCC_XiTh:
12543       _codec ("Theora");
12544       caps = gst_caps_new_empty_simple ("video/x-theora");
12545       /* theora uses one byte of padding in the data stream because it does not
12546        * allow 0 sized packets while theora does */
12547       stream->padding = 1;
12548       break;
12549     case FOURCC_drac:
12550       _codec ("Dirac");
12551       caps = gst_caps_new_empty_simple ("video/x-dirac");
12552       break;
12553     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12554       _codec ("TIFF still images");
12555       caps = gst_caps_new_empty_simple ("image/tiff");
12556       break;
12557     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12558       _codec ("Apple Intermediate Codec");
12559       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12560       break;
12561     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12562       _codec ("AVID DNxHD");
12563       caps = gst_caps_from_string ("video/x-dnxhd");
12564       break;
12565     case FOURCC_VP80:
12566       _codec ("On2 VP8");
12567       caps = gst_caps_from_string ("video/x-vp8");
12568       break;
12569     case FOURCC_apcs:
12570       _codec ("Apple ProRes LT");
12571       caps =
12572           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12573           NULL);
12574       break;
12575     case FOURCC_apch:
12576       _codec ("Apple ProRes HQ");
12577       caps =
12578           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12579           NULL);
12580       break;
12581     case FOURCC_apcn:
12582       _codec ("Apple ProRes");
12583       caps =
12584           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12585           "standard", NULL);
12586       break;
12587     case FOURCC_apco:
12588       _codec ("Apple ProRes Proxy");
12589       caps =
12590           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12591           "proxy", NULL);
12592       break;
12593     case FOURCC_ap4h:
12594       _codec ("Apple ProRes 4444");
12595       caps =
12596           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12597           "4444", NULL);
12598       break;
12599     case FOURCC_vc_1:
12600     case FOURCC_ovc1:
12601       _codec ("VC-1");
12602       caps = gst_caps_new_simple ("video/x-wmv",
12603           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12604       break;
12605     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12606     default:
12607     {
12608       char *s, fourstr[5];
12609
12610       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12611       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12612       caps = gst_caps_new_empty_simple (s);
12613       g_free (s);
12614       break;
12615     }
12616   }
12617
12618   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12619     GstVideoInfo info;
12620
12621     gst_video_info_init (&info);
12622     gst_video_info_set_format (&info, format, stream->width, stream->height);
12623
12624     caps = gst_video_info_to_caps (&info);
12625     *codec_name = gst_pb_utils_get_codec_description (caps);
12626
12627     /* enable clipping for raw video streams */
12628     stream->need_clip = TRUE;
12629   }
12630
12631   return caps;
12632 }
12633
12634 static GstCaps *
12635 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12636     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12637 {
12638   GstCaps *caps;
12639   const GstStructure *s;
12640   const gchar *name;
12641   gint endian = 0;
12642   GstAudioFormat format = 0;
12643   gint depth;
12644
12645   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12646
12647   depth = stream->bytes_per_packet * 8;
12648
12649   switch (fourcc) {
12650     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12651     case FOURCC_raw_:
12652       /* 8-bit audio is unsigned */
12653       if (depth == 8)
12654         format = GST_AUDIO_FORMAT_U8;
12655       /* otherwise it's signed and big-endian just like 'twos' */
12656     case FOURCC_twos:
12657       endian = G_BIG_ENDIAN;
12658       /* fall-through */
12659     case FOURCC_sowt:
12660     {
12661       gchar *str;
12662
12663       if (!endian)
12664         endian = G_LITTLE_ENDIAN;
12665
12666       if (!format)
12667         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
12668
12669       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
12670       _codec (str);
12671       g_free (str);
12672
12673       caps = gst_caps_new_simple ("audio/x-raw",
12674           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12675           "layout", G_TYPE_STRING, "interleaved", NULL);
12676       break;
12677     }
12678     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
12679       _codec ("Raw 64-bit floating-point audio");
12680       caps = gst_caps_new_simple ("audio/x-raw",
12681           "format", G_TYPE_STRING, "F64BE",
12682           "layout", G_TYPE_STRING, "interleaved", NULL);
12683       break;
12684     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
12685       _codec ("Raw 32-bit floating-point audio");
12686       caps = gst_caps_new_simple ("audio/x-raw",
12687           "format", G_TYPE_STRING, "F32BE",
12688           "layout", G_TYPE_STRING, "interleaved", NULL);
12689       break;
12690     case FOURCC_in24:
12691       _codec ("Raw 24-bit PCM audio");
12692       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
12693        * endian later */
12694       caps = gst_caps_new_simple ("audio/x-raw",
12695           "format", G_TYPE_STRING, "S24BE",
12696           "layout", G_TYPE_STRING, "interleaved", NULL);
12697       break;
12698     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
12699       _codec ("Raw 32-bit PCM audio");
12700       caps = gst_caps_new_simple ("audio/x-raw",
12701           "format", G_TYPE_STRING, "S32BE",
12702           "layout", G_TYPE_STRING, "interleaved", NULL);
12703       break;
12704     case FOURCC_ulaw:
12705       _codec ("Mu-law audio");
12706       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
12707       break;
12708     case FOURCC_alaw:
12709       _codec ("A-law audio");
12710       caps = gst_caps_new_empty_simple ("audio/x-alaw");
12711       break;
12712     case 0x0200736d:
12713     case 0x6d730002:
12714       _codec ("Microsoft ADPCM");
12715       /* Microsoft ADPCM-ACM code 2 */
12716       caps = gst_caps_new_simple ("audio/x-adpcm",
12717           "layout", G_TYPE_STRING, "microsoft", NULL);
12718       break;
12719     case 0x1100736d:
12720     case 0x6d730011:
12721       _codec ("DVI/IMA ADPCM");
12722       caps = gst_caps_new_simple ("audio/x-adpcm",
12723           "layout", G_TYPE_STRING, "dvi", NULL);
12724       break;
12725     case 0x1700736d:
12726     case 0x6d730017:
12727       _codec ("DVI/Intel IMA ADPCM");
12728       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
12729       caps = gst_caps_new_simple ("audio/x-adpcm",
12730           "layout", G_TYPE_STRING, "quicktime", NULL);
12731       break;
12732     case 0x5500736d:
12733     case 0x6d730055:
12734       /* MPEG layer 3, CBR only (pre QT4.1) */
12735     case FOURCC__mp3:
12736       _codec ("MPEG-1 layer 3");
12737       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
12738       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
12739           "mpegversion", G_TYPE_INT, 1, NULL);
12740       break;
12741     case 0x20736d:
12742     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
12743       _codec ("EAC-3 audio");
12744       caps = gst_caps_new_simple ("audio/x-eac3",
12745           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12746       stream->sampled = TRUE;
12747       break;
12748     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
12749     case FOURCC_ac_3:
12750       _codec ("AC-3 audio");
12751       caps = gst_caps_new_simple ("audio/x-ac3",
12752           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12753       stream->sampled = TRUE;
12754       break;
12755     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
12756     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
12757       _codec ("DTS audio");
12758       caps = gst_caps_new_simple ("audio/x-dts",
12759           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12760       stream->sampled = TRUE;
12761       break;
12762     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
12763     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
12764       _codec ("DTS-HD audio");
12765       caps = gst_caps_new_simple ("audio/x-dts",
12766           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12767       stream->sampled = TRUE;
12768       break;
12769     case FOURCC_MAC3:
12770       _codec ("MACE-3");
12771       caps = gst_caps_new_simple ("audio/x-mace",
12772           "maceversion", G_TYPE_INT, 3, NULL);
12773       break;
12774     case FOURCC_MAC6:
12775       _codec ("MACE-6");
12776       caps = gst_caps_new_simple ("audio/x-mace",
12777           "maceversion", G_TYPE_INT, 6, NULL);
12778       break;
12779     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
12780       /* ogg/vorbis */
12781       caps = gst_caps_new_empty_simple ("application/ogg");
12782       break;
12783     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
12784       _codec ("DV audio");
12785       caps = gst_caps_new_empty_simple ("audio/x-dv");
12786       break;
12787     case FOURCC_mp4a:
12788       _codec ("MPEG-4 AAC audio");
12789       caps = gst_caps_new_simple ("audio/mpeg",
12790           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
12791           "stream-format", G_TYPE_STRING, "raw", NULL);
12792       break;
12793     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
12794       _codec ("QDesign Music");
12795       caps = gst_caps_new_empty_simple ("audio/x-qdm");
12796       break;
12797     case FOURCC_QDM2:
12798       _codec ("QDesign Music v.2");
12799       /* FIXME: QDesign music version 2 (no constant) */
12800       if (FALSE && data) {
12801         caps = gst_caps_new_simple ("audio/x-qdm2",
12802             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
12803             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
12804             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
12805       } else {
12806         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
12807       }
12808       break;
12809     case FOURCC_agsm:
12810       _codec ("GSM audio");
12811       caps = gst_caps_new_empty_simple ("audio/x-gsm");
12812       break;
12813     case FOURCC_samr:
12814       _codec ("AMR audio");
12815       caps = gst_caps_new_empty_simple ("audio/AMR");
12816       break;
12817     case FOURCC_sawb:
12818       _codec ("AMR-WB audio");
12819       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
12820       break;
12821     case FOURCC_ima4:
12822       _codec ("Quicktime IMA ADPCM");
12823       caps = gst_caps_new_simple ("audio/x-adpcm",
12824           "layout", G_TYPE_STRING, "quicktime", NULL);
12825       break;
12826     case FOURCC_alac:
12827       _codec ("Apple lossless audio");
12828       caps = gst_caps_new_empty_simple ("audio/x-alac");
12829       break;
12830     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
12831       _codec ("QualComm PureVoice");
12832       caps = gst_caps_from_string ("audio/qcelp");
12833       break;
12834     case FOURCC_wma_:
12835     case FOURCC_owma:
12836       _codec ("WMA");
12837       caps = gst_caps_new_empty_simple ("audio/x-wma");
12838       break;
12839     case FOURCC_opus:
12840       _codec ("Opus");
12841       caps = gst_caps_new_empty_simple ("audio/x-opus");
12842       break;
12843     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
12844     {
12845       guint32 flags = 0;
12846       guint32 depth = 0;
12847       guint32 width = 0;
12848       GstAudioFormat format;
12849       enum
12850       {
12851         FLAG_IS_FLOAT = 0x1,
12852         FLAG_IS_BIG_ENDIAN = 0x2,
12853         FLAG_IS_SIGNED = 0x4,
12854         FLAG_IS_PACKED = 0x8,
12855         FLAG_IS_ALIGNED_HIGH = 0x10,
12856         FLAG_IS_NON_INTERLEAVED = 0x20
12857       };
12858       _codec ("Raw LPCM audio");
12859
12860       if (data && len >= 56) {
12861         depth = QT_UINT32 (data + 40);
12862         flags = QT_UINT32 (data + 44);
12863         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
12864       }
12865       if ((flags & FLAG_IS_FLOAT) == 0) {
12866         if (depth == 0)
12867           depth = 16;
12868         if (width == 0)
12869           width = 16;
12870         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
12871             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
12872             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
12873         caps = gst_caps_new_simple ("audio/x-raw",
12874             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12875             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12876             "non-interleaved" : "interleaved", NULL);
12877       } else {
12878         if (width == 0)
12879           width = 32;
12880         if (width == 64) {
12881           if (flags & FLAG_IS_BIG_ENDIAN)
12882             format = GST_AUDIO_FORMAT_F64BE;
12883           else
12884             format = GST_AUDIO_FORMAT_F64LE;
12885         } else {
12886           if (flags & FLAG_IS_BIG_ENDIAN)
12887             format = GST_AUDIO_FORMAT_F32BE;
12888           else
12889             format = GST_AUDIO_FORMAT_F32LE;
12890         }
12891         caps = gst_caps_new_simple ("audio/x-raw",
12892             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12893             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12894             "non-interleaved" : "interleaved", NULL);
12895       }
12896       break;
12897     }
12898     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
12899       /* ? */
12900     default:
12901     {
12902       char *s, fourstr[5];
12903
12904       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12905       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
12906       caps = gst_caps_new_empty_simple (s);
12907       g_free (s);
12908       break;
12909     }
12910   }
12911
12912   if (caps) {
12913     GstCaps *templ_caps =
12914         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
12915     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
12916     gst_caps_unref (caps);
12917     gst_caps_unref (templ_caps);
12918     caps = intersection;
12919   }
12920
12921   /* enable clipping for raw audio streams */
12922   s = gst_caps_get_structure (caps, 0);
12923   name = gst_structure_get_name (s);
12924   if (g_str_has_prefix (name, "audio/x-raw")) {
12925     stream->need_clip = TRUE;
12926     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
12927     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
12928   }
12929   return caps;
12930 }
12931
12932 static GstCaps *
12933 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12934     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12935 {
12936   GstCaps *caps;
12937
12938   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12939
12940   switch (fourcc) {
12941     case FOURCC_mp4s:
12942       _codec ("DVD subtitle");
12943       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12944       stream->need_process = TRUE;
12945       break;
12946     case FOURCC_text:
12947       _codec ("Quicktime timed text");
12948       goto text;
12949     case FOURCC_tx3g:
12950       _codec ("3GPP timed text");
12951     text:
12952       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12953           "utf8", NULL);
12954       /* actual text piece needs to be extracted */
12955       stream->need_process = TRUE;
12956       break;
12957     case FOURCC_stpp:
12958       _codec ("XML subtitles");
12959       caps = gst_caps_new_empty_simple ("application/ttml+xml");
12960       break;
12961     default:
12962     {
12963       char *s, fourstr[5];
12964
12965       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12966       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12967       caps = gst_caps_new_empty_simple (s);
12968       g_free (s);
12969       break;
12970     }
12971   }
12972   return caps;
12973 }
12974
12975 static GstCaps *
12976 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12977     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12978 {
12979   GstCaps *caps;
12980
12981   switch (fourcc) {
12982     case FOURCC_m1v:
12983       _codec ("MPEG 1 video");
12984       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12985           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12986       break;
12987     default:
12988       caps = NULL;
12989       break;
12990   }
12991   return caps;
12992 }
12993
12994 static void
12995 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
12996     const gchar * system_id)
12997 {
12998   gint i;
12999
13000   if (!qtdemux->protection_system_ids)
13001     qtdemux->protection_system_ids =
13002         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13003   /* Check whether we already have an entry for this system ID. */
13004   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13005     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13006     if (g_ascii_strcasecmp (system_id, id) == 0) {
13007       return;
13008     }
13009   }
13010   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13011   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13012           -1));
13013 }