qtdemux: don't push encrypted buffer without cenc metadata
[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   const guint8 *aux_info_type_data = NULL;
3169
3170   g_return_val_if_fail (qtdemux != NULL, FALSE);
3171   g_return_val_if_fail (stream != NULL, FALSE);
3172   g_return_val_if_fail (br != NULL, FALSE);
3173   g_return_val_if_fail (offset != NULL, FALSE);
3174
3175   if (!gst_byte_reader_get_uint8 (br, &version))
3176     return FALSE;
3177
3178   if (!gst_byte_reader_get_uint24_be (br, &flags))
3179     return FALSE;
3180
3181   if (flags & 0x1) {
3182
3183     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3184       return FALSE;
3185     aux_info_type = QT_FOURCC (aux_info_type_data);
3186
3187     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3188       return FALSE;
3189   } else if (stream->protected) {
3190     aux_info_type = stream->protection_scheme_type;
3191   } else {
3192     aux_info_type = stream->fourcc;
3193   }
3194
3195   if (info_type)
3196     *info_type = aux_info_type;
3197   if (info_type_parameter)
3198     *info_type_parameter = aux_info_type_parameter;
3199
3200   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3201       "aux_info_type_parameter:  %#06x",
3202       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3203
3204   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3205     return FALSE;
3206
3207   if (entry_count != 1) {
3208     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3209     return FALSE;
3210   }
3211
3212   if (version == 0) {
3213     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3214       return FALSE;
3215     *offset = (guint64) off_32;
3216   } else {
3217     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3218       return FALSE;
3219     *offset = off_64;
3220   }
3221
3222   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3223   return TRUE;
3224 }
3225
3226 static void
3227 qtdemux_gst_structure_free (GstStructure * gststructure)
3228 {
3229   if (gststructure) {
3230     gst_structure_free (gststructure);
3231   }
3232 }
3233
3234 /* Parses auxiliary information relating to samples protected using Common
3235  * Encryption (cenc); the format of this information is defined in
3236  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3237 static gboolean
3238 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3239     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3240 {
3241   QtDemuxCencSampleSetInfo *ss_info = NULL;
3242   guint8 size;
3243   gint i;
3244
3245   g_return_val_if_fail (qtdemux != NULL, FALSE);
3246   g_return_val_if_fail (stream != NULL, FALSE);
3247   g_return_val_if_fail (br != NULL, FALSE);
3248   g_return_val_if_fail (stream->protected, FALSE);
3249   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3250
3251   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3252
3253   if (ss_info->crypto_info) {
3254     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3255     g_ptr_array_free (ss_info->crypto_info, TRUE);
3256   }
3257
3258   ss_info->crypto_info =
3259       g_ptr_array_new_full (sample_count,
3260       (GDestroyNotify) qtdemux_gst_structure_free);
3261
3262   for (i = 0; i < sample_count; ++i) {
3263     GstStructure *properties;
3264     guint16 n_subsamples = 0;
3265     guint8 *data;
3266     guint iv_size;
3267     GstBuffer *buf;
3268
3269     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3270     if (properties == NULL) {
3271       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3272       return FALSE;
3273     }
3274     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3275       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3276       gst_structure_free (properties);
3277       return FALSE;
3278     }
3279     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3280       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3281       gst_structure_free (properties);
3282       return FALSE;
3283     }
3284     buf = gst_buffer_new_wrapped (data, iv_size);
3285     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3286     gst_buffer_unref (buf);
3287     size = info_sizes[i];
3288     if (size > iv_size) {
3289       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3290           || !(n_subsamples > 0)) {
3291         gst_structure_free (properties);
3292         GST_ERROR_OBJECT (qtdemux,
3293             "failed to get subsample count for sample %u", i);
3294         return FALSE;
3295       }
3296       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3297       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3298         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3299             i);
3300         gst_structure_free (properties);
3301         return FALSE;
3302       }
3303       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3304       if (!buf) {
3305         gst_structure_free (properties);
3306         return FALSE;
3307       }
3308       gst_structure_set (properties,
3309           "subsample_count", G_TYPE_UINT, n_subsamples,
3310           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3311       gst_buffer_unref (buf);
3312     } else {
3313       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3314     }
3315     g_ptr_array_add (ss_info->crypto_info, properties);
3316   }
3317   return TRUE;
3318 }
3319
3320 /* Converts a UUID in raw byte form to a string representation, as defined in
3321  * RFC 4122. The caller takes ownership of the returned string and is
3322  * responsible for freeing it after use. */
3323 static gchar *
3324 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3325 {
3326   const guint8 *uuid = (const guint8 *) uuid_bytes;
3327
3328   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3329       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3330       uuid[0], uuid[1], uuid[2], uuid[3],
3331       uuid[4], uuid[5], uuid[6], uuid[7],
3332       uuid[8], uuid[9], uuid[10], uuid[11],
3333       uuid[12], uuid[13], uuid[14], uuid[15]);
3334 }
3335
3336 /* Parses a Protection System Specific Header box (pssh), as defined in the
3337  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3338  * information needed by a specific content protection system in order to
3339  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3340  * otherwise. */
3341 static gboolean
3342 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3343 {
3344   gchar *sysid_string;
3345   guint32 pssh_size = QT_UINT32 (node->data);
3346   GstBuffer *pssh = NULL;
3347   GstEvent *event = NULL;
3348   guint32 parent_box_type;
3349   gint i;
3350
3351   if (G_UNLIKELY (pssh_size < 32U)) {
3352     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3353     return FALSE;
3354   }
3355
3356   sysid_string =
3357       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3358
3359   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3360
3361   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3362   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3363       gst_buffer_get_size (pssh));
3364
3365   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3366
3367   /* Push an event containing the pssh box onto the queues of all streams. */
3368   event = gst_event_new_protection (sysid_string, pssh,
3369       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3370   for (i = 0; i < qtdemux->n_streams; ++i) {
3371     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3372         gst_event_ref (event));
3373   }
3374   g_free (sysid_string);
3375   gst_event_unref (event);
3376   gst_buffer_unref (pssh);
3377   return TRUE;
3378 }
3379
3380 static gboolean
3381 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3382     guint64 moof_offset, QtDemuxStream * stream)
3383 {
3384   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3385   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3386   GNode *saiz_node, *saio_node, *pssh_node;
3387   GstByteReader saiz_data, saio_data;
3388   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3389   gint64 base_offset, running_offset;
3390   guint32 frag_num;
3391
3392   /* NOTE @stream ignored */
3393
3394   moof_node = g_node_new ((guint8 *) buffer);
3395   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3396   qtdemux_node_dump (qtdemux, moof_node);
3397
3398   /* Get fragment number from mfhd and check it's valid */
3399   mfhd_node =
3400       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3401   if (mfhd_node == NULL)
3402     goto missing_mfhd;
3403   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3404     goto fail;
3405   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3406
3407   /* unknown base_offset to start with */
3408   base_offset = running_offset = -1;
3409   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3410   while (traf_node) {
3411     guint64 decode_time = 0;
3412
3413     /* Fragment Header node */
3414     tfhd_node =
3415         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3416         &tfhd_data);
3417     if (!tfhd_node)
3418       goto missing_tfhd;
3419     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3420             &ds_size, &ds_flags, &base_offset))
3421       goto missing_tfhd;
3422
3423     /* The following code assumes at most a single set of sample auxiliary
3424      * data in the fragment (consisting of a saiz box and a corresponding saio
3425      * box); in theory, however, there could be multiple sets of sample
3426      * auxiliary data in a fragment. */
3427     saiz_node =
3428         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3429         &saiz_data);
3430     if (saiz_node) {
3431       guint32 info_type = 0;
3432       guint64 offset = 0;
3433       guint32 info_type_parameter = 0;
3434
3435       g_free (qtdemux->cenc_aux_info_sizes);
3436
3437       qtdemux->cenc_aux_info_sizes =
3438           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3439           &qtdemux->cenc_aux_sample_count);
3440       if (qtdemux->cenc_aux_info_sizes == NULL) {
3441         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3442         goto fail;
3443       }
3444       saio_node =
3445           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3446           &saio_data);
3447       if (!saio_node) {
3448         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3449         g_free (qtdemux->cenc_aux_info_sizes);
3450         qtdemux->cenc_aux_info_sizes = NULL;
3451         goto fail;
3452       }
3453
3454       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3455                   &info_type, &info_type_parameter, &offset))) {
3456         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3457         g_free (qtdemux->cenc_aux_info_sizes);
3458         qtdemux->cenc_aux_info_sizes = NULL;
3459         goto fail;
3460       }
3461       if (base_offset > qtdemux->moof_offset)
3462         offset += (guint64) (base_offset - qtdemux->moof_offset);
3463       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3464         GstByteReader br;
3465         if (offset > length) {
3466           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3467           qtdemux->cenc_aux_info_offset = offset;
3468         } else {
3469           gst_byte_reader_init (&br, buffer + offset, length - offset);
3470           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3471                   qtdemux->cenc_aux_info_sizes,
3472                   qtdemux->cenc_aux_sample_count)) {
3473             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3474             g_free (qtdemux->cenc_aux_info_sizes);
3475             qtdemux->cenc_aux_info_sizes = NULL;
3476             goto fail;
3477           }
3478         }
3479       }
3480     }
3481
3482     tfdt_node =
3483         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3484         &tfdt_data);
3485     if (tfdt_node) {
3486       GstClockTime decode_time_ts;
3487
3488       /* We'll use decode_time to interpolate timestamps
3489        * in case the input timestamps are missing */
3490       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3491
3492       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3493
3494       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3495           " (%" GST_TIME_FORMAT ")", decode_time,
3496           GST_TIME_ARGS (decode_time_ts));
3497
3498       /* Discard the fragment buffer timestamp info to avoid using it.
3499        * Rely on tfdt instead as it is more accurate than the timestamp
3500        * that is fetched from a manifest/playlist and is usually
3501        * less accurate. */
3502       qtdemux->fragment_start = -1;
3503     }
3504
3505     if (G_UNLIKELY (!stream)) {
3506       /* we lost track of offset, we'll need to regain it,
3507        * but can delay complaining until later or avoid doing so altogether */
3508       base_offset = -2;
3509       goto next;
3510     }
3511     if (G_UNLIKELY (base_offset < -1))
3512       goto lost_offset;
3513
3514     if (qtdemux->upstream_format_is_time)
3515       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3516
3517     /* initialise moof sample data */
3518     stream->n_samples_moof = 0;
3519     stream->duration_moof = 0;
3520
3521     /* Track Run node */
3522     trun_node =
3523         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3524         &trun_data);
3525     while (trun_node) {
3526       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3527           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3528           &running_offset, decode_time);
3529       /* iterate all siblings */
3530       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3531           &trun_data);
3532     }
3533     /* if no new base_offset provided for next traf,
3534      * base is end of current traf */
3535     base_offset = running_offset;
3536     running_offset = -1;
3537
3538     if (stream->n_samples_moof && stream->duration_moof)
3539       stream->new_caps = TRUE;
3540
3541   next:
3542     /* iterate all siblings */
3543     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3544   }
3545
3546   /* parse any protection system info */
3547   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3548   while (pssh_node) {
3549     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3550     qtdemux_parse_pssh (qtdemux, pssh_node);
3551     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3552   }
3553
3554   g_node_destroy (moof_node);
3555   return TRUE;
3556
3557 missing_tfhd:
3558   {
3559     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3560     goto fail;
3561   }
3562 missing_mfhd:
3563   {
3564     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3565     goto fail;
3566   }
3567 lost_offset:
3568   {
3569     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3570     goto fail;
3571   }
3572 fail:
3573   {
3574     g_node_destroy (moof_node);
3575     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3576         (_("This file is corrupt and cannot be played.")), (NULL));
3577     return FALSE;
3578   }
3579 }
3580
3581 #if 0
3582 /* might be used if some day we actually use mfra & co
3583  * for random access to fragments,
3584  * but that will require quite some modifications and much less relying
3585  * on a sample array */
3586 #endif
3587
3588 static gboolean
3589 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3590 {
3591   QtDemuxStream *stream;
3592   guint32 ver_flags, track_id, len, num_entries, i;
3593   guint value_size, traf_size, trun_size, sample_size;
3594   guint64 time = 0, moof_offset = 0;
3595 #if 0
3596   GstBuffer *buf = NULL;
3597   GstFlowReturn ret;
3598 #endif
3599   GstByteReader tfra;
3600
3601   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3602
3603   if (!gst_byte_reader_skip (&tfra, 8))
3604     return FALSE;
3605
3606   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3607     return FALSE;
3608
3609   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3610       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3611       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3612     return FALSE;
3613
3614   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3615
3616   stream = qtdemux_find_stream (qtdemux, track_id);
3617   if (stream == NULL)
3618     goto unknown_trackid;
3619
3620   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3621   sample_size = (len & 3) + 1;
3622   trun_size = ((len & 12) >> 2) + 1;
3623   traf_size = ((len & 48) >> 4) + 1;
3624
3625   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3626       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3627
3628   if (num_entries == 0)
3629     goto no_samples;
3630
3631   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3632           value_size + value_size + traf_size + trun_size + sample_size))
3633     goto corrupt_file;
3634
3635   g_free (stream->ra_entries);
3636   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3637   stream->n_ra_entries = num_entries;
3638
3639   for (i = 0; i < num_entries; i++) {
3640     qt_atom_parser_get_offset (&tfra, value_size, &time);
3641     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3642     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3643     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3644     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3645
3646     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3647
3648     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3649         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3650
3651     stream->ra_entries[i].ts = time;
3652     stream->ra_entries[i].moof_offset = moof_offset;
3653
3654     /* don't want to go through the entire file and read all moofs at startup */
3655 #if 0
3656     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3657     if (ret != GST_FLOW_OK)
3658       goto corrupt_file;
3659     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3660         moof_offset, stream);
3661     gst_buffer_unref (buf);
3662 #endif
3663   }
3664
3665   check_update_duration (qtdemux, time);
3666
3667   return TRUE;
3668
3669 /* ERRORS */
3670 unknown_trackid:
3671   {
3672     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3673     return FALSE;
3674   }
3675 corrupt_file:
3676   {
3677     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3678     return FALSE;
3679   }
3680 no_samples:
3681   {
3682     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3683     return FALSE;
3684   }
3685 }
3686
3687 static gboolean
3688 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3689 {
3690   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3691   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3692   GstBuffer *mfro = NULL, *mfra = NULL;
3693   GstFlowReturn flow;
3694   gboolean ret = FALSE;
3695   GNode *mfra_node, *tfra_node;
3696   guint64 mfra_offset = 0;
3697   guint32 fourcc, mfra_size;
3698   gint64 len;
3699
3700   /* query upstream size in bytes */
3701   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3702     goto size_query_failed;
3703
3704   /* mfro box should be at the very end of the file */
3705   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3706   if (flow != GST_FLOW_OK)
3707     goto exit;
3708
3709   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3710
3711   fourcc = QT_FOURCC (mfro_map.data + 4);
3712   if (fourcc != FOURCC_mfro)
3713     goto exit;
3714
3715   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3716   if (mfro_map.size < 16)
3717     goto invalid_mfro_size;
3718
3719   mfra_size = QT_UINT32 (mfro_map.data + 12);
3720   if (mfra_size >= len)
3721     goto invalid_mfra_size;
3722
3723   mfra_offset = len - mfra_size;
3724
3725   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3726       mfra_offset, mfra_size);
3727
3728   /* now get and parse mfra box */
3729   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3730   if (flow != GST_FLOW_OK)
3731     goto broken_file;
3732
3733   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3734
3735   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3736   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3737
3738   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3739
3740   while (tfra_node) {
3741     qtdemux_parse_tfra (qtdemux, tfra_node);
3742     /* iterate all siblings */
3743     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3744   }
3745   g_node_destroy (mfra_node);
3746
3747   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3748   ret = TRUE;
3749
3750 exit:
3751
3752   if (mfro) {
3753     if (mfro_map.memory != NULL)
3754       gst_buffer_unmap (mfro, &mfro_map);
3755     gst_buffer_unref (mfro);
3756   }
3757   if (mfra) {
3758     if (mfra_map.memory != NULL)
3759       gst_buffer_unmap (mfra, &mfra_map);
3760     gst_buffer_unref (mfra);
3761   }
3762   return ret;
3763
3764 /* ERRORS */
3765 size_query_failed:
3766   {
3767     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3768     goto exit;
3769   }
3770 invalid_mfro_size:
3771   {
3772     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3773     goto exit;
3774   }
3775 invalid_mfra_size:
3776   {
3777     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3778     goto exit;
3779   }
3780 broken_file:
3781   {
3782     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3783     goto exit;
3784   }
3785 }
3786
3787 static guint64
3788 add_offset (guint64 offset, guint64 advance)
3789 {
3790   /* Avoid 64-bit overflow by clamping */
3791   if (offset > G_MAXUINT64 - advance)
3792     return G_MAXUINT64;
3793   return offset + advance;
3794 }
3795
3796 static GstFlowReturn
3797 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
3798 {
3799   guint64 length = 0;
3800   guint32 fourcc = 0;
3801   GstBuffer *buf = NULL;
3802   GstFlowReturn ret = GST_FLOW_OK;
3803   guint64 cur_offset = qtdemux->offset;
3804   GstMapInfo map;
3805
3806   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
3807   if (G_UNLIKELY (ret != GST_FLOW_OK))
3808     goto beach;
3809   gst_buffer_map (buf, &map, GST_MAP_READ);
3810   if (G_LIKELY (map.size >= 8))
3811     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
3812   gst_buffer_unmap (buf, &map);
3813   gst_buffer_unref (buf);
3814
3815   /* maybe we already got most we needed, so only consider this eof */
3816   if (G_UNLIKELY (length == 0)) {
3817     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
3818         (_("Invalid atom size.")),
3819         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
3820             GST_FOURCC_ARGS (fourcc)));
3821     ret = GST_FLOW_EOS;
3822     goto beach;
3823   }
3824
3825   switch (fourcc) {
3826     case FOURCC_moof:
3827       /* record for later parsing when needed */
3828       if (!qtdemux->moof_offset) {
3829         qtdemux->moof_offset = qtdemux->offset;
3830       }
3831       if (qtdemux_pull_mfro_mfra (qtdemux)) {
3832         /* FIXME */
3833       } else {
3834         qtdemux->offset += length;      /* skip moof and keep going */
3835       }
3836       if (qtdemux->got_moov) {
3837         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3838         ret = GST_FLOW_EOS;
3839         goto beach;
3840       }
3841       break;
3842     case FOURCC_mdat:
3843     case FOURCC_free:
3844     case FOURCC_wide:
3845     case FOURCC_PICT:
3846     case FOURCC_pnot:
3847     {
3848       GST_LOG_OBJECT (qtdemux,
3849           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3850           GST_FOURCC_ARGS (fourcc), cur_offset);
3851       qtdemux->offset = add_offset (qtdemux->offset, length);
3852       break;
3853     }
3854     case FOURCC_moov:
3855     {
3856       GstBuffer *moov = NULL;
3857
3858       if (qtdemux->got_moov) {
3859         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3860         qtdemux->offset = add_offset (qtdemux->offset, length);
3861         goto beach;
3862       }
3863
3864       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3865       if (ret != GST_FLOW_OK)
3866         goto beach;
3867       gst_buffer_map (moov, &map, GST_MAP_READ);
3868
3869       if (length != map.size) {
3870         /* Some files have a 'moov' atom at the end of the file which contains
3871          * a terminal 'free' atom where the body of the atom is missing.
3872          * Check for, and permit, this special case.
3873          */
3874         if (map.size >= 8) {
3875           guint8 *final_data = map.data + (map.size - 8);
3876           guint32 final_length = QT_UINT32 (final_data);
3877           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3878
3879           if (final_fourcc == FOURCC_free
3880               && map.size + final_length - 8 == length) {
3881             /* Ok, we've found that special case. Allocate a new buffer with
3882              * that free atom actually present. */
3883             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3884             gst_buffer_fill (newmoov, 0, map.data, map.size);
3885             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3886             gst_buffer_unmap (moov, &map);
3887             gst_buffer_unref (moov);
3888             moov = newmoov;
3889             gst_buffer_map (moov, &map, GST_MAP_READ);
3890           }
3891         }
3892       }
3893
3894       if (length != map.size) {
3895         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3896             (_("This file is incomplete and cannot be played.")),
3897             ("We got less than expected (received %" G_GSIZE_FORMAT
3898                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3899                 (guint) length, cur_offset));
3900         gst_buffer_unmap (moov, &map);
3901         gst_buffer_unref (moov);
3902         ret = GST_FLOW_ERROR;
3903         goto beach;
3904       }
3905       qtdemux->offset += length;
3906
3907       qtdemux_parse_moov (qtdemux, map.data, length);
3908       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3909
3910       qtdemux_parse_tree (qtdemux);
3911       g_node_destroy (qtdemux->moov_node);
3912       gst_buffer_unmap (moov, &map);
3913       gst_buffer_unref (moov);
3914       qtdemux->moov_node = NULL;
3915       qtdemux->got_moov = TRUE;
3916
3917       break;
3918     }
3919     case FOURCC_ftyp:
3920     {
3921       GstBuffer *ftyp = NULL;
3922
3923       /* extract major brand; might come in handy for ISO vs QT issues */
3924       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3925       if (ret != GST_FLOW_OK)
3926         goto beach;
3927       qtdemux->offset += length;
3928       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3929       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3930       gst_buffer_unmap (ftyp, &map);
3931       gst_buffer_unref (ftyp);
3932       break;
3933     }
3934     case FOURCC_uuid:
3935     {
3936       GstBuffer *uuid = NULL;
3937
3938       /* uuid are extension atoms */
3939       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3940       if (ret != GST_FLOW_OK)
3941         goto beach;
3942       qtdemux->offset += length;
3943       gst_buffer_map (uuid, &map, GST_MAP_READ);
3944       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3945       gst_buffer_unmap (uuid, &map);
3946       gst_buffer_unref (uuid);
3947       break;
3948     }
3949     case FOURCC_sidx:
3950     {
3951       GstBuffer *sidx = NULL;
3952       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3953       if (ret != GST_FLOW_OK)
3954         goto beach;
3955       qtdemux->offset += length;
3956       gst_buffer_map (sidx, &map, GST_MAP_READ);
3957       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3958       gst_buffer_unmap (sidx, &map);
3959       gst_buffer_unref (sidx);
3960       break;
3961     }
3962     default:
3963     {
3964       GstBuffer *unknown = NULL;
3965
3966       GST_LOG_OBJECT (qtdemux,
3967           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3968           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3969           cur_offset);
3970       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3971       if (ret != GST_FLOW_OK)
3972         goto beach;
3973       gst_buffer_map (unknown, &map, GST_MAP_READ);
3974       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3975       gst_buffer_unmap (unknown, &map);
3976       gst_buffer_unref (unknown);
3977       qtdemux->offset += length;
3978       break;
3979     }
3980   }
3981
3982 beach:
3983   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3984     /* digested all data, show what we have */
3985     qtdemux_prepare_streams (qtdemux);
3986     ret = qtdemux_expose_streams (qtdemux);
3987
3988     qtdemux->state = QTDEMUX_STATE_MOVIE;
3989     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3990         qtdemux->state);
3991     return ret;
3992   }
3993   return ret;
3994 }
3995
3996 /* Seeks to the previous keyframe of the indexed stream and
3997  * aligns other streams with respect to the keyframe timestamp
3998  * of indexed stream. Only called in case of Reverse Playback
3999  */
4000 static GstFlowReturn
4001 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4002 {
4003   guint8 n = 0;
4004   guint32 seg_idx = 0, k_index = 0;
4005   guint32 ref_seg_idx, ref_k_index;
4006   GstClockTime k_pos = 0, last_stop = 0;
4007   QtDemuxSegment *seg = NULL;
4008   QtDemuxStream *ref_str = NULL;
4009   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4010   guint64 target_ts;
4011
4012   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4013    * and finally align all the other streams on that timestamp with their
4014    * respective keyframes */
4015   for (n = 0; n < qtdemux->n_streams; n++) {
4016     QtDemuxStream *str = qtdemux->streams[n];
4017
4018     /* No candidate yet, take the first stream */
4019     if (!ref_str) {
4020       ref_str = str;
4021       continue;
4022     }
4023
4024     /* So that stream has a segment, we prefer video streams */
4025     if (str->subtype == FOURCC_vide) {
4026       ref_str = str;
4027       break;
4028     }
4029   }
4030
4031   if (G_UNLIKELY (!ref_str)) {
4032     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4033     goto eos;
4034   }
4035
4036   if (G_UNLIKELY (!ref_str->from_sample)) {
4037     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4038     goto eos;
4039   }
4040
4041   /* So that stream has been playing from from_sample to to_sample. We will
4042    * get the timestamp of the previous sample and search for a keyframe before
4043    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4044   if (ref_str->subtype == FOURCC_vide) {
4045     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4046         ref_str->from_sample - 1);
4047   } else {
4048     if (ref_str->from_sample >= 10)
4049       k_index = ref_str->from_sample - 10;
4050     else
4051       k_index = 0;
4052   }
4053
4054   target_ts =
4055       ref_str->samples[k_index].timestamp +
4056       ref_str->samples[k_index].pts_offset;
4057
4058   /* get current segment for that stream */
4059   seg = &ref_str->segments[ref_str->segment_index];
4060   /* Use segment start in original timescale for comparisons */
4061   seg_media_start_mov = seg->trak_media_start;
4062
4063   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4064       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4065       k_index, target_ts, seg_media_start_mov,
4066       GST_TIME_ARGS (seg->media_start));
4067
4068   /* Crawl back through segments to find the one containing this I frame */
4069   while (target_ts < seg_media_start_mov) {
4070     GST_DEBUG_OBJECT (qtdemux,
4071         "keyframe position (sample %u) is out of segment %u " " target %"
4072         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4073         ref_str->segment_index, target_ts, seg_media_start_mov);
4074
4075     if (G_UNLIKELY (!ref_str->segment_index)) {
4076       /* Reached first segment, let's consider it's EOS */
4077       goto eos;
4078     }
4079     ref_str->segment_index--;
4080     seg = &ref_str->segments[ref_str->segment_index];
4081     /* Use segment start in original timescale for comparisons */
4082     seg_media_start_mov = seg->trak_media_start;
4083   }
4084   /* Calculate time position of the keyframe and where we should stop */
4085   k_pos =
4086       QTSTREAMTIME_TO_GSTTIME (ref_str,
4087       target_ts - seg->trak_media_start) + seg->time;
4088   last_stop =
4089       QTSTREAMTIME_TO_GSTTIME (ref_str,
4090       ref_str->samples[ref_str->from_sample].timestamp -
4091       seg->trak_media_start) + seg->time;
4092
4093   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4094       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4095       k_index, GST_TIME_ARGS (k_pos));
4096
4097   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4098   qtdemux->segment.position = last_stop;
4099   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4100       GST_TIME_ARGS (last_stop));
4101
4102   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4103     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4104     goto eos;
4105   }
4106
4107   ref_seg_idx = ref_str->segment_index;
4108   ref_k_index = k_index;
4109
4110   /* Align them all on this */
4111   for (n = 0; n < qtdemux->n_streams; n++) {
4112     guint32 index = 0;
4113     GstClockTime seg_time = 0;
4114     QtDemuxStream *str = qtdemux->streams[n];
4115
4116     /* aligning reference stream again might lead to backing up to yet another
4117      * keyframe (due to timestamp rounding issues),
4118      * potentially putting more load on downstream; so let's try to avoid */
4119     if (str == ref_str) {
4120       seg_idx = ref_seg_idx;
4121       seg = &str->segments[seg_idx];
4122       k_index = ref_k_index;
4123       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4124           "sample at index %d", n, ref_str->segment_index, k_index);
4125     } else {
4126       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4127       GST_DEBUG_OBJECT (qtdemux,
4128           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4129           seg_idx, GST_TIME_ARGS (k_pos));
4130
4131       /* get segment and time in the segment */
4132       seg = &str->segments[seg_idx];
4133       seg_time = k_pos - seg->time;
4134
4135       /* get the media time in the segment.
4136        * No adjustment for empty "filler" segments */
4137       if (seg->media_start != GST_CLOCK_TIME_NONE)
4138         seg_time += seg->media_start;
4139
4140       /* get the index of the sample with media time */
4141       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4142       GST_DEBUG_OBJECT (qtdemux,
4143           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4144           GST_TIME_ARGS (seg_time), index);
4145
4146       /* find previous keyframe */
4147       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4148     }
4149
4150     /* Remember until where we want to go */
4151     str->to_sample = str->from_sample - 1;
4152     /* Define our time position */
4153     target_ts =
4154         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4155     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4156     if (seg->media_start != GST_CLOCK_TIME_NONE)
4157       str->time_position -= seg->media_start;
4158
4159     /* Now seek back in time */
4160     gst_qtdemux_move_stream (qtdemux, str, k_index);
4161     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4162         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4163         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4164   }
4165
4166   return GST_FLOW_OK;
4167
4168 eos:
4169   return GST_FLOW_EOS;
4170 }
4171
4172 /* activate the given segment number @seg_idx of @stream at time @offset.
4173  * @offset is an absolute global position over all the segments.
4174  *
4175  * This will push out a NEWSEGMENT event with the right values and
4176  * position the stream index to the first decodable sample before
4177  * @offset.
4178  */
4179 static gboolean
4180 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4181     guint32 seg_idx, GstClockTime offset)
4182 {
4183   GstEvent *event;
4184   QtDemuxSegment *segment;
4185   guint32 index, kf_index;
4186   GstClockTime seg_time;
4187   GstClockTime start, stop, time;
4188   gdouble rate;
4189
4190   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4191       seg_idx, GST_TIME_ARGS (offset));
4192
4193   /* update the current segment */
4194   stream->segment_index = seg_idx;
4195
4196   /* get the segment */
4197   segment = &stream->segments[seg_idx];
4198
4199   if (G_UNLIKELY (offset < segment->time)) {
4200     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4201         GST_TIME_ARGS (segment->time));
4202     return FALSE;
4203   }
4204
4205   /* segment lies beyond total indicated duration */
4206   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4207           segment->time > qtdemux->segment.duration)) {
4208     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4209         " < segment->time %" GST_TIME_FORMAT,
4210         GST_TIME_ARGS (qtdemux->segment.duration),
4211         GST_TIME_ARGS (segment->time));
4212     return FALSE;
4213   }
4214
4215   /* get time in this segment */
4216   seg_time = offset - segment->time;
4217
4218   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4219       GST_TIME_ARGS (seg_time));
4220
4221   if (G_UNLIKELY (seg_time > segment->duration)) {
4222     GST_LOG_OBJECT (stream->pad,
4223         "seg_time > segment->duration %" GST_TIME_FORMAT,
4224         GST_TIME_ARGS (segment->duration));
4225     seg_time = segment->duration;
4226   }
4227
4228   /* qtdemux->segment.stop is in outside-time-realm, whereas
4229    * segment->media_stop is in track-time-realm.
4230    *
4231    * In order to compare the two, we need to bring segment.stop
4232    * into the track-time-realm */
4233
4234   stop = qtdemux->segment.stop;
4235   if (stop == GST_CLOCK_TIME_NONE)
4236     stop = qtdemux->segment.duration;
4237   if (stop == GST_CLOCK_TIME_NONE)
4238     stop = segment->media_stop;
4239   else
4240     stop =
4241         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4242
4243   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4244     start = segment->time + seg_time;
4245     time = offset;
4246     stop = start - seg_time + segment->duration;
4247   } else if (qtdemux->segment.rate >= 0) {
4248     start = MIN (segment->media_start + seg_time, stop);
4249     time = offset;
4250   } else {
4251     if (segment->media_start >= qtdemux->segment.start) {
4252       time = segment->time;
4253     } else {
4254       time = segment->time + (qtdemux->segment.start - segment->media_start);
4255     }
4256
4257     start = MAX (segment->media_start, qtdemux->segment.start);
4258     stop = MIN (segment->media_start + seg_time, stop);
4259   }
4260
4261   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4262       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4263       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4264
4265   /* combine global rate with that of the segment */
4266   rate = segment->rate * qtdemux->segment.rate;
4267
4268   /* Copy flags from main segment */
4269   stream->segment.flags = qtdemux->segment.flags;
4270
4271   /* update the segment values used for clipping */
4272   stream->segment.offset = qtdemux->segment.offset;
4273   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4274   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4275   stream->segment.rate = rate;
4276   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4277       stream->cslg_shift);
4278   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4279       stream->cslg_shift);
4280   stream->segment.time = time;
4281   stream->segment.position = stream->segment.start;
4282
4283   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4284       &stream->segment);
4285
4286   /* now prepare and send the segment */
4287   if (stream->pad) {
4288     event = gst_event_new_segment (&stream->segment);
4289     if (stream->segment_seqnum) {
4290       gst_event_set_seqnum (event, stream->segment_seqnum);
4291     }
4292     gst_pad_push_event (stream->pad, event);
4293     /* assume we can send more data now */
4294     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4295     /* clear to send tags on this pad now */
4296     gst_qtdemux_push_tags (qtdemux, stream);
4297   }
4298
4299   /* in the fragmented case, we pick a fragment that starts before our
4300    * desired position and rely on downstream to wait for a keyframe
4301    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4302    * tfra entries tells us which trun/sample the key unit is in, but we don't
4303    * make use of this additional information at the moment) */
4304   if (qtdemux->fragmented) {
4305     stream->to_sample = G_MAXUINT32;
4306     return TRUE;
4307   }
4308
4309   /* We don't need to look for a sample in push-based */
4310   if (!qtdemux->pullbased)
4311     return TRUE;
4312
4313   /* and move to the keyframe before the indicated media time of the
4314    * segment */
4315   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4316     if (qtdemux->segment.rate >= 0) {
4317       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4318       stream->to_sample = G_MAXUINT32;
4319       GST_DEBUG_OBJECT (stream->pad,
4320           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4321           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4322           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4323     } else {
4324       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4325       stream->to_sample = index;
4326       GST_DEBUG_OBJECT (stream->pad,
4327           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4328           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4329           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4330     }
4331   } else {
4332     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4333         "this is an empty segment");
4334     return TRUE;
4335   }
4336
4337   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4338    * encountered an error and printed a message so we return appropriately */
4339   if (index == -1)
4340     return FALSE;
4341
4342   /* we're at the right spot */
4343   if (index == stream->sample_index) {
4344     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4345     return TRUE;
4346   }
4347
4348   /* find keyframe of the target index */
4349   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4350
4351 /* *INDENT-OFF* */
4352 /* indent does stupid stuff with stream->samples[].timestamp */
4353
4354   /* if we move forwards, we don't have to go back to the previous
4355    * keyframe since we already sent that. We can also just jump to
4356    * the keyframe right before the target index if there is one. */
4357   if (index > stream->sample_index) {
4358     /* moving forwards check if we move past a keyframe */
4359     if (kf_index > stream->sample_index) {
4360       GST_DEBUG_OBJECT (stream->pad,
4361            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", 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       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4365     } else {
4366       GST_DEBUG_OBJECT (stream->pad,
4367           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", 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     }
4371   } else {
4372     GST_DEBUG_OBJECT (stream->pad,
4373         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4374         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4375         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4376     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4377   }
4378
4379 /* *INDENT-ON* */
4380
4381   return TRUE;
4382 }
4383
4384 /* prepare to get the current sample of @stream, getting essential values.
4385  *
4386  * This function will also prepare and send the segment when needed.
4387  *
4388  * Return FALSE if the stream is EOS.
4389  *
4390  * PULL-BASED
4391  */
4392 static gboolean
4393 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4394     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4395     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4396     gboolean * keyframe)
4397 {
4398   QtDemuxSample *sample;
4399   GstClockTime time_position;
4400   guint32 seg_idx;
4401
4402   g_return_val_if_fail (stream != NULL, FALSE);
4403
4404   time_position = stream->time_position;
4405   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4406     goto eos;
4407
4408   seg_idx = stream->segment_index;
4409   if (G_UNLIKELY (seg_idx == -1)) {
4410     /* find segment corresponding to time_position if we are looking
4411      * for a segment. */
4412     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4413   }
4414
4415   /* different segment, activate it, sample_index will be set. */
4416   if (G_UNLIKELY (stream->segment_index != seg_idx))
4417     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4418
4419   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4420                   segment_index]))) {
4421     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4422
4423     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4424         " prepare empty sample");
4425
4426     *empty = TRUE;
4427     *pts = *dts = time_position;
4428     *duration = seg->duration - (time_position - seg->time);
4429
4430     return TRUE;
4431   }
4432
4433   *empty = FALSE;
4434
4435   if (stream->sample_index == -1)
4436     stream->sample_index = 0;
4437
4438   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4439       stream->sample_index, stream->n_samples);
4440
4441   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4442     if (!qtdemux->fragmented)
4443       goto eos;
4444
4445     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4446     do {
4447       GstFlowReturn flow;
4448
4449       GST_OBJECT_LOCK (qtdemux);
4450       flow = qtdemux_add_fragmented_samples (qtdemux);
4451       GST_OBJECT_UNLOCK (qtdemux);
4452
4453       if (flow != GST_FLOW_OK)
4454         goto eos;
4455     }
4456     while (stream->sample_index >= stream->n_samples);
4457   }
4458
4459   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4460     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4461         stream->sample_index);
4462     return FALSE;
4463   }
4464
4465   /* now get the info for the sample we're at */
4466   sample = &stream->samples[stream->sample_index];
4467
4468   *dts = QTSAMPLE_DTS (stream, sample);
4469   *pts = QTSAMPLE_PTS (stream, sample);
4470   *offset = sample->offset;
4471   *size = sample->size;
4472   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4473   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4474
4475   return TRUE;
4476
4477   /* special cases */
4478 eos:
4479   {
4480     stream->time_position = GST_CLOCK_TIME_NONE;
4481     return FALSE;
4482   }
4483 }
4484
4485 /* move to the next sample in @stream.
4486  *
4487  * Moves to the next segment when needed.
4488  */
4489 static void
4490 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4491 {
4492   QtDemuxSample *sample;
4493   QtDemuxSegment *segment;
4494
4495   /* get current segment */
4496   segment = &stream->segments[stream->segment_index];
4497
4498   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4499     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4500     goto next_segment;
4501   }
4502
4503   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4504     /* Mark the stream as EOS */
4505     GST_DEBUG_OBJECT (qtdemux,
4506         "reached max allowed sample %u, mark EOS", stream->to_sample);
4507     stream->time_position = GST_CLOCK_TIME_NONE;
4508     return;
4509   }
4510
4511   /* move to next sample */
4512   stream->sample_index++;
4513   stream->offset_in_sample = 0;
4514
4515   /* reached the last sample, we need the next segment */
4516   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4517     goto next_segment;
4518
4519   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4520     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4521         stream->sample_index);
4522     return;
4523   }
4524
4525   /* get next sample */
4526   sample = &stream->samples[stream->sample_index];
4527
4528   /* see if we are past the segment */
4529   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4530     goto next_segment;
4531
4532   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4533     /* inside the segment, update time_position, looks very familiar to
4534      * GStreamer segments, doesn't it? */
4535     stream->time_position =
4536         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4537   } else {
4538     /* not yet in segment, time does not yet increment. This means
4539      * that we are still prerolling keyframes to the decoder so it can
4540      * decode the first sample of the segment. */
4541     stream->time_position = segment->time;
4542   }
4543   return;
4544
4545   /* move to the next segment */
4546 next_segment:
4547   {
4548     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4549
4550     if (stream->segment_index == stream->n_segments - 1) {
4551       /* are we at the end of the last segment, we're EOS */
4552       stream->time_position = GST_CLOCK_TIME_NONE;
4553     } else {
4554       /* else we're only at the end of the current segment */
4555       stream->time_position = segment->stop_time;
4556     }
4557     /* make sure we select a new segment */
4558
4559     /* accumulate previous segments */
4560     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4561       stream->accumulated_base +=
4562           (stream->segment.stop -
4563           stream->segment.start) / ABS (stream->segment.rate);
4564
4565     stream->segment_index = -1;
4566   }
4567 }
4568
4569 static void
4570 gst_qtdemux_sync_streams (GstQTDemux * demux)
4571 {
4572   gint i;
4573
4574   if (demux->n_streams <= 1)
4575     return;
4576
4577   for (i = 0; i < demux->n_streams; i++) {
4578     QtDemuxStream *stream;
4579     GstClockTime end_time;
4580
4581     stream = demux->streams[i];
4582
4583     if (!stream->pad)
4584       continue;
4585
4586     /* TODO advance time on subtitle streams here, if any some day */
4587
4588     /* some clips/trailers may have unbalanced streams at the end,
4589      * so send EOS on shorter stream to prevent stalling others */
4590
4591     /* do not mess with EOS if SEGMENT seeking */
4592     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4593       continue;
4594
4595     if (demux->pullbased) {
4596       /* loop mode is sample time based */
4597       if (!STREAM_IS_EOS (stream))
4598         continue;
4599     } else {
4600       /* push mode is byte position based */
4601       if (stream->n_samples &&
4602           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4603         continue;
4604     }
4605
4606     if (stream->sent_eos)
4607       continue;
4608
4609     /* only act if some gap */
4610     end_time = stream->segments[stream->n_segments - 1].stop_time;
4611     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4612         ", stream end: %" GST_TIME_FORMAT,
4613         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4614     if (GST_CLOCK_TIME_IS_VALID (end_time)
4615         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4616       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4617           GST_PAD_NAME (stream->pad));
4618       stream->sent_eos = TRUE;
4619       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4620     }
4621   }
4622 }
4623
4624 /* EOS and NOT_LINKED need to be combined. This means that we return:
4625  *
4626  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4627  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4628  */
4629 static GstFlowReturn
4630 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4631     GstFlowReturn ret)
4632 {
4633   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4634
4635   if (stream->pad)
4636     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4637         ret);
4638   else
4639     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4640
4641   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4642   return ret;
4643 }
4644
4645 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4646  * completely clipped
4647  *
4648  * Should be used only with raw buffers */
4649 static GstBuffer *
4650 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4651     GstBuffer * buf)
4652 {
4653   guint64 start, stop, cstart, cstop, diff;
4654   GstClockTime pts, duration;
4655   gsize size, osize;
4656   gint num_rate, denom_rate;
4657   gint frame_size;
4658   gboolean clip_data;
4659   guint offset;
4660
4661   osize = size = gst_buffer_get_size (buf);
4662   offset = 0;
4663
4664   /* depending on the type, setup the clip parameters */
4665   if (stream->subtype == FOURCC_soun) {
4666     frame_size = stream->bytes_per_frame;
4667     num_rate = GST_SECOND;
4668     denom_rate = (gint) stream->rate;
4669     clip_data = TRUE;
4670   } else if (stream->subtype == FOURCC_vide) {
4671     frame_size = size;
4672     num_rate = stream->fps_n;
4673     denom_rate = stream->fps_d;
4674     clip_data = FALSE;
4675   } else
4676     goto wrong_type;
4677
4678   if (frame_size <= 0)
4679     goto bad_frame_size;
4680
4681   /* we can only clip if we have a valid pts */
4682   pts = GST_BUFFER_PTS (buf);
4683   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4684     goto no_pts;
4685
4686   duration = GST_BUFFER_DURATION (buf);
4687
4688   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4689     duration =
4690         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4691   }
4692
4693   start = pts;
4694   stop = start + duration;
4695
4696   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4697               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4698     goto clipped;
4699
4700   /* see if some clipping happened */
4701   diff = cstart - start;
4702   if (diff > 0) {
4703     pts += diff;
4704     duration -= diff;
4705
4706     if (clip_data) {
4707       /* bring clipped time to samples and to bytes */
4708       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4709       diff *= frame_size;
4710
4711       GST_DEBUG_OBJECT (qtdemux,
4712           "clipping start to %" GST_TIME_FORMAT " %"
4713           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4714
4715       offset = diff;
4716       size -= diff;
4717     }
4718   }
4719   diff = stop - cstop;
4720   if (diff > 0) {
4721     duration -= diff;
4722
4723     if (clip_data) {
4724       /* bring clipped time to samples and then to bytes */
4725       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4726       diff *= frame_size;
4727       GST_DEBUG_OBJECT (qtdemux,
4728           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4729           " bytes", GST_TIME_ARGS (cstop), diff);
4730       size -= diff;
4731     }
4732   }
4733
4734   if (offset != 0 || size != osize)
4735     gst_buffer_resize (buf, offset, size);
4736
4737   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4738   GST_BUFFER_PTS (buf) = pts;
4739   GST_BUFFER_DURATION (buf) = duration;
4740
4741   return buf;
4742
4743   /* dropped buffer */
4744 wrong_type:
4745   {
4746     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4747     return buf;
4748   }
4749 bad_frame_size:
4750   {
4751     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4752     return buf;
4753   }
4754 no_pts:
4755   {
4756     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4757     return buf;
4758   }
4759 clipped:
4760   {
4761     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4762     gst_buffer_unref (buf);
4763     return NULL;
4764   }
4765 }
4766
4767 /* the input buffer metadata must be writable,
4768  * but time/duration etc not yet set and need not be preserved */
4769 static GstBuffer *
4770 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4771     GstBuffer * buf)
4772 {
4773   GstMapInfo map;
4774   guint nsize = 0;
4775   gchar *str;
4776
4777   /* not many cases for now */
4778   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4779     /* send a one time dvd clut event */
4780     if (stream->pending_event && stream->pad)
4781       gst_pad_push_event (stream->pad, stream->pending_event);
4782     stream->pending_event = NULL;
4783   }
4784
4785   if (G_UNLIKELY (stream->subtype != FOURCC_text
4786           && stream->subtype != FOURCC_sbtl &&
4787           stream->subtype != FOURCC_subp)) {
4788     return buf;
4789   }
4790
4791   gst_buffer_map (buf, &map, GST_MAP_READ);
4792
4793   /* empty buffer is sent to terminate previous subtitle */
4794   if (map.size <= 2) {
4795     gst_buffer_unmap (buf, &map);
4796     gst_buffer_unref (buf);
4797     return NULL;
4798   }
4799   if (stream->subtype == FOURCC_subp) {
4800     /* That's all the processing needed for subpictures */
4801     gst_buffer_unmap (buf, &map);
4802     return buf;
4803   }
4804
4805   nsize = GST_READ_UINT16_BE (map.data);
4806   nsize = MIN (nsize, map.size - 2);
4807
4808   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4809       nsize, map.size);
4810
4811   /* takes care of UTF-8 validation or UTF-16 recognition,
4812    * no other encoding expected */
4813   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4814   gst_buffer_unmap (buf, &map);
4815   if (str) {
4816     gst_buffer_unref (buf);
4817     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4818   } else {
4819     /* this should not really happen unless the subtitle is corrupted */
4820     gst_buffer_unref (buf);
4821     buf = NULL;
4822   }
4823
4824   /* FIXME ? convert optional subsequent style info to markup */
4825
4826   return buf;
4827 }
4828
4829 /* Sets a buffer's attributes properly and pushes it downstream.
4830  * Also checks for additional actions and custom processing that may
4831  * need to be done first.
4832  */
4833 static GstFlowReturn
4834 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4835     QtDemuxStream * stream, GstBuffer * buf,
4836     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4837     gboolean keyframe, GstClockTime position, guint64 byte_position)
4838 {
4839   GstFlowReturn ret = GST_FLOW_OK;
4840
4841   /* offset the timestamps according to the edit list */
4842
4843   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4844     gchar *url;
4845     GstMapInfo map;
4846
4847     gst_buffer_map (buf, &map, GST_MAP_READ);
4848     url = g_strndup ((gchar *) map.data, map.size);
4849     gst_buffer_unmap (buf, &map);
4850     if (url != NULL && strlen (url) != 0) {
4851       /* we have RTSP redirect now */
4852       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4853           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4854               gst_structure_new ("redirect",
4855                   "new-location", G_TYPE_STRING, url, NULL)));
4856       qtdemux->posted_redirect = TRUE;
4857     } else {
4858       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4859           "posting");
4860     }
4861     g_free (url);
4862   }
4863
4864   /* position reporting */
4865   if (qtdemux->segment.rate >= 0) {
4866     qtdemux->segment.position = position;
4867     gst_qtdemux_sync_streams (qtdemux);
4868   }
4869
4870   if (G_UNLIKELY (!stream->pad)) {
4871     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4872     gst_buffer_unref (buf);
4873     goto exit;
4874   }
4875
4876   /* send out pending buffers */
4877   while (stream->buffers) {
4878     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4879
4880     if (G_UNLIKELY (stream->discont)) {
4881       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4882       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4883       stream->discont = FALSE;
4884     } else {
4885       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4886     }
4887
4888     gst_pad_push (stream->pad, buffer);
4889
4890     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4891   }
4892
4893   /* we're going to modify the metadata */
4894   buf = gst_buffer_make_writable (buf);
4895
4896   if (G_UNLIKELY (stream->need_process))
4897     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4898
4899   if (!buf) {
4900     goto exit;
4901   }
4902
4903   GST_BUFFER_DTS (buf) = dts;
4904   GST_BUFFER_PTS (buf) = pts;
4905   GST_BUFFER_DURATION (buf) = duration;
4906   GST_BUFFER_OFFSET (buf) = -1;
4907   GST_BUFFER_OFFSET_END (buf) = -1;
4908
4909   if (G_UNLIKELY (stream->rgb8_palette))
4910     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4911
4912   if (G_UNLIKELY (stream->padding)) {
4913     gst_buffer_resize (buf, stream->padding, -1);
4914   }
4915 #if 0
4916   if (G_UNLIKELY (qtdemux->element_index)) {
4917     GstClockTime stream_time;
4918
4919     stream_time =
4920         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4921         timestamp);
4922     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4923       GST_LOG_OBJECT (qtdemux,
4924           "adding association %" GST_TIME_FORMAT "-> %"
4925           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4926       gst_index_add_association (qtdemux->element_index,
4927           qtdemux->index_id,
4928           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4929           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4930           GST_FORMAT_BYTES, byte_position, NULL);
4931     }
4932   }
4933 #endif
4934
4935   if (stream->need_clip)
4936     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4937
4938   if (G_UNLIKELY (buf == NULL))
4939     goto exit;
4940
4941   if (G_UNLIKELY (stream->discont)) {
4942     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4943     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4944     stream->discont = FALSE;
4945   } else {
4946     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4947   }
4948
4949   if (!keyframe) {
4950     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4951     stream->on_keyframe = FALSE;
4952   } else {
4953     stream->on_keyframe = TRUE;
4954   }
4955
4956
4957   GST_LOG_OBJECT (qtdemux,
4958       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4959       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4960       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4961       GST_PAD_NAME (stream->pad));
4962
4963   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
4964     GstStructure *crypto_info;
4965     QtDemuxCencSampleSetInfo *info =
4966         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4967     gint index;
4968     GstEvent *event;
4969
4970     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
4971       gst_pad_push_event (stream->pad, event);
4972     }
4973
4974     if (qtdemux->cenc_aux_info_offset > 0 && info->crypto_info == NULL) {
4975       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
4976       gst_buffer_unref (buf);
4977       goto exit;
4978     }
4979
4980     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
4981     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
4982       /* steal structure from array */
4983       crypto_info = g_ptr_array_index (info->crypto_info, index);
4984       g_ptr_array_index (info->crypto_info, index) = NULL;
4985       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
4986       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
4987         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
4988     }
4989   }
4990
4991   ret = gst_pad_push (stream->pad, buf);
4992
4993   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4994     /* mark position in stream, we'll need this to know when to send GAP event */
4995     stream->segment.position = pts + duration;
4996   }
4997
4998 exit:
4999   return ret;
5000 }
5001
5002 static const QtDemuxRandomAccessEntry *
5003 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5004     GstClockTime pos, gboolean after)
5005 {
5006   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5007   guint n_entries = stream->n_ra_entries;
5008   guint i;
5009
5010   /* we assume the table is sorted */
5011   for (i = 0; i < n_entries; ++i) {
5012     if (entries[i].ts > pos)
5013       break;
5014   }
5015
5016   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5017    * probably okay to assume that the index lists the very first fragment */
5018   if (i == 0)
5019     return &entries[0];
5020
5021   if (after)
5022     return &entries[i];
5023   else
5024     return &entries[i - 1];
5025 }
5026
5027 static gboolean
5028 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5029 {
5030   const QtDemuxRandomAccessEntry *best_entry = NULL;
5031   guint i;
5032
5033   GST_OBJECT_LOCK (qtdemux);
5034
5035   g_assert (qtdemux->n_streams > 0);
5036
5037   for (i = 0; i < qtdemux->n_streams; i++) {
5038     const QtDemuxRandomAccessEntry *entry;
5039     QtDemuxStream *stream;
5040     gboolean is_audio_or_video;
5041
5042     stream = qtdemux->streams[i];
5043
5044     g_free (stream->samples);
5045     stream->samples = NULL;
5046     stream->n_samples = 0;
5047     stream->stbl_index = -1;    /* no samples have yet been parsed */
5048     stream->sample_index = -1;
5049
5050     if (stream->ra_entries == NULL)
5051       continue;
5052
5053     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5054       is_audio_or_video = TRUE;
5055     else
5056       is_audio_or_video = FALSE;
5057
5058     entry =
5059         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5060         stream->time_position, !is_audio_or_video);
5061
5062     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5063         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5064
5065     stream->pending_seek = entry;
5066
5067     /* decide position to jump to just based on audio/video tracks, not subs */
5068     if (!is_audio_or_video)
5069       continue;
5070
5071     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5072       best_entry = entry;
5073   }
5074
5075   if (best_entry == NULL) {
5076     GST_OBJECT_UNLOCK (qtdemux);
5077     return FALSE;
5078   }
5079
5080   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5081       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5082       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5083       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5084
5085   qtdemux->moof_offset = best_entry->moof_offset;
5086
5087   qtdemux_add_fragmented_samples (qtdemux);
5088
5089   GST_OBJECT_UNLOCK (qtdemux);
5090   return TRUE;
5091 }
5092
5093 static GstFlowReturn
5094 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5095 {
5096   GstFlowReturn ret = GST_FLOW_OK;
5097   GstBuffer *buf = NULL;
5098   QtDemuxStream *stream;
5099   GstClockTime min_time;
5100   guint64 offset = 0;
5101   GstClockTime dts = GST_CLOCK_TIME_NONE;
5102   GstClockTime pts = GST_CLOCK_TIME_NONE;
5103   GstClockTime duration = 0;
5104   gboolean keyframe = FALSE;
5105   guint sample_size = 0;
5106   gboolean empty = 0;
5107   guint size;
5108   gint index;
5109   gint i;
5110
5111   gst_qtdemux_push_pending_newsegment (qtdemux);
5112
5113   if (qtdemux->fragmented_seek_pending) {
5114     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5115     gst_qtdemux_do_fragmented_seek (qtdemux);
5116     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5117     qtdemux->fragmented_seek_pending = FALSE;
5118   }
5119
5120   /* Figure out the next stream sample to output, min_time is expressed in
5121    * global time and runs over the edit list segments. */
5122   min_time = G_MAXUINT64;
5123   index = -1;
5124   for (i = 0; i < qtdemux->n_streams; i++) {
5125     GstClockTime position;
5126
5127     stream = qtdemux->streams[i];
5128     position = stream->time_position;
5129
5130     /* position of -1 is EOS */
5131     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5132       min_time = position;
5133       index = i;
5134     }
5135   }
5136   /* all are EOS */
5137   if (G_UNLIKELY (index == -1)) {
5138     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5139     goto eos;
5140   }
5141
5142   /* check for segment end */
5143   if (G_UNLIKELY (qtdemux->segment.stop != -1
5144           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5145               || (qtdemux->segment.rate < 0
5146                   && qtdemux->segment.start > min_time))
5147           && qtdemux->streams[index]->on_keyframe)) {
5148     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5149     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5150     goto eos_stream;
5151   }
5152
5153   /* gap events for subtitle streams */
5154   for (i = 0; i < qtdemux->n_streams; i++) {
5155     stream = qtdemux->streams[i];
5156     if (stream->pad && (stream->subtype == FOURCC_subp
5157             || stream->subtype == FOURCC_text
5158             || stream->subtype == FOURCC_sbtl)) {
5159       /* send one second gap events until the stream catches up */
5160       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5161       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5162           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5163           stream->segment.position + GST_SECOND < min_time) {
5164         GstEvent *gap =
5165             gst_event_new_gap (stream->segment.position, GST_SECOND);
5166         gst_pad_push_event (stream->pad, gap);
5167         stream->segment.position += GST_SECOND;
5168       }
5169     }
5170   }
5171
5172   stream = qtdemux->streams[index];
5173   if (stream->new_caps) {
5174     gst_qtdemux_configure_stream (qtdemux, stream);
5175     qtdemux_do_allocation (qtdemux, stream);
5176   }
5177
5178   /* fetch info for the current sample of this stream */
5179   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5180               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5181     goto eos_stream;
5182
5183   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5184   if (G_UNLIKELY (qtdemux->
5185           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5186     if (stream->subtype == FOURCC_vide && !keyframe) {
5187       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5188       goto next;
5189     }
5190   }
5191
5192   GST_DEBUG_OBJECT (qtdemux,
5193       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5194       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5195       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5196       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5197
5198   if (G_UNLIKELY (empty)) {
5199     /* empty segment, push a gap and move to the next one */
5200     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5201     stream->segment.position = pts + duration;
5202     goto next;
5203   }
5204
5205   /* hmm, empty sample, skip and move to next sample */
5206   if (G_UNLIKELY (sample_size <= 0))
5207     goto next;
5208
5209   /* last pushed sample was out of boundary, goto next sample */
5210   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5211     goto next;
5212
5213   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5214     size = sample_size;
5215   } else {
5216     GST_DEBUG_OBJECT (qtdemux,
5217         "size %d larger than stream max_buffer_size %d, trimming",
5218         sample_size, stream->max_buffer_size);
5219     size =
5220         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5221   }
5222
5223   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5224       offset);
5225
5226   if (stream->use_allocator) {
5227     /* if we have a per-stream allocator, use it */
5228     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5229   }
5230
5231   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5232       size, &buf);
5233   if (G_UNLIKELY (ret != GST_FLOW_OK))
5234     goto beach;
5235
5236   if (size != sample_size) {
5237     pts += gst_util_uint64_scale_int (GST_SECOND,
5238         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5239     dts += gst_util_uint64_scale_int (GST_SECOND,
5240         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5241     duration = gst_util_uint64_scale_int (GST_SECOND,
5242         size / stream->bytes_per_frame, stream->timescale);
5243   }
5244
5245   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5246       dts, pts, duration, keyframe, min_time, offset);
5247
5248   if (size != sample_size) {
5249     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5250     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5251
5252     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5253         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5254     if (time_position >= segment->media_start) {
5255       /* inside the segment, update time_position, looks very familiar to
5256        * GStreamer segments, doesn't it? */
5257       stream->time_position = (time_position - segment->media_start) +
5258           segment->time;
5259     } else {
5260       /* not yet in segment, time does not yet increment. This means
5261        * that we are still prerolling keyframes to the decoder so it can
5262        * decode the first sample of the segment. */
5263       stream->time_position = segment->time;
5264     }
5265   }
5266
5267   /* combine flows */
5268   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5269   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5270    * we have no more data for the pad to push */
5271   if (ret == GST_FLOW_EOS)
5272     ret = GST_FLOW_OK;
5273
5274   stream->offset_in_sample += size;
5275   if (stream->offset_in_sample >= sample_size) {
5276     gst_qtdemux_advance_sample (qtdemux, stream);
5277   }
5278   goto beach;
5279
5280 next:
5281   gst_qtdemux_advance_sample (qtdemux, stream);
5282
5283 beach:
5284   return ret;
5285
5286   /* special cases */
5287 eos:
5288   {
5289     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5290     ret = GST_FLOW_EOS;
5291     goto beach;
5292   }
5293 eos_stream:
5294   {
5295     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5296     /* EOS will be raised if all are EOS */
5297     ret = GST_FLOW_OK;
5298     goto beach;
5299   }
5300 }
5301
5302 static void
5303 gst_qtdemux_loop (GstPad * pad)
5304 {
5305   GstQTDemux *qtdemux;
5306   guint64 cur_offset;
5307   GstFlowReturn ret;
5308
5309   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5310
5311   cur_offset = qtdemux->offset;
5312   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5313       cur_offset, qtdemux->state);
5314
5315   switch (qtdemux->state) {
5316     case QTDEMUX_STATE_INITIAL:
5317     case QTDEMUX_STATE_HEADER:
5318       ret = gst_qtdemux_loop_state_header (qtdemux);
5319       break;
5320     case QTDEMUX_STATE_MOVIE:
5321       ret = gst_qtdemux_loop_state_movie (qtdemux);
5322       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5323         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5324       }
5325       break;
5326     default:
5327       /* ouch */
5328       goto invalid_state;
5329   }
5330
5331   /* if something went wrong, pause */
5332   if (ret != GST_FLOW_OK)
5333     goto pause;
5334
5335 done:
5336   gst_object_unref (qtdemux);
5337   return;
5338
5339   /* ERRORS */
5340 invalid_state:
5341   {
5342     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5343         (NULL), ("streaming stopped, invalid state"));
5344     gst_pad_pause_task (pad);
5345     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5346     goto done;
5347   }
5348 pause:
5349   {
5350     const gchar *reason = gst_flow_get_name (ret);
5351
5352     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5353
5354     gst_pad_pause_task (pad);
5355
5356     /* fatal errors need special actions */
5357     /* check EOS */
5358     if (ret == GST_FLOW_EOS) {
5359       if (qtdemux->n_streams == 0) {
5360         /* we have no streams, post an error */
5361         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5362       }
5363       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5364         gint64 stop;
5365
5366         if ((stop = qtdemux->segment.stop) == -1)
5367           stop = qtdemux->segment.duration;
5368
5369         if (qtdemux->segment.rate >= 0) {
5370           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5371           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5372               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5373                   GST_FORMAT_TIME, stop));
5374           gst_qtdemux_push_event (qtdemux,
5375               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
5376         } else {
5377           /*  For Reverse Playback */
5378           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5379           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5380               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5381                   GST_FORMAT_TIME, qtdemux->segment.start));
5382           gst_qtdemux_push_event (qtdemux,
5383               gst_event_new_segment_done (GST_FORMAT_TIME,
5384                   qtdemux->segment.start));
5385         }
5386       } else {
5387         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5388         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5389       }
5390     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5391       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5392           (NULL), ("streaming stopped, reason %s", reason));
5393       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5394     }
5395     goto done;
5396   }
5397 }
5398
5399 /*
5400  * has_next_entry
5401  *
5402  * Returns if there are samples to be played.
5403  */
5404 static gboolean
5405 has_next_entry (GstQTDemux * demux)
5406 {
5407   QtDemuxStream *stream;
5408   int i;
5409
5410   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5411
5412   for (i = 0; i < demux->n_streams; i++) {
5413     stream = demux->streams[i];
5414
5415     if (stream->sample_index == -1) {
5416       stream->sample_index = 0;
5417       stream->offset_in_sample = 0;
5418     }
5419
5420     if (stream->sample_index >= stream->n_samples) {
5421       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5422       continue;
5423     }
5424     GST_DEBUG_OBJECT (demux, "Found a sample");
5425     return TRUE;
5426   }
5427
5428   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5429   return FALSE;
5430 }
5431
5432 /*
5433  * next_entry_size
5434  *
5435  * Returns the size of the first entry at the current offset.
5436  * If -1, there are none (which means EOS or empty file).
5437  */
5438 static guint64
5439 next_entry_size (GstQTDemux * demux)
5440 {
5441   QtDemuxStream *stream;
5442   int i;
5443   int smallidx = -1;
5444   guint64 smalloffs = (guint64) - 1;
5445   QtDemuxSample *sample;
5446
5447   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5448       demux->offset);
5449
5450   for (i = 0; i < demux->n_streams; i++) {
5451     stream = demux->streams[i];
5452
5453     if (stream->sample_index == -1) {
5454       stream->sample_index = 0;
5455       stream->offset_in_sample = 0;
5456     }
5457
5458     if (stream->sample_index >= stream->n_samples) {
5459       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5460       continue;
5461     }
5462
5463     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5464       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5465           stream->sample_index);
5466       return -1;
5467     }
5468
5469     sample = &stream->samples[stream->sample_index];
5470
5471     GST_LOG_OBJECT (demux,
5472         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5473         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5474         sample->offset, sample->size);
5475
5476     if (((smalloffs == -1)
5477             || (sample->offset < smalloffs)) && (sample->size)) {
5478       smallidx = i;
5479       smalloffs = sample->offset;
5480     }
5481   }
5482
5483   GST_LOG_OBJECT (demux,
5484       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5485       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5486
5487   if (smallidx == -1)
5488     return -1;
5489
5490   stream = demux->streams[smallidx];
5491   sample = &stream->samples[stream->sample_index];
5492
5493   if (sample->offset >= demux->offset) {
5494     demux->todrop = sample->offset - demux->offset;
5495     return sample->size + demux->todrop;
5496   }
5497
5498   GST_DEBUG_OBJECT (demux,
5499       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5500   return -1;
5501 }
5502
5503 static void
5504 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5505 {
5506   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5507
5508   gst_element_post_message (GST_ELEMENT_CAST (demux),
5509       gst_message_new_element (GST_OBJECT_CAST (demux),
5510           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5511 }
5512
5513 static gboolean
5514 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5515 {
5516   GstEvent *event;
5517   gboolean res = 0;
5518
5519   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5520
5521   event =
5522       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5523       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5524       GST_SEEK_TYPE_NONE, -1);
5525
5526   /* store seqnum to drop flush events, they don't need to reach downstream */
5527   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5528   res = gst_pad_push_event (demux->sinkpad, event);
5529   demux->offset_seek_seqnum = 0;
5530
5531   return res;
5532 }
5533
5534 /* check for seekable upstream, above and beyond a mere query */
5535 static void
5536 gst_qtdemux_check_seekability (GstQTDemux * demux)
5537 {
5538   GstQuery *query;
5539   gboolean seekable = FALSE;
5540   gint64 start = -1, stop = -1;
5541
5542   if (demux->upstream_size)
5543     return;
5544
5545   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5546   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5547     GST_DEBUG_OBJECT (demux, "seeking query failed");
5548     goto done;
5549   }
5550
5551   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5552
5553   /* try harder to query upstream size if we didn't get it the first time */
5554   if (seekable && stop == -1) {
5555     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5556     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5557   }
5558
5559   /* if upstream doesn't know the size, it's likely that it's not seekable in
5560    * practice even if it technically may be seekable */
5561   if (seekable && (start != 0 || stop <= start)) {
5562     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5563     seekable = FALSE;
5564   }
5565
5566 done:
5567   gst_query_unref (query);
5568
5569   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5570       G_GUINT64_FORMAT ")", seekable, start, stop);
5571   demux->upstream_seekable = seekable;
5572   demux->upstream_size = seekable ? stop : -1;
5573 }
5574
5575 static void
5576 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5577 {
5578   g_return_if_fail (bytes <= demux->todrop);
5579
5580   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5581   gst_adapter_flush (demux->adapter, bytes);
5582   demux->neededbytes -= bytes;
5583   demux->offset += bytes;
5584   demux->todrop -= bytes;
5585 }
5586
5587 static void
5588 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5589 {
5590   if (G_UNLIKELY (demux->pending_newsegment)) {
5591     gint i;
5592
5593     gst_qtdemux_push_pending_newsegment (demux);
5594     /* clear to send tags on all streams */
5595     for (i = 0; i < demux->n_streams; i++) {
5596       QtDemuxStream *stream;
5597       stream = demux->streams[i];
5598       gst_qtdemux_push_tags (demux, stream);
5599       if (stream->sparse) {
5600         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5601         gst_pad_push_event (stream->pad,
5602             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5603       }
5604     }
5605   }
5606 }
5607
5608 static void
5609 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5610     QtDemuxStream * stream)
5611 {
5612   gint i;
5613
5614   /* Push any initial gap segments before proceeding to the
5615    * 'real' data */
5616   for (i = 0; i < stream->n_segments; i++) {
5617     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
5618
5619     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
5620       GstClockTime ts, dur;
5621       GstEvent *gap;
5622
5623       ts = stream->time_position;
5624       dur =
5625           stream->segments[i].duration - (stream->time_position -
5626           stream->segments[i].time);
5627       gap = gst_event_new_gap (ts, dur);
5628       stream->time_position += dur;
5629
5630       GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5631           "segment: %" GST_PTR_FORMAT, gap);
5632       gst_pad_push_event (stream->pad, gap);
5633     } else {
5634       /* Only support empty segment at the beginning followed by
5635        * one non-empty segment, this was checked when parsing the
5636        * edts atom, arriving here is unexpected */
5637       g_assert (i + 1 == stream->n_segments);
5638       break;
5639     }
5640   }
5641 }
5642
5643 static GstFlowReturn
5644 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5645 {
5646   GstQTDemux *demux;
5647
5648   demux = GST_QTDEMUX (parent);
5649
5650   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5651     gint i;
5652
5653     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5654
5655     for (i = 0; i < demux->n_streams; i++) {
5656       demux->streams[i]->discont = TRUE;
5657     }
5658
5659     /* Reverse fragmented playback, need to flush all we have before
5660      * consuming a new fragment.
5661      * The samples array have the timestamps calculated by accumulating the
5662      * durations but this won't work for reverse playback of fragments as
5663      * the timestamps of a subsequent fragment should be smaller than the
5664      * previously received one. */
5665     if (demux->fragmented && demux->segment.rate < 0) {
5666       gst_qtdemux_process_adapter (demux, TRUE);
5667       for (i = 0; i < demux->n_streams; i++)
5668         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5669     }
5670   }
5671
5672   gst_adapter_push (demux->adapter, inbuf);
5673
5674   GST_DEBUG_OBJECT (demux,
5675       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5676       demux->neededbytes, gst_adapter_available (demux->adapter));
5677
5678   return gst_qtdemux_process_adapter (demux, FALSE);
5679 }
5680
5681 static GstFlowReturn
5682 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5683 {
5684   GstFlowReturn ret = GST_FLOW_OK;
5685
5686   /* we never really mean to buffer that much */
5687   if (demux->neededbytes == -1) {
5688     goto eos;
5689   }
5690
5691   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5692       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5693
5694     GST_DEBUG_OBJECT (demux,
5695         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5696         demux->state, demux->neededbytes, demux->offset);
5697
5698     switch (demux->state) {
5699       case QTDEMUX_STATE_INITIAL:{
5700         const guint8 *data;
5701         guint32 fourcc;
5702         guint64 size;
5703
5704         gst_qtdemux_check_seekability (demux);
5705
5706         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5707
5708         /* get fourcc/length, set neededbytes */
5709         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5710             &size, &fourcc);
5711         gst_adapter_unmap (demux->adapter);
5712         data = NULL;
5713         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5714             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5715         if (size == 0) {
5716           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5717               (_("This file is invalid and cannot be played.")),
5718               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5719                   GST_FOURCC_ARGS (fourcc)));
5720           ret = GST_FLOW_ERROR;
5721           break;
5722         }
5723         if (fourcc == FOURCC_mdat) {
5724           gint next_entry = next_entry_size (demux);
5725           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5726             /* we have the headers, start playback */
5727             demux->state = QTDEMUX_STATE_MOVIE;
5728             demux->neededbytes = next_entry;
5729             demux->mdatleft = size;
5730           } else {
5731             /* no headers yet, try to get them */
5732             guint bs;
5733             gboolean res;
5734             guint64 old, target;
5735
5736           buffer_data:
5737             old = demux->offset;
5738             target = old + size;
5739
5740             /* try to jump over the atom with a seek */
5741             /* only bother if it seems worth doing so,
5742              * and avoids possible upstream/server problems */
5743             if (demux->upstream_seekable &&
5744                 demux->upstream_size > 4 * (1 << 20)) {
5745               res = qtdemux_seek_offset (demux, target);
5746             } else {
5747               GST_DEBUG_OBJECT (demux, "skipping seek");
5748               res = FALSE;
5749             }
5750
5751             if (res) {
5752               GST_DEBUG_OBJECT (demux, "seek success");
5753               /* remember the offset fo the first mdat so we can seek back to it
5754                * after we have the headers */
5755               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5756                 demux->first_mdat = old;
5757                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5758                     demux->first_mdat);
5759               }
5760               /* seek worked, continue reading */
5761               demux->offset = target;
5762               demux->neededbytes = 16;
5763               demux->state = QTDEMUX_STATE_INITIAL;
5764             } else {
5765               /* seek failed, need to buffer */
5766               demux->offset = old;
5767               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5768               /* there may be multiple mdat (or alike) buffers */
5769               /* sanity check */
5770               if (demux->mdatbuffer)
5771                 bs = gst_buffer_get_size (demux->mdatbuffer);
5772               else
5773                 bs = 0;
5774               if (size + bs > 10 * (1 << 20))
5775                 goto no_moov;
5776               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5777               demux->neededbytes = size;
5778               if (!demux->mdatbuffer)
5779                 demux->mdatoffset = demux->offset;
5780             }
5781           }
5782         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5783           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5784               (_("This file is invalid and cannot be played.")),
5785               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5786                   GST_FOURCC_ARGS (fourcc), size));
5787           ret = GST_FLOW_ERROR;
5788           break;
5789         } else {
5790           /* this means we already started buffering and still no moov header,
5791            * let's continue buffering everything till we get moov */
5792           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5793                   || fourcc == FOURCC_moof))
5794             goto buffer_data;
5795           demux->neededbytes = size;
5796           demux->state = QTDEMUX_STATE_HEADER;
5797         }
5798         break;
5799       }
5800       case QTDEMUX_STATE_HEADER:{
5801         const guint8 *data;
5802         guint32 fourcc;
5803
5804         GST_DEBUG_OBJECT (demux, "In header");
5805
5806         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5807
5808         /* parse the header */
5809         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5810             &fourcc);
5811         if (fourcc == FOURCC_moov) {
5812           gint n;
5813           gboolean got_samples = FALSE;
5814
5815           /* in usual fragmented setup we could try to scan for more
5816            * and end up at the the moov (after mdat) again */
5817           if (demux->got_moov && demux->n_streams > 0 &&
5818               (!demux->fragmented
5819                   || demux->last_moov_offset == demux->offset)) {
5820             GST_DEBUG_OBJECT (demux,
5821                 "Skipping moov atom as we have (this) one already");
5822           } else {
5823             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5824
5825             if (demux->got_moov && demux->fragmented) {
5826               GST_DEBUG_OBJECT (demux,
5827                   "Got a second moov, clean up data from old one");
5828               if (demux->moov_node)
5829                 g_node_destroy (demux->moov_node);
5830               demux->moov_node = NULL;
5831               demux->moov_node_compressed = NULL;
5832             } else {
5833               /* prepare newsegment to send when streaming actually starts */
5834               if (!demux->pending_newsegment)
5835                 demux->pending_newsegment =
5836                     gst_event_new_segment (&demux->segment);
5837             }
5838
5839             demux->last_moov_offset = demux->offset;
5840
5841             qtdemux_parse_moov (demux, data, demux->neededbytes);
5842             qtdemux_node_dump (demux, demux->moov_node);
5843             qtdemux_parse_tree (demux);
5844             qtdemux_prepare_streams (demux);
5845
5846             for (n = 0; n < demux->n_streams; n++) {
5847               QtDemuxStream *stream = demux->streams[n];
5848               got_samples |= stream->stbl_index >= 0;
5849             }
5850             if (!demux->fragmented || got_samples) {
5851               if (!demux->got_moov) {
5852                 qtdemux_expose_streams (demux);
5853               } else {
5854                 for (n = 0; n < demux->n_streams; n++) {
5855                   QtDemuxStream *stream = demux->streams[n];
5856                   gst_qtdemux_configure_stream (demux, stream);
5857                 }
5858               }
5859               gst_qtdemux_check_send_pending_segment (demux);
5860               demux->pending_configure = FALSE;
5861             } else {
5862               demux->pending_configure = TRUE;
5863             }
5864
5865             demux->got_moov = TRUE;
5866
5867             /* fragmented streams headers shouldn't contain edts atoms */
5868             if (!demux->fragmented) {
5869               for (n = 0; n < demux->n_streams; n++) {
5870                 gst_qtdemux_stream_send_initial_gap_segments (demux,
5871                     demux->streams[n]);
5872               }
5873             }
5874
5875             g_node_destroy (demux->moov_node);
5876             demux->moov_node = NULL;
5877             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5878           }
5879         } else if (fourcc == FOURCC_moof) {
5880           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5881             guint64 dist = 0;
5882             GstClockTime prev_pts;
5883             guint64 prev_offset;
5884             gint n;
5885
5886             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5887
5888             /*
5889              * The timestamp of the moof buffer is relevant as some scenarios
5890              * won't have the initial timestamp in the atoms. Whenever a new
5891              * buffer has started, we get that buffer's PTS and use it as a base
5892              * timestamp for the trun entries.
5893              *
5894              * To keep track of the current buffer timestamp and starting point
5895              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5896              * from the beggining of the buffer, with the distance and demux->offset
5897              * we know if it is still the same buffer or not.
5898              */
5899             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5900             prev_offset = demux->offset - dist;
5901             if (demux->fragment_start_offset == -1
5902                 || prev_offset > demux->fragment_start_offset) {
5903               demux->fragment_start_offset = prev_offset;
5904               demux->fragment_start = prev_pts;
5905               GST_DEBUG_OBJECT (demux,
5906                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5907                   GST_TIME_FORMAT, demux->fragment_start_offset,
5908                   GST_TIME_ARGS (demux->fragment_start));
5909             }
5910
5911             demux->moof_offset = demux->offset;
5912             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5913                     demux->offset, NULL)) {
5914               gst_adapter_unmap (demux->adapter);
5915               ret = GST_FLOW_ERROR;
5916               goto done;
5917             }
5918             /* in MSS we need to expose the pads after the first moof as we won't get a moov 
5919              * Also, fragmented format need to be exposed if a moov have no valid sample data */
5920             if (demux->mss_mode || demux->pending_configure) {
5921               if (!demux->exposed) {
5922                 if (!demux->pending_newsegment) {
5923                   GstSegment segment;
5924                   gst_segment_init (&segment, GST_FORMAT_TIME);
5925                   GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5926                   demux->pending_newsegment = gst_event_new_segment (&segment);
5927                 }
5928                 qtdemux_expose_streams (demux);
5929               } else {
5930                 for (n = 0; n < demux->n_streams; n++) {
5931                   QtDemuxStream *stream = demux->streams[n];
5932                   gst_qtdemux_configure_stream (demux, stream);
5933                 }
5934               }
5935               gst_qtdemux_check_send_pending_segment (demux);
5936               demux->pending_configure = FALSE;
5937             }
5938           } else {
5939             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5940           }
5941         } else if (fourcc == FOURCC_ftyp) {
5942           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5943           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5944         } else if (fourcc == FOURCC_uuid) {
5945           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5946           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5947         } else if (fourcc == FOURCC_sidx) {
5948           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5949           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5950         } else {
5951           GST_WARNING_OBJECT (demux,
5952               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5953               GST_FOURCC_ARGS (fourcc));
5954           /* Let's jump that one and go back to initial state */
5955         }
5956         gst_adapter_unmap (demux->adapter);
5957         data = NULL;
5958
5959         if (demux->mdatbuffer && demux->n_streams) {
5960           gsize remaining_data_size = 0;
5961
5962           /* the mdat was before the header */
5963           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5964               demux->n_streams, demux->mdatbuffer);
5965           /* restore our adapter/offset view of things with upstream;
5966            * put preceding buffered data ahead of current moov data.
5967            * This should also handle evil mdat, moov, mdat cases and alike */
5968           gst_adapter_flush (demux->adapter, demux->neededbytes);
5969
5970           /* Store any remaining data after the mdat for later usage */
5971           remaining_data_size = gst_adapter_available (demux->adapter);
5972           if (remaining_data_size > 0) {
5973             g_assert (demux->restoredata_buffer == NULL);
5974             demux->restoredata_buffer =
5975                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5976             demux->restoredata_offset = demux->offset + demux->neededbytes;
5977             GST_DEBUG_OBJECT (demux,
5978                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5979                 G_GUINT64_FORMAT, remaining_data_size,
5980                 demux->restoredata_offset);
5981           }
5982
5983           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5984           demux->mdatbuffer = NULL;
5985           demux->offset = demux->mdatoffset;
5986           demux->neededbytes = next_entry_size (demux);
5987           demux->state = QTDEMUX_STATE_MOVIE;
5988           demux->mdatleft = gst_adapter_available (demux->adapter);
5989         } else {
5990           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5991           gst_adapter_flush (demux->adapter, demux->neededbytes);
5992
5993           /* only go back to the mdat if there are samples to play */
5994           if (demux->got_moov && demux->first_mdat != -1
5995               && has_next_entry (demux)) {
5996             gboolean res;
5997
5998             /* we need to seek back */
5999             res = qtdemux_seek_offset (demux, demux->first_mdat);
6000             if (res) {
6001               demux->offset = demux->first_mdat;
6002             } else {
6003               GST_DEBUG_OBJECT (demux, "Seek back failed");
6004             }
6005           } else {
6006             demux->offset += demux->neededbytes;
6007           }
6008           demux->neededbytes = 16;
6009           demux->state = QTDEMUX_STATE_INITIAL;
6010         }
6011
6012         break;
6013       }
6014       case QTDEMUX_STATE_BUFFER_MDAT:{
6015         GstBuffer *buf;
6016         guint8 fourcc[4];
6017
6018         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6019             demux->offset);
6020         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6021         gst_buffer_extract (buf, 0, fourcc, 4);
6022         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6023             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6024         if (demux->mdatbuffer)
6025           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6026         else
6027           demux->mdatbuffer = buf;
6028         demux->offset += demux->neededbytes;
6029         demux->neededbytes = 16;
6030         demux->state = QTDEMUX_STATE_INITIAL;
6031         gst_qtdemux_post_progress (demux, 1, 1);
6032
6033         break;
6034       }
6035       case QTDEMUX_STATE_MOVIE:{
6036         QtDemuxStream *stream = NULL;
6037         QtDemuxSample *sample;
6038         int i = -1;
6039         GstClockTime dts, pts, duration;
6040         gboolean keyframe;
6041
6042         GST_DEBUG_OBJECT (demux,
6043             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6044
6045         if (demux->fragmented) {
6046           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6047               demux->mdatleft);
6048           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6049             /* if needed data starts within this atom,
6050              * then it should not exceed this atom */
6051             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6052               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6053                   (_("This file is invalid and cannot be played.")),
6054                   ("sample data crosses atom boundary"));
6055               ret = GST_FLOW_ERROR;
6056               break;
6057             }
6058             demux->mdatleft -= demux->neededbytes;
6059           } else {
6060             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6061             /* so we are dropping more than left in this atom */
6062             gst_qtdemux_drop_data (demux, demux->mdatleft);
6063             demux->mdatleft = 0;
6064
6065             /* need to resume atom parsing so we do not miss any other pieces */
6066             demux->state = QTDEMUX_STATE_INITIAL;
6067             demux->neededbytes = 16;
6068
6069             /* check if there was any stored post mdat data from previous buffers */
6070             if (demux->restoredata_buffer) {
6071               g_assert (gst_adapter_available (demux->adapter) == 0);
6072
6073               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6074               demux->restoredata_buffer = NULL;
6075               demux->offset = demux->restoredata_offset;
6076             }
6077
6078             break;
6079           }
6080         }
6081
6082         if (demux->todrop) {
6083           if (demux->cenc_aux_info_offset > 0) {
6084             GstByteReader br;
6085             const guint8 *data;
6086
6087             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6088             data = gst_adapter_map (demux->adapter, demux->todrop);
6089             gst_byte_reader_init (&br, data + 8, demux->todrop);
6090             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6091                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6092               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6093               ret = GST_FLOW_ERROR;
6094               gst_adapter_unmap (demux->adapter);
6095               g_free (demux->cenc_aux_info_sizes);
6096               demux->cenc_aux_info_sizes = NULL;
6097               goto done;
6098             }
6099             demux->cenc_aux_info_offset = 0;
6100             g_free (demux->cenc_aux_info_sizes);
6101             demux->cenc_aux_info_sizes = NULL;
6102             gst_adapter_unmap (demux->adapter);
6103           }
6104           gst_qtdemux_drop_data (demux, demux->todrop);
6105         }
6106
6107         /* first buffer? */
6108         /* initial newsegment sent here after having added pads,
6109          * possible others in sink_event */
6110         gst_qtdemux_check_send_pending_segment (demux);
6111
6112         /* Figure out which stream this packet belongs to */
6113         for (i = 0; i < demux->n_streams; i++) {
6114           stream = demux->streams[i];
6115           if (stream->sample_index >= stream->n_samples)
6116             continue;
6117           GST_LOG_OBJECT (demux,
6118               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6119               " / size:%d)", i, stream->sample_index,
6120               stream->samples[stream->sample_index].offset,
6121               stream->samples[stream->sample_index].size);
6122
6123           if (stream->samples[stream->sample_index].offset == demux->offset)
6124             break;
6125         }
6126
6127         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6128           goto unknown_stream;
6129
6130         if (stream->new_caps) {
6131           gst_qtdemux_configure_stream (demux, stream);
6132         }
6133
6134         /* Put data in a buffer, set timestamps, caps, ... */
6135         sample = &stream->samples[stream->sample_index];
6136
6137         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6138           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6139               GST_FOURCC_ARGS (stream->fourcc));
6140
6141           dts = QTSAMPLE_DTS (stream, sample);
6142           pts = QTSAMPLE_PTS (stream, sample);
6143           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6144           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6145
6146           /* check for segment end */
6147           if (G_UNLIKELY (demux->segment.stop != -1
6148                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6149             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6150             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6151
6152             /* skip this data, stream is EOS */
6153             gst_adapter_flush (demux->adapter, demux->neededbytes);
6154
6155             /* check if all streams are eos */
6156             ret = GST_FLOW_EOS;
6157             for (i = 0; i < demux->n_streams; i++) {
6158               if (!STREAM_IS_EOS (demux->streams[i])) {
6159                 ret = GST_FLOW_OK;
6160                 break;
6161               }
6162             }
6163
6164             if (ret == GST_FLOW_EOS) {
6165               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6166               goto eos;
6167             }
6168           } else {
6169             GstBuffer *outbuf;
6170
6171             outbuf =
6172                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6173
6174             /* FIXME: should either be an assert or a plain check */
6175             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6176
6177             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6178                 dts, pts, duration, keyframe, dts, demux->offset);
6179           }
6180
6181           /* combine flows */
6182           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6183           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6184             goto non_ok_unlinked_flow;
6185         } else {
6186           /* skip this data, stream is EOS */
6187           gst_adapter_flush (demux->adapter, demux->neededbytes);
6188         }
6189
6190         stream->sample_index++;
6191         stream->offset_in_sample = 0;
6192
6193         /* update current offset and figure out size of next buffer */
6194         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6195             demux->offset, demux->neededbytes);
6196         demux->offset += demux->neededbytes;
6197         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6198             demux->offset);
6199
6200         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6201           if (demux->fragmented) {
6202             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6203             /* there may be more to follow, only finish this atom */
6204             demux->todrop = demux->mdatleft;
6205             demux->neededbytes = demux->todrop;
6206             break;
6207           }
6208           goto eos;
6209         }
6210         break;
6211       }
6212       default:
6213         goto invalid_state;
6214     }
6215   }
6216
6217   /* when buffering movie data, at least show user something is happening */
6218   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6219       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6220     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6221         demux->neededbytes);
6222   }
6223 done:
6224
6225   return ret;
6226
6227   /* ERRORS */
6228 non_ok_unlinked_flow:
6229   {
6230     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6231         gst_flow_get_name (ret));
6232     return ret;
6233   }
6234 unknown_stream:
6235   {
6236     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6237     ret = GST_FLOW_ERROR;
6238     goto done;
6239   }
6240 eos:
6241   {
6242     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6243     ret = GST_FLOW_EOS;
6244     goto done;
6245   }
6246 invalid_state:
6247   {
6248     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6249         (NULL), ("qtdemuxer invalid state %d", demux->state));
6250     ret = GST_FLOW_ERROR;
6251     goto done;
6252   }
6253 no_moov:
6254   {
6255     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6256         (NULL), ("no 'moov' atom within the first 10 MB"));
6257     ret = GST_FLOW_ERROR;
6258     goto done;
6259   }
6260 }
6261
6262 static gboolean
6263 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6264 {
6265   GstQuery *query;
6266   gboolean pull_mode;
6267
6268   query = gst_query_new_scheduling ();
6269
6270   if (!gst_pad_peer_query (sinkpad, query)) {
6271     gst_query_unref (query);
6272     goto activate_push;
6273   }
6274
6275   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6276       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6277   gst_query_unref (query);
6278
6279   if (!pull_mode)
6280     goto activate_push;
6281
6282   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6283   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6284
6285 activate_push:
6286   {
6287     GST_DEBUG_OBJECT (sinkpad, "activating push");
6288     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6289   }
6290 }
6291
6292 static gboolean
6293 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6294     GstPadMode mode, gboolean active)
6295 {
6296   gboolean res;
6297   GstQTDemux *demux = GST_QTDEMUX (parent);
6298
6299   switch (mode) {
6300     case GST_PAD_MODE_PUSH:
6301       demux->pullbased = FALSE;
6302       res = TRUE;
6303       break;
6304     case GST_PAD_MODE_PULL:
6305       if (active) {
6306         demux->pullbased = TRUE;
6307         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6308             sinkpad, NULL);
6309       } else {
6310         res = gst_pad_stop_task (sinkpad);
6311       }
6312       break;
6313     default:
6314       res = FALSE;
6315       break;
6316   }
6317   return res;
6318 }
6319
6320 #ifdef HAVE_ZLIB
6321 static void *
6322 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6323 {
6324   return g_malloc (items * size);
6325 }
6326
6327 static void
6328 qtdemux_zfree (void *opaque, void *addr)
6329 {
6330   g_free (addr);
6331 }
6332
6333 static void *
6334 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6335 {
6336   guint8 *buffer;
6337   z_stream *z;
6338   int ret;
6339
6340   z = g_new0 (z_stream, 1);
6341   z->zalloc = qtdemux_zalloc;
6342   z->zfree = qtdemux_zfree;
6343   z->opaque = NULL;
6344
6345   z->next_in = z_buffer;
6346   z->avail_in = z_length;
6347
6348   buffer = (guint8 *) g_malloc (length);
6349   ret = inflateInit (z);
6350   while (z->avail_in > 0) {
6351     if (z->avail_out == 0) {
6352       length += 1024;
6353       buffer = (guint8 *) g_realloc (buffer, length);
6354       z->next_out = buffer + z->total_out;
6355       z->avail_out = 1024;
6356     }
6357     ret = inflate (z, Z_SYNC_FLUSH);
6358     if (ret != Z_OK)
6359       break;
6360   }
6361   if (ret != Z_STREAM_END) {
6362     g_warning ("inflate() returned %d", ret);
6363   }
6364
6365   g_free (z);
6366   return buffer;
6367 }
6368 #endif /* HAVE_ZLIB */
6369
6370 static gboolean
6371 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6372 {
6373   GNode *cmov;
6374
6375   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6376
6377   /* counts as header data */
6378   qtdemux->header_size += length;
6379
6380   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6381   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6382
6383   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6384   if (cmov) {
6385     guint32 method;
6386     GNode *dcom;
6387     GNode *cmvd;
6388
6389     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6390     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6391     if (dcom == NULL || cmvd == NULL)
6392       goto invalid_compression;
6393
6394     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6395     switch (method) {
6396 #ifdef HAVE_ZLIB
6397       case FOURCC_zlib:{
6398         guint uncompressed_length;
6399         guint compressed_length;
6400         guint8 *buf;
6401
6402         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6403         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6404         GST_LOG ("length = %u", uncompressed_length);
6405
6406         buf =
6407             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6408             compressed_length, uncompressed_length);
6409
6410         qtdemux->moov_node_compressed = qtdemux->moov_node;
6411         qtdemux->moov_node = g_node_new (buf);
6412
6413         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6414             uncompressed_length);
6415         break;
6416       }
6417 #endif /* HAVE_ZLIB */
6418       default:
6419         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6420             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6421         break;
6422     }
6423   }
6424   return TRUE;
6425
6426   /* ERRORS */
6427 invalid_compression:
6428   {
6429     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6430     return FALSE;
6431   }
6432 }
6433
6434 static gboolean
6435 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6436     const guint8 * end)
6437 {
6438   while (G_UNLIKELY (buf < end)) {
6439     GNode *child;
6440     guint32 len;
6441
6442     if (G_UNLIKELY (buf + 4 > end)) {
6443       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6444       break;
6445     }
6446     len = QT_UINT32 (buf);
6447     if (G_UNLIKELY (len == 0)) {
6448       GST_LOG_OBJECT (qtdemux, "empty container");
6449       break;
6450     }
6451     if (G_UNLIKELY (len < 8)) {
6452       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6453       break;
6454     }
6455     if (G_UNLIKELY (len > (end - buf))) {
6456       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6457           (gint) (end - buf));
6458       break;
6459     }
6460
6461     child = g_node_new ((guint8 *) buf);
6462     g_node_append (node, child);
6463     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6464     qtdemux_parse_node (qtdemux, child, buf, len);
6465
6466     buf += len;
6467   }
6468   return TRUE;
6469 }
6470
6471 static gboolean
6472 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6473     GNode * xdxt)
6474 {
6475   int len = QT_UINT32 (xdxt->data);
6476   guint8 *buf = xdxt->data;
6477   guint8 *end = buf + len;
6478   GstBuffer *buffer;
6479
6480   /* skip size and type */
6481   buf += 8;
6482   end -= 8;
6483
6484   while (buf < end) {
6485     gint size;
6486     guint32 type;
6487
6488     size = QT_UINT32 (buf);
6489     type = QT_FOURCC (buf + 4);
6490
6491     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6492
6493     if (buf + size > end || size <= 0)
6494       break;
6495
6496     buf += 8;
6497     size -= 8;
6498
6499     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6500         GST_FOURCC_ARGS (type));
6501
6502     switch (type) {
6503       case FOURCC_tCtH:
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 header");
6508         break;
6509       case FOURCC_tCt_:
6510         buffer = gst_buffer_new_and_alloc (size);
6511         gst_buffer_fill (buffer, 0, buf, size);
6512         stream->buffers = g_slist_append (stream->buffers, buffer);
6513         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6514         break;
6515       case FOURCC_tCtC:
6516         buffer = gst_buffer_new_and_alloc (size);
6517         gst_buffer_fill (buffer, 0, buf, size);
6518         stream->buffers = g_slist_append (stream->buffers, buffer);
6519         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6520         break;
6521       default:
6522         GST_WARNING_OBJECT (qtdemux,
6523             "unknown theora cookie %" GST_FOURCC_FORMAT,
6524             GST_FOURCC_ARGS (type));
6525         break;
6526     }
6527     buf += size;
6528   }
6529   return TRUE;
6530 }
6531
6532 static gboolean
6533 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6534     guint length)
6535 {
6536   guint32 fourcc = 0;
6537   guint32 node_length = 0;
6538   const QtNodeType *type;
6539   const guint8 *end;
6540
6541   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6542
6543   if (G_UNLIKELY (length < 8))
6544     goto not_enough_data;
6545
6546   node_length = QT_UINT32 (buffer);
6547   fourcc = QT_FOURCC (buffer + 4);
6548
6549   /* ignore empty nodes */
6550   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6551     return TRUE;
6552
6553   type = qtdemux_type_get (fourcc);
6554
6555   end = buffer + length;
6556
6557   GST_LOG_OBJECT (qtdemux,
6558       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6559       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6560
6561   if (node_length > length)
6562     goto broken_atom_size;
6563
6564   if (type->flags & QT_FLAG_CONTAINER) {
6565     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6566   } else {
6567     switch (fourcc) {
6568       case FOURCC_stsd:
6569       {
6570         if (node_length < 20) {
6571           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6572           break;
6573         }
6574         GST_DEBUG_OBJECT (qtdemux,
6575             "parsing stsd (sample table, sample description) atom");
6576         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6577         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6578         break;
6579       }
6580       case FOURCC_mp4a:
6581       case FOURCC_alac:
6582       {
6583         guint32 version;
6584         guint32 offset;
6585         guint min_size;
6586
6587         /* also read alac (or whatever) in stead of mp4a in the following,
6588          * since a similar layout is used in other cases as well */
6589         if (fourcc == FOURCC_mp4a)
6590           min_size = 20;
6591         else
6592           min_size = 40;
6593
6594         /* There are two things we might encounter here: a true mp4a atom, and
6595            an mp4a entry in an stsd atom. The latter is what we're interested
6596            in, and it looks like an atom, but isn't really one. The true mp4a
6597            atom is short, so we detect it based on length here. */
6598         if (length < min_size) {
6599           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6600               GST_FOURCC_ARGS (fourcc));
6601           break;
6602         }
6603
6604         /* 'version' here is the sound sample description version. Types 0 and
6605            1 are documented in the QTFF reference, but type 2 is not: it's
6606            described in Apple header files instead (struct SoundDescriptionV2
6607            in Movies.h) */
6608         version = QT_UINT16 (buffer + 16);
6609
6610         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6611             GST_FOURCC_ARGS (fourcc), version);
6612
6613         /* parse any esds descriptors */
6614         switch (version) {
6615           case 0:
6616             offset = 0x24;
6617             break;
6618           case 1:
6619             offset = 0x34;
6620             break;
6621           case 2:
6622             offset = 0x48;
6623             break;
6624           default:
6625             GST_WARNING_OBJECT (qtdemux,
6626                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6627                 GST_FOURCC_ARGS (fourcc), version);
6628             offset = 0;
6629             break;
6630         }
6631         if (offset)
6632           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6633         break;
6634       }
6635       case FOURCC_mp4v:
6636       case FOURCC_MP4V:
6637       case FOURCC_fmp4:
6638       case FOURCC_FMP4:
6639       case FOURCC_apcs:
6640       case FOURCC_apch:
6641       case FOURCC_apcn:
6642       case FOURCC_apco:
6643       case FOURCC_ap4h:
6644       {
6645         const guint8 *buf;
6646         guint32 version;
6647         int tlen;
6648
6649         /* codec_data is contained inside these atoms, which all have
6650          * the same format. */
6651
6652         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6653             GST_FOURCC_ARGS (fourcc));
6654         version = QT_UINT32 (buffer + 16);
6655         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6656         if (1 || version == 0x00000000) {
6657           buf = buffer + 0x32;
6658
6659           /* FIXME Quicktime uses PASCAL string while
6660            * the iso format uses C strings. Check the file
6661            * type before attempting to parse the string here. */
6662           tlen = QT_UINT8 (buf);
6663           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6664           buf++;
6665           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6666           /* the string has a reserved space of 32 bytes so skip
6667            * the remaining 31 */
6668           buf += 31;
6669           buf += 4;             /* and 4 bytes reserved */
6670
6671           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6672
6673           qtdemux_parse_container (qtdemux, node, buf, end);
6674         }
6675         break;
6676       }
6677       case FOURCC_H264:
6678       {
6679         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6680         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6681         break;
6682       }
6683       case FOURCC_avc1:
6684       {
6685         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6686         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6687         break;
6688       }
6689       case FOURCC_avc3:
6690       {
6691         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6692         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6693         break;
6694       }
6695       case FOURCC_H265:
6696       {
6697         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6698         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6699         break;
6700       }
6701       case FOURCC_hvc1:
6702       {
6703         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6704         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6705         break;
6706       }
6707       case FOURCC_hev1:
6708       {
6709         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6710         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6711         break;
6712       }
6713       case FOURCC_mjp2:
6714       {
6715         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6716         break;
6717       }
6718       case FOURCC_meta:
6719       {
6720         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6721         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6722         break;
6723       }
6724       case FOURCC_mp4s:
6725       {
6726         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6727         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6728         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6729         break;
6730       }
6731       case FOURCC_XiTh:
6732       {
6733         guint32 version;
6734         guint32 offset;
6735
6736         version = QT_UINT32 (buffer + 12);
6737         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6738
6739         switch (version) {
6740           case 0x00000001:
6741             offset = 0x62;
6742             break;
6743           default:
6744             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6745             offset = 0;
6746             break;
6747         }
6748         if (offset)
6749           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6750         break;
6751       }
6752       case FOURCC_in24:
6753       {
6754         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6755         break;
6756       }
6757       case FOURCC_uuid:
6758       {
6759         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6760         break;
6761       }
6762       case FOURCC_encv:
6763       {
6764         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6765         break;
6766       }
6767       case FOURCC_enca:
6768       {
6769         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
6770         break;
6771       }
6772       default:
6773         if (!strcmp (type->name, "unknown"))
6774           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6775         break;
6776     }
6777   }
6778   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6779       GST_FOURCC_ARGS (fourcc));
6780   return TRUE;
6781
6782 /* ERRORS */
6783 not_enough_data:
6784   {
6785     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6786         (_("This file is corrupt and cannot be played.")),
6787         ("Not enough data for an atom header, got only %u bytes", length));
6788     return FALSE;
6789   }
6790 broken_atom_size:
6791   {
6792     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6793         (_("This file is corrupt and cannot be played.")),
6794         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6795             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6796             length));
6797     return FALSE;
6798   }
6799 }
6800
6801 static GNode *
6802 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6803 {
6804   GNode *child;
6805   guint8 *buffer;
6806   guint32 child_fourcc;
6807
6808   for (child = g_node_first_child (node); child;
6809       child = g_node_next_sibling (child)) {
6810     buffer = (guint8 *) child->data;
6811
6812     child_fourcc = QT_FOURCC (buffer + 4);
6813
6814     if (G_UNLIKELY (child_fourcc == fourcc)) {
6815       return child;
6816     }
6817   }
6818   return NULL;
6819 }
6820
6821 static GNode *
6822 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6823     GstByteReader * parser)
6824 {
6825   GNode *child;
6826   guint8 *buffer;
6827   guint32 child_fourcc, child_len;
6828
6829   for (child = g_node_first_child (node); child;
6830       child = g_node_next_sibling (child)) {
6831     buffer = (guint8 *) child->data;
6832
6833     child_len = QT_UINT32 (buffer);
6834     child_fourcc = QT_FOURCC (buffer + 4);
6835
6836     if (G_UNLIKELY (child_fourcc == fourcc)) {
6837       if (G_UNLIKELY (child_len < (4 + 4)))
6838         return NULL;
6839       /* FIXME: must verify if atom length < parent atom length */
6840       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6841       return child;
6842     }
6843   }
6844   return NULL;
6845 }
6846
6847 static GNode *
6848 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6849     GstByteReader * parser)
6850 {
6851   GNode *child;
6852   guint8 *buffer;
6853   guint32 child_fourcc, child_len;
6854
6855   for (child = g_node_next_sibling (node); child;
6856       child = g_node_next_sibling (child)) {
6857     buffer = (guint8 *) child->data;
6858
6859     child_fourcc = QT_FOURCC (buffer + 4);
6860
6861     if (child_fourcc == fourcc) {
6862       if (parser) {
6863         child_len = QT_UINT32 (buffer);
6864         if (G_UNLIKELY (child_len < (4 + 4)))
6865           return NULL;
6866         /* FIXME: must verify if atom length < parent atom length */
6867         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6868       }
6869       return child;
6870     }
6871   }
6872   return NULL;
6873 }
6874
6875 static GNode *
6876 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6877 {
6878   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6879 }
6880
6881 static void
6882 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6883 {
6884 /* FIXME: This can only reliably work if demuxers have a
6885  * separate streaming thread per srcpad. This should be
6886  * done in a demuxer base class, which integrates parts
6887  * of multiqueue
6888  *
6889  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6890  */
6891 #if 0
6892   GstQuery *query;
6893
6894   query = gst_query_new_allocation (stream->caps, FALSE);
6895
6896   if (!gst_pad_peer_query (stream->pad, query)) {
6897     /* not a problem, just debug a little */
6898     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6899   }
6900
6901   if (stream->allocator)
6902     gst_object_unref (stream->allocator);
6903
6904   if (gst_query_get_n_allocation_params (query) > 0) {
6905     /* try the allocator */
6906     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6907         &stream->params);
6908     stream->use_allocator = TRUE;
6909   } else {
6910     stream->allocator = NULL;
6911     gst_allocation_params_init (&stream->params);
6912     stream->use_allocator = FALSE;
6913   }
6914   gst_query_unref (query);
6915 #endif
6916 }
6917
6918 static gboolean
6919 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
6920     QtDemuxStream * stream)
6921 {
6922   GstStructure *s;
6923   const gchar *selected_system;
6924
6925   g_return_val_if_fail (qtdemux != NULL, FALSE);
6926   g_return_val_if_fail (stream != NULL, FALSE);
6927   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
6928
6929   if (stream->protection_scheme_type != FOURCC_cenc) {
6930     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
6931     return FALSE;
6932   }
6933   if (qtdemux->protection_system_ids == NULL) {
6934     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
6935         "cenc protection system information has been found");
6936     return FALSE;
6937   }
6938   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
6939   selected_system = gst_protection_select_system ((const gchar **)
6940       qtdemux->protection_system_ids->pdata);
6941   g_ptr_array_remove_index (qtdemux->protection_system_ids,
6942       qtdemux->protection_system_ids->len - 1);
6943   if (!selected_system) {
6944     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
6945         "suitable decryptor element has been found");
6946     return FALSE;
6947   }
6948
6949   s = gst_caps_get_structure (stream->caps, 0);
6950   if (!gst_structure_has_name (s, "application/x-cenc")) {
6951     gst_structure_set (s,
6952         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
6953         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
6954         NULL);
6955     gst_structure_set_name (s, "application/x-cenc");
6956   }
6957   return TRUE;
6958 }
6959
6960 static gboolean
6961 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6962 {
6963   if (stream->subtype == FOURCC_vide) {
6964     /* fps is calculated base on the duration of the average framerate since
6965      * qt does not have a fixed framerate. */
6966     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6967       /* still frame */
6968       stream->fps_n = 0;
6969       stream->fps_d = 1;
6970     } else {
6971       if (stream->duration == 0 || stream->n_samples < 2) {
6972         stream->fps_n = stream->timescale;
6973         stream->fps_d = 1;
6974       } else {
6975         GstClockTime avg_duration;
6976         guint64 duration;
6977         guint32 n_samples;
6978
6979         /* duration and n_samples can be updated for fragmented format
6980          * so, framerate of fragmented format is calculated using data in a moof */
6981         if (qtdemux->fragmented && stream->n_samples_moof > 0
6982             && stream->duration_moof > 0) {
6983           n_samples = stream->n_samples_moof;
6984           duration = stream->duration_moof;
6985         } else {
6986           n_samples = stream->n_samples;
6987           duration = stream->duration;
6988         }
6989
6990         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6991         /* stream->duration is guint64, timescale, n_samples are guint32 */
6992         avg_duration =
6993             gst_util_uint64_scale_round (duration -
6994             stream->first_duration, GST_SECOND,
6995             (guint64) (stream->timescale) * (n_samples - 1));
6996
6997         GST_LOG_OBJECT (qtdemux,
6998             "Calculating avg sample duration based on stream (or moof) duration %"
6999             G_GUINT64_FORMAT
7000             " minus first sample %u, leaving %d samples gives %"
7001             GST_TIME_FORMAT, duration, stream->first_duration,
7002             n_samples - 1, GST_TIME_ARGS (avg_duration));
7003
7004         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7005             &stream->fps_d);
7006       }
7007       GST_DEBUG_OBJECT (qtdemux,
7008           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7009           stream->timescale, stream->fps_n, stream->fps_d);
7010     }
7011
7012     if (stream->caps) {
7013       stream->caps = gst_caps_make_writable (stream->caps);
7014
7015       gst_caps_set_simple (stream->caps,
7016           "width", G_TYPE_INT, stream->width,
7017           "height", G_TYPE_INT, stream->height,
7018           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7019
7020       /* calculate pixel-aspect-ratio using display width and height */
7021       GST_DEBUG_OBJECT (qtdemux,
7022           "video size %dx%d, target display size %dx%d", stream->width,
7023           stream->height, stream->display_width, stream->display_height);
7024       /* qt file might have pasp atom */
7025       if (stream->par_w > 0 && stream->par_h > 0) {
7026         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7027         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7028             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7029       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7030           stream->width > 0 && stream->height > 0) {
7031         gint n, d;
7032
7033         /* calculate the pixel aspect ratio using the display and pixel w/h */
7034         n = stream->display_width * stream->height;
7035         d = stream->display_height * stream->width;
7036         if (n == d)
7037           n = d = 1;
7038         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7039         stream->par_w = n;
7040         stream->par_h = d;
7041         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7042             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7043       }
7044
7045       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7046         guint par_w = 1, par_h = 1;
7047
7048         if (stream->par_w > 0 && stream->par_h > 0) {
7049           par_w = stream->par_w;
7050           par_h = stream->par_h;
7051         }
7052
7053         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7054                 stream->width, stream->height, par_w, par_h)) {
7055           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7056         }
7057
7058         gst_caps_set_simple (stream->caps,
7059             "multiview-mode", G_TYPE_STRING,
7060             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7061             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7062             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7063       }
7064     }
7065   }
7066
7067   else if (stream->subtype == FOURCC_soun) {
7068     if (stream->caps) {
7069       stream->caps = gst_caps_make_writable (stream->caps);
7070       if (stream->rate > 0)
7071         gst_caps_set_simple (stream->caps,
7072             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7073       if (stream->n_channels > 0)
7074         gst_caps_set_simple (stream->caps,
7075             "channels", G_TYPE_INT, stream->n_channels, NULL);
7076       if (stream->n_channels > 2) {
7077         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7078          * correctly; this is just the minimum we can do - assume
7079          * we don't actually have any channel positions. */
7080         gst_caps_set_simple (stream->caps,
7081             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7082       }
7083     }
7084   }
7085
7086   if (stream->pad) {
7087     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7088     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7089     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7090     gst_pad_set_active (stream->pad, TRUE);
7091
7092     gst_pad_use_fixed_caps (stream->pad);
7093
7094     if (stream->protected) {
7095       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7096         GST_ERROR_OBJECT (qtdemux,
7097             "Failed to configure protected stream caps.");
7098         return FALSE;
7099       }
7100     }
7101
7102     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7103     if (stream->new_stream) {
7104       gchar *stream_id;
7105       GstEvent *event;
7106       GstStreamFlags stream_flags;
7107
7108       event =
7109           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7110           0);
7111       if (event) {
7112         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7113           qtdemux->have_group_id = TRUE;
7114         else
7115           qtdemux->have_group_id = FALSE;
7116         gst_event_unref (event);
7117       } else if (!qtdemux->have_group_id) {
7118         qtdemux->have_group_id = TRUE;
7119         qtdemux->group_id = gst_util_group_id_next ();
7120       }
7121
7122       stream->new_stream = FALSE;
7123       stream_id =
7124           gst_pad_create_stream_id_printf (stream->pad,
7125           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7126       event = gst_event_new_stream_start (stream_id);
7127       if (qtdemux->have_group_id)
7128         gst_event_set_group_id (event, qtdemux->group_id);
7129       stream_flags = GST_STREAM_FLAG_NONE;
7130       if (stream->disabled)
7131         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7132       if (stream->sparse)
7133         stream_flags |= GST_STREAM_FLAG_SPARSE;
7134       gst_event_set_stream_flags (event, stream_flags);
7135       gst_pad_push_event (stream->pad, event);
7136       g_free (stream_id);
7137     }
7138     gst_pad_set_caps (stream->pad, stream->caps);
7139     stream->new_caps = FALSE;
7140   }
7141   return TRUE;
7142 }
7143
7144 static gboolean
7145 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7146     QtDemuxStream * stream, GstTagList * list)
7147 {
7148   /* consistent default for push based mode */
7149   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7150
7151   if (stream->subtype == FOURCC_vide) {
7152     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7153
7154     stream->pad =
7155         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7156     g_free (name);
7157
7158     gst_qtdemux_configure_stream (qtdemux, stream);
7159     qtdemux->n_video_streams++;
7160   } else if (stream->subtype == FOURCC_soun) {
7161     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7162
7163     stream->pad =
7164         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7165     g_free (name);
7166     gst_qtdemux_configure_stream (qtdemux, stream);
7167     qtdemux->n_audio_streams++;
7168   } else if (stream->subtype == FOURCC_strm) {
7169     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7170   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7171       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7172     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7173
7174     stream->pad =
7175         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7176     g_free (name);
7177     gst_qtdemux_configure_stream (qtdemux, stream);
7178     qtdemux->n_sub_streams++;
7179   } else if (stream->caps) {
7180     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7181
7182     stream->pad =
7183         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7184     g_free (name);
7185     gst_qtdemux_configure_stream (qtdemux, stream);
7186     qtdemux->n_video_streams++;
7187   } else {
7188     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7189     goto done;
7190   }
7191
7192   if (stream->pad) {
7193     GList *l;
7194
7195     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7196         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7197     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7198     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7199
7200     if (stream->pending_tags)
7201       gst_tag_list_unref (stream->pending_tags);
7202     stream->pending_tags = list;
7203     list = NULL;
7204     /* global tags go on each pad anyway */
7205     stream->send_global_tags = TRUE;
7206     /* send upstream GST_EVENT_PROTECTION events that were received before
7207        this source pad was created */
7208     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7209       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7210   }
7211 done:
7212   if (list)
7213     gst_tag_list_unref (list);
7214   return TRUE;
7215 }
7216
7217 /* find next atom with @fourcc starting at @offset */
7218 static GstFlowReturn
7219 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7220     guint64 * length, guint32 fourcc)
7221 {
7222   GstFlowReturn ret;
7223   guint32 lfourcc;
7224   GstBuffer *buf;
7225
7226   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7227       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7228
7229   while (TRUE) {
7230     GstMapInfo map;
7231
7232     buf = NULL;
7233     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7234     if (G_UNLIKELY (ret != GST_FLOW_OK))
7235       goto locate_failed;
7236     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7237       /* likely EOF */
7238       ret = GST_FLOW_EOS;
7239       gst_buffer_unref (buf);
7240       goto locate_failed;
7241     }
7242     gst_buffer_map (buf, &map, GST_MAP_READ);
7243     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7244     gst_buffer_unmap (buf, &map);
7245     gst_buffer_unref (buf);
7246
7247     if (G_UNLIKELY (*length == 0)) {
7248       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7249       ret = GST_FLOW_ERROR;
7250       goto locate_failed;
7251     }
7252
7253     if (lfourcc == fourcc) {
7254       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7255           *offset);
7256       break;
7257     } else {
7258       GST_LOG_OBJECT (qtdemux,
7259           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7260           GST_FOURCC_ARGS (fourcc), *offset);
7261       *offset += *length;
7262     }
7263   }
7264
7265   return GST_FLOW_OK;
7266
7267 locate_failed:
7268   {
7269     /* might simply have had last one */
7270     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7271     return ret;
7272   }
7273 }
7274
7275 /* should only do something in pull mode */
7276 /* call with OBJECT lock */
7277 static GstFlowReturn
7278 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7279 {
7280   guint64 length, offset;
7281   GstBuffer *buf = NULL;
7282   GstFlowReturn ret = GST_FLOW_OK;
7283   GstFlowReturn res = GST_FLOW_OK;
7284   GstMapInfo map;
7285
7286   offset = qtdemux->moof_offset;
7287   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7288
7289   if (!offset) {
7290     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7291     return GST_FLOW_EOS;
7292   }
7293
7294   /* best not do pull etc with lock held */
7295   GST_OBJECT_UNLOCK (qtdemux);
7296
7297   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7298   if (ret != GST_FLOW_OK)
7299     goto flow_failed;
7300
7301   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7302   if (G_UNLIKELY (ret != GST_FLOW_OK))
7303     goto flow_failed;
7304   gst_buffer_map (buf, &map, GST_MAP_READ);
7305   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7306     gst_buffer_unmap (buf, &map);
7307     gst_buffer_unref (buf);
7308     buf = NULL;
7309     goto parse_failed;
7310   }
7311
7312   gst_buffer_unmap (buf, &map);
7313   gst_buffer_unref (buf);
7314   buf = NULL;
7315
7316   offset += length;
7317   /* look for next moof */
7318   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7319   if (G_UNLIKELY (ret != GST_FLOW_OK))
7320     goto flow_failed;
7321
7322 exit:
7323   GST_OBJECT_LOCK (qtdemux);
7324
7325   qtdemux->moof_offset = offset;
7326
7327   return res;
7328
7329 parse_failed:
7330   {
7331     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7332     offset = 0;
7333     res = GST_FLOW_ERROR;
7334     goto exit;
7335   }
7336 flow_failed:
7337   {
7338     /* maybe upstream temporarily flushing */
7339     if (ret != GST_FLOW_FLUSHING) {
7340       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7341       offset = 0;
7342     } else {
7343       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7344       /* resume at current position next time */
7345     }
7346     res = ret;
7347     goto exit;
7348   }
7349 }
7350
7351 /* initialise bytereaders for stbl sub-atoms */
7352 static gboolean
7353 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7354 {
7355   stream->stbl_index = -1;      /* no samples have yet been parsed */
7356   stream->sample_index = -1;
7357
7358   /* time-to-sample atom */
7359   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7360     goto corrupt_file;
7361
7362   /* copy atom data into a new buffer for later use */
7363   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7364
7365   /* skip version + flags */
7366   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7367       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7368     goto corrupt_file;
7369   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7370
7371   /* make sure there's enough data */
7372   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7373     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7374     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7375         stream->n_sample_times);
7376     if (!stream->n_sample_times)
7377       goto corrupt_file;
7378   }
7379
7380   /* sync sample atom */
7381   stream->stps_present = FALSE;
7382   if ((stream->stss_present =
7383           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7384               &stream->stss) ? TRUE : FALSE) == TRUE) {
7385     /* copy atom data into a new buffer for later use */
7386     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7387
7388     /* skip version + flags */
7389     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7390         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7391       goto corrupt_file;
7392
7393     if (stream->n_sample_syncs) {
7394       /* make sure there's enough data */
7395       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7396         goto corrupt_file;
7397     }
7398
7399     /* partial sync sample atom */
7400     if ((stream->stps_present =
7401             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7402                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7403       /* copy atom data into a new buffer for later use */
7404       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7405
7406       /* skip version + flags */
7407       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7408           !gst_byte_reader_get_uint32_be (&stream->stps,
7409               &stream->n_sample_partial_syncs))
7410         goto corrupt_file;
7411
7412       /* if there are no entries, the stss table contains the real
7413        * sync samples */
7414       if (stream->n_sample_partial_syncs) {
7415         /* make sure there's enough data */
7416         if (!qt_atom_parser_has_chunks (&stream->stps,
7417                 stream->n_sample_partial_syncs, 4))
7418           goto corrupt_file;
7419       }
7420     }
7421   }
7422
7423   /* sample size */
7424   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7425     goto no_samples;
7426
7427   /* copy atom data into a new buffer for later use */
7428   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7429
7430   /* skip version + flags */
7431   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7432       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7433     goto corrupt_file;
7434
7435   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7436     goto corrupt_file;
7437
7438   if (!stream->n_samples)
7439     goto no_samples;
7440
7441   /* sample-to-chunk atom */
7442   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7443     goto corrupt_file;
7444
7445   /* copy atom data into a new buffer for later use */
7446   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7447
7448   /* skip version + flags */
7449   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7450       !gst_byte_reader_get_uint32_be (&stream->stsc,
7451           &stream->n_samples_per_chunk))
7452     goto corrupt_file;
7453
7454   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7455       stream->n_samples_per_chunk);
7456
7457   /* make sure there's enough data */
7458   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7459           12))
7460     goto corrupt_file;
7461
7462
7463   /* chunk offset */
7464   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7465     stream->co_size = sizeof (guint32);
7466   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7467           &stream->stco))
7468     stream->co_size = sizeof (guint64);
7469   else
7470     goto corrupt_file;
7471
7472   /* copy atom data into a new buffer for later use */
7473   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7474
7475   /* skip version + flags */
7476   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7477     goto corrupt_file;
7478
7479   /* chunks_are_samples == TRUE means treat chunks as samples */
7480   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7481   if (stream->chunks_are_samples) {
7482     /* treat chunks as samples */
7483     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7484       goto corrupt_file;
7485   } else {
7486     /* skip number of entries */
7487     if (!gst_byte_reader_skip (&stream->stco, 4))
7488       goto corrupt_file;
7489
7490     /* make sure there are enough data in the stsz atom */
7491     if (!stream->sample_size) {
7492       /* different sizes for each sample */
7493       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7494         goto corrupt_file;
7495     }
7496   }
7497
7498   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7499       stream->n_samples, (guint) sizeof (QtDemuxSample),
7500       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7501
7502   if (stream->n_samples >=
7503       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7504     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7505         "be larger than %uMB (broken file?)", stream->n_samples,
7506         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7507     return FALSE;
7508   }
7509
7510   g_assert (stream->samples == NULL);
7511   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7512   if (!stream->samples) {
7513     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7514         stream->n_samples);
7515     return FALSE;
7516   }
7517
7518   /* composition time-to-sample */
7519   if ((stream->ctts_present =
7520           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7521               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7522     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7523
7524     /* copy atom data into a new buffer for later use */
7525     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7526
7527     /* skip version + flags */
7528     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7529         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7530             &stream->n_composition_times))
7531       goto corrupt_file;
7532
7533     /* make sure there's enough data */
7534     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7535             4 + 4))
7536       goto corrupt_file;
7537
7538     /* This is optional, if missing we iterate the ctts */
7539     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7540       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7541           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7542         g_free ((gpointer) cslg.data);
7543         goto corrupt_file;
7544       }
7545     } else {
7546       gint32 cslg_least = 0;
7547       guint num_entries, pos;
7548       gint i;
7549
7550       pos = gst_byte_reader_get_pos (&stream->ctts);
7551       num_entries = stream->n_composition_times;
7552
7553       stream->cslg_shift = 0;
7554
7555       for (i = 0; i < num_entries; i++) {
7556         gint32 offset;
7557
7558         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7559         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7560
7561         if (offset < cslg_least)
7562           cslg_least = offset;
7563       }
7564
7565       if (cslg_least < 0)
7566         stream->cslg_shift = ABS (cslg_least);
7567       else
7568         stream->cslg_shift = 0;
7569
7570       /* reset the reader so we can generate sample table */
7571       gst_byte_reader_set_pos (&stream->ctts, pos);
7572     }
7573   } else {
7574     /* Ensure the cslg_shift value is consistent so we can use it
7575      * unconditionnally to produce TS and Segment */
7576     stream->cslg_shift = 0;
7577   }
7578
7579   return TRUE;
7580
7581 corrupt_file:
7582   {
7583     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7584         (_("This file is corrupt and cannot be played.")), (NULL));
7585     return FALSE;
7586   }
7587 no_samples:
7588   {
7589     gst_qtdemux_stbl_free (stream);
7590     if (!qtdemux->fragmented) {
7591       /* not quite good */
7592       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7593       return FALSE;
7594     } else {
7595       /* may pick up samples elsewhere */
7596       return TRUE;
7597     }
7598   }
7599 }
7600
7601 /* collect samples from the next sample to be parsed up to sample @n for @stream
7602  * by reading the info from @stbl
7603  *
7604  * This code can be executed from both the streaming thread and the seeking
7605  * thread so it takes the object lock to protect itself
7606  */
7607 static gboolean
7608 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7609 {
7610   gint i, j, k;
7611   QtDemuxSample *samples, *first, *cur, *last;
7612   guint32 n_samples_per_chunk;
7613   guint32 n_samples;
7614
7615   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7616       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7617       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7618
7619   n_samples = stream->n_samples;
7620
7621   if (n >= n_samples)
7622     goto out_of_samples;
7623
7624   GST_OBJECT_LOCK (qtdemux);
7625   if (n <= stream->stbl_index)
7626     goto already_parsed;
7627
7628   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7629
7630   if (!stream->stsz.data) {
7631     /* so we already parsed and passed all the moov samples;
7632      * onto fragmented ones */
7633     g_assert (qtdemux->fragmented);
7634     goto done;
7635   }
7636
7637   /* pointer to the sample table */
7638   samples = stream->samples;
7639
7640   /* starts from -1, moves to the next sample index to parse */
7641   stream->stbl_index++;
7642
7643   /* keep track of the first and last sample to fill */
7644   first = &samples[stream->stbl_index];
7645   last = &samples[n];
7646
7647   if (!stream->chunks_are_samples) {
7648     /* set the sample sizes */
7649     if (stream->sample_size == 0) {
7650       /* different sizes for each sample */
7651       for (cur = first; cur <= last; cur++) {
7652         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7653         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7654             (guint) (cur - samples), cur->size);
7655       }
7656     } else {
7657       /* samples have the same size */
7658       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7659       for (cur = first; cur <= last; cur++)
7660         cur->size = stream->sample_size;
7661     }
7662   }
7663
7664   n_samples_per_chunk = stream->n_samples_per_chunk;
7665   cur = first;
7666
7667   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7668     guint32 last_chunk;
7669
7670     if (stream->stsc_chunk_index >= stream->last_chunk
7671         || stream->stsc_chunk_index < stream->first_chunk) {
7672       stream->first_chunk =
7673           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7674       stream->samples_per_chunk =
7675           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7676       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
7677
7678       /* chunk numbers are counted from 1 it seems */
7679       if (G_UNLIKELY (stream->first_chunk == 0))
7680         goto corrupt_file;
7681
7682       --stream->first_chunk;
7683
7684       /* the last chunk of each entry is calculated by taking the first chunk
7685        * of the next entry; except if there is no next, where we fake it with
7686        * INT_MAX */
7687       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
7688         stream->last_chunk = G_MAXUINT32;
7689       } else {
7690         stream->last_chunk =
7691             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
7692         if (G_UNLIKELY (stream->last_chunk == 0))
7693           goto corrupt_file;
7694
7695         --stream->last_chunk;
7696       }
7697
7698       GST_LOG_OBJECT (qtdemux,
7699           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
7700           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
7701
7702       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
7703         goto corrupt_file;
7704
7705       if (stream->last_chunk != G_MAXUINT32) {
7706         if (!qt_atom_parser_peek_sub (&stream->stco,
7707                 stream->first_chunk * stream->co_size,
7708                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
7709                 &stream->co_chunk))
7710           goto corrupt_file;
7711
7712       } else {
7713         stream->co_chunk = stream->stco;
7714         if (!gst_byte_reader_skip (&stream->co_chunk,
7715                 stream->first_chunk * stream->co_size))
7716           goto corrupt_file;
7717       }
7718
7719       stream->stsc_chunk_index = stream->first_chunk;
7720     }
7721
7722     last_chunk = stream->last_chunk;
7723
7724     if (stream->chunks_are_samples) {
7725       cur = &samples[stream->stsc_chunk_index];
7726
7727       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7728         if (j > n) {
7729           /* save state */
7730           stream->stsc_chunk_index = j;
7731           goto done;
7732         }
7733
7734         cur->offset =
7735             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
7736             stream->co_size);
7737
7738         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7739             "%" G_GUINT64_FORMAT, j, cur->offset);
7740
7741         if (stream->samples_per_frame * stream->bytes_per_frame) {
7742           cur->size =
7743               (stream->samples_per_chunk * stream->n_channels) /
7744               stream->samples_per_frame * stream->bytes_per_frame;
7745         } else {
7746           cur->size = stream->samples_per_chunk;
7747         }
7748
7749         GST_DEBUG_OBJECT (qtdemux,
7750             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7751             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7752                     stream->stco_sample_index)), cur->size);
7753
7754         cur->timestamp = stream->stco_sample_index;
7755         cur->duration = stream->samples_per_chunk;
7756         cur->keyframe = TRUE;
7757         cur++;
7758
7759         stream->stco_sample_index += stream->samples_per_chunk;
7760       }
7761       stream->stsc_chunk_index = j;
7762     } else {
7763       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7764         guint32 samples_per_chunk;
7765         guint64 chunk_offset;
7766
7767         if (!stream->stsc_sample_index
7768             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7769                 &stream->chunk_offset))
7770           goto corrupt_file;
7771
7772         samples_per_chunk = stream->samples_per_chunk;
7773         chunk_offset = stream->chunk_offset;
7774
7775         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7776           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7777               G_GUINT64_FORMAT " and size %d",
7778               (guint) (cur - samples), chunk_offset, cur->size);
7779
7780           cur->offset = chunk_offset;
7781           chunk_offset += cur->size;
7782           cur++;
7783
7784           if (G_UNLIKELY (cur > last)) {
7785             /* save state */
7786             stream->stsc_sample_index = k + 1;
7787             stream->chunk_offset = chunk_offset;
7788             stream->stsc_chunk_index = j;
7789             goto done2;
7790           }
7791         }
7792         stream->stsc_sample_index = 0;
7793       }
7794       stream->stsc_chunk_index = j;
7795     }
7796     stream->stsc_index++;
7797   }
7798
7799   if (stream->chunks_are_samples)
7800     goto ctts;
7801 done2:
7802   {
7803     guint32 n_sample_times;
7804
7805     n_sample_times = stream->n_sample_times;
7806     cur = first;
7807
7808     for (i = stream->stts_index; i < n_sample_times; i++) {
7809       guint32 stts_samples;
7810       gint32 stts_duration;
7811       gint64 stts_time;
7812
7813       if (stream->stts_sample_index >= stream->stts_samples
7814           || !stream->stts_sample_index) {
7815
7816         stream->stts_samples =
7817             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7818         stream->stts_duration =
7819             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7820
7821         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7822             i, stream->stts_samples, stream->stts_duration);
7823
7824         stream->stts_sample_index = 0;
7825       }
7826
7827       stts_samples = stream->stts_samples;
7828       stts_duration = stream->stts_duration;
7829       stts_time = stream->stts_time;
7830
7831       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7832         GST_DEBUG_OBJECT (qtdemux,
7833             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7834             (guint) (cur - samples), j,
7835             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7836
7837         cur->timestamp = stts_time;
7838         cur->duration = stts_duration;
7839
7840         /* avoid 32-bit wrap-around,
7841          * but still mind possible 'negative' duration */
7842         stts_time += (gint64) stts_duration;
7843         cur++;
7844
7845         if (G_UNLIKELY (cur > last)) {
7846           /* save values */
7847           stream->stts_time = stts_time;
7848           stream->stts_sample_index = j + 1;
7849           goto done3;
7850         }
7851       }
7852       stream->stts_sample_index = 0;
7853       stream->stts_time = stts_time;
7854       stream->stts_index++;
7855     }
7856     /* fill up empty timestamps with the last timestamp, this can happen when
7857      * the last samples do not decode and so we don't have timestamps for them.
7858      * We however look at the last timestamp to estimate the track length so we
7859      * need something in here. */
7860     for (; cur < last; cur++) {
7861       GST_DEBUG_OBJECT (qtdemux,
7862           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7863           (guint) (cur - samples),
7864           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7865       cur->timestamp = stream->stts_time;
7866       cur->duration = -1;
7867     }
7868   }
7869 done3:
7870   {
7871     /* sample sync, can be NULL */
7872     if (stream->stss_present == TRUE) {
7873       guint32 n_sample_syncs;
7874
7875       n_sample_syncs = stream->n_sample_syncs;
7876
7877       if (!n_sample_syncs) {
7878         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7879         stream->all_keyframe = TRUE;
7880       } else {
7881         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7882           /* note that the first sample is index 1, not 0 */
7883           guint32 index;
7884
7885           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7886
7887           if (G_LIKELY (index > 0 && index <= n_samples)) {
7888             index -= 1;
7889             samples[index].keyframe = TRUE;
7890             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7891             /* and exit if we have enough samples */
7892             if (G_UNLIKELY (index >= n)) {
7893               i++;
7894               break;
7895             }
7896           }
7897         }
7898         /* save state */
7899         stream->stss_index = i;
7900       }
7901
7902       /* stps marks partial sync frames like open GOP I-Frames */
7903       if (stream->stps_present == TRUE) {
7904         guint32 n_sample_partial_syncs;
7905
7906         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7907
7908         /* if there are no entries, the stss table contains the real
7909          * sync samples */
7910         if (n_sample_partial_syncs) {
7911           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7912             /* note that the first sample is index 1, not 0 */
7913             guint32 index;
7914
7915             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7916
7917             if (G_LIKELY (index > 0 && index <= n_samples)) {
7918               index -= 1;
7919               samples[index].keyframe = TRUE;
7920               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7921               /* and exit if we have enough samples */
7922               if (G_UNLIKELY (index >= n)) {
7923                 i++;
7924                 break;
7925               }
7926             }
7927           }
7928           /* save state */
7929           stream->stps_index = i;
7930         }
7931       }
7932     } else {
7933       /* no stss, all samples are keyframes */
7934       stream->all_keyframe = TRUE;
7935       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7936     }
7937   }
7938
7939 ctts:
7940   /* composition time to sample */
7941   if (stream->ctts_present == TRUE) {
7942     guint32 n_composition_times;
7943     guint32 ctts_count;
7944     gint32 ctts_soffset;
7945
7946     /* Fill in the pts_offsets */
7947     cur = first;
7948     n_composition_times = stream->n_composition_times;
7949
7950     for (i = stream->ctts_index; i < n_composition_times; i++) {
7951       if (stream->ctts_sample_index >= stream->ctts_count
7952           || !stream->ctts_sample_index) {
7953         stream->ctts_count =
7954             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7955         stream->ctts_soffset =
7956             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7957         stream->ctts_sample_index = 0;
7958       }
7959
7960       ctts_count = stream->ctts_count;
7961       ctts_soffset = stream->ctts_soffset;
7962
7963       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7964         cur->pts_offset = ctts_soffset;
7965         cur++;
7966
7967         if (G_UNLIKELY (cur > last)) {
7968           /* save state */
7969           stream->ctts_sample_index = j + 1;
7970           goto done;
7971         }
7972       }
7973       stream->ctts_sample_index = 0;
7974       stream->ctts_index++;
7975     }
7976   }
7977 done:
7978   stream->stbl_index = n;
7979   /* if index has been completely parsed, free data that is no-longer needed */
7980   if (n + 1 == stream->n_samples) {
7981     gst_qtdemux_stbl_free (stream);
7982     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
7983     if (qtdemux->pullbased) {
7984       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
7985       while (n + 1 == stream->n_samples)
7986         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7987           break;
7988     }
7989   }
7990   GST_OBJECT_UNLOCK (qtdemux);
7991
7992   return TRUE;
7993
7994   /* SUCCESS */
7995 already_parsed:
7996   {
7997     GST_LOG_OBJECT (qtdemux,
7998         "Tried to parse up to sample %u but this sample has already been parsed",
7999         n);
8000     /* if fragmented, there may be more */
8001     if (qtdemux->fragmented && n == stream->stbl_index)
8002       goto done;
8003     GST_OBJECT_UNLOCK (qtdemux);
8004     return TRUE;
8005   }
8006   /* ERRORS */
8007 out_of_samples:
8008   {
8009     GST_LOG_OBJECT (qtdemux,
8010         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8011         stream->n_samples);
8012     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8013         (_("This file is corrupt and cannot be played.")), (NULL));
8014     return FALSE;
8015   }
8016 corrupt_file:
8017   {
8018     GST_OBJECT_UNLOCK (qtdemux);
8019     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8020         (_("This file is corrupt and cannot be played.")), (NULL));
8021     return FALSE;
8022   }
8023 }
8024
8025 /* collect all segment info for @stream.
8026  */
8027 static gboolean
8028 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8029     GNode * trak)
8030 {
8031   GNode *edts;
8032   /* accept edts if they contain gaps at start and there is only
8033    * one media segment */
8034   gboolean allow_pushbased_edts = TRUE;
8035   gint media_segments_count = 0;
8036
8037   /* parse and prepare segment info from the edit list */
8038   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8039   stream->n_segments = 0;
8040   stream->segments = NULL;
8041   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8042     GNode *elst;
8043     gint n_segments;
8044     gint i, count;
8045     guint64 time;
8046     GstClockTime stime;
8047     guint8 *buffer;
8048
8049     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8050     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8051       goto done;
8052
8053     buffer = elst->data;
8054
8055     n_segments = QT_UINT32 (buffer + 12);
8056
8057     /* we might allocate a bit too much, at least allocate 1 segment */
8058     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8059
8060     /* segments always start from 0 */
8061     time = 0;
8062     stime = 0;
8063     count = 0;
8064     for (i = 0; i < n_segments; i++) {
8065       guint64 duration;
8066       guint64 media_time;
8067       QtDemuxSegment *segment;
8068       guint32 rate_int;
8069       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8070
8071       media_time = QT_UINT32 (buffer + 20 + i * 12);
8072       duration = QT_UINT32 (buffer + 16 + i * 12);
8073
8074       if (media_time != G_MAXUINT32)
8075         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8076
8077       segment = &stream->segments[count++];
8078
8079       /* time and duration expressed in global timescale */
8080       segment->time = stime;
8081       /* add non scaled values so we don't cause roundoff errors */
8082       if (duration) {
8083         time += duration;
8084         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8085         segment->duration = stime - segment->time;
8086       } else {
8087         /* zero duration does not imply media_start == media_stop
8088          * but, only specify media_start.*/
8089         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8090         if (GST_CLOCK_TIME_IS_VALID (stime) && media_time != G_MAXUINT32
8091             && stime >= media_start) {
8092           segment->duration = stime - media_start;
8093         } else {
8094           segment->duration = GST_CLOCK_TIME_NONE;
8095         }
8096       }
8097       segment->stop_time = stime;
8098
8099       segment->trak_media_start = media_time;
8100       /* media_time expressed in stream timescale */
8101       if (media_time != G_MAXUINT32) {
8102         segment->media_start = media_start;
8103         segment->media_stop = segment->media_start + segment->duration;
8104         media_segments_count++;
8105       } else {
8106         segment->media_start = GST_CLOCK_TIME_NONE;
8107         segment->media_stop = GST_CLOCK_TIME_NONE;
8108       }
8109       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
8110
8111       if (rate_int <= 1) {
8112         /* 0 is not allowed, some programs write 1 instead of the floating point
8113          * value */
8114         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8115             rate_int);
8116         segment->rate = 1;
8117       } else {
8118         segment->rate = rate_int / 65536.0;
8119       }
8120
8121       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8122           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8123           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8124           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8125           i, GST_TIME_ARGS (segment->time),
8126           GST_TIME_ARGS (segment->duration),
8127           GST_TIME_ARGS (segment->media_start), media_time,
8128           GST_TIME_ARGS (segment->media_stop),
8129           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8130           stream->timescale);
8131       if (segment->stop_time > qtdemux->segment.stop) {
8132         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8133             " extends to %" GST_TIME_FORMAT
8134             " past the end of the file duration %" GST_TIME_FORMAT
8135             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8136             GST_TIME_ARGS (qtdemux->segment.stop));
8137         qtdemux->segment.stop = segment->stop_time;
8138       }
8139     }
8140     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8141     stream->n_segments = count;
8142     if (media_segments_count != 1)
8143       allow_pushbased_edts = FALSE;
8144   }
8145 done:
8146
8147   /* push based does not handle segments, so act accordingly here,
8148    * and warn if applicable */
8149   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8150     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8151     /* remove and use default one below, we stream like it anyway */
8152     g_free (stream->segments);
8153     stream->segments = NULL;
8154     stream->n_segments = 0;
8155   }
8156
8157   /* no segments, create one to play the complete trak */
8158   if (stream->n_segments == 0) {
8159     GstClockTime stream_duration =
8160         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8161
8162     if (stream->segments == NULL)
8163       stream->segments = g_new (QtDemuxSegment, 1);
8164
8165     /* represent unknown our way */
8166     if (stream_duration == 0)
8167       stream_duration = GST_CLOCK_TIME_NONE;
8168
8169     stream->segments[0].time = 0;
8170     stream->segments[0].stop_time = stream_duration;
8171     stream->segments[0].duration = stream_duration;
8172     stream->segments[0].media_start = 0;
8173     stream->segments[0].media_stop = stream_duration;
8174     stream->segments[0].rate = 1.0;
8175     stream->segments[0].trak_media_start = 0;
8176
8177     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8178         GST_TIME_ARGS (stream_duration));
8179     stream->n_segments = 1;
8180     stream->dummy_segment = TRUE;
8181   }
8182   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8183
8184   return TRUE;
8185 }
8186
8187 /*
8188  * Parses the stsd atom of a svq3 trak looking for
8189  * the SMI and gama atoms.
8190  */
8191 static void
8192 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8193     guint8 ** gamma, GstBuffer ** seqh)
8194 {
8195   guint8 *_gamma = NULL;
8196   GstBuffer *_seqh = NULL;
8197   guint8 *stsd_data = stsd->data;
8198   guint32 length = QT_UINT32 (stsd_data);
8199   guint16 version;
8200
8201   if (length < 32) {
8202     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8203     goto end;
8204   }
8205
8206   stsd_data += 32;
8207   length -= 32;
8208   version = QT_UINT16 (stsd_data);
8209   if (version == 3) {
8210     if (length >= 70) {
8211       length -= 70;
8212       stsd_data += 70;
8213       while (length > 8) {
8214         guint32 fourcc, size;
8215         guint8 *data;
8216         size = QT_UINT32 (stsd_data);
8217         fourcc = QT_FOURCC (stsd_data + 4);
8218         data = stsd_data + 8;
8219
8220         if (size == 0) {
8221           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8222               "svq3 atom parsing");
8223           goto end;
8224         }
8225
8226         switch (fourcc) {
8227           case FOURCC_gama:{
8228             if (size == 12) {
8229               _gamma = data;
8230             } else {
8231               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8232                   " for gama atom, expected 12", size);
8233             }
8234             break;
8235           }
8236           case FOURCC_SMI_:{
8237             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8238               guint32 seqh_size;
8239               if (_seqh != NULL) {
8240                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8241                     " found, ignoring");
8242               } else {
8243                 seqh_size = QT_UINT32 (data + 4);
8244                 if (seqh_size > 0) {
8245                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8246                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8247                 }
8248               }
8249             }
8250             break;
8251           }
8252           default:{
8253             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8254                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8255           }
8256         }
8257
8258         if (size <= length) {
8259           length -= size;
8260           stsd_data += size;
8261         }
8262       }
8263     } else {
8264       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8265     }
8266   } else {
8267     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8268         G_GUINT16_FORMAT, version);
8269     goto end;
8270   }
8271
8272 end:
8273   if (gamma) {
8274     *gamma = _gamma;
8275   }
8276   if (seqh) {
8277     *seqh = _seqh;
8278   } else if (_seqh) {
8279     gst_buffer_unref (_seqh);
8280   }
8281 }
8282
8283 static gchar *
8284 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8285 {
8286   GNode *dinf;
8287   GstByteReader dref;
8288   gchar *uri = NULL;
8289
8290   /*
8291    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8292    * atom that might contain a 'data' atom with the rtsp uri.
8293    * This case was reported in bug #597497, some info about
8294    * the hndl atom can be found in TN1195
8295    */
8296   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8297   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8298
8299   if (dinf) {
8300     guint32 dref_num_entries = 0;
8301     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8302         gst_byte_reader_skip (&dref, 4) &&
8303         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8304       gint i;
8305
8306       /* search dref entries for hndl atom */
8307       for (i = 0; i < dref_num_entries; i++) {
8308         guint32 size = 0, type;
8309         guint8 string_len = 0;
8310         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8311             qt_atom_parser_get_fourcc (&dref, &type)) {
8312           if (type == FOURCC_hndl) {
8313             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8314
8315             /* skip data reference handle bytes and the
8316              * following pascal string and some extra 4
8317              * bytes I have no idea what are */
8318             if (!gst_byte_reader_skip (&dref, 4) ||
8319                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8320                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8321               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8322               break;
8323             }
8324
8325             /* iterate over the atoms to find the data atom */
8326             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8327               guint32 atom_size;
8328               guint32 atom_type;
8329
8330               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8331                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8332                 if (atom_type == FOURCC_data) {
8333                   const guint8 *uri_aux = NULL;
8334
8335                   /* found the data atom that might contain the rtsp uri */
8336                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8337                       "hndl atom, interpreting it as an URI");
8338                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8339                           &uri_aux)) {
8340                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8341                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8342                     else
8343                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8344                           "didn't contain a rtsp address");
8345                   } else {
8346                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8347                         "atom contents");
8348                   }
8349                   break;
8350                 }
8351                 /* skipping to the next entry */
8352                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8353                   break;
8354               } else {
8355                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8356                     "atom header");
8357                 break;
8358               }
8359             }
8360             break;
8361           }
8362           /* skip to the next entry */
8363           if (!gst_byte_reader_skip (&dref, size - 8))
8364             break;
8365         } else {
8366           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8367         }
8368       }
8369       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8370     }
8371   }
8372   return uri;
8373 }
8374
8375 #define AMR_NB_ALL_MODES        0x81ff
8376 #define AMR_WB_ALL_MODES        0x83ff
8377 static guint
8378 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8379 {
8380   /* The 'damr' atom is of the form:
8381    *
8382    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8383    *    32 b       8 b          16 b           8 b                 8 b
8384    *
8385    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8386    * represents the highest mode used in the stream (and thus the maximum
8387    * bitrate), with a couple of special cases as seen below.
8388    */
8389
8390   /* Map of frame type ID -> bitrate */
8391   static const guint nb_bitrates[] = {
8392     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8393   };
8394   static const guint wb_bitrates[] = {
8395     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8396   };
8397   GstMapInfo map;
8398   gsize max_mode;
8399   guint16 mode_set;
8400
8401   gst_buffer_map (buf, &map, GST_MAP_READ);
8402
8403   if (map.size != 0x11) {
8404     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8405     goto bad_data;
8406   }
8407
8408   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8409     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8410         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8411     goto bad_data;
8412   }
8413
8414   mode_set = QT_UINT16 (map.data + 13);
8415
8416   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8417     max_mode = 7 + (wb ? 1 : 0);
8418   else
8419     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8420     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8421
8422   if (max_mode == -1) {
8423     GST_DEBUG ("No mode indication was found (mode set) = %x",
8424         (guint) mode_set);
8425     goto bad_data;
8426   }
8427
8428   gst_buffer_unmap (buf, &map);
8429   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8430
8431 bad_data:
8432   gst_buffer_unmap (buf, &map);
8433   return 0;
8434 }
8435
8436 static gboolean
8437 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8438     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8439 {
8440   /*
8441    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8442    * [0 1 2]
8443    * [3 4 5]
8444    * [6 7 8]
8445    */
8446
8447   if (gst_byte_reader_get_remaining (reader) < 36)
8448     return FALSE;
8449
8450   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8451   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8452   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8453   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8454   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8455   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8456   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8457   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8458   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8459
8460   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8461   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8462       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8463       matrix[2] & 0xFF);
8464   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8465       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8466       matrix[5] & 0xFF);
8467   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8468       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8469       matrix[8] & 0xFF);
8470
8471   return TRUE;
8472 }
8473
8474 static void
8475 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8476     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8477 {
8478
8479 /* [a b c]
8480  * [d e f]
8481  * [g h i]
8482  *
8483  * This macro will only compare value abdegh, it expects cfi to have already
8484  * been checked
8485  */
8486 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8487                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8488
8489   /* only handle the cases where the last column has standard values */
8490   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8491     const gchar *rotation_tag = NULL;
8492
8493     /* no rotation needed */
8494     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8495       /* NOP */
8496     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8497       rotation_tag = "rotate-90";
8498     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8499       rotation_tag = "rotate-180";
8500     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8501       rotation_tag = "rotate-270";
8502     } else {
8503       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8504     }
8505
8506     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8507         rotation_tag);
8508     if (rotation_tag != NULL) {
8509       if (*taglist == NULL)
8510         *taglist = gst_tag_list_new_empty ();
8511       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8512           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8513     }
8514   } else {
8515     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8516   }
8517 }
8518
8519 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8520  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8521  * Common Encryption (cenc), the function will also parse the tenc box (defined
8522  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8523  * (typically an enc[v|a|t|s] sample entry); the function will set
8524  * @original_fmt to the fourcc of the original unencrypted stream format.
8525  * Returns TRUE if successful; FALSE otherwise. */
8526 static gboolean
8527 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8528     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8529 {
8530   GNode *sinf;
8531   GNode *frma;
8532   GNode *schm;
8533   GNode *schi;
8534
8535   g_return_val_if_fail (qtdemux != NULL, FALSE);
8536   g_return_val_if_fail (stream != NULL, FALSE);
8537   g_return_val_if_fail (container != NULL, FALSE);
8538   g_return_val_if_fail (original_fmt != NULL, FALSE);
8539
8540   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8541   if (G_UNLIKELY (!sinf)) {
8542     if (stream->protection_scheme_type == FOURCC_cenc) {
8543       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8544           "mandatory for Common Encryption");
8545       return FALSE;
8546     }
8547     return TRUE;
8548   }
8549
8550   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8551   if (G_UNLIKELY (!frma)) {
8552     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8553     return FALSE;
8554   }
8555
8556   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8557   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8558       GST_FOURCC_ARGS (*original_fmt));
8559
8560   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8561   if (!schm) {
8562     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8563     return FALSE;
8564   }
8565   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8566   stream->protection_scheme_version =
8567       QT_UINT32 ((const guint8 *) schm->data + 16);
8568
8569   GST_DEBUG_OBJECT (qtdemux,
8570       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8571       "protection_scheme_version: %#010x",
8572       GST_FOURCC_ARGS (stream->protection_scheme_type),
8573       stream->protection_scheme_version);
8574
8575   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8576   if (!schi) {
8577     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8578     return FALSE;
8579   }
8580   if (stream->protection_scheme_type == FOURCC_cenc) {
8581     QtDemuxCencSampleSetInfo *info;
8582     GNode *tenc;
8583     const guint8 *tenc_data;
8584     guint32 isEncrypted;
8585     guint8 iv_size;
8586     const guint8 *default_kid;
8587     GstBuffer *kid_buf;
8588
8589     if (G_UNLIKELY (!stream->protection_scheme_info))
8590       stream->protection_scheme_info =
8591           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8592
8593     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8594
8595     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8596     if (!tenc) {
8597       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8598           "which is mandatory for Common Encryption");
8599       return FALSE;
8600     }
8601     tenc_data = (const guint8 *) tenc->data + 12;
8602     isEncrypted = QT_UINT24 (tenc_data);
8603     iv_size = QT_UINT8 (tenc_data + 3);
8604     default_kid = (tenc_data + 4);
8605     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8606     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8607     if (info->default_properties)
8608       gst_structure_free (info->default_properties);
8609     info->default_properties =
8610         gst_structure_new ("application/x-cenc",
8611         "iv_size", G_TYPE_UINT, iv_size,
8612         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8613         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8614     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8615         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8616     gst_buffer_unref (kid_buf);
8617   }
8618   return TRUE;
8619 }
8620
8621 /* parse the traks.
8622  * With each track we associate a new QtDemuxStream that contains all the info
8623  * about the trak.
8624  * traks that do not decode to something (like strm traks) will not have a pad.
8625  */
8626 static gboolean
8627 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8628 {
8629   GstByteReader tkhd;
8630   int offset;
8631   GNode *mdia;
8632   GNode *mdhd;
8633   GNode *hdlr;
8634   GNode *minf;
8635   GNode *stbl;
8636   GNode *stsd;
8637   GNode *mp4a;
8638   GNode *mp4v;
8639   GNode *wave;
8640   GNode *esds;
8641   GNode *pasp;
8642   GNode *tref;
8643   GNode *udta;
8644   GNode *svmi;
8645
8646   QtDemuxStream *stream = NULL;
8647   gboolean new_stream = FALSE;
8648   gchar *codec = NULL;
8649   const guint8 *stsd_data;
8650   guint16 lang_code;            /* quicktime lang code or packed iso code */
8651   guint32 version;
8652   guint32 tkhd_flags = 0;
8653   guint8 tkhd_version = 0;
8654   guint32 fourcc;
8655   guint value_size, stsd_len, len;
8656   guint32 track_id;
8657   guint32 dummy;
8658
8659   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8660
8661   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8662       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8663       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8664     goto corrupt_file;
8665
8666   /* pick between 64 or 32 bits */
8667   value_size = tkhd_version == 1 ? 8 : 4;
8668   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8669       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8670     goto corrupt_file;
8671
8672   if (!qtdemux->got_moov) {
8673     if (qtdemux_find_stream (qtdemux, track_id))
8674       goto existing_stream;
8675     stream = _create_stream ();
8676     stream->track_id = track_id;
8677     new_stream = TRUE;
8678   } else {
8679     stream = qtdemux_find_stream (qtdemux, track_id);
8680     if (!stream) {
8681       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
8682       goto skip_track;
8683     }
8684
8685     /* flush samples data from this track from previous moov */
8686     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
8687     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
8688   }
8689   /* need defaults for fragments */
8690   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
8691
8692   if (stream->pending_tags == NULL)
8693     stream->pending_tags = gst_tag_list_new_empty ();
8694
8695   if ((tkhd_flags & 1) == 0)
8696     stream->disabled = TRUE;
8697
8698   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
8699       tkhd_version, tkhd_flags, stream->track_id);
8700
8701   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
8702     goto corrupt_file;
8703
8704   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
8705     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
8706     if (qtdemux->major_brand != FOURCC_mjp2 ||
8707         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
8708       goto corrupt_file;
8709   }
8710
8711   len = QT_UINT32 ((guint8 *) mdhd->data);
8712   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
8713   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
8714   if (version == 0x01000000) {
8715     if (len < 38)
8716       goto corrupt_file;
8717     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
8718     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
8719     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
8720   } else {
8721     if (len < 30)
8722       goto corrupt_file;
8723     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
8724     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
8725     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
8726   }
8727
8728   if (lang_code < 0x400) {
8729     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
8730   } else if (lang_code == 0x7fff) {
8731     stream->lang_id[0] = 0;     /* unspecified */
8732   } else {
8733     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
8734     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
8735     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
8736     stream->lang_id[3] = 0;
8737   }
8738
8739   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
8740       stream->timescale);
8741   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
8742       stream->duration);
8743   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
8744       lang_code, stream->lang_id);
8745
8746   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
8747     goto corrupt_file;
8748
8749   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
8750     /* chapters track reference */
8751     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
8752     if (chap) {
8753       gsize length = GST_READ_UINT32_BE (chap->data);
8754       if (qtdemux->chapters_track_id)
8755         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
8756
8757       if (length >= 12) {
8758         qtdemux->chapters_track_id =
8759             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
8760       }
8761     }
8762   }
8763
8764   /* fragmented files may have bogus duration in moov */
8765   if (!qtdemux->fragmented &&
8766       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
8767     guint64 tdur1, tdur2;
8768
8769     /* don't overflow */
8770     tdur1 = stream->timescale * (guint64) qtdemux->duration;
8771     tdur2 = qtdemux->timescale * (guint64) stream->duration;
8772
8773     /* HACK:
8774      * some of those trailers, nowadays, have prologue images that are
8775      * themselves vide tracks as well. I haven't really found a way to
8776      * identify those yet, except for just looking at their duration. */
8777     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
8778       GST_WARNING_OBJECT (qtdemux,
8779           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
8780           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
8781           "found, assuming preview image or something; skipping track",
8782           stream->duration, stream->timescale, qtdemux->duration,
8783           qtdemux->timescale);
8784       if (new_stream)
8785         gst_qtdemux_stream_free (qtdemux, stream);
8786       return TRUE;
8787     }
8788   }
8789
8790   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
8791     goto corrupt_file;
8792
8793   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
8794       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
8795
8796   len = QT_UINT32 ((guint8 *) hdlr->data);
8797   if (len >= 20)
8798     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
8799   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
8800       GST_FOURCC_ARGS (stream->subtype));
8801
8802   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
8803     goto corrupt_file;
8804
8805   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
8806     goto corrupt_file;
8807
8808   /*parse svmi header if existing */
8809   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
8810   if (svmi) {
8811     len = QT_UINT32 ((guint8 *) svmi->data);
8812     version = QT_UINT32 ((guint8 *) svmi->data + 8);
8813     if (!version) {
8814       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
8815       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
8816       guint8 frame_type, frame_layout;
8817
8818       /* MPEG-A stereo video */
8819       if (qtdemux->major_brand == FOURCC_ss02)
8820         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
8821
8822       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
8823       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
8824       switch (frame_type) {
8825         case 0:
8826           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
8827           break;
8828         case 1:
8829           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
8830           break;
8831         case 2:
8832           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
8833           break;
8834         case 3:
8835           /* mode 3 is primary/secondary view sequence, ie
8836            * left/right views in separate tracks. See section 7.2
8837            * of ISO/IEC 23000-11:2009 */
8838           GST_FIXME_OBJECT (qtdemux,
8839               "Implement stereo video in separate streams");
8840       }
8841
8842       if ((frame_layout & 0x1) == 0)
8843         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
8844
8845       GST_LOG_OBJECT (qtdemux,
8846           "StereoVideo: composition type: %u, is_left_first: %u",
8847           frame_type, frame_layout);
8848       stream->multiview_mode = mode;
8849       stream->multiview_flags = flags;
8850     }
8851   }
8852
8853   /* parse stsd */
8854   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
8855     goto corrupt_file;
8856   stsd_data = (const guint8 *) stsd->data;
8857
8858   /* stsd should at least have one entry */
8859   stsd_len = QT_UINT32 (stsd_data);
8860   if (stsd_len < 24) {
8861     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
8862     if (stream->subtype == FOURCC_vivo) {
8863       if (new_stream)
8864         gst_qtdemux_stream_free (qtdemux, stream);
8865       return TRUE;
8866     } else {
8867       goto corrupt_file;
8868     }
8869   }
8870
8871   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
8872
8873   /* and that entry should fit within stsd */
8874   len = QT_UINT32 (stsd_data + 16);
8875   if (len > stsd_len + 16)
8876     goto corrupt_file;
8877
8878   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8879   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8880       GST_FOURCC_ARGS (stream->fourcc));
8881   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8882
8883   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
8884     goto error_encrypted;
8885
8886   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
8887     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
8888     stream->protected = TRUE;
8889     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
8890       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
8891   }
8892
8893   if (stream->subtype == FOURCC_vide) {
8894     guint32 w = 0, h = 0;
8895     gboolean gray;
8896     gint depth, palette_size, palette_count;
8897     guint32 matrix[9];
8898     guint32 *palette_data = NULL;
8899
8900     stream->sampled = TRUE;
8901
8902     /* version 1 uses some 64-bit ints */
8903     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8904       goto corrupt_file;
8905
8906     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8907       goto corrupt_file;
8908
8909     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8910         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8911       goto corrupt_file;
8912
8913     stream->display_width = w >> 16;
8914     stream->display_height = h >> 16;
8915
8916     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8917         &stream->pending_tags);
8918
8919     offset = 16;
8920     if (len < 86)
8921       goto corrupt_file;
8922
8923     stream->width = QT_UINT16 (stsd_data + offset + 32);
8924     stream->height = QT_UINT16 (stsd_data + offset + 34);
8925     stream->fps_n = 0;          /* this is filled in later */
8926     stream->fps_d = 0;          /* this is filled in later */
8927     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8928     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8929
8930     /* if color_table_id is 0, ctab atom must follow; however some files
8931      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
8932      * if color table is not present we'll correct the value */
8933     if (stream->color_table_id == 0 &&
8934         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
8935       stream->color_table_id = -1;
8936     }
8937
8938     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8939         stream->width, stream->height, stream->bits_per_sample,
8940         stream->color_table_id);
8941
8942     depth = stream->bits_per_sample;
8943
8944     /* more than 32 bits means grayscale */
8945     gray = (depth > 32);
8946     /* low 32 bits specify the depth  */
8947     depth &= 0x1F;
8948
8949     /* different number of palette entries is determined by depth. */
8950     palette_count = 0;
8951     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8952       palette_count = (1 << depth);
8953     palette_size = palette_count * 4;
8954
8955     if (stream->color_table_id) {
8956       switch (palette_count) {
8957         case 0:
8958           break;
8959         case 2:
8960           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8961           break;
8962         case 4:
8963           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8964           break;
8965         case 16:
8966           if (gray)
8967             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8968           else
8969             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8970           break;
8971         case 256:
8972           if (gray)
8973             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8974           else
8975             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8976           break;
8977         default:
8978           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8979               (_("The video in this file might not play correctly.")),
8980               ("unsupported palette depth %d", depth));
8981           break;
8982       }
8983     } else {
8984       gint i, j, start, end;
8985
8986       if (len < 94)
8987         goto corrupt_file;
8988
8989       /* read table */
8990       start = QT_UINT32 (stsd_data + offset + 86);
8991       palette_count = QT_UINT16 (stsd_data + offset + 90);
8992       end = QT_UINT16 (stsd_data + offset + 92);
8993
8994       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8995           start, end, palette_count);
8996
8997       if (end > 255)
8998         end = 255;
8999       if (start > end)
9000         start = end;
9001
9002       if (len < 94 + (end - start) * 8)
9003         goto corrupt_file;
9004
9005       /* palette is always the same size */
9006       palette_data = g_malloc0 (256 * 4);
9007       palette_size = 256 * 4;
9008
9009       for (j = 0, i = start; i <= end; j++, i++) {
9010         guint32 a, r, g, b;
9011
9012         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9013         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9014         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9015         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9016
9017         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9018             (g & 0xff00) | (b >> 8);
9019       }
9020     }
9021
9022     if (stream->caps)
9023       gst_caps_unref (stream->caps);
9024
9025     stream->caps =
9026         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9027     if (G_UNLIKELY (!stream->caps)) {
9028       g_free (palette_data);
9029       goto unknown_stream;
9030     }
9031
9032     if (codec) {
9033       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9034           GST_TAG_VIDEO_CODEC, codec, NULL);
9035       g_free (codec);
9036       codec = NULL;
9037     }
9038
9039
9040     if (palette_data) {
9041       GstStructure *s;
9042
9043       if (stream->rgb8_palette)
9044         gst_memory_unref (stream->rgb8_palette);
9045       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9046           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9047
9048       s = gst_caps_get_structure (stream->caps, 0);
9049
9050       /* non-raw video has a palette_data property. raw video has the palette as
9051        * an extra plane that we append to the output buffers before we push
9052        * them*/
9053       if (!gst_structure_has_name (s, "video/x-raw")) {
9054         GstBuffer *palette;
9055
9056         palette = gst_buffer_new ();
9057         gst_buffer_append_memory (palette, stream->rgb8_palette);
9058         stream->rgb8_palette = NULL;
9059
9060         gst_caps_set_simple (stream->caps, "palette_data",
9061             GST_TYPE_BUFFER, palette, NULL);
9062         gst_buffer_unref (palette);
9063       }
9064     } else if (palette_count != 0) {
9065       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9066           (NULL), ("Unsupported palette depth %d", depth));
9067     }
9068
9069     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9070         QT_UINT16 (stsd_data + offset + 48));
9071
9072     esds = NULL;
9073     pasp = NULL;
9074     /* pick 'the' stsd child */
9075     if (!stream->protected)
9076       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9077     else
9078       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9079
9080     if (mp4v) {
9081       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9082       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9083     }
9084
9085     if (pasp) {
9086       const guint8 *pasp_data = (const guint8 *) pasp->data;
9087
9088       stream->par_w = QT_UINT32 (pasp_data + 8);
9089       stream->par_h = QT_UINT32 (pasp_data + 12);
9090     } else {
9091       stream->par_w = 0;
9092       stream->par_h = 0;
9093     }
9094
9095     if (esds) {
9096       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9097     } else {
9098       switch (fourcc) {
9099         case FOURCC_H264:
9100         case FOURCC_avc1:
9101         case FOURCC_avc3:
9102         {
9103           gint len = QT_UINT32 (stsd_data) - 0x66;
9104           const guint8 *avc_data = stsd_data + 0x66;
9105
9106           /* find avcC */
9107           while (len >= 0x8) {
9108             gint size;
9109
9110             if (QT_UINT32 (avc_data) <= len)
9111               size = QT_UINT32 (avc_data) - 0x8;
9112             else
9113               size = len - 0x8;
9114
9115             if (size < 1)
9116               /* No real data, so break out */
9117               break;
9118
9119             switch (QT_FOURCC (avc_data + 0x4)) {
9120               case FOURCC_avcC:
9121               {
9122                 /* parse, if found */
9123                 GstBuffer *buf;
9124
9125                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9126
9127                 /* First 4 bytes are the length of the atom, the next 4 bytes
9128                  * are the fourcc, the next 1 byte is the version, and the
9129                  * subsequent bytes are profile_tier_level structure like data. */
9130                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9131                     avc_data + 8 + 1, size - 1);
9132                 buf = gst_buffer_new_and_alloc (size);
9133                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9134                 gst_caps_set_simple (stream->caps,
9135                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9136                 gst_buffer_unref (buf);
9137
9138                 break;
9139               }
9140               case FOURCC_strf:
9141               {
9142                 GstBuffer *buf;
9143
9144                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9145
9146                 /* First 4 bytes are the length of the atom, the next 4 bytes
9147                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9148                  * next 1 byte is the version, and the
9149                  * subsequent bytes are sequence parameter set like data. */
9150
9151                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9152                 if (size > 1) {
9153                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9154                       avc_data + 8 + 40 + 1, size - 1);
9155
9156                   buf = gst_buffer_new_and_alloc (size);
9157                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9158                   gst_caps_set_simple (stream->caps,
9159                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9160                   gst_buffer_unref (buf);
9161                 }
9162                 break;
9163               }
9164               case FOURCC_btrt:
9165               {
9166                 guint avg_bitrate, max_bitrate;
9167
9168                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9169                 if (size < 12)
9170                   break;
9171
9172                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9173                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9174
9175                 if (!max_bitrate && !avg_bitrate)
9176                   break;
9177
9178                 /* Some muxers seem to swap the average and maximum bitrates
9179                  * (I'm looking at you, YouTube), so we swap for sanity. */
9180                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9181                   guint temp = avg_bitrate;
9182
9183                   avg_bitrate = max_bitrate;
9184                   max_bitrate = temp;
9185                 }
9186
9187                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9188                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9189                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9190                 }
9191                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9192                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9193                       GST_TAG_BITRATE, avg_bitrate, NULL);
9194                 }
9195
9196                 break;
9197               }
9198
9199               default:
9200                 break;
9201             }
9202
9203             len -= size + 8;
9204             avc_data += size + 8;
9205           }
9206
9207           break;
9208         }
9209         case FOURCC_H265:
9210         case FOURCC_hvc1:
9211         case FOURCC_hev1:
9212         {
9213           gint len = QT_UINT32 (stsd_data) - 0x66;
9214           const guint8 *hevc_data = stsd_data + 0x66;
9215
9216           /* find hevc */
9217           while (len >= 0x8) {
9218             gint size;
9219
9220             if (QT_UINT32 (hevc_data) <= len)
9221               size = QT_UINT32 (hevc_data) - 0x8;
9222             else
9223               size = len - 0x8;
9224
9225             if (size < 1)
9226               /* No real data, so break out */
9227               break;
9228
9229             switch (QT_FOURCC (hevc_data + 0x4)) {
9230               case FOURCC_hvcC:
9231               {
9232                 /* parse, if found */
9233                 GstBuffer *buf;
9234
9235                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9236
9237                 /* First 4 bytes are the length of the atom, the next 4 bytes
9238                  * are the fourcc, the next 1 byte is the version, and the
9239                  * subsequent bytes are sequence parameter set like data. */
9240                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9241                     (stream->caps, hevc_data + 8 + 1, size - 1);
9242
9243                 buf = gst_buffer_new_and_alloc (size);
9244                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9245                 gst_caps_set_simple (stream->caps,
9246                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9247                 gst_buffer_unref (buf);
9248                 break;
9249               }
9250               default:
9251                 break;
9252             }
9253             len -= size + 8;
9254             hevc_data += size + 8;
9255           }
9256           break;
9257         }
9258         case FOURCC_mp4v:
9259         case FOURCC_MP4V:
9260         case FOURCC_fmp4:
9261         case FOURCC_FMP4:
9262         {
9263           GNode *glbl;
9264
9265           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9266               GST_FOURCC_ARGS (fourcc));
9267
9268           /* codec data might be in glbl extension atom */
9269           glbl = mp4v ?
9270               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9271           if (glbl) {
9272             guint8 *data;
9273             GstBuffer *buf;
9274             gint len;
9275
9276             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9277             data = glbl->data;
9278             len = QT_UINT32 (data);
9279             if (len > 0x8) {
9280               len -= 0x8;
9281               buf = gst_buffer_new_and_alloc (len);
9282               gst_buffer_fill (buf, 0, data + 8, len);
9283               gst_caps_set_simple (stream->caps,
9284                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9285               gst_buffer_unref (buf);
9286             }
9287           }
9288           break;
9289         }
9290         case FOURCC_mjp2:
9291         {
9292           /* see annex I of the jpeg2000 spec */
9293           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9294           const guint8 *data;
9295           const gchar *colorspace = NULL;
9296           gint ncomp = 0;
9297           guint32 ncomp_map = 0;
9298           gint32 *comp_map = NULL;
9299           guint32 nchan_def = 0;
9300           gint32 *chan_def = NULL;
9301
9302           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9303           /* some required atoms */
9304           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9305           if (!mjp2)
9306             break;
9307           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9308           if (!jp2h)
9309             break;
9310
9311           /* number of components; redundant with info in codestream, but useful
9312              to a muxer */
9313           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9314           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9315             break;
9316           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9317
9318           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9319           if (!colr)
9320             break;
9321           GST_DEBUG_OBJECT (qtdemux, "found colr");
9322           /* extract colour space info */
9323           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9324             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9325               case 16:
9326                 colorspace = "sRGB";
9327                 break;
9328               case 17:
9329                 colorspace = "GRAY";
9330                 break;
9331               case 18:
9332                 colorspace = "sYUV";
9333                 break;
9334               default:
9335                 colorspace = NULL;
9336                 break;
9337             }
9338           }
9339           if (!colorspace)
9340             /* colr is required, and only values 16, 17, and 18 are specified,
9341                so error if we have no colorspace */
9342             break;
9343
9344           /* extract component mapping */
9345           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9346           if (cmap) {
9347             guint32 cmap_len = 0;
9348             int i;
9349             cmap_len = QT_UINT32 (cmap->data);
9350             if (cmap_len >= 8) {
9351               /* normal box, subtract off header */
9352               cmap_len -= 8;
9353               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9354               if (cmap_len % 4 == 0) {
9355                 ncomp_map = (cmap_len / 4);
9356                 comp_map = g_new0 (gint32, ncomp_map);
9357                 for (i = 0; i < ncomp_map; i++) {
9358                   guint16 cmp;
9359                   guint8 mtyp, pcol;
9360                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9361                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9362                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9363                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9364                 }
9365               }
9366             }
9367           }
9368           /* extract channel definitions */
9369           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9370           if (cdef) {
9371             guint32 cdef_len = 0;
9372             int i;
9373             cdef_len = QT_UINT32 (cdef->data);
9374             if (cdef_len >= 10) {
9375               /* normal box, subtract off header and len */
9376               cdef_len -= 10;
9377               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9378               if (cdef_len % 6 == 0) {
9379                 nchan_def = (cdef_len / 6);
9380                 chan_def = g_new0 (gint32, nchan_def);
9381                 for (i = 0; i < nchan_def; i++)
9382                   chan_def[i] = -1;
9383                 for (i = 0; i < nchan_def; i++) {
9384                   guint16 cn, typ, asoc;
9385                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9386                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9387                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9388                   if (cn < nchan_def) {
9389                     switch (typ) {
9390                       case 0:
9391                         chan_def[cn] = asoc;
9392                         break;
9393                       case 1:
9394                         chan_def[cn] = 0;       /* alpha */
9395                         break;
9396                       default:
9397                         chan_def[cn] = -typ;
9398                     }
9399                   }
9400                 }
9401               }
9402             }
9403           }
9404
9405           gst_caps_set_simple (stream->caps,
9406               "num-components", G_TYPE_INT, ncomp, NULL);
9407           gst_caps_set_simple (stream->caps,
9408               "colorspace", G_TYPE_STRING, colorspace, NULL);
9409
9410           if (comp_map) {
9411             GValue arr = { 0, };
9412             GValue elt = { 0, };
9413             int i;
9414             g_value_init (&arr, GST_TYPE_ARRAY);
9415             g_value_init (&elt, G_TYPE_INT);
9416             for (i = 0; i < ncomp_map; i++) {
9417               g_value_set_int (&elt, comp_map[i]);
9418               gst_value_array_append_value (&arr, &elt);
9419             }
9420             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9421                 "component-map", &arr);
9422             g_value_unset (&elt);
9423             g_value_unset (&arr);
9424             g_free (comp_map);
9425           }
9426
9427           if (chan_def) {
9428             GValue arr = { 0, };
9429             GValue elt = { 0, };
9430             int i;
9431             g_value_init (&arr, GST_TYPE_ARRAY);
9432             g_value_init (&elt, G_TYPE_INT);
9433             for (i = 0; i < nchan_def; i++) {
9434               g_value_set_int (&elt, chan_def[i]);
9435               gst_value_array_append_value (&arr, &elt);
9436             }
9437             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9438                 "channel-definitions", &arr);
9439             g_value_unset (&elt);
9440             g_value_unset (&arr);
9441             g_free (chan_def);
9442           }
9443
9444           /* some optional atoms */
9445           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9446           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9447
9448           /* indicate possible fields in caps */
9449           if (field) {
9450             data = (guint8 *) field->data + 8;
9451             if (*data != 1)
9452               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9453                   (gint) * data, NULL);
9454           }
9455           /* add codec_data if provided */
9456           if (prefix) {
9457             GstBuffer *buf;
9458             gint len;
9459
9460             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9461             data = prefix->data;
9462             len = QT_UINT32 (data);
9463             if (len > 0x8) {
9464               len -= 0x8;
9465               buf = gst_buffer_new_and_alloc (len);
9466               gst_buffer_fill (buf, 0, data + 8, len);
9467               gst_caps_set_simple (stream->caps,
9468                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9469               gst_buffer_unref (buf);
9470             }
9471           }
9472           break;
9473         }
9474         case FOURCC_SVQ3:
9475         case FOURCC_VP31:
9476         {
9477           GstBuffer *buf;
9478           GstBuffer *seqh = NULL;
9479           guint8 *gamma_data = NULL;
9480           gint len = QT_UINT32 (stsd_data);
9481
9482           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9483           if (gamma_data) {
9484             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9485                 QT_FP32 (gamma_data), NULL);
9486           }
9487           if (seqh) {
9488             /* sorry for the bad name, but we don't know what this is, other
9489              * than its own fourcc */
9490             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9491                 NULL);
9492           }
9493
9494           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9495           buf = gst_buffer_new_and_alloc (len);
9496           gst_buffer_fill (buf, 0, stsd_data, len);
9497           gst_caps_set_simple (stream->caps,
9498               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9499           gst_buffer_unref (buf);
9500           break;
9501         }
9502         case FOURCC_rle_:
9503         case FOURCC_WRLE:
9504         {
9505           gst_caps_set_simple (stream->caps,
9506               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9507           break;
9508         }
9509         case FOURCC_XiTh:
9510         {
9511           GNode *xith, *xdxt;
9512
9513           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9514           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9515           if (!xith)
9516             break;
9517
9518           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9519           if (!xdxt)
9520             break;
9521
9522           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9523           /* collect the headers and store them in a stream list so that we can
9524            * send them out first */
9525           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9526           break;
9527         }
9528         case FOURCC_ovc1:
9529         {
9530           GNode *ovc1;
9531           guint8 *ovc1_data;
9532           guint ovc1_len;
9533           GstBuffer *buf;
9534
9535           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9536           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9537           if (!ovc1)
9538             break;
9539           ovc1_data = ovc1->data;
9540           ovc1_len = QT_UINT32 (ovc1_data);
9541           if (ovc1_len <= 198) {
9542             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9543             break;
9544           }
9545           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9546           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9547           gst_caps_set_simple (stream->caps,
9548               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9549           gst_buffer_unref (buf);
9550           break;
9551         }
9552         case FOURCC_vc_1:
9553         {
9554           gint len = QT_UINT32 (stsd_data) - 0x66;
9555           const guint8 *vc1_data = stsd_data + 0x66;
9556
9557           /* find dvc1 */
9558           while (len >= 8) {
9559             gint size;
9560
9561             if (QT_UINT32 (vc1_data) <= len)
9562               size = QT_UINT32 (vc1_data) - 8;
9563             else
9564               size = len - 8;
9565
9566             if (size < 1)
9567               /* No real data, so break out */
9568               break;
9569
9570             switch (QT_FOURCC (vc1_data + 0x4)) {
9571               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9572               {
9573                 GstBuffer *buf;
9574
9575                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9576                 buf = gst_buffer_new_and_alloc (size);
9577                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9578                 gst_caps_set_simple (stream->caps,
9579                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9580                 gst_buffer_unref (buf);
9581                 break;
9582               }
9583               default:
9584                 break;
9585             }
9586             len -= size + 8;
9587             vc1_data += size + 8;
9588           }
9589           break;
9590         }
9591         default:
9592           break;
9593       }
9594     }
9595
9596     GST_INFO_OBJECT (qtdemux,
9597         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9598         GST_FOURCC_ARGS (fourcc), stream->caps);
9599
9600   } else if (stream->subtype == FOURCC_soun) {
9601     int version, samplesize;
9602     guint16 compression_id;
9603     gboolean amrwb = FALSE;
9604
9605     offset = 32;
9606     /* sample description entry (16) + sound sample description v0 (20) */
9607     if (len < 36)
9608       goto corrupt_file;
9609
9610     version = QT_UINT32 (stsd_data + offset);
9611     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9612     samplesize = QT_UINT16 (stsd_data + offset + 10);
9613     compression_id = QT_UINT16 (stsd_data + offset + 12);
9614     stream->rate = QT_FP32 (stsd_data + offset + 16);
9615
9616     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9617     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9618         QT_UINT32 (stsd_data + offset + 4));
9619     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9620     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9621     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9622     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9623         QT_UINT16 (stsd_data + offset + 14));
9624     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9625
9626     if (compression_id == 0xfffe)
9627       stream->sampled = TRUE;
9628
9629     /* first assume uncompressed audio */
9630     stream->bytes_per_sample = samplesize / 8;
9631     stream->samples_per_frame = stream->n_channels;
9632     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9633     stream->samples_per_packet = stream->samples_per_frame;
9634     stream->bytes_per_packet = stream->bytes_per_sample;
9635
9636     offset = 52;
9637     switch (fourcc) {
9638         /* Yes, these have to be hard-coded */
9639       case FOURCC_MAC6:
9640       {
9641         stream->samples_per_packet = 6;
9642         stream->bytes_per_packet = 1;
9643         stream->bytes_per_frame = 1 * stream->n_channels;
9644         stream->bytes_per_sample = 1;
9645         stream->samples_per_frame = 6 * stream->n_channels;
9646         break;
9647       }
9648       case FOURCC_MAC3:
9649       {
9650         stream->samples_per_packet = 3;
9651         stream->bytes_per_packet = 1;
9652         stream->bytes_per_frame = 1 * stream->n_channels;
9653         stream->bytes_per_sample = 1;
9654         stream->samples_per_frame = 3 * stream->n_channels;
9655         break;
9656       }
9657       case FOURCC_ima4:
9658       {
9659         stream->samples_per_packet = 64;
9660         stream->bytes_per_packet = 34;
9661         stream->bytes_per_frame = 34 * stream->n_channels;
9662         stream->bytes_per_sample = 2;
9663         stream->samples_per_frame = 64 * stream->n_channels;
9664         break;
9665       }
9666       case FOURCC_ulaw:
9667       case FOURCC_alaw:
9668       {
9669         stream->samples_per_packet = 1;
9670         stream->bytes_per_packet = 1;
9671         stream->bytes_per_frame = 1 * stream->n_channels;
9672         stream->bytes_per_sample = 1;
9673         stream->samples_per_frame = 1 * stream->n_channels;
9674         break;
9675       }
9676       case FOURCC_agsm:
9677       {
9678         stream->samples_per_packet = 160;
9679         stream->bytes_per_packet = 33;
9680         stream->bytes_per_frame = 33 * stream->n_channels;
9681         stream->bytes_per_sample = 2;
9682         stream->samples_per_frame = 160 * stream->n_channels;
9683         break;
9684       }
9685       default:
9686         break;
9687     }
9688
9689     if (version == 0x00010000) {
9690       /* sample description entry (16) + sound sample description v1 (20+16) */
9691       if (len < 52)
9692         goto corrupt_file;
9693
9694       switch (fourcc) {
9695         case FOURCC_twos:
9696         case FOURCC_sowt:
9697         case FOURCC_raw_:
9698           break;
9699         default:
9700         {
9701           /* only parse extra decoding config for non-pcm audio */
9702           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
9703           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
9704           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
9705           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
9706
9707           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
9708               stream->samples_per_packet);
9709           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
9710               stream->bytes_per_packet);
9711           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
9712               stream->bytes_per_frame);
9713           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
9714               stream->bytes_per_sample);
9715
9716           if (!stream->sampled && stream->bytes_per_packet) {
9717             stream->samples_per_frame = (stream->bytes_per_frame /
9718                 stream->bytes_per_packet) * stream->samples_per_packet;
9719             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
9720                 stream->samples_per_frame);
9721           }
9722           break;
9723         }
9724       }
9725     } else if (version == 0x00020000) {
9726       union
9727       {
9728         gdouble fp;
9729         guint64 val;
9730       } qtfp;
9731
9732       /* sample description entry (16) + sound sample description v2 (56) */
9733       if (len < 72)
9734         goto corrupt_file;
9735
9736       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
9737       stream->rate = qtfp.fp;
9738       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
9739
9740       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
9741       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
9742       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
9743       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
9744           QT_UINT32 (stsd_data + offset + 20));
9745       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
9746           QT_UINT32 (stsd_data + offset + 24));
9747       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
9748           QT_UINT32 (stsd_data + offset + 28));
9749       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
9750           QT_UINT32 (stsd_data + offset + 32));
9751     } else if (version != 0x00000) {
9752       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
9753     }
9754
9755     if (stream->caps)
9756       gst_caps_unref (stream->caps);
9757
9758     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
9759         stsd_data + 32, len - 16, &codec);
9760
9761     switch (fourcc) {
9762       case FOURCC_in24:
9763       {
9764         GNode *enda;
9765         GNode *in24;
9766
9767         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
9768
9769         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
9770         if (!enda) {
9771           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
9772           if (wave)
9773             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
9774         }
9775         if (enda) {
9776           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
9777           gst_caps_set_simple (stream->caps,
9778               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
9779         }
9780         break;
9781       }
9782       case FOURCC_owma:
9783       {
9784         GNode *owma;
9785         const guint8 *owma_data;
9786         const gchar *codec_name = NULL;
9787         guint owma_len;
9788         GstBuffer *buf;
9789         gint version = 1;
9790         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9791         /* FIXME this should also be gst_riff_strf_auds,
9792          * but the latter one is actually missing bits-per-sample :( */
9793         typedef struct
9794         {
9795           gint16 wFormatTag;
9796           gint16 nChannels;
9797           gint32 nSamplesPerSec;
9798           gint32 nAvgBytesPerSec;
9799           gint16 nBlockAlign;
9800           gint16 wBitsPerSample;
9801           gint16 cbSize;
9802         } WAVEFORMATEX;
9803         WAVEFORMATEX *wfex;
9804
9805         GST_DEBUG_OBJECT (qtdemux, "parse owma");
9806         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
9807         if (!owma)
9808           break;
9809         owma_data = owma->data;
9810         owma_len = QT_UINT32 (owma_data);
9811         if (owma_len <= 54) {
9812           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
9813           break;
9814         }
9815         wfex = (WAVEFORMATEX *) (owma_data + 36);
9816         buf = gst_buffer_new_and_alloc (owma_len - 54);
9817         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
9818         if (wfex->wFormatTag == 0x0161) {
9819           codec_name = "Windows Media Audio";
9820           version = 2;
9821         } else if (wfex->wFormatTag == 0x0162) {
9822           codec_name = "Windows Media Audio 9 Pro";
9823           version = 3;
9824         } else if (wfex->wFormatTag == 0x0163) {
9825           codec_name = "Windows Media Audio 9 Lossless";
9826           /* is that correct? gstffmpegcodecmap.c is missing it, but
9827            * fluendo codec seems to support it */
9828           version = 4;
9829         }
9830
9831         gst_caps_set_simple (stream->caps,
9832             "codec_data", GST_TYPE_BUFFER, buf,
9833             "wmaversion", G_TYPE_INT, version,
9834             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
9835             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
9836             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9837             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9838             NULL);
9839         gst_buffer_unref (buf);
9840
9841         if (codec_name) {
9842           g_free (codec);
9843           codec = g_strdup (codec_name);
9844         }
9845         break;
9846       }
9847       case FOURCC_wma_:
9848       {
9849         gint len = QT_UINT32 (stsd_data) - offset;
9850         const guint8 *wfex_data = stsd_data + offset;
9851         const gchar *codec_name = NULL;
9852         gint version = 1;
9853         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9854         /* FIXME this should also be gst_riff_strf_auds,
9855          * but the latter one is actually missing bits-per-sample :( */
9856         typedef struct
9857         {
9858           gint16 wFormatTag;
9859           gint16 nChannels;
9860           gint32 nSamplesPerSec;
9861           gint32 nAvgBytesPerSec;
9862           gint16 nBlockAlign;
9863           gint16 wBitsPerSample;
9864           gint16 cbSize;
9865         } WAVEFORMATEX;
9866         WAVEFORMATEX wfex;
9867
9868         /* FIXME: unify with similar wavformatex parsing code above */
9869         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
9870
9871         /* find wfex */
9872         while (len >= 8) {
9873           gint size;
9874
9875           if (QT_UINT32 (wfex_data) <= len)
9876             size = QT_UINT32 (wfex_data) - 8;
9877           else
9878             size = len - 8;
9879
9880           if (size < 1)
9881             /* No real data, so break out */
9882             break;
9883
9884           switch (QT_FOURCC (wfex_data + 4)) {
9885             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
9886             {
9887               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
9888
9889               if (size < 8 + 18)
9890                 break;
9891
9892               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
9893               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
9894               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
9895               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
9896               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9897               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9898               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9899
9900               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9901               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9902                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9903                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9904                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9905                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9906
9907               if (wfex.wFormatTag == 0x0161) {
9908                 codec_name = "Windows Media Audio";
9909                 version = 2;
9910               } else if (wfex.wFormatTag == 0x0162) {
9911                 codec_name = "Windows Media Audio 9 Pro";
9912                 version = 3;
9913               } else if (wfex.wFormatTag == 0x0163) {
9914                 codec_name = "Windows Media Audio 9 Lossless";
9915                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9916                  * fluendo codec seems to support it */
9917                 version = 4;
9918               }
9919
9920               gst_caps_set_simple (stream->caps,
9921                   "wmaversion", G_TYPE_INT, version,
9922                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9923                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9924                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9925                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9926
9927               if (size > wfex.cbSize) {
9928                 GstBuffer *buf;
9929
9930                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9931                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9932                     size - wfex.cbSize);
9933                 gst_caps_set_simple (stream->caps,
9934                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9935                 gst_buffer_unref (buf);
9936               } else {
9937                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9938               }
9939
9940               if (codec_name) {
9941                 g_free (codec);
9942                 codec = g_strdup (codec_name);
9943               }
9944               break;
9945             }
9946             default:
9947               break;
9948           }
9949           len -= size + 8;
9950           wfex_data += size + 8;
9951         }
9952         break;
9953       }
9954       case FOURCC_opus:
9955       {
9956         GNode *opus;
9957         const guint8 *opus_data;
9958         guint8 *channel_mapping = NULL;
9959         guint32 rate;
9960         guint8 channels;
9961         guint8 channel_mapping_family;
9962         guint8 stream_count;
9963         guint8 coupled_count;
9964         guint8 i;
9965
9966         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
9967         opus_data = opus->data;
9968
9969         channels = GST_READ_UINT8 (opus_data + 45);
9970         rate = GST_READ_UINT32_LE (opus_data + 48);
9971         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
9972         stream_count = GST_READ_UINT8 (opus_data + 55);
9973         coupled_count = GST_READ_UINT8 (opus_data + 56);
9974
9975         if (channels > 0) {
9976           channel_mapping = g_malloc (channels * sizeof (guint8));
9977           for (i = 0; i < channels; i++)
9978             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
9979         }
9980
9981         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
9982             channel_mapping_family, stream_count, coupled_count,
9983             channel_mapping);
9984         break;
9985       }
9986       default:
9987         break;
9988     }
9989
9990     if (codec) {
9991       GstStructure *s;
9992       gint bitrate = 0;
9993
9994       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9995           GST_TAG_AUDIO_CODEC, codec, NULL);
9996       g_free (codec);
9997       codec = NULL;
9998
9999       /* some bitrate info may have ended up in caps */
10000       s = gst_caps_get_structure (stream->caps, 0);
10001       gst_structure_get_int (s, "bitrate", &bitrate);
10002       if (bitrate > 0)
10003         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10004             GST_TAG_BITRATE, bitrate, NULL);
10005     }
10006
10007     if (stream->protected && fourcc == FOURCC_mp4a)
10008       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10009     else
10010       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10011
10012     wave = NULL;
10013     esds = NULL;
10014     if (mp4a) {
10015       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10016       if (wave)
10017         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10018       if (!esds)
10019         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10020     }
10021
10022
10023     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10024        16 bits is a byte-swapped wave-style codec identifier,
10025        and we can find a WAVE header internally to a 'wave' atom here.
10026        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10027        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10028        is big-endian).
10029      */
10030     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10031       if (len < offset + 20) {
10032         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10033       } else {
10034         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10035         const guint8 *data = stsd_data + offset + 16;
10036         GNode *wavenode;
10037         GNode *waveheadernode;
10038
10039         wavenode = g_node_new ((guint8 *) data);
10040         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10041           const guint8 *waveheader;
10042           guint32 headerlen;
10043
10044           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10045           if (waveheadernode) {
10046             waveheader = (const guint8 *) waveheadernode->data;
10047             headerlen = QT_UINT32 (waveheader);
10048
10049             if (headerlen > 8) {
10050               gst_riff_strf_auds *header = NULL;
10051               GstBuffer *headerbuf;
10052               GstBuffer *extra;
10053
10054               waveheader += 8;
10055               headerlen -= 8;
10056
10057               headerbuf = gst_buffer_new_and_alloc (headerlen);
10058               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10059
10060               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10061                       headerbuf, &header, &extra)) {
10062                 gst_caps_unref (stream->caps);
10063                 /* FIXME: Need to do something with the channel reorder map */
10064                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10065                     header, extra, NULL, NULL, NULL);
10066
10067                 if (extra)
10068                   gst_buffer_unref (extra);
10069                 g_free (header);
10070               }
10071             }
10072           } else
10073             GST_DEBUG ("Didn't find waveheadernode for this codec");
10074         }
10075         g_node_destroy (wavenode);
10076       }
10077     } else if (esds) {
10078       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10079     } else {
10080       switch (fourcc) {
10081 #if 0
10082           /* FIXME: what is in the chunk? */
10083         case FOURCC_QDMC:
10084         {
10085           gint len = QT_UINT32 (stsd_data);
10086
10087           /* seems to be always = 116 = 0x74 */
10088           break;
10089         }
10090 #endif
10091         case FOURCC_QDM2:
10092         {
10093           gint len = QT_UINT32 (stsd_data);
10094
10095           if (len > 0x4C) {
10096             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10097
10098             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10099             gst_caps_set_simple (stream->caps,
10100                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10101             gst_buffer_unref (buf);
10102           }
10103           gst_caps_set_simple (stream->caps,
10104               "samplesize", G_TYPE_INT, samplesize, NULL);
10105           break;
10106         }
10107         case FOURCC_alac:
10108         {
10109           GNode *alac, *wave = NULL;
10110
10111           /* apparently, m4a has this atom appended directly in the stsd entry,
10112            * while mov has it in a wave atom */
10113           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10114           if (alac) {
10115             /* alac now refers to stsd entry atom */
10116             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10117             if (wave)
10118               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10119             else
10120               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10121           }
10122           if (alac) {
10123             const guint8 *alac_data = alac->data;
10124             gint len = QT_UINT32 (alac->data);
10125             GstBuffer *buf;
10126
10127             if (len < 36) {
10128               GST_DEBUG_OBJECT (qtdemux,
10129                   "discarding alac atom with unexpected len %d", len);
10130             } else {
10131               /* codec-data contains alac atom size and prefix,
10132                * ffmpeg likes it that way, not quite gst-ish though ...*/
10133               buf = gst_buffer_new_and_alloc (len);
10134               gst_buffer_fill (buf, 0, alac->data, len);
10135               gst_caps_set_simple (stream->caps,
10136                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10137               gst_buffer_unref (buf);
10138
10139               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10140               stream->n_channels = QT_UINT8 (alac_data + 21);
10141               stream->rate = QT_UINT32 (alac_data + 32);
10142             }
10143           }
10144           gst_caps_set_simple (stream->caps,
10145               "samplesize", G_TYPE_INT, samplesize, NULL);
10146           break;
10147         }
10148         case FOURCC_sawb:
10149           /* Fallthrough! */
10150           amrwb = TRUE;
10151         case FOURCC_samr:
10152         {
10153           gint len = QT_UINT32 (stsd_data);
10154
10155           if (len > 0x34) {
10156             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10157             guint bitrate;
10158
10159             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10160
10161             /* If we have enough data, let's try to get the 'damr' atom. See
10162              * the 3GPP container spec (26.244) for more details. */
10163             if ((len - 0x34) > 8 &&
10164                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10165               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10166                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10167             }
10168
10169             gst_caps_set_simple (stream->caps,
10170                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10171             gst_buffer_unref (buf);
10172           }
10173           break;
10174         }
10175         case FOURCC_mp4a:
10176         {
10177           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10178           gint len = QT_UINT32 (stsd_data);
10179
10180           if (len >= 50) {
10181             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10182
10183             if (sound_version == 1) {
10184               guint16 channels = QT_UINT16 (stsd_data + 40);
10185               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10186               guint8 codec_data[2];
10187               GstBuffer *buf;
10188               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10189
10190               gint sample_rate_index =
10191                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10192
10193               /* build AAC codec data */
10194               codec_data[0] = profile << 3;
10195               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10196               codec_data[1] = (sample_rate_index & 0x01) << 7;
10197               codec_data[1] |= (channels & 0xF) << 3;
10198
10199               buf = gst_buffer_new_and_alloc (2);
10200               gst_buffer_fill (buf, 0, codec_data, 2);
10201               gst_caps_set_simple (stream->caps,
10202                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10203               gst_buffer_unref (buf);
10204             }
10205           }
10206           break;
10207         }
10208         default:
10209           GST_INFO_OBJECT (qtdemux,
10210               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10211           break;
10212       }
10213     }
10214     GST_INFO_OBJECT (qtdemux,
10215         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10216         GST_FOURCC_ARGS (fourcc), stream->caps);
10217
10218   } else if (stream->subtype == FOURCC_strm) {
10219     if (fourcc == FOURCC_rtsp) {
10220       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10221     } else {
10222       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10223           GST_FOURCC_ARGS (fourcc));
10224       goto unknown_stream;
10225     }
10226     stream->sampled = TRUE;
10227   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10228       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10229
10230     stream->sampled = TRUE;
10231     stream->sparse = TRUE;
10232
10233     stream->caps =
10234         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10235     if (codec) {
10236       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10237           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10238       g_free (codec);
10239       codec = NULL;
10240     }
10241
10242     /* hunt for sort-of codec data */
10243     switch (fourcc) {
10244       case FOURCC_mp4s:
10245       {
10246         GNode *mp4s = NULL;
10247         GNode *esds = NULL;
10248
10249         /* look for palette in a stsd->mp4s->esds sub-atom */
10250         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10251         if (mp4s)
10252           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10253         if (esds == NULL) {
10254           /* Invalid STSD */
10255           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10256           break;
10257         }
10258
10259         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10260         break;
10261       }
10262       default:
10263         GST_INFO_OBJECT (qtdemux,
10264             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10265         break;
10266     }
10267     GST_INFO_OBJECT (qtdemux,
10268         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10269         GST_FOURCC_ARGS (fourcc), stream->caps);
10270   } else {
10271     /* everything in 1 sample */
10272     stream->sampled = TRUE;
10273
10274     stream->caps =
10275         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10276
10277     if (stream->caps == NULL)
10278       goto unknown_stream;
10279
10280     if (codec) {
10281       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10282           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10283       g_free (codec);
10284       codec = NULL;
10285     }
10286   }
10287
10288   /* promote to sampled format */
10289   if (stream->fourcc == FOURCC_samr) {
10290     /* force mono 8000 Hz for AMR */
10291     stream->sampled = TRUE;
10292     stream->n_channels = 1;
10293     stream->rate = 8000;
10294   } else if (stream->fourcc == FOURCC_sawb) {
10295     /* force mono 16000 Hz for AMR-WB */
10296     stream->sampled = TRUE;
10297     stream->n_channels = 1;
10298     stream->rate = 16000;
10299   } else if (stream->fourcc == FOURCC_mp4a) {
10300     stream->sampled = TRUE;
10301   }
10302
10303   /* collect sample information */
10304   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10305     goto samples_failed;
10306
10307   if (qtdemux->fragmented) {
10308     guint64 offset;
10309
10310     /* need all moov samples as basis; probably not many if any at all */
10311     /* prevent moof parsing taking of at this time */
10312     offset = qtdemux->moof_offset;
10313     qtdemux->moof_offset = 0;
10314     if (stream->n_samples &&
10315         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10316       qtdemux->moof_offset = offset;
10317       goto samples_failed;
10318     }
10319     qtdemux->moof_offset = 0;
10320     /* movie duration more reliable in this case (e.g. mehd) */
10321     if (qtdemux->segment.duration &&
10322         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10323       stream->duration =
10324           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10325   }
10326
10327   /* configure segments */
10328   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10329     goto segments_failed;
10330
10331   /* add some language tag, if useful */
10332   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10333       strcmp (stream->lang_id, "und")) {
10334     const gchar *lang_code;
10335
10336     /* convert ISO 639-2 code to ISO 639-1 */
10337     lang_code = gst_tag_get_language_code (stream->lang_id);
10338     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10339         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10340   }
10341
10342   /* Check for UDTA tags */
10343   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10344     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10345   }
10346
10347   /* now we are ready to add the stream */
10348   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10349     goto too_many_streams;
10350
10351   if (!qtdemux->got_moov) {
10352     qtdemux->streams[qtdemux->n_streams] = stream;
10353     qtdemux->n_streams++;
10354     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10355   }
10356
10357   return TRUE;
10358
10359 /* ERRORS */
10360 skip_track:
10361   {
10362     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10363     if (new_stream)
10364       gst_qtdemux_stream_free (qtdemux, stream);
10365     return TRUE;
10366   }
10367 corrupt_file:
10368   {
10369     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10370         (_("This file is corrupt and cannot be played.")), (NULL));
10371     if (new_stream)
10372       gst_qtdemux_stream_free (qtdemux, stream);
10373     return FALSE;
10374   }
10375 error_encrypted:
10376   {
10377     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10378     if (new_stream)
10379       gst_qtdemux_stream_free (qtdemux, stream);
10380     return FALSE;
10381   }
10382 samples_failed:
10383 segments_failed:
10384   {
10385     /* we posted an error already */
10386     /* free stbl sub-atoms */
10387     gst_qtdemux_stbl_free (stream);
10388     if (new_stream)
10389       gst_qtdemux_stream_free (qtdemux, stream);
10390     return FALSE;
10391   }
10392 existing_stream:
10393   {
10394     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10395         track_id);
10396     if (new_stream)
10397       gst_qtdemux_stream_free (qtdemux, stream);
10398     return TRUE;
10399   }
10400 unknown_stream:
10401   {
10402     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10403         GST_FOURCC_ARGS (stream->subtype));
10404     if (new_stream)
10405       gst_qtdemux_stream_free (qtdemux, stream);
10406     return TRUE;
10407   }
10408 too_many_streams:
10409   {
10410     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10411         (_("This file contains too many streams. Only playing first %d"),
10412             GST_QTDEMUX_MAX_STREAMS), (NULL));
10413     return TRUE;
10414   }
10415 }
10416
10417 /* If we can estimate the overall bitrate, and don't have information about the
10418  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10419  * the overall bitrate minus the sum of the bitrates of all other streams. This
10420  * should be useful for the common case where we have one audio and one video
10421  * stream and can estimate the bitrate of one, but not the other. */
10422 static void
10423 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10424 {
10425   QtDemuxStream *stream = NULL;
10426   gint64 size, sys_bitrate, sum_bitrate = 0;
10427   GstClockTime duration;
10428   gint i;
10429   guint bitrate;
10430
10431   if (qtdemux->fragmented)
10432     return;
10433
10434   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10435
10436   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10437       || size <= 0) {
10438     GST_DEBUG_OBJECT (qtdemux,
10439         "Size in bytes of the stream not known - bailing");
10440     return;
10441   }
10442
10443   /* Subtract the header size */
10444   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10445       size, qtdemux->header_size);
10446
10447   if (size < qtdemux->header_size)
10448     return;
10449
10450   size = size - qtdemux->header_size;
10451
10452   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
10453       duration == GST_CLOCK_TIME_NONE) {
10454     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10455     return;
10456   }
10457
10458   for (i = 0; i < qtdemux->n_streams; i++) {
10459     switch (qtdemux->streams[i]->subtype) {
10460       case FOURCC_soun:
10461       case FOURCC_vide:
10462         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10463             qtdemux->streams[i]->caps);
10464         /* retrieve bitrate, prefer avg then max */
10465         bitrate = 0;
10466         if (qtdemux->streams[i]->pending_tags) {
10467           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10468               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10469           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10470           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10471               GST_TAG_NOMINAL_BITRATE, &bitrate);
10472           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10473           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10474               GST_TAG_BITRATE, &bitrate);
10475           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10476         }
10477         if (bitrate)
10478           sum_bitrate += bitrate;
10479         else {
10480           if (stream) {
10481             GST_DEBUG_OBJECT (qtdemux,
10482                 ">1 stream with unknown bitrate - bailing");
10483             return;
10484           } else
10485             stream = qtdemux->streams[i];
10486         }
10487
10488       default:
10489         /* For other subtypes, we assume no significant impact on bitrate */
10490         break;
10491     }
10492   }
10493
10494   if (!stream) {
10495     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10496     return;
10497   }
10498
10499   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10500
10501   if (sys_bitrate < sum_bitrate) {
10502     /* This can happen, since sum_bitrate might be derived from maximum
10503      * bitrates and not average bitrates */
10504     GST_DEBUG_OBJECT (qtdemux,
10505         "System bitrate less than sum bitrate - bailing");
10506     return;
10507   }
10508
10509   bitrate = sys_bitrate - sum_bitrate;
10510   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10511       ", Stream bitrate = %u", sys_bitrate, bitrate);
10512
10513   if (!stream->pending_tags)
10514     stream->pending_tags = gst_tag_list_new_empty ();
10515
10516   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10517       GST_TAG_BITRATE, bitrate, NULL);
10518 }
10519
10520 static GstFlowReturn
10521 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10522 {
10523   gint i;
10524   GstFlowReturn ret = GST_FLOW_OK;
10525
10526   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10527
10528   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10529     QtDemuxStream *stream = qtdemux->streams[i];
10530     guint32 sample_num = 0;
10531
10532     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10533         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10534
10535     if (qtdemux->fragmented) {
10536       /* need all moov samples first */
10537       GST_OBJECT_LOCK (qtdemux);
10538       while (stream->n_samples == 0)
10539         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10540           break;
10541       GST_OBJECT_UNLOCK (qtdemux);
10542     } else {
10543       /* discard any stray moof */
10544       qtdemux->moof_offset = 0;
10545     }
10546
10547     /* prepare braking */
10548     if (ret != GST_FLOW_ERROR)
10549       ret = GST_FLOW_OK;
10550
10551     /* in pull mode, we should have parsed some sample info by now;
10552      * and quite some code will not handle no samples.
10553      * in push mode, we'll just have to deal with it */
10554     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10555       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10556       gst_qtdemux_remove_stream (qtdemux, i);
10557       i--;
10558       continue;
10559     }
10560
10561     /* parse the initial sample for use in setting the frame rate cap */
10562     while (sample_num == 0 && sample_num < stream->n_samples) {
10563       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10564         break;
10565       ++sample_num;
10566     }
10567     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10568       stream->first_duration = stream->samples[0].duration;
10569       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10570           stream->track_id, stream->first_duration);
10571     }
10572   }
10573
10574   return ret;
10575 }
10576
10577 static GstFlowReturn
10578 qtdemux_expose_streams (GstQTDemux * qtdemux)
10579 {
10580   gint i;
10581   GstFlowReturn ret = GST_FLOW_OK;
10582   GSList *oldpads = NULL;
10583   GSList *iter;
10584
10585   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10586
10587   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10588     QtDemuxStream *stream = qtdemux->streams[i];
10589     GstPad *oldpad = stream->pad;
10590     GstTagList *list;
10591
10592     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10593         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10594
10595     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10596         stream->track_id == qtdemux->chapters_track_id) {
10597       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10598          so that it doesn't look like a subtitle track */
10599       gst_qtdemux_remove_stream (qtdemux, i);
10600       i--;
10601       continue;
10602     }
10603
10604     /* now we have all info and can expose */
10605     list = stream->pending_tags;
10606     stream->pending_tags = NULL;
10607     if (oldpad)
10608       oldpads = g_slist_prepend (oldpads, oldpad);
10609     gst_qtdemux_add_stream (qtdemux, stream, list);
10610   }
10611
10612   gst_qtdemux_guess_bitrate (qtdemux);
10613
10614   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10615
10616   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10617     GstPad *oldpad = iter->data;
10618
10619     gst_pad_push_event (oldpad, gst_event_new_eos ());
10620     gst_pad_set_active (oldpad, FALSE);
10621     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10622     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10623     gst_object_unref (oldpad);
10624   }
10625
10626   /* check if we should post a redirect in case there is a single trak
10627    * and it is a redirecting trak */
10628   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10629     GstMessage *m;
10630
10631     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10632         "an external content");
10633     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10634         gst_structure_new ("redirect",
10635             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10636             NULL));
10637     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10638     qtdemux->posted_redirect = TRUE;
10639   }
10640
10641   for (i = 0; i < qtdemux->n_streams; i++) {
10642     QtDemuxStream *stream = qtdemux->streams[i];
10643
10644     qtdemux_do_allocation (qtdemux, stream);
10645   }
10646
10647   qtdemux->exposed = TRUE;
10648   return ret;
10649 }
10650
10651 /* check if major or compatible brand is 3GP */
10652 static inline gboolean
10653 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10654 {
10655   if (major) {
10656     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10657         FOURCC_3g__);
10658   } else if (qtdemux->comp_brands != NULL) {
10659     GstMapInfo map;
10660     guint8 *data;
10661     gsize size;
10662     gboolean res = FALSE;
10663
10664     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10665     data = map.data;
10666     size = map.size;
10667     while (size >= 4) {
10668       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10669           FOURCC_3g__);
10670       data += 4;
10671       size -= 4;
10672     }
10673     gst_buffer_unmap (qtdemux->comp_brands, &map);
10674     return res;
10675   } else {
10676     return FALSE;
10677   }
10678 }
10679
10680 /* check if tag is a spec'ed 3GP tag keyword storing a string */
10681 static inline gboolean
10682 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
10683 {
10684   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
10685       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
10686       || fourcc == FOURCC_albm;
10687 }
10688
10689 static void
10690 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
10691     const char *tag, const char *dummy, GNode * node)
10692 {
10693   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10694   int offset;
10695   char *name;
10696   gchar *data;
10697   gdouble longitude, latitude, altitude;
10698   gint len;
10699
10700   len = QT_UINT32 (node->data);
10701   if (len <= 14)
10702     goto short_read;
10703
10704   data = node->data;
10705   offset = 14;
10706
10707   /* TODO: language code skipped */
10708
10709   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
10710
10711   if (!name) {
10712     /* do not alarm in trivial case, but bail out otherwise */
10713     if (*(data + offset) != 0) {
10714       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
10715           "giving up", tag);
10716     }
10717   } else {
10718     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10719         GST_TAG_GEO_LOCATION_NAME, name, NULL);
10720     offset += strlen (name);
10721     g_free (name);
10722   }
10723
10724   if (len < offset + 2 + 4 + 4 + 4)
10725     goto short_read;
10726
10727   /* +1 +1 = skip null-terminator and location role byte */
10728   offset += 1 + 1;
10729   /* table in spec says unsigned, semantics say negative has meaning ... */
10730   longitude = QT_SFP32 (data + offset);
10731
10732   offset += 4;
10733   latitude = QT_SFP32 (data + offset);
10734
10735   offset += 4;
10736   altitude = QT_SFP32 (data + offset);
10737
10738   /* one invalid means all are invalid */
10739   if (longitude >= -180.0 && longitude <= 180.0 &&
10740       latitude >= -90.0 && latitude <= 90.0) {
10741     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10742         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
10743         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
10744         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
10745   }
10746
10747   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
10748
10749   return;
10750
10751   /* ERRORS */
10752 short_read:
10753   {
10754     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
10755     return;
10756   }
10757 }
10758
10759
10760 static void
10761 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
10762     const char *tag, const char *dummy, GNode * node)
10763 {
10764   guint16 y;
10765   GDate *date;
10766   gint len;
10767
10768   len = QT_UINT32 (node->data);
10769   if (len < 14)
10770     return;
10771
10772   y = QT_UINT16 ((guint8 *) node->data + 12);
10773   if (y == 0) {
10774     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
10775     return;
10776   }
10777   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
10778
10779   date = g_date_new_dmy (1, 1, y);
10780   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10781   g_date_free (date);
10782 }
10783
10784 static void
10785 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
10786     const char *tag, const char *dummy, GNode * node)
10787 {
10788   int offset;
10789   char *tag_str = NULL;
10790   guint8 *entity;
10791   guint16 table;
10792   gint len;
10793
10794   len = QT_UINT32 (node->data);
10795   if (len <= 20)
10796     goto short_read;
10797
10798   offset = 12;
10799   entity = (guint8 *) node->data + offset;
10800   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
10801     GST_DEBUG_OBJECT (qtdemux,
10802         "classification info: %c%c%c%c invalid classification entity",
10803         entity[0], entity[1], entity[2], entity[3]);
10804     return;
10805   }
10806
10807   offset += 4;
10808   table = QT_UINT16 ((guint8 *) node->data + offset);
10809
10810   /* Language code skipped */
10811
10812   offset += 4;
10813
10814   /* Tag format: "XXXX://Y[YYYY]/classification info string"
10815    * XXXX: classification entity, fixed length 4 chars.
10816    * Y[YYYY]: classification table, max 5 chars.
10817    */
10818   tag_str = g_strdup_printf ("----://%u/%s",
10819       table, (char *) node->data + offset);
10820
10821   /* memcpy To be sure we're preserving byte order */
10822   memcpy (tag_str, entity, 4);
10823   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
10824
10825   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
10826
10827   g_free (tag_str);
10828
10829   return;
10830
10831   /* ERRORS */
10832 short_read:
10833   {
10834     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
10835     return;
10836   }
10837 }
10838
10839 static gboolean
10840 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
10841     const char *tag, const char *dummy, GNode * node)
10842 {
10843   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10844   GNode *data;
10845   char *s;
10846   int len;
10847   guint32 type;
10848   int offset;
10849   gboolean ret = TRUE;
10850   const gchar *charset = NULL;
10851
10852   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10853   if (data) {
10854     len = QT_UINT32 (data->data);
10855     type = QT_UINT32 ((guint8 *) data->data + 8);
10856     if (type == 0x00000001 && len > 16) {
10857       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
10858           env_vars);
10859       if (s) {
10860         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10861         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10862         g_free (s);
10863       } else {
10864         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10865       }
10866     }
10867   } else {
10868     len = QT_UINT32 (node->data);
10869     type = QT_UINT32 ((guint8 *) node->data + 4);
10870     if ((type >> 24) == 0xa9) {
10871       gint str_len;
10872       gint lang_code;
10873
10874       /* Type starts with the (C) symbol, so the next data is a list
10875        * of (string size(16), language code(16), string) */
10876
10877       str_len = QT_UINT16 ((guint8 *) node->data + 8);
10878       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
10879
10880       /* the string + fourcc + size + 2 16bit fields,
10881        * means that there are more tags in this atom */
10882       if (len > str_len + 8 + 4) {
10883         /* TODO how to represent the same tag in different languages? */
10884         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
10885             "text alternatives, reading only first one");
10886       }
10887
10888       offset = 12;
10889       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
10890       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
10891
10892       if (lang_code < 0x800) {  /* MAC encoded string */
10893         charset = "mac";
10894       }
10895     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
10896             QT_FOURCC ((guint8 *) node->data + 4))) {
10897       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
10898
10899       /* we go for 3GP style encoding if major brands claims so,
10900        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
10901       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10902           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
10903               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
10904         offset = 14;
10905         /* 16-bit Language code is ignored here as well */
10906         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
10907       } else {
10908         goto normal;
10909       }
10910     } else {
10911     normal:
10912       offset = 8;
10913       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
10914       ret = FALSE;              /* may have to fallback */
10915     }
10916     if (charset) {
10917       GError *err = NULL;
10918
10919       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
10920           charset, NULL, NULL, &err);
10921       if (err) {
10922         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
10923             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
10924             err->message);
10925         g_error_free (err);
10926       }
10927     } else {
10928       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10929           len - offset, env_vars);
10930     }
10931     if (s) {
10932       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10933       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10934       g_free (s);
10935       ret = TRUE;
10936     } else {
10937       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10938     }
10939   }
10940   return ret;
10941 }
10942
10943 static void
10944 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10945     const char *tag, const char *dummy, GNode * node)
10946 {
10947   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10948 }
10949
10950 static void
10951 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10952     const char *tag, const char *dummy, GNode * node)
10953 {
10954   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10955   guint8 *data;
10956   char *s, *t, *k = NULL;
10957   int len;
10958   int offset;
10959   int count;
10960
10961   /* first try normal string tag if major brand not 3GP */
10962   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10963     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10964       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10965        * let's try it 3gpp way after minor safety check */
10966       data = node->data;
10967       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10968         return;
10969     } else
10970       return;
10971   }
10972
10973   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10974
10975   data = node->data;
10976
10977   len = QT_UINT32 (data);
10978   if (len < 15)
10979     goto short_read;
10980
10981   count = QT_UINT8 (data + 14);
10982   offset = 15;
10983   for (; count; count--) {
10984     gint slen;
10985
10986     if (offset + 1 > len)
10987       goto short_read;
10988     slen = QT_UINT8 (data + offset);
10989     offset += 1;
10990     if (offset + slen > len)
10991       goto short_read;
10992     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10993         slen, env_vars);
10994     if (s) {
10995       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10996       if (k) {
10997         t = g_strjoin (",", k, s, NULL);
10998         g_free (s);
10999         g_free (k);
11000         k = t;
11001       } else {
11002         k = s;
11003       }
11004     } else {
11005       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11006     }
11007     offset += slen;
11008   }
11009
11010 done:
11011   if (k) {
11012     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11013     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11014   }
11015   g_free (k);
11016
11017   return;
11018
11019   /* ERRORS */
11020 short_read:
11021   {
11022     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11023     goto done;
11024   }
11025 }
11026
11027 static void
11028 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11029     const char *tag1, const char *tag2, GNode * node)
11030 {
11031   GNode *data;
11032   int len;
11033   int type;
11034   int n1, n2;
11035
11036   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11037   if (data) {
11038     len = QT_UINT32 (data->data);
11039     type = QT_UINT32 ((guint8 *) data->data + 8);
11040     if (type == 0x00000000 && len >= 22) {
11041       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11042       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11043       if (n1 > 0) {
11044         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11045         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11046       }
11047       if (n2 > 0) {
11048         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11049         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11050       }
11051     }
11052   }
11053 }
11054
11055 static void
11056 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11057     const char *tag1, const char *dummy, GNode * node)
11058 {
11059   GNode *data;
11060   int len;
11061   int type;
11062   int n1;
11063
11064   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11065   if (data) {
11066     len = QT_UINT32 (data->data);
11067     type = QT_UINT32 ((guint8 *) data->data + 8);
11068     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11069     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11070     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11071       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11072       if (n1) {
11073         /* do not add bpm=0 */
11074         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11075         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11076             NULL);
11077       }
11078     }
11079   }
11080 }
11081
11082 static void
11083 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11084     const char *tag1, const char *dummy, GNode * node)
11085 {
11086   GNode *data;
11087   int len;
11088   int type;
11089   guint32 num;
11090
11091   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11092   if (data) {
11093     len = QT_UINT32 (data->data);
11094     type = QT_UINT32 ((guint8 *) data->data + 8);
11095     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11096     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11097     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11098       num = QT_UINT32 ((guint8 *) data->data + 16);
11099       if (num) {
11100         /* do not add num=0 */
11101         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11102         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11103       }
11104     }
11105   }
11106 }
11107
11108 static void
11109 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11110     const char *tag1, const char *dummy, GNode * node)
11111 {
11112   GNode *data;
11113   int len;
11114   int type;
11115   GstSample *sample;
11116
11117   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11118   if (data) {
11119     len = QT_UINT32 (data->data);
11120     type = QT_UINT32 ((guint8 *) data->data + 8);
11121     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11122     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11123       if ((sample =
11124               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11125                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11126         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11127         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11128         gst_sample_unref (sample);
11129       }
11130     }
11131   }
11132 }
11133
11134 static void
11135 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11136     const char *tag, const char *dummy, GNode * node)
11137 {
11138   GNode *data;
11139   char *s;
11140   int len;
11141   int type;
11142
11143   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11144   if (data) {
11145     len = QT_UINT32 (data->data);
11146     type = QT_UINT32 ((guint8 *) data->data + 8);
11147     if (type == 0x00000001 && len > 16) {
11148       guint y, m = 1, d = 1;
11149       gint ret;
11150
11151       s = g_strndup ((char *) data->data + 16, len - 16);
11152       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11153       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11154       if (ret >= 1 && y > 1500 && y < 3000) {
11155         GDate *date;
11156
11157         date = g_date_new_dmy (d, m, y);
11158         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11159         g_date_free (date);
11160       } else {
11161         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11162       }
11163       g_free (s);
11164     }
11165   }
11166 }
11167
11168 static void
11169 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11170     const char *tag, const char *dummy, GNode * node)
11171 {
11172   GNode *data;
11173
11174   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11175
11176   /* re-route to normal string tag if major brand says so
11177    * or no data atom and compatible brand suggests so */
11178   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11179       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11180     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11181     return;
11182   }
11183
11184   if (data) {
11185     guint len, type, n;
11186
11187     len = QT_UINT32 (data->data);
11188     type = QT_UINT32 ((guint8 *) data->data + 8);
11189     if (type == 0x00000000 && len >= 18) {
11190       n = QT_UINT16 ((guint8 *) data->data + 16);
11191       if (n > 0) {
11192         const gchar *genre;
11193
11194         genre = gst_tag_id3_genre_get (n - 1);
11195         if (genre != NULL) {
11196           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11197           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11198         }
11199       }
11200     }
11201   }
11202 }
11203
11204 static void
11205 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11206     const gchar * tag, guint8 * data, guint32 datasize)
11207 {
11208   gdouble value;
11209   gchar *datacopy;
11210
11211   /* make a copy to have \0 at the end */
11212   datacopy = g_strndup ((gchar *) data, datasize);
11213
11214   /* convert the str to double */
11215   if (sscanf (datacopy, "%lf", &value) == 1) {
11216     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11217     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11218   } else {
11219     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11220         datacopy);
11221   }
11222   g_free (datacopy);
11223 }
11224
11225
11226 static void
11227 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11228     const char *tag, const char *tag_bis, GNode * node)
11229 {
11230   GNode *mean;
11231   GNode *name;
11232   GNode *data;
11233   guint32 meansize;
11234   guint32 namesize;
11235   guint32 datatype;
11236   guint32 datasize;
11237   const gchar *meanstr;
11238   const gchar *namestr;
11239
11240   /* checking the whole ---- atom size for consistency */
11241   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11242     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11243     return;
11244   }
11245
11246   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11247   if (!mean) {
11248     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11249     return;
11250   }
11251
11252   meansize = QT_UINT32 (mean->data);
11253   if (meansize <= 12) {
11254     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11255     return;
11256   }
11257   meanstr = ((gchar *) mean->data) + 12;
11258   meansize -= 12;
11259
11260   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11261   if (!name) {
11262     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11263     return;
11264   }
11265
11266   namesize = QT_UINT32 (name->data);
11267   if (namesize <= 12) {
11268     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11269     return;
11270   }
11271   namestr = ((gchar *) name->data) + 12;
11272   namesize -= 12;
11273
11274   /*
11275    * Data atom is:
11276    * uint32 - size
11277    * uint32 - name
11278    * uint8  - version
11279    * uint24 - data type
11280    * uint32 - all 0
11281    * rest   - the data
11282    */
11283   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11284   if (!data) {
11285     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11286     return;
11287   }
11288   datasize = QT_UINT32 (data->data);
11289   if (datasize <= 16) {
11290     GST_WARNING_OBJECT (demux, "Data atom too small");
11291     return;
11292   }
11293   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11294
11295   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11296       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11297     static const struct
11298     {
11299       const gchar name[28];
11300       const gchar tag[28];
11301     } tags[] = {
11302       {
11303       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11304       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11305       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11306       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11307       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11308       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11309       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11310       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11311     };
11312     int i;
11313
11314     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11315       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11316         switch (gst_tag_get_type (tags[i].tag)) {
11317           case G_TYPE_DOUBLE:
11318             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11319                 ((guint8 *) data->data) + 16, datasize - 16);
11320             break;
11321           case G_TYPE_STRING:
11322             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11323             break;
11324           default:
11325             /* not reached */
11326             break;
11327         }
11328         break;
11329       }
11330     }
11331     if (i == G_N_ELEMENTS (tags))
11332       goto unknown_tag;
11333   } else {
11334     goto unknown_tag;
11335   }
11336
11337   return;
11338
11339 /* errors */
11340 unknown_tag:
11341 #ifndef GST_DISABLE_GST_DEBUG
11342   {
11343     gchar *namestr_dbg;
11344     gchar *meanstr_dbg;
11345
11346     meanstr_dbg = g_strndup (meanstr, meansize);
11347     namestr_dbg = g_strndup (namestr, namesize);
11348
11349     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11350         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11351
11352     g_free (namestr_dbg);
11353     g_free (meanstr_dbg);
11354   }
11355 #endif
11356   return;
11357 }
11358
11359 static void
11360 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11361     const char *tag_bis, GNode * node)
11362 {
11363   guint8 *data;
11364   GstBuffer *buf;
11365   guint len;
11366   GstTagList *id32_taglist = NULL;
11367
11368   GST_LOG_OBJECT (demux, "parsing ID32");
11369
11370   data = node->data;
11371   len = GST_READ_UINT32_BE (data);
11372
11373   /* need at least full box and language tag */
11374   if (len < 12 + 2)
11375     return;
11376
11377   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11378   gst_buffer_fill (buf, 0, data + 14, len - 14);
11379
11380   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11381   if (id32_taglist) {
11382     GST_LOG_OBJECT (demux, "parsing ok");
11383     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11384     gst_tag_list_unref (id32_taglist);
11385   } else {
11386     GST_LOG_OBJECT (demux, "parsing failed");
11387   }
11388
11389   gst_buffer_unref (buf);
11390 }
11391
11392 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11393     const char *tag, const char *tag_bis, GNode * node);
11394
11395 /* unmapped tags
11396 FOURCC_pcst -> if media is a podcast -> bool
11397 FOURCC_cpil -> if media is part of a compilation -> bool
11398 FOURCC_pgap -> if media is part of a gapless context -> bool
11399 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11400 */
11401
11402 static const struct
11403 {
11404   guint32 fourcc;
11405   const gchar *gst_tag;
11406   const gchar *gst_tag_bis;
11407   const GstQTDemuxAddTagFunc func;
11408 } add_funcs[] = {
11409   {
11410   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11411   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11412   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11413   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11414   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11415   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11416   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11417   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11418   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11419   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11420   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11421   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11422   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11423   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11424   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11425   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11426   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11427   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11428   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11429   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11430   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11431   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11432   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11433         qtdemux_tag_add_num}, {
11434   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11435         qtdemux_tag_add_num}, {
11436   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11437   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11438   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11439   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11440   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11441   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11442   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11443   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11444   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11445   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11446   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11447   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11448   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11449   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11450   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11451   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11452   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11453   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11454         qtdemux_tag_add_classification}, {
11455   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11456   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11457   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11458
11459     /* This is a special case, some tags are stored in this
11460      * 'reverse dns naming', according to:
11461      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11462      * bug #614471
11463      */
11464   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11465     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11466   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11467 };
11468
11469 struct _GstQtDemuxTagList
11470 {
11471   GstQTDemux *demux;
11472   GstTagList *taglist;
11473 };
11474 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11475
11476 static void
11477 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11478 {
11479   gint len;
11480   guint8 *data;
11481   GstBuffer *buf;
11482   gchar *media_type;
11483   const gchar *style;
11484   GstSample *sample;
11485   GstStructure *s;
11486   guint i;
11487   guint8 ndata[4];
11488   GstQTDemux *demux = qtdemuxtaglist->demux;
11489   GstTagList *taglist = qtdemuxtaglist->taglist;
11490
11491   data = node->data;
11492   len = QT_UINT32 (data);
11493   buf = gst_buffer_new_and_alloc (len);
11494   gst_buffer_fill (buf, 0, data, len);
11495
11496   /* heuristic to determine style of tag */
11497   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11498       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11499     style = "itunes";
11500   else if (demux->major_brand == FOURCC_qt__)
11501     style = "quicktime";
11502   /* fall back to assuming iso/3gp tag style */
11503   else
11504     style = "iso";
11505
11506   /* santize the name for the caps. */
11507   for (i = 0; i < 4; i++) {
11508     guint8 d = data[4 + i];
11509     if (g_ascii_isalnum (d))
11510       ndata[i] = g_ascii_tolower (d);
11511     else
11512       ndata[i] = '_';
11513   }
11514
11515   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11516       ndata[0], ndata[1], ndata[2], ndata[3]);
11517   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11518
11519   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11520   sample = gst_sample_new (buf, NULL, NULL, s);
11521   gst_buffer_unref (buf);
11522   g_free (media_type);
11523
11524   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11525       len, s);
11526
11527   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11528       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11529
11530   gst_sample_unref (sample);
11531 }
11532
11533 static void
11534 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11535 {
11536   GNode *meta;
11537   GNode *ilst;
11538   GNode *xmp_;
11539   GNode *node;
11540   gint i;
11541   GstQtDemuxTagList demuxtaglist;
11542
11543   demuxtaglist.demux = qtdemux;
11544   demuxtaglist.taglist = taglist;
11545
11546   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11547   if (meta != NULL) {
11548     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11549     if (ilst == NULL) {
11550       GST_LOG_OBJECT (qtdemux, "no ilst");
11551       return;
11552     }
11553   } else {
11554     ilst = udta;
11555     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11556   }
11557
11558   i = 0;
11559   while (i < G_N_ELEMENTS (add_funcs)) {
11560     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11561     if (node) {
11562       gint len;
11563
11564       len = QT_UINT32 (node->data);
11565       if (len < 12) {
11566         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11567             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11568       } else {
11569         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11570             add_funcs[i].gst_tag_bis, node);
11571       }
11572       g_node_destroy (node);
11573     } else {
11574       i++;
11575     }
11576   }
11577
11578   /* parsed nodes have been removed, pass along remainder as blob */
11579   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11580       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11581
11582   /* parse up XMP_ node if existing */
11583   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11584   if (xmp_ != NULL) {
11585     GstBuffer *buf;
11586     GstTagList *xmptaglist;
11587
11588     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11589         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11590     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11591     gst_buffer_unref (buf);
11592
11593     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11594   } else {
11595     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11596   }
11597 }
11598
11599 typedef struct
11600 {
11601   GstStructure *structure;      /* helper for sort function */
11602   gchar *location;
11603   guint min_req_bitrate;
11604   guint min_req_qt_version;
11605 } GstQtReference;
11606
11607 static gint
11608 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11609 {
11610   GstQtReference *ref_a = (GstQtReference *) a;
11611   GstQtReference *ref_b = (GstQtReference *) b;
11612
11613   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11614     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11615
11616   /* known bitrates go before unknown; higher bitrates go first */
11617   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11618 }
11619
11620 /* sort the redirects and post a message for the application.
11621  */
11622 static void
11623 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11624 {
11625   GstQtReference *best;
11626   GstStructure *s;
11627   GstMessage *msg;
11628   GValue list_val = { 0, };
11629   GList *l;
11630
11631   g_assert (references != NULL);
11632
11633   references = g_list_sort (references, qtdemux_redirects_sort_func);
11634
11635   best = (GstQtReference *) references->data;
11636
11637   g_value_init (&list_val, GST_TYPE_LIST);
11638
11639   for (l = references; l != NULL; l = l->next) {
11640     GstQtReference *ref = (GstQtReference *) l->data;
11641     GValue struct_val = { 0, };
11642
11643     ref->structure = gst_structure_new ("redirect",
11644         "new-location", G_TYPE_STRING, ref->location, NULL);
11645
11646     if (ref->min_req_bitrate > 0) {
11647       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11648           ref->min_req_bitrate, NULL);
11649     }
11650
11651     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11652     g_value_set_boxed (&struct_val, ref->structure);
11653     gst_value_list_append_value (&list_val, &struct_val);
11654     g_value_unset (&struct_val);
11655     /* don't free anything here yet, since we need best->structure below */
11656   }
11657
11658   g_assert (best != NULL);
11659   s = gst_structure_copy (best->structure);
11660
11661   if (g_list_length (references) > 1) {
11662     gst_structure_set_value (s, "locations", &list_val);
11663   }
11664
11665   g_value_unset (&list_val);
11666
11667   for (l = references; l != NULL; l = l->next) {
11668     GstQtReference *ref = (GstQtReference *) l->data;
11669
11670     gst_structure_free (ref->structure);
11671     g_free (ref->location);
11672     g_free (ref);
11673   }
11674   g_list_free (references);
11675
11676   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
11677   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
11678   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
11679   qtdemux->posted_redirect = TRUE;
11680 }
11681
11682 /* look for redirect nodes, collect all redirect information and
11683  * process it.
11684  */
11685 static gboolean
11686 qtdemux_parse_redirects (GstQTDemux * qtdemux)
11687 {
11688   GNode *rmra, *rmda, *rdrf;
11689
11690   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
11691   if (rmra) {
11692     GList *redirects = NULL;
11693
11694     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
11695     while (rmda) {
11696       GstQtReference ref = { NULL, NULL, 0, 0 };
11697       GNode *rmdr, *rmvc;
11698
11699       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
11700         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
11701         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
11702             ref.min_req_bitrate);
11703       }
11704
11705       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
11706         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
11707         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
11708
11709 #ifndef GST_DISABLE_GST_DEBUG
11710         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
11711 #endif
11712         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
11713
11714         GST_LOG_OBJECT (qtdemux,
11715             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
11716             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
11717             bitmask, check_type);
11718         if (package == FOURCC_qtim && check_type == 0) {
11719           ref.min_req_qt_version = version;
11720         }
11721       }
11722
11723       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
11724       if (rdrf) {
11725         guint32 ref_type;
11726         guint8 *ref_data;
11727         guint ref_len;
11728
11729         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
11730         if (ref_len > 20) {
11731           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
11732           ref_data = (guint8 *) rdrf->data + 20;
11733           if (ref_type == FOURCC_alis) {
11734             guint record_len, record_version, fn_len;
11735
11736             if (ref_len > 70) {
11737               /* MacOSX alias record, google for alias-layout.txt */
11738               record_len = QT_UINT16 (ref_data + 4);
11739               record_version = QT_UINT16 (ref_data + 4 + 2);
11740               fn_len = QT_UINT8 (ref_data + 50);
11741               if (record_len > 50 && record_version == 2 && fn_len > 0) {
11742                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
11743               }
11744             } else {
11745               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
11746                   ref_len);
11747             }
11748           } else if (ref_type == FOURCC_url_) {
11749             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
11750           } else {
11751             GST_DEBUG_OBJECT (qtdemux,
11752                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
11753                 GST_FOURCC_ARGS (ref_type));
11754           }
11755           if (ref.location != NULL) {
11756             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
11757             redirects =
11758                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
11759           } else {
11760             GST_WARNING_OBJECT (qtdemux,
11761                 "Failed to extract redirect location from rdrf atom");
11762           }
11763         } else {
11764           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
11765         }
11766       }
11767
11768       /* look for others */
11769       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
11770     }
11771
11772     if (redirects != NULL) {
11773       qtdemux_process_redirects (qtdemux, redirects);
11774     }
11775   }
11776   return TRUE;
11777 }
11778
11779 static GstTagList *
11780 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
11781 {
11782   const gchar *fmt;
11783
11784   if (tags == NULL) {
11785     tags = gst_tag_list_new_empty ();
11786     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
11787   }
11788
11789   if (qtdemux->major_brand == FOURCC_mjp2)
11790     fmt = "Motion JPEG 2000";
11791   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
11792     fmt = "3GP";
11793   else if (qtdemux->major_brand == FOURCC_qt__)
11794     fmt = "Quicktime";
11795   else if (qtdemux->fragmented)
11796     fmt = "ISO fMP4";
11797   else
11798     fmt = "ISO MP4/M4A";
11799
11800   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
11801       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
11802
11803   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
11804       fmt, NULL);
11805
11806   return tags;
11807 }
11808
11809 /* we have read th complete moov node now.
11810  * This function parses all of the relevant info, creates the traks and
11811  * prepares all data structures for playback
11812  */
11813 static gboolean
11814 qtdemux_parse_tree (GstQTDemux * qtdemux)
11815 {
11816   GNode *mvhd;
11817   GNode *trak;
11818   GNode *udta;
11819   GNode *mvex;
11820   GstClockTime duration;
11821   GNode *pssh;
11822   guint64 creation_time;
11823   GstDateTime *datetime = NULL;
11824   gint version;
11825
11826   /* make sure we have a usable taglist */
11827   if (!qtdemux->tag_list) {
11828     qtdemux->tag_list = gst_tag_list_new_empty ();
11829     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11830   } else {
11831     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11832   }
11833
11834   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
11835   if (mvhd == NULL) {
11836     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
11837     return qtdemux_parse_redirects (qtdemux);
11838   }
11839
11840   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
11841   if (version == 1) {
11842     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
11843     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
11844     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
11845   } else if (version == 0) {
11846     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
11847     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
11848     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
11849   } else {
11850     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
11851     return FALSE;
11852   }
11853
11854   /* Moving qt creation time (secs since 1904) to unix time */
11855   if (creation_time != 0) {
11856     /* Try to use epoch first as it should be faster and more commonly found */
11857     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
11858       GTimeVal now;
11859
11860       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
11861       /* some data cleansing sanity */
11862       g_get_current_time (&now);
11863       if (now.tv_sec + 24 * 3600 < creation_time) {
11864         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
11865       } else {
11866         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
11867       }
11868     } else {
11869       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
11870       GDateTime *dt, *dt_local;
11871
11872       dt = g_date_time_add_seconds (base_dt, creation_time);
11873       dt_local = g_date_time_to_local (dt);
11874       datetime = gst_date_time_new_from_g_date_time (dt_local);
11875
11876       g_date_time_unref (base_dt);
11877       g_date_time_unref (dt);
11878     }
11879   }
11880   if (datetime) {
11881     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
11882     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
11883         datetime, NULL);
11884     gst_date_time_unref (datetime);
11885   }
11886
11887   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
11888   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
11889
11890   /* check for fragmented file and get some (default) data */
11891   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
11892   if (mvex) {
11893     GNode *mehd;
11894     GstByteReader mehd_data;
11895
11896     /* let track parsing or anyone know weird stuff might happen ... */
11897     qtdemux->fragmented = TRUE;
11898
11899     /* compensate for total duration */
11900     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
11901     if (mehd)
11902       qtdemux_parse_mehd (qtdemux, &mehd_data);
11903   }
11904
11905   /* set duration in the segment info */
11906   gst_qtdemux_get_duration (qtdemux, &duration);
11907   if (duration) {
11908     qtdemux->segment.duration = duration;
11909     /* also do not exceed duration; stop is set that way post seek anyway,
11910      * and segment activation falls back to duration,
11911      * whereas loop only checks stop, so let's align this here as well */
11912     qtdemux->segment.stop = duration;
11913   }
11914
11915   /* parse all traks */
11916   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
11917   while (trak) {
11918     qtdemux_parse_trak (qtdemux, trak);
11919     /* iterate all siblings */
11920     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
11921   }
11922
11923   if (!qtdemux->tag_list) {
11924     GST_DEBUG_OBJECT (qtdemux, "new tag list");
11925     qtdemux->tag_list = gst_tag_list_new_empty ();
11926     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11927   } else {
11928     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11929   }
11930
11931   /* find tags */
11932   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11933   if (udta) {
11934     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11935   } else {
11936     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11937   }
11938
11939   /* maybe also some tags in meta box */
11940   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11941   if (udta) {
11942     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11943     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11944   } else {
11945     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11946   }
11947
11948   /* parse any protection system info */
11949   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
11950   while (pssh) {
11951     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
11952     qtdemux_parse_pssh (qtdemux, pssh);
11953     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
11954   }
11955
11956   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11957
11958   return TRUE;
11959 }
11960
11961 /* taken from ffmpeg */
11962 static int
11963 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11964 {
11965   int count = 4;
11966   int len = 0;
11967
11968   while (count--) {
11969     int c;
11970
11971     if (ptr >= end)
11972       return -1;
11973
11974     c = *ptr++;
11975     len = (len << 7) | (c & 0x7f);
11976     if (!(c & 0x80))
11977       break;
11978   }
11979   *end_out = ptr;
11980   return len;
11981 }
11982
11983 /* this can change the codec originally present in @list */
11984 static void
11985 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11986     GNode * esds, GstTagList * list)
11987 {
11988   int len = QT_UINT32 (esds->data);
11989   guint8 *ptr = esds->data;
11990   guint8 *end = ptr + len;
11991   int tag;
11992   guint8 *data_ptr = NULL;
11993   int data_len = 0;
11994   guint8 object_type_id = 0;
11995   const char *codec_name = NULL;
11996   GstCaps *caps = NULL;
11997
11998   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11999   ptr += 8;
12000   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12001   ptr += 4;
12002   while (ptr + 1 < end) {
12003     tag = QT_UINT8 (ptr);
12004     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12005     ptr++;
12006     len = read_descr_size (ptr, end, &ptr);
12007     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12008
12009     /* Check the stated amount of data is available for reading */
12010     if (len < 0 || ptr + len > end)
12011       break;
12012
12013     switch (tag) {
12014       case ES_DESCRIPTOR_TAG:
12015         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12016         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12017         ptr += 3;
12018         break;
12019       case DECODER_CONFIG_DESC_TAG:{
12020         guint max_bitrate, avg_bitrate;
12021
12022         object_type_id = QT_UINT8 (ptr);
12023         max_bitrate = QT_UINT32 (ptr + 5);
12024         avg_bitrate = QT_UINT32 (ptr + 9);
12025         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12026         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12027         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12028         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12029         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12030         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12031           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12032               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12033         }
12034         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12035           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12036               avg_bitrate, NULL);
12037         }
12038         ptr += 13;
12039         break;
12040       }
12041       case DECODER_SPECIFIC_INFO_TAG:
12042         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12043         if (object_type_id == 0xe0 && len == 0x40) {
12044           guint8 *data;
12045           GstStructure *s;
12046           guint32 clut[16];
12047           gint i;
12048
12049           GST_DEBUG_OBJECT (qtdemux,
12050               "Have VOBSUB palette. Creating palette event");
12051           /* move to decConfigDescr data and read palette */
12052           data = ptr;
12053           for (i = 0; i < 16; i++) {
12054             clut[i] = QT_UINT32 (data);
12055             data += 4;
12056           }
12057
12058           s = gst_structure_new ("application/x-gst-dvd", "event",
12059               G_TYPE_STRING, "dvd-spu-clut-change",
12060               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12061               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12062               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12063               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12064               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12065               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12066               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12067               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12068               NULL);
12069
12070           /* store event and trigger custom processing */
12071           stream->pending_event =
12072               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12073         } else {
12074           /* Generic codec_data handler puts it on the caps */
12075           data_ptr = ptr;
12076           data_len = len;
12077         }
12078
12079         ptr += len;
12080         break;
12081       case SL_CONFIG_DESC_TAG:
12082         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12083         ptr += 1;
12084         break;
12085       default:
12086         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12087             tag);
12088         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12089         ptr += len;
12090         break;
12091     }
12092   }
12093
12094   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12095    * in use, and should also be used to override some other parameters for some
12096    * codecs. */
12097   switch (object_type_id) {
12098     case 0x20:                 /* MPEG-4 */
12099       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12100        * profile_and_level_indication */
12101       if (data_ptr != NULL && data_len >= 5 &&
12102           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12103         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12104             data_ptr + 4, data_len - 4);
12105       }
12106       break;                    /* Nothing special needed here */
12107     case 0x21:                 /* H.264 */
12108       codec_name = "H.264 / AVC";
12109       caps = gst_caps_new_simple ("video/x-h264",
12110           "stream-format", G_TYPE_STRING, "avc",
12111           "alignment", G_TYPE_STRING, "au", NULL);
12112       break;
12113     case 0x40:                 /* AAC (any) */
12114     case 0x66:                 /* AAC Main */
12115     case 0x67:                 /* AAC LC */
12116     case 0x68:                 /* AAC SSR */
12117       /* Override channels and rate based on the codec_data, as it's often
12118        * wrong. */
12119       /* Only do so for basic setup without HE-AAC extension */
12120       if (data_ptr && data_len == 2) {
12121         guint channels, rateindex, rate;
12122
12123         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
12124         channels = (data_ptr[1] & 0x7f) >> 3;
12125         if (channels > 0 && channels < 7) {
12126           stream->n_channels = channels;
12127         } else if (channels == 7) {
12128           stream->n_channels = 8;
12129         }
12130
12131         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
12132         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
12133         if (rate > 0)
12134           stream->rate = rate;
12135       }
12136
12137       /* Set level and profile if possible */
12138       if (data_ptr != NULL && data_len >= 2) {
12139         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12140             data_ptr, data_len);
12141       }
12142       break;
12143     case 0x60:                 /* MPEG-2, various profiles */
12144     case 0x61:
12145     case 0x62:
12146     case 0x63:
12147     case 0x64:
12148     case 0x65:
12149       codec_name = "MPEG-2 video";
12150       caps = gst_caps_new_simple ("video/mpeg",
12151           "mpegversion", G_TYPE_INT, 2,
12152           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12153       break;
12154     case 0x69:                 /* MPEG-2 BC audio */
12155     case 0x6B:                 /* MPEG-1 audio */
12156       caps = gst_caps_new_simple ("audio/mpeg",
12157           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12158       codec_name = "MPEG-1 audio";
12159       break;
12160     case 0x6A:                 /* MPEG-1 */
12161       codec_name = "MPEG-1 video";
12162       caps = gst_caps_new_simple ("video/mpeg",
12163           "mpegversion", G_TYPE_INT, 1,
12164           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12165       break;
12166     case 0x6C:                 /* MJPEG */
12167       caps =
12168           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12169           NULL);
12170       codec_name = "Motion-JPEG";
12171       break;
12172     case 0x6D:                 /* PNG */
12173       caps =
12174           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12175           NULL);
12176       codec_name = "PNG still images";
12177       break;
12178     case 0x6E:                 /* JPEG2000 */
12179       codec_name = "JPEG-2000";
12180       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12181       break;
12182     case 0xA4:                 /* Dirac */
12183       codec_name = "Dirac";
12184       caps = gst_caps_new_empty_simple ("video/x-dirac");
12185       break;
12186     case 0xA5:                 /* AC3 */
12187       codec_name = "AC-3 audio";
12188       caps = gst_caps_new_simple ("audio/x-ac3",
12189           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12190       break;
12191     case 0xA9:                 /* AC3 */
12192       codec_name = "DTS audio";
12193       caps = gst_caps_new_simple ("audio/x-dts",
12194           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12195       break;
12196     case 0xE1:                 /* QCELP */
12197       /* QCELP, the codec_data is a riff tag (little endian) with
12198        * 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). */
12199       caps = gst_caps_new_empty_simple ("audio/qcelp");
12200       codec_name = "QCELP";
12201       break;
12202     default:
12203       break;
12204   }
12205
12206   /* If we have a replacement caps, then change our caps for this stream */
12207   if (caps) {
12208     gst_caps_unref (stream->caps);
12209     stream->caps = caps;
12210   }
12211
12212   if (codec_name && list)
12213     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12214         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12215
12216   /* Add the codec_data attribute to caps, if we have it */
12217   if (data_ptr) {
12218     GstBuffer *buffer;
12219
12220     buffer = gst_buffer_new_and_alloc (data_len);
12221     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12222
12223     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12224     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12225
12226     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12227         buffer, NULL);
12228     gst_buffer_unref (buffer);
12229   }
12230
12231 }
12232
12233 #define _codec(name) \
12234   do { \
12235     if (codec_name) { \
12236       *codec_name = g_strdup (name); \
12237     } \
12238   } while (0)
12239
12240 static GstCaps *
12241 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12242     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12243 {
12244   GstCaps *caps = NULL;
12245   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12246
12247   switch (fourcc) {
12248     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12249       _codec ("PNG still images");
12250       caps = gst_caps_new_empty_simple ("image/png");
12251       break;
12252     case FOURCC_jpeg:
12253       _codec ("JPEG still images");
12254       caps =
12255           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12256           NULL);
12257       break;
12258     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12259     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12260     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12261     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12262       _codec ("Motion-JPEG");
12263       caps =
12264           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12265           NULL);
12266       break;
12267     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12268       _codec ("Motion-JPEG format B");
12269       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12270       break;
12271     case FOURCC_mjp2:
12272       _codec ("JPEG-2000");
12273       /* override to what it should be according to spec, avoid palette_data */
12274       stream->bits_per_sample = 24;
12275       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12276       break;
12277     case FOURCC_SVQ3:
12278       _codec ("Sorensen video v.3");
12279       caps = gst_caps_new_simple ("video/x-svq",
12280           "svqversion", G_TYPE_INT, 3, NULL);
12281       break;
12282     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12283     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12284       _codec ("Sorensen video v.1");
12285       caps = gst_caps_new_simple ("video/x-svq",
12286           "svqversion", G_TYPE_INT, 1, NULL);
12287       break;
12288     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12289       caps = gst_caps_new_empty_simple ("video/x-raw");
12290       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12291       _codec ("Windows Raw RGB");
12292       break;
12293     case FOURCC_raw_:
12294     {
12295       guint16 bps;
12296
12297       bps = QT_UINT16 (stsd_data + 98);
12298       switch (bps) {
12299         case 15:
12300           format = GST_VIDEO_FORMAT_RGB15;
12301           break;
12302         case 16:
12303           format = GST_VIDEO_FORMAT_RGB16;
12304           break;
12305         case 24:
12306           format = GST_VIDEO_FORMAT_RGB;
12307           break;
12308         case 32:
12309           format = GST_VIDEO_FORMAT_ARGB;
12310           break;
12311         default:
12312           /* unknown */
12313           break;
12314       }
12315       break;
12316     }
12317     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12318       format = GST_VIDEO_FORMAT_I420;
12319       break;
12320     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12321     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12322       format = GST_VIDEO_FORMAT_I420;
12323       break;
12324     case FOURCC_2vuy:
12325     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12326       format = GST_VIDEO_FORMAT_UYVY;
12327       break;
12328     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12329       format = GST_VIDEO_FORMAT_v308;
12330       break;
12331     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12332       format = GST_VIDEO_FORMAT_v216;
12333       break;
12334     case FOURCC_v210:
12335       format = GST_VIDEO_FORMAT_v210;
12336       break;
12337     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12338       format = GST_VIDEO_FORMAT_r210;
12339       break;
12340       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12341          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12342          format = GST_VIDEO_FORMAT_v410;
12343          break;
12344        */
12345       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12346        * but different order than AYUV
12347        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12348        format = GST_VIDEO_FORMAT_v408;
12349        break;
12350        */
12351     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12352     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12353       _codec ("MPEG-1 video");
12354       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12355           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12356       break;
12357     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12358     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12359     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12360     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12361     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12362     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12363     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12364     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12365     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12366     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12367     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12368     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12369     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12370     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12371     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12372     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12373     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12374     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12375     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12376     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12377     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12378     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12379     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12380     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12381     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12382     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12383     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12384     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12385     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12386     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12387     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12388     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12389     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12390     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12391     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12392     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12393     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12394     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12395     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12396     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12397     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12398     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12399     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12400     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12401     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12402     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12403       _codec ("MPEG-2 video");
12404       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12405           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12406       break;
12407     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12408       _codec ("GIF still images");
12409       caps = gst_caps_new_empty_simple ("image/gif");
12410       break;
12411     case FOURCC_h263:
12412     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12413     case FOURCC_s263:
12414     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12415       _codec ("H.263");
12416       /* ffmpeg uses the height/width props, don't know why */
12417       caps = gst_caps_new_simple ("video/x-h263",
12418           "variant", G_TYPE_STRING, "itu", NULL);
12419       break;
12420     case FOURCC_mp4v:
12421     case FOURCC_MP4V:
12422       _codec ("MPEG-4 video");
12423       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12424           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12425       break;
12426     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12427     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12428       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12429       caps = gst_caps_new_simple ("video/x-msmpeg",
12430           "msmpegversion", G_TYPE_INT, 43, NULL);
12431       break;
12432     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12433       _codec ("DivX 3");
12434       caps = gst_caps_new_simple ("video/x-divx",
12435           "divxversion", G_TYPE_INT, 3, NULL);
12436       break;
12437     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12438     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12439       _codec ("DivX 4");
12440       caps = gst_caps_new_simple ("video/x-divx",
12441           "divxversion", G_TYPE_INT, 4, NULL);
12442       break;
12443     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12444       _codec ("DivX 5");
12445       caps = gst_caps_new_simple ("video/x-divx",
12446           "divxversion", G_TYPE_INT, 5, NULL);
12447       break;
12448
12449     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12450       _codec ("FFV1");
12451       caps = gst_caps_new_simple ("video/x-ffv",
12452           "ffvversion", G_TYPE_INT, 1, NULL);
12453       break;
12454
12455     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12456     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12457     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12458     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12459     case FOURCC_FMP4:
12460     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12461       caps = gst_caps_new_simple ("video/mpeg",
12462           "mpegversion", G_TYPE_INT, 4, NULL);
12463       _codec ("MPEG-4");
12464       break;
12465
12466     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12467       _codec ("Cinepak");
12468       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12469       break;
12470     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12471       _codec ("Apple QuickDraw");
12472       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12473       break;
12474     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12475       _codec ("Apple video");
12476       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12477       break;
12478     case FOURCC_H264:
12479     case FOURCC_avc1:
12480       _codec ("H.264 / AVC");
12481       caps = gst_caps_new_simple ("video/x-h264",
12482           "stream-format", G_TYPE_STRING, "avc",
12483           "alignment", G_TYPE_STRING, "au", NULL);
12484       break;
12485     case FOURCC_avc3:
12486       _codec ("H.264 / AVC");
12487       caps = gst_caps_new_simple ("video/x-h264",
12488           "stream-format", G_TYPE_STRING, "avc3",
12489           "alignment", G_TYPE_STRING, "au", NULL);
12490       break;
12491     case FOURCC_H265:
12492     case FOURCC_hvc1:
12493       _codec ("H.265 / HEVC");
12494       caps = gst_caps_new_simple ("video/x-h265",
12495           "stream-format", G_TYPE_STRING, "hvc1",
12496           "alignment", G_TYPE_STRING, "au", NULL);
12497       break;
12498     case FOURCC_hev1:
12499       _codec ("H.265 / HEVC");
12500       caps = gst_caps_new_simple ("video/x-h265",
12501           "stream-format", G_TYPE_STRING, "hev1",
12502           "alignment", G_TYPE_STRING, "au", NULL);
12503       break;
12504     case FOURCC_rle_:
12505       _codec ("Run-length encoding");
12506       caps = gst_caps_new_simple ("video/x-rle",
12507           "layout", G_TYPE_STRING, "quicktime", NULL);
12508       break;
12509     case FOURCC_WRLE:
12510       _codec ("Run-length encoding");
12511       caps = gst_caps_new_simple ("video/x-rle",
12512           "layout", G_TYPE_STRING, "microsoft", NULL);
12513       break;
12514     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12515     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12516       _codec ("Indeo Video 3");
12517       caps = gst_caps_new_simple ("video/x-indeo",
12518           "indeoversion", G_TYPE_INT, 3, NULL);
12519       break;
12520     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12521     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12522       _codec ("Intel Video 4");
12523       caps = gst_caps_new_simple ("video/x-indeo",
12524           "indeoversion", G_TYPE_INT, 4, NULL);
12525       break;
12526     case FOURCC_dvcp:
12527     case FOURCC_dvc_:
12528     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12529     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12530     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12531     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12532     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12533     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12534       _codec ("DV Video");
12535       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12536           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12537       break;
12538     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12539     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12540       _codec ("DVCPro50 Video");
12541       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12542           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12543       break;
12544     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12545     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12546       _codec ("DVCProHD Video");
12547       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12548           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12549       break;
12550     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12551       _codec ("Apple Graphics (SMC)");
12552       caps = gst_caps_new_empty_simple ("video/x-smc");
12553       break;
12554     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12555       _codec ("VP3");
12556       caps = gst_caps_new_empty_simple ("video/x-vp3");
12557       break;
12558     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12559       _codec ("VP6 Flash");
12560       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12561       break;
12562     case FOURCC_XiTh:
12563       _codec ("Theora");
12564       caps = gst_caps_new_empty_simple ("video/x-theora");
12565       /* theora uses one byte of padding in the data stream because it does not
12566        * allow 0 sized packets while theora does */
12567       stream->padding = 1;
12568       break;
12569     case FOURCC_drac:
12570       _codec ("Dirac");
12571       caps = gst_caps_new_empty_simple ("video/x-dirac");
12572       break;
12573     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12574       _codec ("TIFF still images");
12575       caps = gst_caps_new_empty_simple ("image/tiff");
12576       break;
12577     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12578       _codec ("Apple Intermediate Codec");
12579       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12580       break;
12581     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12582       _codec ("AVID DNxHD");
12583       caps = gst_caps_from_string ("video/x-dnxhd");
12584       break;
12585     case FOURCC_VP80:
12586       _codec ("On2 VP8");
12587       caps = gst_caps_from_string ("video/x-vp8");
12588       break;
12589     case FOURCC_apcs:
12590       _codec ("Apple ProRes LT");
12591       caps =
12592           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12593           NULL);
12594       break;
12595     case FOURCC_apch:
12596       _codec ("Apple ProRes HQ");
12597       caps =
12598           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12599           NULL);
12600       break;
12601     case FOURCC_apcn:
12602       _codec ("Apple ProRes");
12603       caps =
12604           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12605           "standard", NULL);
12606       break;
12607     case FOURCC_apco:
12608       _codec ("Apple ProRes Proxy");
12609       caps =
12610           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12611           "proxy", NULL);
12612       break;
12613     case FOURCC_ap4h:
12614       _codec ("Apple ProRes 4444");
12615       caps =
12616           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12617           "4444", NULL);
12618       break;
12619     case FOURCC_vc_1:
12620     case FOURCC_ovc1:
12621       _codec ("VC-1");
12622       caps = gst_caps_new_simple ("video/x-wmv",
12623           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12624       break;
12625     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12626     default:
12627     {
12628       char *s, fourstr[5];
12629
12630       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12631       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12632       caps = gst_caps_new_empty_simple (s);
12633       g_free (s);
12634       break;
12635     }
12636   }
12637
12638   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12639     GstVideoInfo info;
12640
12641     gst_video_info_init (&info);
12642     gst_video_info_set_format (&info, format, stream->width, stream->height);
12643
12644     caps = gst_video_info_to_caps (&info);
12645     *codec_name = gst_pb_utils_get_codec_description (caps);
12646
12647     /* enable clipping for raw video streams */
12648     stream->need_clip = TRUE;
12649   }
12650
12651   return caps;
12652 }
12653
12654 static GstCaps *
12655 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12656     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12657 {
12658   GstCaps *caps;
12659   const GstStructure *s;
12660   const gchar *name;
12661   gint endian = 0;
12662   GstAudioFormat format = 0;
12663   gint depth;
12664
12665   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12666
12667   depth = stream->bytes_per_packet * 8;
12668
12669   switch (fourcc) {
12670     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12671     case FOURCC_raw_:
12672       /* 8-bit audio is unsigned */
12673       if (depth == 8)
12674         format = GST_AUDIO_FORMAT_U8;
12675       /* otherwise it's signed and big-endian just like 'twos' */
12676     case FOURCC_twos:
12677       endian = G_BIG_ENDIAN;
12678       /* fall-through */
12679     case FOURCC_sowt:
12680     {
12681       gchar *str;
12682
12683       if (!endian)
12684         endian = G_LITTLE_ENDIAN;
12685
12686       if (!format)
12687         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
12688
12689       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
12690       _codec (str);
12691       g_free (str);
12692
12693       caps = gst_caps_new_simple ("audio/x-raw",
12694           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12695           "layout", G_TYPE_STRING, "interleaved", NULL);
12696       break;
12697     }
12698     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
12699       _codec ("Raw 64-bit floating-point audio");
12700       caps = gst_caps_new_simple ("audio/x-raw",
12701           "format", G_TYPE_STRING, "F64BE",
12702           "layout", G_TYPE_STRING, "interleaved", NULL);
12703       break;
12704     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
12705       _codec ("Raw 32-bit floating-point audio");
12706       caps = gst_caps_new_simple ("audio/x-raw",
12707           "format", G_TYPE_STRING, "F32BE",
12708           "layout", G_TYPE_STRING, "interleaved", NULL);
12709       break;
12710     case FOURCC_in24:
12711       _codec ("Raw 24-bit PCM audio");
12712       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
12713        * endian later */
12714       caps = gst_caps_new_simple ("audio/x-raw",
12715           "format", G_TYPE_STRING, "S24BE",
12716           "layout", G_TYPE_STRING, "interleaved", NULL);
12717       break;
12718     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
12719       _codec ("Raw 32-bit PCM audio");
12720       caps = gst_caps_new_simple ("audio/x-raw",
12721           "format", G_TYPE_STRING, "S32BE",
12722           "layout", G_TYPE_STRING, "interleaved", NULL);
12723       break;
12724     case FOURCC_ulaw:
12725       _codec ("Mu-law audio");
12726       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
12727       break;
12728     case FOURCC_alaw:
12729       _codec ("A-law audio");
12730       caps = gst_caps_new_empty_simple ("audio/x-alaw");
12731       break;
12732     case 0x0200736d:
12733     case 0x6d730002:
12734       _codec ("Microsoft ADPCM");
12735       /* Microsoft ADPCM-ACM code 2 */
12736       caps = gst_caps_new_simple ("audio/x-adpcm",
12737           "layout", G_TYPE_STRING, "microsoft", NULL);
12738       break;
12739     case 0x1100736d:
12740     case 0x6d730011:
12741       _codec ("DVI/IMA ADPCM");
12742       caps = gst_caps_new_simple ("audio/x-adpcm",
12743           "layout", G_TYPE_STRING, "dvi", NULL);
12744       break;
12745     case 0x1700736d:
12746     case 0x6d730017:
12747       _codec ("DVI/Intel IMA ADPCM");
12748       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
12749       caps = gst_caps_new_simple ("audio/x-adpcm",
12750           "layout", G_TYPE_STRING, "quicktime", NULL);
12751       break;
12752     case 0x5500736d:
12753     case 0x6d730055:
12754       /* MPEG layer 3, CBR only (pre QT4.1) */
12755     case FOURCC__mp3:
12756       _codec ("MPEG-1 layer 3");
12757       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
12758       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
12759           "mpegversion", G_TYPE_INT, 1, NULL);
12760       break;
12761     case 0x20736d:
12762     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
12763       _codec ("EAC-3 audio");
12764       caps = gst_caps_new_simple ("audio/x-eac3",
12765           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12766       stream->sampled = TRUE;
12767       break;
12768     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
12769     case FOURCC_ac_3:
12770       _codec ("AC-3 audio");
12771       caps = gst_caps_new_simple ("audio/x-ac3",
12772           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12773       stream->sampled = TRUE;
12774       break;
12775     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
12776     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
12777       _codec ("DTS audio");
12778       caps = gst_caps_new_simple ("audio/x-dts",
12779           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12780       stream->sampled = TRUE;
12781       break;
12782     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
12783     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
12784       _codec ("DTS-HD audio");
12785       caps = gst_caps_new_simple ("audio/x-dts",
12786           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12787       stream->sampled = TRUE;
12788       break;
12789     case FOURCC_MAC3:
12790       _codec ("MACE-3");
12791       caps = gst_caps_new_simple ("audio/x-mace",
12792           "maceversion", G_TYPE_INT, 3, NULL);
12793       break;
12794     case FOURCC_MAC6:
12795       _codec ("MACE-6");
12796       caps = gst_caps_new_simple ("audio/x-mace",
12797           "maceversion", G_TYPE_INT, 6, NULL);
12798       break;
12799     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
12800       /* ogg/vorbis */
12801       caps = gst_caps_new_empty_simple ("application/ogg");
12802       break;
12803     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
12804       _codec ("DV audio");
12805       caps = gst_caps_new_empty_simple ("audio/x-dv");
12806       break;
12807     case FOURCC_mp4a:
12808       _codec ("MPEG-4 AAC audio");
12809       caps = gst_caps_new_simple ("audio/mpeg",
12810           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
12811           "stream-format", G_TYPE_STRING, "raw", NULL);
12812       break;
12813     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
12814       _codec ("QDesign Music");
12815       caps = gst_caps_new_empty_simple ("audio/x-qdm");
12816       break;
12817     case FOURCC_QDM2:
12818       _codec ("QDesign Music v.2");
12819       /* FIXME: QDesign music version 2 (no constant) */
12820       if (FALSE && data) {
12821         caps = gst_caps_new_simple ("audio/x-qdm2",
12822             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
12823             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
12824             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
12825       } else {
12826         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
12827       }
12828       break;
12829     case FOURCC_agsm:
12830       _codec ("GSM audio");
12831       caps = gst_caps_new_empty_simple ("audio/x-gsm");
12832       break;
12833     case FOURCC_samr:
12834       _codec ("AMR audio");
12835       caps = gst_caps_new_empty_simple ("audio/AMR");
12836       break;
12837     case FOURCC_sawb:
12838       _codec ("AMR-WB audio");
12839       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
12840       break;
12841     case FOURCC_ima4:
12842       _codec ("Quicktime IMA ADPCM");
12843       caps = gst_caps_new_simple ("audio/x-adpcm",
12844           "layout", G_TYPE_STRING, "quicktime", NULL);
12845       break;
12846     case FOURCC_alac:
12847       _codec ("Apple lossless audio");
12848       caps = gst_caps_new_empty_simple ("audio/x-alac");
12849       break;
12850     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
12851       _codec ("QualComm PureVoice");
12852       caps = gst_caps_from_string ("audio/qcelp");
12853       break;
12854     case FOURCC_wma_:
12855     case FOURCC_owma:
12856       _codec ("WMA");
12857       caps = gst_caps_new_empty_simple ("audio/x-wma");
12858       break;
12859     case FOURCC_opus:
12860       _codec ("Opus");
12861       caps = gst_caps_new_empty_simple ("audio/x-opus");
12862       break;
12863     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
12864     {
12865       guint32 flags = 0;
12866       guint32 depth = 0;
12867       guint32 width = 0;
12868       GstAudioFormat format;
12869       enum
12870       {
12871         FLAG_IS_FLOAT = 0x1,
12872         FLAG_IS_BIG_ENDIAN = 0x2,
12873         FLAG_IS_SIGNED = 0x4,
12874         FLAG_IS_PACKED = 0x8,
12875         FLAG_IS_ALIGNED_HIGH = 0x10,
12876         FLAG_IS_NON_INTERLEAVED = 0x20
12877       };
12878       _codec ("Raw LPCM audio");
12879
12880       if (data && len >= 56) {
12881         depth = QT_UINT32 (data + 40);
12882         flags = QT_UINT32 (data + 44);
12883         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
12884       }
12885       if ((flags & FLAG_IS_FLOAT) == 0) {
12886         if (depth == 0)
12887           depth = 16;
12888         if (width == 0)
12889           width = 16;
12890         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
12891             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
12892             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
12893         caps = gst_caps_new_simple ("audio/x-raw",
12894             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12895             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12896             "non-interleaved" : "interleaved", NULL);
12897       } else {
12898         if (width == 0)
12899           width = 32;
12900         if (width == 64) {
12901           if (flags & FLAG_IS_BIG_ENDIAN)
12902             format = GST_AUDIO_FORMAT_F64BE;
12903           else
12904             format = GST_AUDIO_FORMAT_F64LE;
12905         } else {
12906           if (flags & FLAG_IS_BIG_ENDIAN)
12907             format = GST_AUDIO_FORMAT_F32BE;
12908           else
12909             format = GST_AUDIO_FORMAT_F32LE;
12910         }
12911         caps = gst_caps_new_simple ("audio/x-raw",
12912             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12913             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12914             "non-interleaved" : "interleaved", NULL);
12915       }
12916       break;
12917     }
12918     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
12919       /* ? */
12920     default:
12921     {
12922       char *s, fourstr[5];
12923
12924       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12925       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
12926       caps = gst_caps_new_empty_simple (s);
12927       g_free (s);
12928       break;
12929     }
12930   }
12931
12932   if (caps) {
12933     GstCaps *templ_caps =
12934         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
12935     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
12936     gst_caps_unref (caps);
12937     gst_caps_unref (templ_caps);
12938     caps = intersection;
12939   }
12940
12941   /* enable clipping for raw audio streams */
12942   s = gst_caps_get_structure (caps, 0);
12943   name = gst_structure_get_name (s);
12944   if (g_str_has_prefix (name, "audio/x-raw")) {
12945     stream->need_clip = TRUE;
12946     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
12947     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
12948   }
12949   return caps;
12950 }
12951
12952 static GstCaps *
12953 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12954     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12955 {
12956   GstCaps *caps;
12957
12958   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12959
12960   switch (fourcc) {
12961     case FOURCC_mp4s:
12962       _codec ("DVD subtitle");
12963       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12964       stream->need_process = TRUE;
12965       break;
12966     case FOURCC_text:
12967       _codec ("Quicktime timed text");
12968       goto text;
12969     case FOURCC_tx3g:
12970       _codec ("3GPP timed text");
12971     text:
12972       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12973           "utf8", NULL);
12974       /* actual text piece needs to be extracted */
12975       stream->need_process = TRUE;
12976       break;
12977     case FOURCC_stpp:
12978       _codec ("XML subtitles");
12979       caps = gst_caps_new_empty_simple ("application/ttml+xml");
12980       break;
12981     default:
12982     {
12983       char *s, fourstr[5];
12984
12985       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12986       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12987       caps = gst_caps_new_empty_simple (s);
12988       g_free (s);
12989       break;
12990     }
12991   }
12992   return caps;
12993 }
12994
12995 static GstCaps *
12996 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12997     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12998 {
12999   GstCaps *caps;
13000
13001   switch (fourcc) {
13002     case FOURCC_m1v:
13003       _codec ("MPEG 1 video");
13004       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13005           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13006       break;
13007     default:
13008       caps = NULL;
13009       break;
13010   }
13011   return caps;
13012 }
13013
13014 static void
13015 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13016     const gchar * system_id)
13017 {
13018   gint i;
13019
13020   if (!qtdemux->protection_system_ids)
13021     qtdemux->protection_system_ids =
13022         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13023   /* Check whether we already have an entry for this system ID. */
13024   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13025     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13026     if (g_ascii_strcasecmp (system_id, id) == 0) {
13027       return;
13028     }
13029   }
13030   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13031   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13032           -1));
13033 }