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