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