qtdemux: properly activate segment with rate != 1.0
[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
318   /* quicktime segments */
319   guint32 n_segments;
320   QtDemuxSegment *segments;
321   gboolean dummy_segment;
322   guint32 from_sample;
323   guint32 to_sample;
324
325   gboolean sent_eos;
326   GstTagList *pending_tags;
327   gboolean send_global_tags;
328
329   GstEvent *pending_event;
330
331   GstByteReader stco;
332   GstByteReader stsz;
333   GstByteReader stsc;
334   GstByteReader stts;
335   GstByteReader stss;
336   GstByteReader stps;
337   GstByteReader ctts;
338
339   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
340   gint64 stbl_index;
341   /* stco */
342   guint co_size;
343   GstByteReader co_chunk;
344   guint32 first_chunk;
345   guint32 current_chunk;
346   guint32 last_chunk;
347   guint32 samples_per_chunk;
348   guint32 stco_sample_index;
349   /* stsz */
350   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
351   /* stsc */
352   guint32 stsc_index;
353   guint32 n_samples_per_chunk;
354   guint32 stsc_chunk_index;
355   guint32 stsc_sample_index;
356   guint64 chunk_offset;
357   /* stts */
358   guint32 stts_index;
359   guint32 stts_samples;
360   guint32 n_sample_times;
361   guint32 stts_sample_index;
362   guint64 stts_time;
363   guint32 stts_duration;
364   /* stss */
365   gboolean stss_present;
366   guint32 n_sample_syncs;
367   guint32 stss_index;
368   /* stps */
369   gboolean stps_present;
370   guint32 n_sample_partial_syncs;
371   guint32 stps_index;
372   QtDemuxRandomAccessEntry *ra_entries;
373   guint n_ra_entries;
374
375   const QtDemuxRandomAccessEntry *pending_seek;
376
377   /* ctts */
378   gboolean ctts_present;
379   guint32 n_composition_times;
380   guint32 ctts_index;
381   guint32 ctts_sample_index;
382   guint32 ctts_count;
383   gint32 ctts_soffset;
384
385   /* cslg */
386   guint32 cslg_shift;
387
388   /* fragmented */
389   gboolean parsed_trex;
390   guint32 def_sample_duration;
391   guint32 def_sample_size;
392   guint32 def_sample_flags;
393
394   gboolean disabled;
395
396   /* stereoscopic video streams */
397   GstVideoMultiviewMode multiview_mode;
398   GstVideoMultiviewFlags multiview_flags;
399
400   /* protected streams */
401   gboolean protected;
402   guint32 protection_scheme_type;
403   guint32 protection_scheme_version;
404   gpointer protection_scheme_info;      /* specific to the protection scheme */
405   GQueue protection_scheme_event_queue;
406 };
407
408 /* Contains properties and cryptographic info for a set of samples from a
409  * track protected using Common Encryption (cenc) */
410 struct _QtDemuxCencSampleSetInfo
411 {
412   GstStructure *default_properties;
413
414   /* @crypto_info holds one GstStructure per sample */
415   GPtrArray *crypto_info;
416 };
417
418 enum QtDemuxState
419 {
420   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
421   QTDEMUX_STATE_HEADER,         /* Parsing the header */
422   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
423   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
424 };
425
426 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
427 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
428     guint32 fourcc, GstByteReader * parser);
429 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
430 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
431     guint32 fourcc, GstByteReader * parser);
432
433 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
434
435 static GstStaticPadTemplate gst_qtdemux_sink_template =
436     GST_STATIC_PAD_TEMPLATE ("sink",
437     GST_PAD_SINK,
438     GST_PAD_ALWAYS,
439     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
440         "application/x-3gp")
441     );
442
443 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
444 GST_STATIC_PAD_TEMPLATE ("video_%u",
445     GST_PAD_SRC,
446     GST_PAD_SOMETIMES,
447     GST_STATIC_CAPS_ANY);
448
449 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
450 GST_STATIC_PAD_TEMPLATE ("audio_%u",
451     GST_PAD_SRC,
452     GST_PAD_SOMETIMES,
453     GST_STATIC_CAPS_ANY);
454
455 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
456 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
457     GST_PAD_SRC,
458     GST_PAD_SOMETIMES,
459     GST_STATIC_CAPS_ANY);
460
461 #define gst_qtdemux_parent_class parent_class
462 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
463
464 static void gst_qtdemux_dispose (GObject * object);
465
466 static guint32
467 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
468     GstClockTime media_time);
469 static guint32
470 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
471     QtDemuxStream * str, gint64 media_offset);
472
473 #if 0
474 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
475 static GstIndex *gst_qtdemux_get_index (GstElement * element);
476 #endif
477 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
478     GstStateChange transition);
479 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
480 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
481     GstObject * parent, GstPadMode mode, gboolean active);
482
483 static void gst_qtdemux_loop (GstPad * pad);
484 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
485     GstBuffer * inbuf);
486 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
487     GstEvent * event);
488 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
489 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
490     QtDemuxStream * stream);
491 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
492     gboolean force);
493
494 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
495     const guint8 * buffer, guint length);
496 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
497     const guint8 * buffer, guint length);
498 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
499 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
500     GNode * udta);
501
502 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
503     QtDemuxStream * stream, GNode * esds, GstTagList * list);
504 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
505     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
506     gchar ** codec_name);
507 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
508     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
509     gchar ** codec_name);
510 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
511     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
512     gchar ** codec_name);
513 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
514     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
515     gchar ** codec_name);
516
517 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
518     QtDemuxStream * stream, guint32 n);
519 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
520 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
521     QtDemuxStream * stream);
522 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
523     QtDemuxStream * stream);
524 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
525 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
526 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
527     QtDemuxStream * stream);
528 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
529     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
530 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
531     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
532     GstClockTime * _start, GstClockTime * _stop);
533
534 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
535 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
536
537 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
538
539 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
540     QtDemuxStream * stream, guint sample_index);
541 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
542     const gchar * id);
543 static void qtdemux_gst_structure_free (GstStructure * gststructure);
544
545 static void
546 gst_qtdemux_class_init (GstQTDemuxClass * klass)
547 {
548   GObjectClass *gobject_class;
549   GstElementClass *gstelement_class;
550
551   gobject_class = (GObjectClass *) klass;
552   gstelement_class = (GstElementClass *) klass;
553
554   parent_class = g_type_class_peek_parent (klass);
555
556   gobject_class->dispose = gst_qtdemux_dispose;
557
558   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
559 #if 0
560   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
561   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
562 #endif
563
564   gst_tag_register_musicbrainz_tags ();
565
566   gst_element_class_add_static_pad_template (gstelement_class,
567       &gst_qtdemux_sink_template);
568   gst_element_class_add_static_pad_template (gstelement_class,
569       &gst_qtdemux_videosrc_template);
570   gst_element_class_add_static_pad_template (gstelement_class,
571       &gst_qtdemux_audiosrc_template);
572   gst_element_class_add_static_pad_template (gstelement_class,
573       &gst_qtdemux_subsrc_template);
574   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
575       "Codec/Demuxer",
576       "Demultiplex a QuickTime file into audio and video streams",
577       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
578
579   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
580
581 }
582
583 static void
584 gst_qtdemux_init (GstQTDemux * qtdemux)
585 {
586   qtdemux->sinkpad =
587       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
588   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
589   gst_pad_set_activatemode_function (qtdemux->sinkpad,
590       qtdemux_sink_activate_mode);
591   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
592   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
593   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
594
595   qtdemux->state = QTDEMUX_STATE_INITIAL;
596   qtdemux->pullbased = FALSE;
597   qtdemux->posted_redirect = FALSE;
598   qtdemux->neededbytes = 16;
599   qtdemux->todrop = 0;
600   qtdemux->adapter = gst_adapter_new ();
601   qtdemux->offset = 0;
602   qtdemux->first_mdat = -1;
603   qtdemux->got_moov = FALSE;
604   qtdemux->mdatoffset = -1;
605   qtdemux->mdatbuffer = NULL;
606   qtdemux->restoredata_buffer = NULL;
607   qtdemux->restoredata_offset = -1;
608   qtdemux->fragment_start = -1;
609   qtdemux->fragment_start_offset = -1;
610   qtdemux->media_caps = NULL;
611   qtdemux->exposed = FALSE;
612   qtdemux->mss_mode = FALSE;
613   qtdemux->pending_newsegment = NULL;
614   qtdemux->upstream_format_is_time = FALSE;
615   qtdemux->have_group_id = FALSE;
616   qtdemux->group_id = G_MAXUINT;
617   qtdemux->cenc_aux_info_offset = 0;
618   qtdemux->cenc_aux_info_sizes = NULL;
619   qtdemux->cenc_aux_sample_count = 0;
620   qtdemux->protection_system_ids = NULL;
621   g_queue_init (&qtdemux->protection_event_queue);
622   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
623   qtdemux->flowcombiner = gst_flow_combiner_new ();
624
625   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
626 }
627
628 static void
629 gst_qtdemux_dispose (GObject * object)
630 {
631   GstQTDemux *qtdemux = GST_QTDEMUX (object);
632
633   if (qtdemux->adapter) {
634     g_object_unref (G_OBJECT (qtdemux->adapter));
635     qtdemux->adapter = NULL;
636   }
637   gst_flow_combiner_free (qtdemux->flowcombiner);
638   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
639       NULL);
640   g_queue_clear (&qtdemux->protection_event_queue);
641
642   g_free (qtdemux->cenc_aux_info_sizes);
643   qtdemux->cenc_aux_info_sizes = NULL;
644
645   G_OBJECT_CLASS (parent_class)->dispose (object);
646 }
647
648 static void
649 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
650 {
651   if (qtdemux->posted_redirect) {
652     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
653         (_("This file contains no playable streams.")),
654         ("no known streams found, a redirect message has been posted"));
655   } else {
656     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
657         (_("This file contains no playable streams.")),
658         ("no known streams found"));
659   }
660 }
661
662 static GstBuffer *
663 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
664 {
665   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
666       mem, size, 0, size, mem, free_func);
667 }
668
669 static GstFlowReturn
670 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
671     GstBuffer ** buf)
672 {
673   GstFlowReturn flow;
674   GstMapInfo map;
675   gsize bsize;
676
677   if (G_UNLIKELY (size == 0)) {
678     GstFlowReturn ret;
679     GstBuffer *tmp = NULL;
680
681     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
682     if (ret != GST_FLOW_OK)
683       return ret;
684
685     gst_buffer_map (tmp, &map, GST_MAP_READ);
686     size = QT_UINT32 (map.data);
687     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
688
689     gst_buffer_unmap (tmp, &map);
690     gst_buffer_unref (tmp);
691   }
692
693   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
694   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
695     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
696       /* we're pulling header but already got most interesting bits,
697        * so never mind the rest (e.g. tags) (that much) */
698       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
699           size);
700       return GST_FLOW_EOS;
701     } else {
702       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
703           (_("This file is invalid and cannot be played.")),
704           ("atom has bogus size %" G_GUINT64_FORMAT, size));
705       return GST_FLOW_ERROR;
706     }
707   }
708
709   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
710
711   if (G_UNLIKELY (flow != GST_FLOW_OK))
712     return flow;
713
714   bsize = gst_buffer_get_size (*buf);
715   /* Catch short reads - we don't want any partial atoms */
716   if (G_UNLIKELY (bsize < size)) {
717     GST_WARNING_OBJECT (qtdemux,
718         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
719     gst_buffer_unref (*buf);
720     *buf = NULL;
721     return GST_FLOW_EOS;
722   }
723
724   return flow;
725 }
726
727 #if 1
728 static gboolean
729 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
730     GstFormat src_format, gint64 src_value, GstFormat dest_format,
731     gint64 * dest_value)
732 {
733   gboolean res = TRUE;
734   QtDemuxStream *stream = gst_pad_get_element_private (pad);
735   gint32 index;
736
737   if (stream->subtype != FOURCC_vide) {
738     res = FALSE;
739     goto done;
740   }
741
742   switch (src_format) {
743     case GST_FORMAT_TIME:
744       switch (dest_format) {
745         case GST_FORMAT_BYTES:{
746           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
747           if (-1 == index) {
748             res = FALSE;
749             goto done;
750           }
751
752           *dest_value = stream->samples[index].offset;
753
754           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
755               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
756               GST_TIME_ARGS (src_value), *dest_value);
757           break;
758         }
759         default:
760           res = FALSE;
761           break;
762       }
763       break;
764     case GST_FORMAT_BYTES:
765       switch (dest_format) {
766         case GST_FORMAT_TIME:{
767           index =
768               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
769               stream, src_value);
770
771           if (-1 == index) {
772             res = FALSE;
773             goto done;
774           }
775
776           *dest_value =
777               QTSTREAMTIME_TO_GSTTIME (stream,
778               stream->samples[index].timestamp);
779           GST_DEBUG_OBJECT (qtdemux,
780               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
781               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
782           break;
783         }
784         default:
785           res = FALSE;
786           break;
787       }
788       break;
789     default:
790       res = FALSE;
791       break;
792   }
793
794 done:
795   return res;
796 }
797 #endif
798
799 static gboolean
800 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
801 {
802   gboolean res = FALSE;
803
804   *duration = GST_CLOCK_TIME_NONE;
805
806   if (qtdemux->duration != 0 &&
807       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
808     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
809     res = TRUE;
810   } else {
811     *duration = GST_CLOCK_TIME_NONE;
812   }
813
814   return res;
815 }
816
817 static gboolean
818 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
819     GstQuery * query)
820 {
821   gboolean res = FALSE;
822   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
823
824   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
825
826   switch (GST_QUERY_TYPE (query)) {
827     case GST_QUERY_POSITION:{
828       GstFormat fmt;
829
830       gst_query_parse_position (query, &fmt, NULL);
831       if (fmt == GST_FORMAT_TIME
832           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
833         gst_query_set_position (query, GST_FORMAT_TIME,
834             qtdemux->segment.position);
835         res = TRUE;
836       }
837     }
838       break;
839     case GST_QUERY_DURATION:{
840       GstFormat fmt;
841
842       gst_query_parse_duration (query, &fmt, NULL);
843       if (fmt == GST_FORMAT_TIME) {
844         /* First try to query upstream */
845         res = gst_pad_query_default (pad, parent, query);
846         if (!res) {
847           GstClockTime duration;
848           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
849             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
850             res = TRUE;
851           }
852         }
853       }
854       break;
855     }
856     case GST_QUERY_CONVERT:{
857       GstFormat src_fmt, dest_fmt;
858       gint64 src_value, dest_value = 0;
859
860       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
861
862       res = gst_qtdemux_src_convert (qtdemux, pad,
863           src_fmt, src_value, dest_fmt, &dest_value);
864       if (res) {
865         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
866         res = TRUE;
867       }
868       break;
869     }
870     case GST_QUERY_FORMATS:
871       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
872       res = TRUE;
873       break;
874     case GST_QUERY_SEEKING:{
875       GstFormat fmt;
876       gboolean seekable;
877
878       /* try upstream first */
879       res = gst_pad_query_default (pad, parent, query);
880
881       if (!res) {
882         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
883         if (fmt == GST_FORMAT_TIME) {
884           GstClockTime duration;
885
886           gst_qtdemux_get_duration (qtdemux, &duration);
887           seekable = TRUE;
888           if (!qtdemux->pullbased) {
889             GstQuery *q;
890
891             /* we might be able with help from upstream */
892             seekable = FALSE;
893             q = gst_query_new_seeking (GST_FORMAT_BYTES);
894             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
895               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
896               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
897             }
898             gst_query_unref (q);
899           }
900           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
901           res = TRUE;
902         }
903       }
904       break;
905     }
906     case GST_QUERY_SEGMENT:
907     {
908       GstFormat format;
909       gint64 start, stop;
910
911       format = qtdemux->segment.format;
912
913       start =
914           gst_segment_to_stream_time (&qtdemux->segment, format,
915           qtdemux->segment.start);
916       if ((stop = qtdemux->segment.stop) == -1)
917         stop = qtdemux->segment.duration;
918       else
919         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
920
921       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
922       res = TRUE;
923       break;
924     }
925     default:
926       res = gst_pad_query_default (pad, parent, query);
927       break;
928   }
929
930   return res;
931 }
932
933 static void
934 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
935 {
936   if (G_LIKELY (stream->pad)) {
937     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
938         GST_DEBUG_PAD_NAME (stream->pad));
939
940     if (G_UNLIKELY (stream->pending_tags)) {
941       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
942           stream->pending_tags);
943       gst_pad_push_event (stream->pad,
944           gst_event_new_tag (stream->pending_tags));
945       stream->pending_tags = NULL;
946     }
947
948     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
949       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
950           qtdemux->tag_list);
951       gst_pad_push_event (stream->pad,
952           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
953       stream->send_global_tags = FALSE;
954     }
955   }
956 }
957
958 /* push event on all source pads; takes ownership of the event */
959 static void
960 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
961 {
962   guint n;
963   gboolean has_valid_stream = FALSE;
964   GstEventType etype = GST_EVENT_TYPE (event);
965
966   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
967       GST_EVENT_TYPE_NAME (event));
968
969   for (n = 0; n < qtdemux->n_streams; n++) {
970     GstPad *pad;
971     QtDemuxStream *stream = qtdemux->streams[n];
972     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
973
974     if ((pad = stream->pad)) {
975       has_valid_stream = TRUE;
976
977       if (etype == GST_EVENT_EOS) {
978         /* let's not send twice */
979         if (stream->sent_eos)
980           continue;
981         stream->sent_eos = TRUE;
982       }
983
984       gst_pad_push_event (pad, gst_event_ref (event));
985     }
986   }
987
988   gst_event_unref (event);
989
990   /* if it is EOS and there are no pads, post an error */
991   if (!has_valid_stream && etype == GST_EVENT_EOS) {
992     gst_qtdemux_post_no_playable_stream_error (qtdemux);
993   }
994 }
995
996 /* push a pending newsegment event, if any from the streaming thread */
997 static void
998 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
999 {
1000   if (qtdemux->pending_newsegment) {
1001     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1002     qtdemux->pending_newsegment = NULL;
1003   }
1004 }
1005
1006 typedef struct
1007 {
1008   guint64 media_time;
1009 } FindData;
1010
1011 static gint
1012 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1013 {
1014   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1015     return 1;
1016   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1017     return 0;
1018
1019   return -1;
1020 }
1021
1022 /* find the index of the sample that includes the data for @media_time using a
1023  * binary search.  Only to be called in optimized cases of linear search below.
1024  *
1025  * Returns the index of the sample.
1026  */
1027 static guint32
1028 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1029     guint64 media_time)
1030 {
1031   QtDemuxSample *result;
1032   guint32 index;
1033
1034   /* convert media_time to mov format */
1035   media_time =
1036       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1037
1038   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1039       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1040       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1041
1042   if (G_LIKELY (result))
1043     index = result - str->samples;
1044   else
1045     index = 0;
1046
1047   return index;
1048 }
1049
1050
1051
1052 /* find the index of the sample that includes the data for @media_offset using a
1053  * linear search
1054  *
1055  * Returns the index of the sample.
1056  */
1057 static guint32
1058 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1059     QtDemuxStream * str, gint64 media_offset)
1060 {
1061   QtDemuxSample *result = str->samples;
1062   guint32 index = 0;
1063
1064   if (result == NULL || str->n_samples == 0)
1065     return -1;
1066
1067   if (media_offset == result->offset)
1068     return index;
1069
1070   result++;
1071   while (index < str->n_samples - 1) {
1072     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1073       goto parse_failed;
1074
1075     if (media_offset < result->offset)
1076       break;
1077
1078     index++;
1079     result++;
1080   }
1081   return index;
1082
1083   /* ERRORS */
1084 parse_failed:
1085   {
1086     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1087     return -1;
1088   }
1089 }
1090
1091 /* find the index of the sample that includes the data for @media_time using a
1092  * linear search, and keeping in mind that not all samples may have been parsed
1093  * yet.  If possible, it will delegate to binary search.
1094  *
1095  * Returns the index of the sample.
1096  */
1097 static guint32
1098 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1099     GstClockTime media_time)
1100 {
1101   guint32 index = 0;
1102   guint64 mov_time;
1103   QtDemuxSample *sample;
1104
1105   /* convert media_time to mov format */
1106   mov_time =
1107       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1108
1109   sample = str->samples;
1110   if (mov_time == sample->timestamp + sample->pts_offset)
1111     return index;
1112
1113   /* use faster search if requested time in already parsed range */
1114   sample = str->samples + str->stbl_index;
1115   if (str->stbl_index >= 0 &&
1116       mov_time <= (sample->timestamp + sample->pts_offset))
1117     return gst_qtdemux_find_index (qtdemux, str, media_time);
1118
1119   while (index < str->n_samples - 1) {
1120     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1121       goto parse_failed;
1122
1123     sample = str->samples + index + 1;
1124     if (mov_time < (sample->timestamp + sample->pts_offset))
1125       break;
1126
1127     index++;
1128   }
1129   return index;
1130
1131   /* ERRORS */
1132 parse_failed:
1133   {
1134     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1135     return -1;
1136   }
1137 }
1138
1139 /* find the index of the keyframe needed to decode the sample at @index
1140  * of stream @str.
1141  *
1142  * Returns the index of the keyframe.
1143  */
1144 static guint32
1145 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1146     guint32 index)
1147 {
1148   guint32 new_index = index;
1149
1150   if (index >= str->n_samples) {
1151     new_index = str->n_samples;
1152     goto beach;
1153   }
1154
1155   /* all keyframes, return index */
1156   if (str->all_keyframe) {
1157     new_index = index;
1158     goto beach;
1159   }
1160
1161   /* else go back until we have a keyframe */
1162   while (TRUE) {
1163     if (str->samples[new_index].keyframe)
1164       break;
1165
1166     if (new_index == 0)
1167       break;
1168
1169     new_index--;
1170   }
1171
1172 beach:
1173   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1174       "gave %u", index, new_index);
1175
1176   return new_index;
1177 }
1178
1179 /* find the segment for @time_position for @stream
1180  *
1181  * Returns the index of the segment containing @time_position.
1182  * Returns the last segment and sets the @eos variable to TRUE
1183  * if the time is beyond the end. @eos may be NULL
1184  */
1185 static guint32
1186 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1187     GstClockTime time_position)
1188 {
1189   gint i;
1190   guint32 seg_idx;
1191
1192   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1193       GST_TIME_ARGS (time_position));
1194
1195   seg_idx = -1;
1196   for (i = 0; i < stream->n_segments; i++) {
1197     QtDemuxSegment *segment = &stream->segments[i];
1198
1199     GST_LOG_OBJECT (stream->pad,
1200         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1201         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1202
1203     /* For the last segment we include stop_time in the last segment */
1204     if (i < stream->n_segments - 1) {
1205       if (segment->time <= time_position && time_position < segment->stop_time) {
1206         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1207         seg_idx = i;
1208         break;
1209       }
1210     } else {
1211       /* Last segment always matches */
1212       seg_idx = i;
1213       break;
1214     }
1215   }
1216   return seg_idx;
1217 }
1218
1219 /* move the stream @str to the sample position @index.
1220  *
1221  * Updates @str->sample_index and marks discontinuity if needed.
1222  */
1223 static void
1224 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1225     guint32 index)
1226 {
1227   /* no change needed */
1228   if (index == str->sample_index)
1229     return;
1230
1231   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1232       str->n_samples);
1233
1234   /* position changed, we have a discont */
1235   str->sample_index = index;
1236   str->offset_in_sample = 0;
1237   /* Each time we move in the stream we store the position where we are
1238    * starting from */
1239   str->from_sample = index;
1240   str->discont = TRUE;
1241 }
1242
1243 static void
1244 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1245     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1246 {
1247   guint64 min_offset;
1248   gint64 min_byte_offset = -1;
1249   gint n;
1250
1251   min_offset = desired_time;
1252
1253   /* for each stream, find the index of the sample in the segment
1254    * and move back to the previous keyframe. */
1255   for (n = 0; n < qtdemux->n_streams; n++) {
1256     QtDemuxStream *str;
1257     guint32 index, kindex;
1258     guint32 seg_idx;
1259     GstClockTime media_start;
1260     GstClockTime media_time;
1261     GstClockTime seg_time;
1262     QtDemuxSegment *seg;
1263     gboolean empty_segment = FALSE;
1264
1265     str = qtdemux->streams[n];
1266
1267     if (str->sparse && !use_sparse)
1268       continue;
1269
1270     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1271     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1272
1273     /* get segment and time in the segment */
1274     seg = &str->segments[seg_idx];
1275     seg_time = (desired_time - seg->time) * seg->rate;
1276
1277     while (QTSEGMENT_IS_EMPTY (seg)) {
1278       seg_time = 0;
1279       empty_segment = TRUE;
1280       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1281           seg_idx);
1282       seg_idx++;
1283       if (seg_idx == str->n_segments)
1284         break;
1285       seg = &str->segments[seg_idx];
1286     }
1287
1288     if (seg_idx == str->n_segments) {
1289       /* FIXME track shouldn't have the last segment as empty, but if it
1290        * happens we better handle it */
1291       continue;
1292     }
1293
1294     /* get the media time in the segment */
1295     media_start = seg->media_start + seg_time;
1296
1297     /* get the index of the sample with media time */
1298     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1299     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1300         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1301         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1302         empty_segment);
1303
1304     if (!empty_segment) {
1305       /* find previous keyframe */
1306       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1307
1308       /* if the keyframe is at a different position, we need to update the
1309        * requested seek time */
1310       if (index != kindex) {
1311         index = kindex;
1312
1313         /* get timestamp of keyframe */
1314         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1315         GST_DEBUG_OBJECT (qtdemux,
1316             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1317             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1318             str->samples[kindex].offset);
1319
1320         /* keyframes in the segment get a chance to change the
1321          * desired_offset. keyframes out of the segment are
1322          * ignored. */
1323         if (media_time >= seg->media_start) {
1324           GstClockTime seg_time;
1325
1326           /* this keyframe is inside the segment, convert back to
1327            * segment time */
1328           seg_time = (media_time - seg->media_start) + seg->time;
1329           if (seg_time < min_offset)
1330             min_offset = seg_time;
1331         }
1332       }
1333     }
1334
1335     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1336       min_byte_offset = str->samples[index].offset;
1337   }
1338
1339   if (key_time)
1340     *key_time = min_offset;
1341   if (key_offset)
1342     *key_offset = min_byte_offset;
1343 }
1344
1345 static gboolean
1346 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1347     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1348 {
1349   gboolean res;
1350
1351   g_return_val_if_fail (format != NULL, FALSE);
1352   g_return_val_if_fail (cur != NULL, FALSE);
1353   g_return_val_if_fail (stop != NULL, FALSE);
1354
1355   if (*format == GST_FORMAT_TIME)
1356     return TRUE;
1357
1358   res = TRUE;
1359   if (cur_type != GST_SEEK_TYPE_NONE)
1360     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1361   if (res && stop_type != GST_SEEK_TYPE_NONE)
1362     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1363
1364   if (res)
1365     *format = GST_FORMAT_TIME;
1366
1367   return res;
1368 }
1369
1370 /* perform seek in push based mode:
1371    find BYTE position to move to based on time and delegate to upstream
1372 */
1373 static gboolean
1374 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1375 {
1376   gdouble rate;
1377   GstFormat format;
1378   GstSeekFlags flags;
1379   GstSeekType cur_type, stop_type;
1380   gint64 cur, stop, key_cur;
1381   gboolean res;
1382   gint64 byte_cur;
1383   gint64 original_stop;
1384   guint32 seqnum;
1385
1386   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1387
1388   gst_event_parse_seek (event, &rate, &format, &flags,
1389       &cur_type, &cur, &stop_type, &stop);
1390   seqnum = gst_event_get_seqnum (event);
1391
1392   /* only forward streaming and seeking is possible */
1393   if (rate <= 0)
1394     goto unsupported_seek;
1395
1396   /* convert to TIME if needed and possible */
1397   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1398           stop_type, &stop))
1399     goto no_format;
1400
1401   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1402    * the original stop position to use when upstream pushes the new segment
1403    * for this seek */
1404   original_stop = stop;
1405   stop = -1;
1406
1407   /* find reasonable corresponding BYTE position,
1408    * also try to mind about keyframes, since we can not go back a bit for them
1409    * later on */
1410   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1411
1412   if (byte_cur == -1)
1413     goto abort_seek;
1414
1415   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1416       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1417       stop);
1418
1419   GST_OBJECT_LOCK (qtdemux);
1420   qtdemux->seek_offset = byte_cur;
1421   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1422     qtdemux->push_seek_start = cur;
1423   } else {
1424     qtdemux->push_seek_start = key_cur;
1425   }
1426
1427   if (stop_type == GST_SEEK_TYPE_NONE) {
1428     qtdemux->push_seek_stop = qtdemux->segment.stop;
1429   } else {
1430     qtdemux->push_seek_stop = original_stop;
1431   }
1432   GST_OBJECT_UNLOCK (qtdemux);
1433
1434   /* BYTE seek event */
1435   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1436       stop_type, stop);
1437   gst_event_set_seqnum (event, seqnum);
1438   res = gst_pad_push_event (qtdemux->sinkpad, event);
1439
1440   return res;
1441
1442   /* ERRORS */
1443 abort_seek:
1444   {
1445     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1446         "seek aborted.");
1447     return FALSE;
1448   }
1449 unsupported_seek:
1450   {
1451     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1452     return FALSE;
1453   }
1454 no_format:
1455   {
1456     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1457     return FALSE;
1458   }
1459 }
1460
1461 /* perform the seek.
1462  *
1463  * We set all segment_indexes in the streams to unknown and
1464  * adjust the time_position to the desired position. this is enough
1465  * to trigger a segment switch in the streaming thread to start
1466  * streaming from the desired position.
1467  *
1468  * Keyframe seeking is a little more complicated when dealing with
1469  * segments. Ideally we want to move to the previous keyframe in
1470  * the segment but there might not be a keyframe in the segment. In
1471  * fact, none of the segments could contain a keyframe. We take a
1472  * practical approach: seek to the previous keyframe in the segment,
1473  * if there is none, seek to the beginning of the segment.
1474  *
1475  * Called with STREAM_LOCK
1476  */
1477 static gboolean
1478 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1479     guint32 seqnum, GstSeekFlags flags)
1480 {
1481   gint64 desired_offset;
1482   gint n;
1483
1484   desired_offset = segment->position;
1485
1486   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1487       GST_TIME_ARGS (desired_offset));
1488
1489   /* may not have enough fragmented info to do this adjustment,
1490    * and we can't scan (and probably should not) at this time with
1491    * possibly flushing upstream */
1492   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1493     gint64 min_offset;
1494
1495     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1496     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1497         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1498     desired_offset = min_offset;
1499   }
1500
1501   /* and set all streams to the final position */
1502   gst_flow_combiner_reset (qtdemux->flowcombiner);
1503   qtdemux->segment_seqnum = seqnum;
1504   for (n = 0; n < qtdemux->n_streams; n++) {
1505     QtDemuxStream *stream = qtdemux->streams[n];
1506
1507     stream->time_position = desired_offset;
1508     stream->accumulated_base = 0;
1509     stream->sample_index = -1;
1510     stream->offset_in_sample = 0;
1511     stream->segment_index = -1;
1512     stream->sent_eos = FALSE;
1513
1514     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1515       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1516   }
1517   segment->position = desired_offset;
1518   segment->time = desired_offset;
1519   if (segment->rate >= 0) {
1520     segment->start = desired_offset;
1521
1522     /* we stop at the end */
1523     if (segment->stop == -1)
1524       segment->stop = segment->duration;
1525   } else {
1526     segment->stop = desired_offset;
1527   }
1528
1529   if (qtdemux->fragmented)
1530     qtdemux->fragmented_seek_pending = TRUE;
1531
1532   return TRUE;
1533 }
1534
1535 /* do a seek in pull based mode */
1536 static gboolean
1537 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1538 {
1539   gdouble rate;
1540   GstFormat format;
1541   GstSeekFlags flags;
1542   GstSeekType cur_type, stop_type;
1543   gint64 cur, stop;
1544   gboolean flush;
1545   gboolean update;
1546   GstSegment seeksegment;
1547   guint32 seqnum = 0;
1548   GstEvent *flush_event;
1549
1550   if (event) {
1551     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1552
1553     gst_event_parse_seek (event, &rate, &format, &flags,
1554         &cur_type, &cur, &stop_type, &stop);
1555     seqnum = gst_event_get_seqnum (event);
1556
1557     /* we have to have a format as the segment format. Try to convert
1558      * if not. */
1559     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1560             stop_type, &stop))
1561       goto no_format;
1562
1563     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1564   } else {
1565     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1566     flags = 0;
1567   }
1568
1569   flush = flags & GST_SEEK_FLAG_FLUSH;
1570
1571   /* stop streaming, either by flushing or by pausing the task */
1572   if (flush) {
1573     flush_event = gst_event_new_flush_start ();
1574     if (seqnum)
1575       gst_event_set_seqnum (flush_event, seqnum);
1576     /* unlock upstream pull_range */
1577     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1578     /* make sure out loop function exits */
1579     gst_qtdemux_push_event (qtdemux, flush_event);
1580   } else {
1581     /* non flushing seek, pause the task */
1582     gst_pad_pause_task (qtdemux->sinkpad);
1583   }
1584
1585   /* wait for streaming to finish */
1586   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1587
1588   /* copy segment, we need this because we still need the old
1589    * segment when we close the current segment. */
1590   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1591
1592   if (event) {
1593     /* configure the segment with the seek variables */
1594     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1595     gst_segment_do_seek (&seeksegment, rate, format, flags,
1596         cur_type, cur, stop_type, stop, &update);
1597   }
1598
1599   /* now do the seek, this actually never returns FALSE */
1600   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1601
1602   /* prepare for streaming again */
1603   if (flush) {
1604     flush_event = gst_event_new_flush_stop (TRUE);
1605     if (seqnum)
1606       gst_event_set_seqnum (flush_event, seqnum);
1607
1608     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1609     gst_qtdemux_push_event (qtdemux, flush_event);
1610   }
1611
1612   /* commit the new segment */
1613   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1614
1615   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1616     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1617         qtdemux->segment.format, qtdemux->segment.position);
1618     if (seqnum)
1619       gst_message_set_seqnum (msg, seqnum);
1620     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1621   }
1622
1623   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1624   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1625       qtdemux->sinkpad, NULL);
1626
1627   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1628
1629   return TRUE;
1630
1631   /* ERRORS */
1632 no_format:
1633   {
1634     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1635     return FALSE;
1636   }
1637 }
1638
1639 static gboolean
1640 qtdemux_ensure_index (GstQTDemux * qtdemux)
1641 {
1642   guint i;
1643
1644   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1645
1646   /* Build complete index */
1647   for (i = 0; i < qtdemux->n_streams; i++) {
1648     QtDemuxStream *stream = qtdemux->streams[i];
1649
1650     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1651       goto parse_error;
1652   }
1653   return TRUE;
1654
1655   /* ERRORS */
1656 parse_error:
1657   {
1658     GST_LOG_OBJECT (qtdemux,
1659         "Building complete index of stream %u for seeking failed!", i);
1660     return FALSE;
1661   }
1662 }
1663
1664 static gboolean
1665 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1666     GstEvent * event)
1667 {
1668   gboolean res = TRUE;
1669   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1670
1671   switch (GST_EVENT_TYPE (event)) {
1672     case GST_EVENT_SEEK:
1673     {
1674 #ifndef GST_DISABLE_GST_DEBUG
1675       GstClockTime ts = gst_util_get_timestamp ();
1676 #endif
1677
1678       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1679         /* seek should be handled by upstream, we might need to re-download fragments */
1680         GST_DEBUG_OBJECT (qtdemux,
1681             "let upstream handle seek for fragmented playback");
1682         goto upstream;
1683       }
1684
1685       /* Build complete index for seeking;
1686        * if not a fragmented file at least */
1687       if (!qtdemux->fragmented)
1688         if (!qtdemux_ensure_index (qtdemux))
1689           goto index_failed;
1690 #ifndef GST_DISABLE_GST_DEBUG
1691       ts = gst_util_get_timestamp () - ts;
1692       GST_INFO_OBJECT (qtdemux,
1693           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1694 #endif
1695     }
1696       if (qtdemux->pullbased) {
1697         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1698       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1699         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1700         res = TRUE;
1701       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1702           && !qtdemux->fragmented) {
1703         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1704       } else {
1705         GST_DEBUG_OBJECT (qtdemux,
1706             "ignoring seek in push mode in current state");
1707         res = FALSE;
1708       }
1709       gst_event_unref (event);
1710       break;
1711     case GST_EVENT_QOS:
1712     case GST_EVENT_NAVIGATION:
1713       res = FALSE;
1714       gst_event_unref (event);
1715       break;
1716     default:
1717     upstream:
1718       res = gst_pad_event_default (pad, parent, event);
1719       break;
1720   }
1721
1722 done:
1723   return res;
1724
1725   /* ERRORS */
1726 index_failed:
1727   {
1728     GST_ERROR_OBJECT (qtdemux, "Index failed");
1729     gst_event_unref (event);
1730     res = FALSE;
1731     goto done;
1732   }
1733 }
1734
1735 /* stream/index return sample that is min/max w.r.t. byte position,
1736  * time is min/max w.r.t. time of samples,
1737  * the latter need not be time of the former sample */
1738 static void
1739 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1740     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1741 {
1742   gint i, n, index;
1743   gint64 time, min_time;
1744   QtDemuxStream *stream;
1745
1746   min_time = -1;
1747   stream = NULL;
1748   index = -1;
1749
1750   for (n = 0; n < qtdemux->n_streams; ++n) {
1751     QtDemuxStream *str;
1752     gint inc;
1753     gboolean set_sample;
1754
1755     str = qtdemux->streams[n];
1756     set_sample = !set;
1757
1758     if (fw) {
1759       i = 0;
1760       inc = 1;
1761     } else {
1762       i = str->n_samples - 1;
1763       inc = -1;
1764     }
1765
1766     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1767       if (str->samples[i].size == 0)
1768         continue;
1769
1770       if (fw && (str->samples[i].offset < byte_pos))
1771         continue;
1772
1773       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1774         continue;
1775
1776       /* move stream to first available sample */
1777       if (set) {
1778         gst_qtdemux_move_stream (qtdemux, str, i);
1779         set_sample = TRUE;
1780       }
1781
1782       /* avoid index from sparse streams since they might be far away */
1783       if (!str->sparse) {
1784         /* determine min/max time */
1785         time = QTSAMPLE_PTS (str, &str->samples[i]);
1786         if (min_time == -1 || (!fw && time > min_time) ||
1787             (fw && time < min_time)) {
1788           min_time = time;
1789         }
1790
1791         /* determine stream with leading sample, to get its position */
1792         if (!stream ||
1793             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1794             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1795           stream = str;
1796           index = i;
1797         }
1798       }
1799       break;
1800     }
1801
1802     /* no sample for this stream, mark eos */
1803     if (!set_sample)
1804       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1805   }
1806
1807   if (_time)
1808     *_time = min_time;
1809   if (_stream)
1810     *_stream = stream;
1811   if (_index)
1812     *_index = index;
1813 }
1814
1815 static QtDemuxStream *
1816 _create_stream (void)
1817 {
1818   QtDemuxStream *stream;
1819
1820   stream = g_new0 (QtDemuxStream, 1);
1821   /* new streams always need a discont */
1822   stream->discont = TRUE;
1823   /* we enable clipping for raw audio/video streams */
1824   stream->need_clip = FALSE;
1825   stream->need_process = FALSE;
1826   stream->segment_index = -1;
1827   stream->time_position = 0;
1828   stream->sample_index = -1;
1829   stream->offset_in_sample = 0;
1830   stream->new_stream = TRUE;
1831   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1832   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1833   stream->protected = FALSE;
1834   stream->protection_scheme_type = 0;
1835   stream->protection_scheme_version = 0;
1836   stream->protection_scheme_info = NULL;
1837   stream->n_samples_moof = 0;
1838   stream->duration_moof = 0;
1839   g_queue_init (&stream->protection_scheme_event_queue);
1840   return stream;
1841 }
1842
1843 static gboolean
1844 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1845 {
1846   GstStructure *structure;
1847   const gchar *variant;
1848   const GstCaps *mediacaps = NULL;
1849
1850   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1851
1852   structure = gst_caps_get_structure (caps, 0);
1853   variant = gst_structure_get_string (structure, "variant");
1854
1855   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1856     QtDemuxStream *stream;
1857     const GValue *value;
1858
1859     demux->fragmented = TRUE;
1860     demux->mss_mode = TRUE;
1861
1862     if (demux->n_streams > 1) {
1863       /* can't do this, we can only renegotiate for another mss format */
1864       return FALSE;
1865     }
1866
1867     value = gst_structure_get_value (structure, "media-caps");
1868     /* create stream */
1869     if (value) {
1870       const GValue *timescale_v;
1871
1872       /* TODO update when stream changes during playback */
1873
1874       if (demux->n_streams == 0) {
1875         stream = _create_stream ();
1876         demux->streams[demux->n_streams] = stream;
1877         demux->n_streams = 1;
1878       } else {
1879         stream = demux->streams[0];
1880       }
1881
1882       timescale_v = gst_structure_get_value (structure, "timescale");
1883       if (timescale_v) {
1884         stream->timescale = g_value_get_uint64 (timescale_v);
1885       } else {
1886         /* default mss timescale */
1887         stream->timescale = 10000000;
1888       }
1889       demux->timescale = stream->timescale;
1890
1891       mediacaps = gst_value_get_caps (value);
1892       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1893         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1894             mediacaps);
1895         stream->new_caps = TRUE;
1896       }
1897       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1898       structure = gst_caps_get_structure (mediacaps, 0);
1899       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1900         stream->subtype = FOURCC_vide;
1901
1902         gst_structure_get_int (structure, "width", &stream->width);
1903         gst_structure_get_int (structure, "height", &stream->height);
1904         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1905             &stream->fps_d);
1906       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1907         gint rate = 0;
1908         stream->subtype = FOURCC_soun;
1909         gst_structure_get_int (structure, "channels", &stream->n_channels);
1910         gst_structure_get_int (structure, "rate", &rate);
1911         stream->rate = rate;
1912       }
1913     }
1914     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1915   } else {
1916     demux->mss_mode = FALSE;
1917   }
1918
1919   return TRUE;
1920 }
1921
1922 static void
1923 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1924 {
1925   gint n;
1926
1927   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1928   gst_pad_stop_task (qtdemux->sinkpad);
1929
1930   if (hard || qtdemux->upstream_format_is_time) {
1931     qtdemux->state = QTDEMUX_STATE_INITIAL;
1932     qtdemux->neededbytes = 16;
1933     qtdemux->todrop = 0;
1934     qtdemux->pullbased = FALSE;
1935     qtdemux->posted_redirect = FALSE;
1936     qtdemux->first_mdat = -1;
1937     qtdemux->header_size = 0;
1938     qtdemux->mdatoffset = -1;
1939     qtdemux->restoredata_offset = -1;
1940     if (qtdemux->mdatbuffer)
1941       gst_buffer_unref (qtdemux->mdatbuffer);
1942     if (qtdemux->restoredata_buffer)
1943       gst_buffer_unref (qtdemux->restoredata_buffer);
1944     qtdemux->mdatbuffer = NULL;
1945     qtdemux->restoredata_buffer = NULL;
1946     qtdemux->mdatleft = 0;
1947     if (qtdemux->comp_brands)
1948       gst_buffer_unref (qtdemux->comp_brands);
1949     qtdemux->comp_brands = NULL;
1950     qtdemux->last_moov_offset = -1;
1951     if (qtdemux->moov_node)
1952       g_node_destroy (qtdemux->moov_node);
1953     qtdemux->moov_node = NULL;
1954     qtdemux->moov_node_compressed = NULL;
1955     if (qtdemux->tag_list)
1956       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1957     qtdemux->tag_list = NULL;
1958 #if 0
1959     if (qtdemux->element_index)
1960       gst_object_unref (qtdemux->element_index);
1961     qtdemux->element_index = NULL;
1962 #endif
1963     qtdemux->major_brand = 0;
1964     if (qtdemux->pending_newsegment)
1965       gst_event_unref (qtdemux->pending_newsegment);
1966     qtdemux->pending_newsegment = NULL;
1967     qtdemux->upstream_format_is_time = FALSE;
1968     qtdemux->upstream_seekable = FALSE;
1969     qtdemux->upstream_size = 0;
1970
1971     qtdemux->fragment_start = -1;
1972     qtdemux->fragment_start_offset = -1;
1973     qtdemux->duration = 0;
1974     qtdemux->moof_offset = 0;
1975     qtdemux->chapters_track_id = 0;
1976     qtdemux->have_group_id = FALSE;
1977     qtdemux->group_id = G_MAXUINT;
1978
1979     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1980         NULL);
1981     g_queue_clear (&qtdemux->protection_event_queue);
1982   }
1983   qtdemux->offset = 0;
1984   gst_adapter_clear (qtdemux->adapter);
1985   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1986   qtdemux->segment_seqnum = 0;
1987
1988   if (hard) {
1989     for (n = 0; n < qtdemux->n_streams; n++) {
1990       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1991       qtdemux->streams[n] = NULL;
1992     }
1993     qtdemux->n_streams = 0;
1994     qtdemux->n_video_streams = 0;
1995     qtdemux->n_audio_streams = 0;
1996     qtdemux->n_sub_streams = 0;
1997     qtdemux->exposed = FALSE;
1998     qtdemux->fragmented = FALSE;
1999     qtdemux->mss_mode = FALSE;
2000     gst_caps_replace (&qtdemux->media_caps, NULL);
2001     qtdemux->timescale = 0;
2002     qtdemux->got_moov = FALSE;
2003     if (qtdemux->protection_system_ids) {
2004       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2005       qtdemux->protection_system_ids = NULL;
2006     }
2007   } else if (qtdemux->mss_mode) {
2008     gst_flow_combiner_reset (qtdemux->flowcombiner);
2009     for (n = 0; n < qtdemux->n_streams; n++)
2010       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2011   } else {
2012     gst_flow_combiner_reset (qtdemux->flowcombiner);
2013     for (n = 0; n < qtdemux->n_streams; n++) {
2014       qtdemux->streams[n]->sent_eos = FALSE;
2015       qtdemux->streams[n]->time_position = 0;
2016       qtdemux->streams[n]->accumulated_base = 0;
2017     }
2018     if (!qtdemux->pending_newsegment) {
2019       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2020     }
2021   }
2022 }
2023
2024 static gboolean
2025 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2026     GstEvent * event)
2027 {
2028   GstQTDemux *demux = GST_QTDEMUX (parent);
2029   gboolean res = TRUE;
2030
2031   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2032
2033   switch (GST_EVENT_TYPE (event)) {
2034     case GST_EVENT_SEGMENT:
2035     {
2036       gint64 offset = 0;
2037       QtDemuxStream *stream;
2038       gint idx;
2039       GstSegment segment;
2040       GstEvent *segment_event;
2041
2042       /* some debug output */
2043       gst_event_copy_segment (event, &segment);
2044       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2045           &segment);
2046
2047       if (segment.format == GST_FORMAT_TIME) {
2048         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2049         gst_event_replace (&demux->pending_newsegment, event);
2050         demux->upstream_format_is_time = TRUE;
2051       } else {
2052         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2053             "not in time format");
2054
2055         /* chain will send initial newsegment after pads have been added */
2056         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2057           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2058           goto exit;
2059         }
2060       }
2061
2062       /* check if this matches a time seek we received previously
2063        * FIXME for backwards compatibility reasons we use the
2064        * seek_offset here to compare. In the future we might want to
2065        * change this to use the seqnum as it uniquely should identify
2066        * the segment that corresponds to the seek. */
2067       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2068           ", received segment offset %" G_GINT64_FORMAT,
2069           demux->seek_offset, segment.start);
2070       if (segment.format == GST_FORMAT_BYTES
2071           && demux->seek_offset == segment.start) {
2072         GST_OBJECT_LOCK (demux);
2073         offset = segment.start;
2074
2075         segment.format = GST_FORMAT_TIME;
2076         segment.start = demux->push_seek_start;
2077         segment.stop = demux->push_seek_stop;
2078         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2079             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2080             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2081         GST_OBJECT_UNLOCK (demux);
2082       }
2083
2084       /* we only expect a BYTE segment, e.g. following a seek */
2085       if (segment.format == GST_FORMAT_BYTES) {
2086         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2087           offset = segment.start;
2088
2089           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2090               NULL, (gint64 *) & segment.start);
2091           if ((gint64) segment.start < 0)
2092             segment.start = 0;
2093         }
2094         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2095           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2096               NULL, (gint64 *) & segment.stop);
2097           /* keyframe seeking should already arrange for start >= stop,
2098            * but make sure in other rare cases */
2099           segment.stop = MAX (segment.stop, segment.start);
2100         }
2101       } else if (segment.format == GST_FORMAT_TIME) {
2102         /* push all data on the adapter before starting this
2103          * new segment */
2104         gst_qtdemux_process_adapter (demux, TRUE);
2105       } else {
2106         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2107         goto exit;
2108       }
2109
2110       /* accept upstream's notion of segment and distribute along */
2111       segment.format = GST_FORMAT_TIME;
2112       segment.position = segment.time = segment.start;
2113       segment.duration = demux->segment.duration;
2114       segment.base = gst_segment_to_running_time (&demux->segment,
2115           GST_FORMAT_TIME, demux->segment.position);
2116
2117       gst_segment_copy_into (&segment, &demux->segment);
2118       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2119       segment_event = gst_event_new_segment (&segment);
2120       gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2121       /* erase any previously set segment */
2122       gst_event_replace (&demux->pending_newsegment, NULL);
2123       gst_qtdemux_push_event (demux, segment_event);
2124
2125       /* clear leftover in current segment, if any */
2126       gst_adapter_clear (demux->adapter);
2127
2128       /* set up streaming thread */
2129       demux->offset = offset;
2130       if (demux->upstream_format_is_time) {
2131         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2132             "set values to restart reading from a new atom");
2133         demux->neededbytes = 16;
2134         demux->todrop = 0;
2135       } else {
2136         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2137             NULL);
2138         if (stream) {
2139           demux->todrop = stream->samples[idx].offset - offset;
2140           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2141         } else {
2142           /* set up for EOS */
2143           demux->neededbytes = -1;
2144           demux->todrop = 0;
2145         }
2146       }
2147     exit:
2148       gst_event_unref (event);
2149       res = TRUE;
2150       goto drop;
2151     }
2152     case GST_EVENT_FLUSH_START:
2153     {
2154       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2155         gst_event_unref (event);
2156         goto drop;
2157       }
2158       break;
2159     }
2160     case GST_EVENT_FLUSH_STOP:
2161     {
2162       guint64 dur;
2163
2164       dur = demux->segment.duration;
2165       gst_qtdemux_reset (demux, FALSE);
2166       demux->segment.duration = dur;
2167
2168       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2169         gst_event_unref (event);
2170         goto drop;
2171       }
2172       break;
2173     }
2174     case GST_EVENT_EOS:
2175       /* If we are in push mode, and get an EOS before we've seen any streams,
2176        * then error out - we have nowhere to send the EOS */
2177       if (!demux->pullbased) {
2178         gint i;
2179         gboolean has_valid_stream = FALSE;
2180         for (i = 0; i < demux->n_streams; i++) {
2181           if (demux->streams[i]->pad != NULL) {
2182             has_valid_stream = TRUE;
2183             break;
2184           }
2185         }
2186         if (!has_valid_stream)
2187           gst_qtdemux_post_no_playable_stream_error (demux);
2188         else {
2189           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2190               (guint) gst_adapter_available (demux->adapter));
2191           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2192             res = FALSE;
2193           }
2194         }
2195       }
2196       break;
2197     case GST_EVENT_CAPS:{
2198       GstCaps *caps = NULL;
2199
2200       gst_event_parse_caps (event, &caps);
2201       gst_qtdemux_setcaps (demux, caps);
2202       res = TRUE;
2203       gst_event_unref (event);
2204       goto drop;
2205     }
2206     case GST_EVENT_PROTECTION:
2207     {
2208       const gchar *system_id = NULL;
2209
2210       gst_event_parse_protection (event, &system_id, NULL, NULL);
2211       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2212           system_id);
2213       gst_qtdemux_append_protection_system_id (demux, system_id);
2214       /* save the event for later, for source pads that have not been created */
2215       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2216       /* send it to all pads that already exist */
2217       gst_qtdemux_push_event (demux, event);
2218       res = TRUE;
2219       goto drop;
2220     }
2221     default:
2222       break;
2223   }
2224
2225   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2226
2227 drop:
2228   return res;
2229 }
2230
2231 #if 0
2232 static void
2233 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2234 {
2235   GstQTDemux *demux = GST_QTDEMUX (element);
2236
2237   GST_OBJECT_LOCK (demux);
2238   if (demux->element_index)
2239     gst_object_unref (demux->element_index);
2240   if (index) {
2241     demux->element_index = gst_object_ref (index);
2242   } else {
2243     demux->element_index = NULL;
2244   }
2245   GST_OBJECT_UNLOCK (demux);
2246   /* object lock might be taken again */
2247   if (index)
2248     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2249   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2250       demux->element_index, demux->index_id);
2251 }
2252
2253 static GstIndex *
2254 gst_qtdemux_get_index (GstElement * element)
2255 {
2256   GstIndex *result = NULL;
2257   GstQTDemux *demux = GST_QTDEMUX (element);
2258
2259   GST_OBJECT_LOCK (demux);
2260   if (demux->element_index)
2261     result = gst_object_ref (demux->element_index);
2262   GST_OBJECT_UNLOCK (demux);
2263
2264   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2265
2266   return result;
2267 }
2268 #endif
2269
2270 static void
2271 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2272 {
2273   g_free ((gpointer) stream->stco.data);
2274   stream->stco.data = NULL;
2275   g_free ((gpointer) stream->stsz.data);
2276   stream->stsz.data = NULL;
2277   g_free ((gpointer) stream->stsc.data);
2278   stream->stsc.data = NULL;
2279   g_free ((gpointer) stream->stts.data);
2280   stream->stts.data = NULL;
2281   g_free ((gpointer) stream->stss.data);
2282   stream->stss.data = NULL;
2283   g_free ((gpointer) stream->stps.data);
2284   stream->stps.data = NULL;
2285   g_free ((gpointer) stream->ctts.data);
2286   stream->ctts.data = NULL;
2287 }
2288
2289 static void
2290 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2291     QtDemuxStream * stream)
2292 {
2293   g_free (stream->segments);
2294   stream->segments = NULL;
2295   stream->segment_index = -1;
2296   stream->accumulated_base = 0;
2297 }
2298
2299 static void
2300 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2301     QtDemuxStream * stream)
2302 {
2303   g_free (stream->samples);
2304   stream->samples = NULL;
2305   gst_qtdemux_stbl_free (stream);
2306
2307   /* fragments */
2308   g_free (stream->ra_entries);
2309   stream->ra_entries = NULL;
2310   stream->n_ra_entries = 0;
2311
2312   stream->sample_index = -1;
2313   stream->stbl_index = -1;
2314   stream->n_samples = 0;
2315   stream->time_position = 0;
2316
2317   stream->n_samples_moof = 0;
2318   stream->duration_moof = 0;
2319 }
2320
2321 static void
2322 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2323 {
2324   if (stream->allocator)
2325     gst_object_unref (stream->allocator);
2326   while (stream->buffers) {
2327     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2328     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2329   }
2330   if (stream->rgb8_palette) {
2331     gst_memory_unref (stream->rgb8_palette);
2332     stream->rgb8_palette = NULL;
2333   }
2334
2335   if (stream->pending_tags)
2336     gst_tag_list_unref (stream->pending_tags);
2337   stream->pending_tags = NULL;
2338   g_free (stream->redirect_uri);
2339   stream->redirect_uri = NULL;
2340   stream->sent_eos = FALSE;
2341   stream->sparse = FALSE;
2342   stream->protected = FALSE;
2343   if (stream->protection_scheme_info) {
2344     if (stream->protection_scheme_type == FOURCC_cenc) {
2345       QtDemuxCencSampleSetInfo *info =
2346           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2347       if (info->default_properties)
2348         gst_structure_free (info->default_properties);
2349       if (info->crypto_info)
2350         g_ptr_array_free (info->crypto_info, TRUE);
2351     }
2352     g_free (stream->protection_scheme_info);
2353     stream->protection_scheme_info = NULL;
2354   }
2355   stream->protection_scheme_type = 0;
2356   stream->protection_scheme_version = 0;
2357   g_queue_foreach (&stream->protection_scheme_event_queue,
2358       (GFunc) gst_event_unref, NULL);
2359   g_queue_clear (&stream->protection_scheme_event_queue);
2360   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2361   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2362 }
2363
2364 static void
2365 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2366 {
2367   gst_qtdemux_stream_clear (qtdemux, stream);
2368   if (stream->caps)
2369     gst_caps_unref (stream->caps);
2370   stream->caps = NULL;
2371   if (stream->pad) {
2372     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2373     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2374   }
2375   g_free (stream);
2376 }
2377
2378 static void
2379 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2380 {
2381   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2382
2383   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2384   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2385   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2386   qtdemux->n_streams--;
2387 }
2388
2389 static GstStateChangeReturn
2390 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2391 {
2392   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2393   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2394
2395   switch (transition) {
2396     case GST_STATE_CHANGE_PAUSED_TO_READY:
2397       break;
2398     default:
2399       break;
2400   }
2401
2402   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2403
2404   switch (transition) {
2405     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2406       gst_qtdemux_reset (qtdemux, TRUE);
2407       break;
2408     }
2409     default:
2410       break;
2411   }
2412
2413   return result;
2414 }
2415
2416 static void
2417 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2418 {
2419   /* counts as header data */
2420   qtdemux->header_size += length;
2421
2422   /* only consider at least a sufficiently complete ftyp atom */
2423   if (length >= 20) {
2424     GstBuffer *buf;
2425
2426     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2427     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2428         GST_FOURCC_ARGS (qtdemux->major_brand));
2429     if (qtdemux->comp_brands)
2430       gst_buffer_unref (qtdemux->comp_brands);
2431     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2432     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2433   }
2434 }
2435
2436 static void
2437 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2438     GstTagList * xmptaglist)
2439 {
2440   /* Strip out bogus fields */
2441   if (xmptaglist) {
2442     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2443       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2444       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2445     } else {
2446       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2447     }
2448
2449     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2450
2451     /* prioritize native tags using _KEEP mode */
2452     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2453     gst_tag_list_unref (xmptaglist);
2454   }
2455 }
2456
2457 static void
2458 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2459     guint offset)
2460 {
2461   GstByteReader br;
2462   guint8 version;
2463   guint32 flags = 0;
2464   guint i;
2465   guint8 iv_size = 8;
2466   QtDemuxStream *stream;
2467   GstStructure *structure;
2468   QtDemuxCencSampleSetInfo *ss_info = NULL;
2469   const gchar *system_id;
2470   gboolean uses_sub_sample_encryption = FALSE;
2471
2472   if (qtdemux->n_streams == 0)
2473     return;
2474
2475   stream = qtdemux->streams[0];
2476
2477   structure = gst_caps_get_structure (stream->caps, 0);
2478   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2479     GST_WARNING_OBJECT (qtdemux,
2480         "Attempting PIFF box parsing on an unencrypted stream.");
2481     return;
2482   }
2483
2484   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2485       G_TYPE_STRING, &system_id, NULL);
2486   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2487
2488   stream->protected = TRUE;
2489   stream->protection_scheme_type = FOURCC_cenc;
2490
2491   if (!stream->protection_scheme_info)
2492     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2493
2494   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2495
2496   if (ss_info->default_properties)
2497     gst_structure_free (ss_info->default_properties);
2498
2499   ss_info->default_properties =
2500       gst_structure_new ("application/x-cenc",
2501       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2502
2503   if (ss_info->crypto_info) {
2504     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2505     g_ptr_array_free (ss_info->crypto_info, TRUE);
2506     ss_info->crypto_info = NULL;
2507   }
2508
2509   /* skip UUID */
2510   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2511
2512   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2513     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2514     return;
2515   }
2516
2517   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2518     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2519     return;
2520   }
2521
2522   if ((flags & 0x000001)) {
2523     guint32 algorithm_id = 0;
2524     const guint8 *kid;
2525     GstBuffer *kid_buf;
2526     gboolean is_encrypted = TRUE;
2527
2528     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2529       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2530       return;
2531     }
2532
2533     algorithm_id >>= 8;
2534     if (algorithm_id == 0) {
2535       is_encrypted = FALSE;
2536     } else if (algorithm_id == 1) {
2537       /* FIXME: maybe store this in properties? */
2538       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2539     } else if (algorithm_id == 2) {
2540       /* FIXME: maybe store this in properties? */
2541       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2542     }
2543
2544     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2545       return;
2546
2547     if (!gst_byte_reader_get_data (&br, 16, &kid))
2548       return;
2549
2550     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2551     gst_buffer_fill (kid_buf, 0, kid, 16);
2552     if (ss_info->default_properties)
2553       gst_structure_free (ss_info->default_properties);
2554     ss_info->default_properties =
2555         gst_structure_new ("application/x-cenc",
2556         "iv_size", G_TYPE_UINT, iv_size,
2557         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2558         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2559     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2560         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2561     gst_buffer_unref (kid_buf);
2562   } else if ((flags & 0x000002)) {
2563     uses_sub_sample_encryption = TRUE;
2564   }
2565
2566   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2567     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2568     return;
2569   }
2570
2571   ss_info->crypto_info =
2572       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2573       (GDestroyNotify) qtdemux_gst_structure_free);
2574
2575   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2576     GstStructure *properties;
2577     guint8 *data;
2578     GstBuffer *buf;
2579
2580     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2581     if (properties == NULL) {
2582       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2583       return;
2584     }
2585
2586     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2587       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2588       gst_structure_free (properties);
2589       return;
2590     }
2591     buf = gst_buffer_new_wrapped (data, iv_size);
2592     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2593     gst_buffer_unref (buf);
2594
2595     if (uses_sub_sample_encryption) {
2596       guint16 n_subsamples;
2597
2598       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2599           || n_subsamples == 0) {
2600         GST_ERROR_OBJECT (qtdemux,
2601             "failed to get subsample count for sample %u", i);
2602         gst_structure_free (properties);
2603         return;
2604       }
2605       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2606       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2607         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2608             i);
2609         gst_structure_free (properties);
2610         return;
2611       }
2612       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2613       gst_structure_set (properties,
2614           "subsample_count", G_TYPE_UINT, n_subsamples,
2615           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2616       gst_buffer_unref (buf);
2617     } else {
2618       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2619     }
2620
2621     g_ptr_array_add (ss_info->crypto_info, properties);
2622   }
2623 }
2624
2625 static void
2626 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2627 {
2628   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2629     0x97, 0xA9, 0x42, 0xE8,
2630     0x9C, 0x71, 0x99, 0x94,
2631     0x91, 0xE3, 0xAF, 0xAC
2632   };
2633   static const guint8 playready_uuid[] = {
2634     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2635     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2636   };
2637
2638   static const guint8 piff_sample_encryption_uuid[] = {
2639     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2640     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2641   };
2642
2643   guint offset;
2644
2645   /* counts as header data */
2646   qtdemux->header_size += length;
2647
2648   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2649
2650   if (length <= offset + 16) {
2651     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2652     return;
2653   }
2654
2655   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2656     GstBuffer *buf;
2657     GstTagList *taglist;
2658
2659     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2660         length - offset - 16, NULL);
2661     taglist = gst_tag_list_from_xmp_buffer (buf);
2662     gst_buffer_unref (buf);
2663
2664     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2665
2666   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2667     int len;
2668     const gunichar2 *s_utf16;
2669     char *contents;
2670
2671     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2672     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2673     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2674     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2675
2676     g_free (contents);
2677
2678     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2679         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2680         (NULL));
2681   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2682     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2683   } else {
2684     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2685         GST_READ_UINT32_LE (buffer + offset),
2686         GST_READ_UINT32_LE (buffer + offset + 4),
2687         GST_READ_UINT32_LE (buffer + offset + 8),
2688         GST_READ_UINT32_LE (buffer + offset + 12));
2689   }
2690 }
2691
2692 static void
2693 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2694 {
2695   GstSidxParser sidx_parser;
2696   GstIsoffParserResult res;
2697   guint consumed;
2698
2699   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2700
2701   res =
2702       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2703       &consumed);
2704   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2705   if (res == GST_ISOFF_QT_PARSER_DONE) {
2706     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2707   }
2708   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2709 }
2710
2711 /* caller verifies at least 8 bytes in buf */
2712 static void
2713 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2714     guint64 * plength, guint32 * pfourcc)
2715 {
2716   guint64 length;
2717   guint32 fourcc;
2718
2719   length = QT_UINT32 (data);
2720   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2721   fourcc = QT_FOURCC (data + 4);
2722   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2723
2724   if (length == 0) {
2725     length = G_MAXUINT64;
2726   } else if (length == 1 && size >= 16) {
2727     /* this means we have an extended size, which is the 64 bit value of
2728      * the next 8 bytes */
2729     length = QT_UINT64 (data + 8);
2730     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2731   }
2732
2733   if (plength)
2734     *plength = length;
2735   if (pfourcc)
2736     *pfourcc = fourcc;
2737 }
2738
2739 static gboolean
2740 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2741 {
2742   guint32 version = 0;
2743   GstClockTime duration = 0;
2744
2745   if (!gst_byte_reader_get_uint32_be (br, &version))
2746     goto failed;
2747
2748   version >>= 24;
2749   if (version == 1) {
2750     if (!gst_byte_reader_get_uint64_be (br, &duration))
2751       goto failed;
2752   } else {
2753     guint32 dur = 0;
2754
2755     if (!gst_byte_reader_get_uint32_be (br, &dur))
2756       goto failed;
2757     duration = dur;
2758   }
2759
2760   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2761   qtdemux->duration = duration;
2762
2763   return TRUE;
2764
2765 failed:
2766   {
2767     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2768     return FALSE;
2769   }
2770 }
2771
2772 static gboolean
2773 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2774     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2775 {
2776   if (!stream->parsed_trex && qtdemux->moov_node) {
2777     GNode *mvex, *trex;
2778     GstByteReader trex_data;
2779
2780     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2781     if (mvex) {
2782       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2783           &trex_data);
2784       while (trex) {
2785         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2786
2787         /* skip version/flags */
2788         if (!gst_byte_reader_skip (&trex_data, 4))
2789           goto next;
2790         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2791           goto next;
2792         if (id != stream->track_id)
2793           goto next;
2794         /* sample description index; ignore */
2795         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2796           goto next;
2797         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2798           goto next;
2799         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2800           goto next;
2801         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2802           goto next;
2803
2804         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2805             "duration %d,  size %d, flags 0x%x", stream->track_id,
2806             dur, size, flags);
2807
2808         stream->parsed_trex = TRUE;
2809         stream->def_sample_duration = dur;
2810         stream->def_sample_size = size;
2811         stream->def_sample_flags = flags;
2812
2813       next:
2814         /* iterate all siblings */
2815         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2816             &trex_data);
2817       }
2818     }
2819   }
2820
2821   *ds_duration = stream->def_sample_duration;
2822   *ds_size = stream->def_sample_size;
2823   *ds_flags = stream->def_sample_flags;
2824
2825   /* even then, above values are better than random ... */
2826   if (G_UNLIKELY (!stream->parsed_trex)) {
2827     GST_WARNING_OBJECT (qtdemux,
2828         "failed to find fragment defaults for stream %d", stream->track_id);
2829     return FALSE;
2830   }
2831
2832   return TRUE;
2833 }
2834
2835 /* This method should be called whenever a more accurate duration might
2836  * have been found. It will update all relevant variables if/where needed
2837  */
2838 static void
2839 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2840 {
2841   guint i;
2842   guint64 movdur;
2843   GstClockTime prevdur;
2844
2845   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2846
2847   if (movdur > qtdemux->duration) {
2848     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2849     GST_DEBUG_OBJECT (qtdemux,
2850         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2851         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2852     qtdemux->duration = movdur;
2853     GST_DEBUG_OBJECT (qtdemux,
2854         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2855         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2856         GST_TIME_ARGS (qtdemux->segment.stop));
2857     if (qtdemux->segment.duration == prevdur) {
2858       /* If the current segment has duration/stop identical to previous duration
2859        * update them also (because they were set at that point in time with
2860        * the wrong duration */
2861       /* We convert the value *from* the timescale version to avoid rounding errors */
2862       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2863       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2864       qtdemux->segment.duration = fixeddur;
2865       qtdemux->segment.stop = fixeddur;
2866     }
2867   }
2868   for (i = 0; i < qtdemux->n_streams; i++) {
2869     QtDemuxStream *stream = qtdemux->streams[i];
2870     if (stream) {
2871       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2872       if (movdur > stream->duration) {
2873         GST_DEBUG_OBJECT (qtdemux,
2874             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2875             GST_TIME_ARGS (duration));
2876         stream->duration = movdur;
2877         if (stream->dummy_segment) {
2878           /* Update all dummy values to new duration */
2879           stream->segments[0].stop_time = duration;
2880           stream->segments[0].duration = duration;
2881           stream->segments[0].media_stop = duration;
2882
2883           /* let downstream know we possibly have a new stop time */
2884           if (stream->segment_index != -1) {
2885             GstClockTime pos;
2886
2887             if (qtdemux->segment.rate >= 0) {
2888               pos = stream->segment.start;
2889             } else {
2890               pos = stream->segment.stop;
2891             }
2892
2893             gst_qtdemux_stream_update_segment (qtdemux, stream,
2894                 stream->segment_index, pos, NULL, NULL);
2895           }
2896         }
2897       }
2898     }
2899   }
2900 }
2901
2902 static gboolean
2903 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2904     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2905     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2906     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2907 {
2908   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2909   guint64 timestamp;
2910   gint32 data_offset = 0;
2911   guint32 flags = 0, first_flags = 0, samples_count = 0;
2912   gint i;
2913   guint8 *data;
2914   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2915   QtDemuxSample *sample;
2916   gboolean ismv = FALSE;
2917
2918   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2919       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2920       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2921       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2922
2923   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2924     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2925     return TRUE;
2926   }
2927
2928   /* presence of stss or not can't really tell us much,
2929    * and flags and so on tend to be marginally reliable in these files */
2930   if (stream->subtype == FOURCC_soun) {
2931     GST_DEBUG_OBJECT (qtdemux,
2932         "sound track in fragmented file; marking all keyframes");
2933     stream->all_keyframe = TRUE;
2934   }
2935
2936   if (!gst_byte_reader_skip (trun, 1) ||
2937       !gst_byte_reader_get_uint24_be (trun, &flags))
2938     goto fail;
2939
2940   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2941     goto fail;
2942
2943   if (flags & TR_DATA_OFFSET) {
2944     /* note this is really signed */
2945     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2946       goto fail;
2947     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2948     /* default base offset = first byte of moof */
2949     if (*base_offset == -1) {
2950       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
2951       *base_offset = moof_offset;
2952     }
2953     *running_offset = *base_offset + data_offset;
2954   } else {
2955     /* if no offset at all, that would mean data starts at moof start,
2956      * which is a bit wrong and is ismv crappy way, so compensate
2957      * assuming data is in mdat following moof */
2958     if (*base_offset == -1) {
2959       *base_offset = moof_offset + moof_length + 8;
2960       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
2961       ismv = TRUE;
2962     }
2963     if (*running_offset == -1)
2964       *running_offset = *base_offset;
2965   }
2966
2967   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
2968       *running_offset);
2969   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
2970       data_offset, flags, samples_count);
2971
2972   if (flags & TR_FIRST_SAMPLE_FLAGS) {
2973     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
2974       GST_DEBUG_OBJECT (qtdemux,
2975           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
2976       flags ^= TR_FIRST_SAMPLE_FLAGS;
2977     } else {
2978       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
2979         goto fail;
2980       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
2981     }
2982   }
2983
2984   /* FIXME ? spec says other bits should also be checked to determine
2985    * entry size (and prefix size for that matter) */
2986   entry_size = 0;
2987   dur_offset = size_offset = 0;
2988   if (flags & TR_SAMPLE_DURATION) {
2989     GST_LOG_OBJECT (qtdemux, "entry duration present");
2990     dur_offset = entry_size;
2991     entry_size += 4;
2992   }
2993   if (flags & TR_SAMPLE_SIZE) {
2994     GST_LOG_OBJECT (qtdemux, "entry size present");
2995     size_offset = entry_size;
2996     entry_size += 4;
2997   }
2998   if (flags & TR_SAMPLE_FLAGS) {
2999     GST_LOG_OBJECT (qtdemux, "entry flags present");
3000     flags_offset = entry_size;
3001     entry_size += 4;
3002   }
3003   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3004     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3005     ct_offset = entry_size;
3006     entry_size += 4;
3007   }
3008
3009   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3010     goto fail;
3011   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3012
3013   if (stream->n_samples + samples_count >=
3014       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3015     goto index_too_big;
3016
3017   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3018       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3019       (stream->n_samples + samples_count) *
3020       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3021
3022   /* create a new array of samples if it's the first sample parsed */
3023   if (stream->n_samples == 0) {
3024     g_assert (stream->samples == NULL);
3025     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3026     /* or try to reallocate it with space enough to insert the new samples */
3027   } else
3028     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3029         stream->n_samples + samples_count);
3030   if (stream->samples == NULL)
3031     goto out_of_memory;
3032
3033   if (qtdemux->fragment_start != -1) {
3034     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3035     qtdemux->fragment_start = -1;
3036   } else {
3037     if (stream->n_samples == 0) {
3038       if (decode_ts > 0) {
3039         timestamp = decode_ts;
3040       } else if (stream->pending_seek != NULL) {
3041         /* if we don't have a timestamp from a tfdt box, we'll use the one
3042          * from the mfra seek table */
3043         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3044             GST_TIME_ARGS (stream->pending_seek->ts));
3045
3046         /* FIXME: this is not fully correct, the timestamp refers to the random
3047          * access sample refered to in the tfra entry, which may not necessarily
3048          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3049         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3050       } else {
3051         timestamp = 0;
3052       }
3053
3054       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3055       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3056           GST_TIME_ARGS (gst_ts));
3057     } else {
3058       /* subsequent fragments extend stream */
3059       timestamp =
3060           stream->samples[stream->n_samples - 1].timestamp +
3061           stream->samples[stream->n_samples - 1].duration;
3062
3063       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3064       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3065           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3066     }
3067   }
3068
3069   sample = stream->samples + stream->n_samples;
3070   for (i = 0; i < samples_count; i++) {
3071     guint32 dur, size, sflags, ct;
3072
3073     /* first read sample data */
3074     if (flags & TR_SAMPLE_DURATION) {
3075       dur = QT_UINT32 (data + dur_offset);
3076     } else {
3077       dur = d_sample_duration;
3078     }
3079     if (flags & TR_SAMPLE_SIZE) {
3080       size = QT_UINT32 (data + size_offset);
3081     } else {
3082       size = d_sample_size;
3083     }
3084     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3085       if (i == 0) {
3086         sflags = first_flags;
3087       } else {
3088         sflags = d_sample_flags;
3089       }
3090     } else if (flags & TR_SAMPLE_FLAGS) {
3091       sflags = QT_UINT32 (data + flags_offset);
3092     } else {
3093       sflags = d_sample_flags;
3094     }
3095     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3096       ct = QT_UINT32 (data + ct_offset);
3097     } else {
3098       ct = 0;
3099     }
3100     data += entry_size;
3101
3102     /* fill the sample information */
3103     sample->offset = *running_offset;
3104     sample->pts_offset = ct;
3105     sample->size = size;
3106     sample->timestamp = timestamp;
3107     sample->duration = dur;
3108     /* sample-is-difference-sample */
3109     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3110      * now idea how it relates to bitfield other than massive LE/BE confusion */
3111     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3112     *running_offset += size;
3113     timestamp += dur;
3114     stream->duration_moof += dur;
3115     sample++;
3116   }
3117
3118   /* Update total duration if needed */
3119   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3120
3121   stream->n_samples += samples_count;
3122   stream->n_samples_moof += samples_count;
3123
3124   if (stream->pending_seek != NULL)
3125     stream->pending_seek = NULL;
3126
3127   return TRUE;
3128
3129 fail:
3130   {
3131     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3132     return FALSE;
3133   }
3134 out_of_memory:
3135   {
3136     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3137         stream->n_samples);
3138     return FALSE;
3139   }
3140 index_too_big:
3141   {
3142     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3143         "be larger than %uMB (broken file?)", stream->n_samples,
3144         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3145     return FALSE;
3146   }
3147 }
3148
3149 /* find stream with @id */
3150 static inline QtDemuxStream *
3151 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3152 {
3153   QtDemuxStream *stream;
3154   gint i;
3155
3156   /* check */
3157   if (G_UNLIKELY (!id)) {
3158     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3159     return NULL;
3160   }
3161
3162   /* try to get it fast and simple */
3163   if (G_LIKELY (id <= qtdemux->n_streams)) {
3164     stream = qtdemux->streams[id - 1];
3165     if (G_LIKELY (stream->track_id == id))
3166       return stream;
3167   }
3168
3169   /* linear search otherwise */
3170   for (i = 0; i < qtdemux->n_streams; i++) {
3171     stream = qtdemux->streams[i];
3172     if (stream->track_id == id)
3173       return stream;
3174   }
3175   if (qtdemux->mss_mode) {
3176     /* mss should have only 1 stream anyway */
3177     return qtdemux->streams[0];
3178   }
3179
3180   return NULL;
3181 }
3182
3183 static gboolean
3184 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3185     guint32 * fragment_number)
3186 {
3187   if (!gst_byte_reader_skip (mfhd, 4))
3188     goto fail;
3189   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3190     goto fail;
3191   return TRUE;
3192 fail:
3193   {
3194     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3195     return FALSE;
3196   }
3197 }
3198
3199 static gboolean
3200 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3201     QtDemuxStream ** stream, guint32 * default_sample_duration,
3202     guint32 * default_sample_size, guint32 * default_sample_flags,
3203     gint64 * base_offset)
3204 {
3205   guint32 flags = 0;
3206   guint32 track_id = 0;
3207
3208   if (!gst_byte_reader_skip (tfhd, 1) ||
3209       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3210     goto invalid_track;
3211
3212   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3213     goto invalid_track;
3214
3215   *stream = qtdemux_find_stream (qtdemux, track_id);
3216   if (G_UNLIKELY (!*stream))
3217     goto unknown_stream;
3218
3219   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3220     *base_offset = qtdemux->moof_offset;
3221
3222   if (flags & TF_BASE_DATA_OFFSET)
3223     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3224       goto invalid_track;
3225
3226   /* obtain stream defaults */
3227   qtdemux_parse_trex (qtdemux, *stream,
3228       default_sample_duration, default_sample_size, default_sample_flags);
3229
3230   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3231   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3232     if (!gst_byte_reader_skip (tfhd, 4))
3233       goto invalid_track;
3234
3235   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3236     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3237       goto invalid_track;
3238
3239   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3240     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3241       goto invalid_track;
3242
3243   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3244     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3245       goto invalid_track;
3246
3247   return TRUE;
3248
3249 invalid_track:
3250   {
3251     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3252     return FALSE;
3253   }
3254 unknown_stream:
3255   {
3256     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3257     return TRUE;
3258   }
3259 }
3260
3261 static gboolean
3262 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3263     guint64 * decode_time)
3264 {
3265   guint32 version = 0;
3266
3267   if (!gst_byte_reader_get_uint32_be (br, &version))
3268     return FALSE;
3269
3270   version >>= 24;
3271   if (version == 1) {
3272     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3273       goto failed;
3274   } else {
3275     guint32 dec_time = 0;
3276     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3277       goto failed;
3278     *decode_time = dec_time;
3279   }
3280
3281   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3282       *decode_time);
3283
3284   return TRUE;
3285
3286 failed:
3287   {
3288     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3289     return FALSE;
3290   }
3291 }
3292
3293 /* Returns a pointer to a GstStructure containing the properties of
3294  * the stream sample identified by @sample_index. The caller must unref
3295  * the returned object after use. Returns NULL if unsuccessful. */
3296 static GstStructure *
3297 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3298     QtDemuxStream * stream, guint sample_index)
3299 {
3300   QtDemuxCencSampleSetInfo *info = NULL;
3301
3302   g_return_val_if_fail (stream != NULL, NULL);
3303   g_return_val_if_fail (stream->protected, NULL);
3304   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3305
3306   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3307
3308   /* Currently, cenc properties for groups of samples are not supported, so
3309    * simply return a copy of the default sample properties */
3310   return gst_structure_copy (info->default_properties);
3311 }
3312
3313 /* Parses the sizes of sample auxiliary information contained within a stream,
3314  * as given in a saiz box. Returns array of sample_count guint8 size values,
3315  * or NULL on failure */
3316 static guint8 *
3317 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3318     GstByteReader * br, guint32 * sample_count)
3319 {
3320   guint32 flags = 0;
3321   guint8 *info_sizes;
3322   guint8 default_info_size;
3323
3324   g_return_val_if_fail (qtdemux != NULL, NULL);
3325   g_return_val_if_fail (stream != NULL, NULL);
3326   g_return_val_if_fail (br != NULL, NULL);
3327   g_return_val_if_fail (sample_count != NULL, NULL);
3328
3329   if (!gst_byte_reader_get_uint32_be (br, &flags))
3330     return NULL;
3331
3332   if (flags & 0x1) {
3333     /* aux_info_type and aux_info_type_parameter are ignored */
3334     if (!gst_byte_reader_skip (br, 8))
3335       return NULL;
3336   }
3337
3338   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3339     return NULL;
3340   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3341
3342   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3343     return NULL;
3344   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3345
3346
3347   if (default_info_size == 0) {
3348     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3349       return NULL;
3350     }
3351   } else {
3352     info_sizes = g_new (guint8, *sample_count);
3353     memset (info_sizes, default_info_size, *sample_count);
3354   }
3355
3356   return info_sizes;
3357 }
3358
3359 /* Parses the offset of sample auxiliary information contained within a stream,
3360  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3361 static gboolean
3362 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3363     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3364     guint64 * offset)
3365 {
3366   guint8 version = 0;
3367   guint32 flags = 0;
3368   guint32 aux_info_type = 0;
3369   guint32 aux_info_type_parameter = 0;
3370   guint32 entry_count;
3371   guint32 off_32;
3372   guint64 off_64;
3373   const guint8 *aux_info_type_data = NULL;
3374
3375   g_return_val_if_fail (qtdemux != NULL, FALSE);
3376   g_return_val_if_fail (stream != NULL, FALSE);
3377   g_return_val_if_fail (br != NULL, FALSE);
3378   g_return_val_if_fail (offset != NULL, FALSE);
3379
3380   if (!gst_byte_reader_get_uint8 (br, &version))
3381     return FALSE;
3382
3383   if (!gst_byte_reader_get_uint24_be (br, &flags))
3384     return FALSE;
3385
3386   if (flags & 0x1) {
3387
3388     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3389       return FALSE;
3390     aux_info_type = QT_FOURCC (aux_info_type_data);
3391
3392     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3393       return FALSE;
3394   } else if (stream->protected) {
3395     aux_info_type = stream->protection_scheme_type;
3396   } else {
3397     aux_info_type = stream->fourcc;
3398   }
3399
3400   if (info_type)
3401     *info_type = aux_info_type;
3402   if (info_type_parameter)
3403     *info_type_parameter = aux_info_type_parameter;
3404
3405   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3406       "aux_info_type_parameter:  %#06x",
3407       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3408
3409   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3410     return FALSE;
3411
3412   if (entry_count != 1) {
3413     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3414     return FALSE;
3415   }
3416
3417   if (version == 0) {
3418     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3419       return FALSE;
3420     *offset = (guint64) off_32;
3421   } else {
3422     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3423       return FALSE;
3424     *offset = off_64;
3425   }
3426
3427   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3428   return TRUE;
3429 }
3430
3431 static void
3432 qtdemux_gst_structure_free (GstStructure * gststructure)
3433 {
3434   if (gststructure) {
3435     gst_structure_free (gststructure);
3436   }
3437 }
3438
3439 /* Parses auxiliary information relating to samples protected using Common
3440  * Encryption (cenc); the format of this information is defined in
3441  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3442 static gboolean
3443 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3444     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3445 {
3446   QtDemuxCencSampleSetInfo *ss_info = NULL;
3447   guint8 size;
3448   gint i;
3449
3450   g_return_val_if_fail (qtdemux != NULL, FALSE);
3451   g_return_val_if_fail (stream != NULL, FALSE);
3452   g_return_val_if_fail (br != NULL, FALSE);
3453   g_return_val_if_fail (stream->protected, FALSE);
3454   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3455
3456   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3457
3458   if (ss_info->crypto_info) {
3459     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3460     g_ptr_array_free (ss_info->crypto_info, TRUE);
3461   }
3462
3463   ss_info->crypto_info =
3464       g_ptr_array_new_full (sample_count,
3465       (GDestroyNotify) qtdemux_gst_structure_free);
3466
3467   for (i = 0; i < sample_count; ++i) {
3468     GstStructure *properties;
3469     guint16 n_subsamples = 0;
3470     guint8 *data;
3471     guint iv_size;
3472     GstBuffer *buf;
3473
3474     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3475     if (properties == NULL) {
3476       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3477       return FALSE;
3478     }
3479     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3480       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3481       gst_structure_free (properties);
3482       return FALSE;
3483     }
3484     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3485       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3486       gst_structure_free (properties);
3487       return FALSE;
3488     }
3489     buf = gst_buffer_new_wrapped (data, iv_size);
3490     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3491     gst_buffer_unref (buf);
3492     size = info_sizes[i];
3493     if (size > iv_size) {
3494       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3495           || !(n_subsamples > 0)) {
3496         gst_structure_free (properties);
3497         GST_ERROR_OBJECT (qtdemux,
3498             "failed to get subsample count for sample %u", i);
3499         return FALSE;
3500       }
3501       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3502       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3503         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3504             i);
3505         gst_structure_free (properties);
3506         return FALSE;
3507       }
3508       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3509       if (!buf) {
3510         gst_structure_free (properties);
3511         return FALSE;
3512       }
3513       gst_structure_set (properties,
3514           "subsample_count", G_TYPE_UINT, n_subsamples,
3515           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3516       gst_buffer_unref (buf);
3517     } else {
3518       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3519     }
3520     g_ptr_array_add (ss_info->crypto_info, properties);
3521   }
3522   return TRUE;
3523 }
3524
3525 /* Converts a UUID in raw byte form to a string representation, as defined in
3526  * RFC 4122. The caller takes ownership of the returned string and is
3527  * responsible for freeing it after use. */
3528 static gchar *
3529 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3530 {
3531   const guint8 *uuid = (const guint8 *) uuid_bytes;
3532
3533   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3534       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3535       uuid[0], uuid[1], uuid[2], uuid[3],
3536       uuid[4], uuid[5], uuid[6], uuid[7],
3537       uuid[8], uuid[9], uuid[10], uuid[11],
3538       uuid[12], uuid[13], uuid[14], uuid[15]);
3539 }
3540
3541 /* Parses a Protection System Specific Header box (pssh), as defined in the
3542  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3543  * information needed by a specific content protection system in order to
3544  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3545  * otherwise. */
3546 static gboolean
3547 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3548 {
3549   gchar *sysid_string;
3550   guint32 pssh_size = QT_UINT32 (node->data);
3551   GstBuffer *pssh = NULL;
3552   GstEvent *event = NULL;
3553   guint32 parent_box_type;
3554   gint i;
3555
3556   if (G_UNLIKELY (pssh_size < 32U)) {
3557     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3558     return FALSE;
3559   }
3560
3561   sysid_string =
3562       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3563
3564   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3565
3566   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3567   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3568       gst_buffer_get_size (pssh));
3569
3570   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3571
3572   /* Push an event containing the pssh box onto the queues of all streams. */
3573   event = gst_event_new_protection (sysid_string, pssh,
3574       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3575   for (i = 0; i < qtdemux->n_streams; ++i) {
3576     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3577         gst_event_ref (event));
3578   }
3579   g_free (sysid_string);
3580   gst_event_unref (event);
3581   gst_buffer_unref (pssh);
3582   return TRUE;
3583 }
3584
3585 static gboolean
3586 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3587     guint64 moof_offset, QtDemuxStream * stream)
3588 {
3589   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3590   GNode *uuid_node;
3591   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3592   GNode *saiz_node, *saio_node, *pssh_node;
3593   GstByteReader saiz_data, saio_data;
3594   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3595   gint64 base_offset, running_offset;
3596   guint32 frag_num;
3597
3598   /* NOTE @stream ignored */
3599
3600   moof_node = g_node_new ((guint8 *) buffer);
3601   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3602   qtdemux_node_dump (qtdemux, moof_node);
3603
3604   /* Get fragment number from mfhd and check it's valid */
3605   mfhd_node =
3606       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3607   if (mfhd_node == NULL)
3608     goto missing_mfhd;
3609   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3610     goto fail;
3611   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3612
3613   /* unknown base_offset to start with */
3614   base_offset = running_offset = -1;
3615   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3616   while (traf_node) {
3617     guint64 decode_time = 0;
3618
3619     /* Fragment Header node */
3620     tfhd_node =
3621         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3622         &tfhd_data);
3623     if (!tfhd_node)
3624       goto missing_tfhd;
3625     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3626             &ds_size, &ds_flags, &base_offset))
3627       goto missing_tfhd;
3628
3629     /* The following code assumes at most a single set of sample auxiliary
3630      * data in the fragment (consisting of a saiz box and a corresponding saio
3631      * box); in theory, however, there could be multiple sets of sample
3632      * auxiliary data in a fragment. */
3633     saiz_node =
3634         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3635         &saiz_data);
3636     if (saiz_node) {
3637       guint32 info_type = 0;
3638       guint64 offset = 0;
3639       guint32 info_type_parameter = 0;
3640
3641       g_free (qtdemux->cenc_aux_info_sizes);
3642
3643       qtdemux->cenc_aux_info_sizes =
3644           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3645           &qtdemux->cenc_aux_sample_count);
3646       if (qtdemux->cenc_aux_info_sizes == NULL) {
3647         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3648         goto fail;
3649       }
3650       saio_node =
3651           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3652           &saio_data);
3653       if (!saio_node) {
3654         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3655         g_free (qtdemux->cenc_aux_info_sizes);
3656         qtdemux->cenc_aux_info_sizes = NULL;
3657         goto fail;
3658       }
3659
3660       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3661                   &info_type, &info_type_parameter, &offset))) {
3662         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3663         g_free (qtdemux->cenc_aux_info_sizes);
3664         qtdemux->cenc_aux_info_sizes = NULL;
3665         goto fail;
3666       }
3667       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3668         offset += (guint64) (base_offset - qtdemux->moof_offset);
3669       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3670         GstByteReader br;
3671         if (offset > length) {
3672           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3673           qtdemux->cenc_aux_info_offset = offset;
3674         } else {
3675           gst_byte_reader_init (&br, buffer + offset, length - offset);
3676           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3677                   qtdemux->cenc_aux_info_sizes,
3678                   qtdemux->cenc_aux_sample_count)) {
3679             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3680             g_free (qtdemux->cenc_aux_info_sizes);
3681             qtdemux->cenc_aux_info_sizes = NULL;
3682             goto fail;
3683           }
3684         }
3685       }
3686     }
3687
3688     tfdt_node =
3689         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3690         &tfdt_data);
3691     if (tfdt_node) {
3692       GstClockTime decode_time_ts;
3693
3694       /* We'll use decode_time to interpolate timestamps
3695        * in case the input timestamps are missing */
3696       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3697
3698       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3699
3700       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3701           " (%" GST_TIME_FORMAT ")", decode_time,
3702           GST_TIME_ARGS (decode_time_ts));
3703
3704       /* Discard the fragment buffer timestamp info to avoid using it.
3705        * Rely on tfdt instead as it is more accurate than the timestamp
3706        * that is fetched from a manifest/playlist and is usually
3707        * less accurate. */
3708       qtdemux->fragment_start = -1;
3709     }
3710
3711     if (G_UNLIKELY (!stream)) {
3712       /* we lost track of offset, we'll need to regain it,
3713        * but can delay complaining until later or avoid doing so altogether */
3714       base_offset = -2;
3715       goto next;
3716     }
3717     if (G_UNLIKELY (base_offset < -1))
3718       goto lost_offset;
3719
3720     if (qtdemux->upstream_format_is_time)
3721       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3722
3723     /* initialise moof sample data */
3724     stream->n_samples_moof = 0;
3725     stream->duration_moof = 0;
3726
3727     /* Track Run node */
3728     trun_node =
3729         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3730         &trun_data);
3731     while (trun_node) {
3732       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3733           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3734           &running_offset, decode_time);
3735       /* iterate all siblings */
3736       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3737           &trun_data);
3738     }
3739
3740     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3741     if (uuid_node) {
3742       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3743       guint32 box_length = QT_UINT32 (uuid_buffer);
3744
3745       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3746     }
3747
3748     /* if no new base_offset provided for next traf,
3749      * base is end of current traf */
3750     base_offset = running_offset;
3751     running_offset = -1;
3752
3753     if (stream->n_samples_moof && stream->duration_moof)
3754       stream->new_caps = TRUE;
3755
3756   next:
3757     /* iterate all siblings */
3758     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3759   }
3760
3761   /* parse any protection system info */
3762   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3763   while (pssh_node) {
3764     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3765     qtdemux_parse_pssh (qtdemux, pssh_node);
3766     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3767   }
3768
3769   g_node_destroy (moof_node);
3770   return TRUE;
3771
3772 missing_tfhd:
3773   {
3774     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3775     goto fail;
3776   }
3777 missing_mfhd:
3778   {
3779     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3780     goto fail;
3781   }
3782 lost_offset:
3783   {
3784     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3785     goto fail;
3786   }
3787 fail:
3788   {
3789     g_node_destroy (moof_node);
3790     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3791         (_("This file is corrupt and cannot be played.")), (NULL));
3792     return FALSE;
3793   }
3794 }
3795
3796 #if 0
3797 /* might be used if some day we actually use mfra & co
3798  * for random access to fragments,
3799  * but that will require quite some modifications and much less relying
3800  * on a sample array */
3801 #endif
3802
3803 static gboolean
3804 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3805 {
3806   QtDemuxStream *stream;
3807   guint32 ver_flags, track_id, len, num_entries, i;
3808   guint value_size, traf_size, trun_size, sample_size;
3809   guint64 time = 0, moof_offset = 0;
3810 #if 0
3811   GstBuffer *buf = NULL;
3812   GstFlowReturn ret;
3813 #endif
3814   GstByteReader tfra;
3815
3816   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3817
3818   if (!gst_byte_reader_skip (&tfra, 8))
3819     return FALSE;
3820
3821   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3822     return FALSE;
3823
3824   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3825       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3826       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3827     return FALSE;
3828
3829   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3830
3831   stream = qtdemux_find_stream (qtdemux, track_id);
3832   if (stream == NULL)
3833     goto unknown_trackid;
3834
3835   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3836   sample_size = (len & 3) + 1;
3837   trun_size = ((len & 12) >> 2) + 1;
3838   traf_size = ((len & 48) >> 4) + 1;
3839
3840   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3841       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3842
3843   if (num_entries == 0)
3844     goto no_samples;
3845
3846   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3847           value_size + value_size + traf_size + trun_size + sample_size))
3848     goto corrupt_file;
3849
3850   g_free (stream->ra_entries);
3851   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3852   stream->n_ra_entries = num_entries;
3853
3854   for (i = 0; i < num_entries; i++) {
3855     qt_atom_parser_get_offset (&tfra, value_size, &time);
3856     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3857     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3858     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3859     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3860
3861     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3862
3863     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3864         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3865
3866     stream->ra_entries[i].ts = time;
3867     stream->ra_entries[i].moof_offset = moof_offset;
3868
3869     /* don't want to go through the entire file and read all moofs at startup */
3870 #if 0
3871     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3872     if (ret != GST_FLOW_OK)
3873       goto corrupt_file;
3874     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3875         moof_offset, stream);
3876     gst_buffer_unref (buf);
3877 #endif
3878   }
3879
3880   check_update_duration (qtdemux, time);
3881
3882   return TRUE;
3883
3884 /* ERRORS */
3885 unknown_trackid:
3886   {
3887     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3888     return FALSE;
3889   }
3890 corrupt_file:
3891   {
3892     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3893     return FALSE;
3894   }
3895 no_samples:
3896   {
3897     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3898     return FALSE;
3899   }
3900 }
3901
3902 static gboolean
3903 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3904 {
3905   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3906   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3907   GstBuffer *mfro = NULL, *mfra = NULL;
3908   GstFlowReturn flow;
3909   gboolean ret = FALSE;
3910   GNode *mfra_node, *tfra_node;
3911   guint64 mfra_offset = 0;
3912   guint32 fourcc, mfra_size;
3913   gint64 len;
3914
3915   /* query upstream size in bytes */
3916   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3917     goto size_query_failed;
3918
3919   /* mfro box should be at the very end of the file */
3920   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3921   if (flow != GST_FLOW_OK)
3922     goto exit;
3923
3924   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3925
3926   fourcc = QT_FOURCC (mfro_map.data + 4);
3927   if (fourcc != FOURCC_mfro)
3928     goto exit;
3929
3930   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3931   if (mfro_map.size < 16)
3932     goto invalid_mfro_size;
3933
3934   mfra_size = QT_UINT32 (mfro_map.data + 12);
3935   if (mfra_size >= len)
3936     goto invalid_mfra_size;
3937
3938   mfra_offset = len - mfra_size;
3939
3940   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3941       mfra_offset, mfra_size);
3942
3943   /* now get and parse mfra box */
3944   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3945   if (flow != GST_FLOW_OK)
3946     goto broken_file;
3947
3948   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3949
3950   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3951   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3952
3953   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3954
3955   while (tfra_node) {
3956     qtdemux_parse_tfra (qtdemux, tfra_node);
3957     /* iterate all siblings */
3958     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3959   }
3960   g_node_destroy (mfra_node);
3961
3962   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3963   ret = TRUE;
3964
3965 exit:
3966
3967   if (mfro) {
3968     if (mfro_map.memory != NULL)
3969       gst_buffer_unmap (mfro, &mfro_map);
3970     gst_buffer_unref (mfro);
3971   }
3972   if (mfra) {
3973     if (mfra_map.memory != NULL)
3974       gst_buffer_unmap (mfra, &mfra_map);
3975     gst_buffer_unref (mfra);
3976   }
3977   return ret;
3978
3979 /* ERRORS */
3980 size_query_failed:
3981   {
3982     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3983     goto exit;
3984   }
3985 invalid_mfro_size:
3986   {
3987     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3988     goto exit;
3989   }
3990 invalid_mfra_size:
3991   {
3992     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3993     goto exit;
3994   }
3995 broken_file:
3996   {
3997     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3998     goto exit;
3999   }
4000 }
4001
4002 static guint64
4003 add_offset (guint64 offset, guint64 advance)
4004 {
4005   /* Avoid 64-bit overflow by clamping */
4006   if (offset > G_MAXUINT64 - advance)
4007     return G_MAXUINT64;
4008   return offset + advance;
4009 }
4010
4011 static GstFlowReturn
4012 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4013 {
4014   guint64 length = 0;
4015   guint32 fourcc = 0;
4016   GstBuffer *buf = NULL;
4017   GstFlowReturn ret = GST_FLOW_OK;
4018   guint64 cur_offset = qtdemux->offset;
4019   GstMapInfo map;
4020
4021   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4022   if (G_UNLIKELY (ret != GST_FLOW_OK))
4023     goto beach;
4024   gst_buffer_map (buf, &map, GST_MAP_READ);
4025   if (G_LIKELY (map.size >= 8))
4026     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4027   gst_buffer_unmap (buf, &map);
4028   gst_buffer_unref (buf);
4029
4030   /* maybe we already got most we needed, so only consider this eof */
4031   if (G_UNLIKELY (length == 0)) {
4032     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4033         (_("Invalid atom size.")),
4034         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4035             GST_FOURCC_ARGS (fourcc)));
4036     ret = GST_FLOW_EOS;
4037     goto beach;
4038   }
4039
4040   switch (fourcc) {
4041     case FOURCC_moof:
4042       /* record for later parsing when needed */
4043       if (!qtdemux->moof_offset) {
4044         qtdemux->moof_offset = qtdemux->offset;
4045       }
4046       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4047         /* FIXME */
4048       } else {
4049         qtdemux->offset += length;      /* skip moof and keep going */
4050       }
4051       if (qtdemux->got_moov) {
4052         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4053         ret = GST_FLOW_EOS;
4054         goto beach;
4055       }
4056       break;
4057     case FOURCC_mdat:
4058     case FOURCC_free:
4059     case FOURCC_wide:
4060     case FOURCC_PICT:
4061     case FOURCC_pnot:
4062     {
4063       GST_LOG_OBJECT (qtdemux,
4064           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4065           GST_FOURCC_ARGS (fourcc), cur_offset);
4066       qtdemux->offset = add_offset (qtdemux->offset, length);
4067       break;
4068     }
4069     case FOURCC_moov:
4070     {
4071       GstBuffer *moov = NULL;
4072
4073       if (qtdemux->got_moov) {
4074         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4075         qtdemux->offset = add_offset (qtdemux->offset, length);
4076         goto beach;
4077       }
4078
4079       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4080       if (ret != GST_FLOW_OK)
4081         goto beach;
4082       gst_buffer_map (moov, &map, GST_MAP_READ);
4083
4084       if (length != map.size) {
4085         /* Some files have a 'moov' atom at the end of the file which contains
4086          * a terminal 'free' atom where the body of the atom is missing.
4087          * Check for, and permit, this special case.
4088          */
4089         if (map.size >= 8) {
4090           guint8 *final_data = map.data + (map.size - 8);
4091           guint32 final_length = QT_UINT32 (final_data);
4092           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4093
4094           if (final_fourcc == FOURCC_free
4095               && map.size + final_length - 8 == length) {
4096             /* Ok, we've found that special case. Allocate a new buffer with
4097              * that free atom actually present. */
4098             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4099             gst_buffer_fill (newmoov, 0, map.data, map.size);
4100             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4101             gst_buffer_unmap (moov, &map);
4102             gst_buffer_unref (moov);
4103             moov = newmoov;
4104             gst_buffer_map (moov, &map, GST_MAP_READ);
4105           }
4106         }
4107       }
4108
4109       if (length != map.size) {
4110         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4111             (_("This file is incomplete and cannot be played.")),
4112             ("We got less than expected (received %" G_GSIZE_FORMAT
4113                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4114                 (guint) length, cur_offset));
4115         gst_buffer_unmap (moov, &map);
4116         gst_buffer_unref (moov);
4117         ret = GST_FLOW_ERROR;
4118         goto beach;
4119       }
4120       qtdemux->offset += length;
4121
4122       qtdemux_parse_moov (qtdemux, map.data, length);
4123       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4124
4125       qtdemux_parse_tree (qtdemux);
4126       g_node_destroy (qtdemux->moov_node);
4127       gst_buffer_unmap (moov, &map);
4128       gst_buffer_unref (moov);
4129       qtdemux->moov_node = NULL;
4130       qtdemux->got_moov = TRUE;
4131
4132       break;
4133     }
4134     case FOURCC_ftyp:
4135     {
4136       GstBuffer *ftyp = NULL;
4137
4138       /* extract major brand; might come in handy for ISO vs QT issues */
4139       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4140       if (ret != GST_FLOW_OK)
4141         goto beach;
4142       qtdemux->offset += length;
4143       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4144       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4145       gst_buffer_unmap (ftyp, &map);
4146       gst_buffer_unref (ftyp);
4147       break;
4148     }
4149     case FOURCC_uuid:
4150     {
4151       GstBuffer *uuid = NULL;
4152
4153       /* uuid are extension atoms */
4154       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4155       if (ret != GST_FLOW_OK)
4156         goto beach;
4157       qtdemux->offset += length;
4158       gst_buffer_map (uuid, &map, GST_MAP_READ);
4159       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4160       gst_buffer_unmap (uuid, &map);
4161       gst_buffer_unref (uuid);
4162       break;
4163     }
4164     case FOURCC_sidx:
4165     {
4166       GstBuffer *sidx = NULL;
4167       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4168       if (ret != GST_FLOW_OK)
4169         goto beach;
4170       qtdemux->offset += length;
4171       gst_buffer_map (sidx, &map, GST_MAP_READ);
4172       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4173       gst_buffer_unmap (sidx, &map);
4174       gst_buffer_unref (sidx);
4175       break;
4176     }
4177     default:
4178     {
4179       GstBuffer *unknown = NULL;
4180
4181       GST_LOG_OBJECT (qtdemux,
4182           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4183           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4184           cur_offset);
4185       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4186       if (ret != GST_FLOW_OK)
4187         goto beach;
4188       gst_buffer_map (unknown, &map, GST_MAP_READ);
4189       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4190       gst_buffer_unmap (unknown, &map);
4191       gst_buffer_unref (unknown);
4192       qtdemux->offset += length;
4193       break;
4194     }
4195   }
4196
4197 beach:
4198   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4199     /* digested all data, show what we have */
4200     qtdemux_prepare_streams (qtdemux);
4201     ret = qtdemux_expose_streams (qtdemux);
4202
4203     qtdemux->state = QTDEMUX_STATE_MOVIE;
4204     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4205         qtdemux->state);
4206     return ret;
4207   }
4208   return ret;
4209 }
4210
4211 /* Seeks to the previous keyframe of the indexed stream and
4212  * aligns other streams with respect to the keyframe timestamp
4213  * of indexed stream. Only called in case of Reverse Playback
4214  */
4215 static GstFlowReturn
4216 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4217 {
4218   guint8 n = 0;
4219   guint32 seg_idx = 0, k_index = 0;
4220   guint32 ref_seg_idx, ref_k_index;
4221   GstClockTime k_pos = 0, last_stop = 0;
4222   QtDemuxSegment *seg = NULL;
4223   QtDemuxStream *ref_str = NULL;
4224   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4225   guint64 target_ts;
4226
4227   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4228    * and finally align all the other streams on that timestamp with their
4229    * respective keyframes */
4230   for (n = 0; n < qtdemux->n_streams; n++) {
4231     QtDemuxStream *str = qtdemux->streams[n];
4232
4233     /* No candidate yet, take the first stream */
4234     if (!ref_str) {
4235       ref_str = str;
4236       continue;
4237     }
4238
4239     /* So that stream has a segment, we prefer video streams */
4240     if (str->subtype == FOURCC_vide) {
4241       ref_str = str;
4242       break;
4243     }
4244   }
4245
4246   if (G_UNLIKELY (!ref_str)) {
4247     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4248     goto eos;
4249   }
4250
4251   if (G_UNLIKELY (!ref_str->from_sample)) {
4252     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4253     goto eos;
4254   }
4255
4256   /* So that stream has been playing from from_sample to to_sample. We will
4257    * get the timestamp of the previous sample and search for a keyframe before
4258    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4259   if (ref_str->subtype == FOURCC_vide) {
4260     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4261         ref_str->from_sample - 1);
4262   } else {
4263     if (ref_str->from_sample >= 10)
4264       k_index = ref_str->from_sample - 10;
4265     else
4266       k_index = 0;
4267   }
4268
4269   target_ts =
4270       ref_str->samples[k_index].timestamp +
4271       ref_str->samples[k_index].pts_offset;
4272
4273   /* get current segment for that stream */
4274   seg = &ref_str->segments[ref_str->segment_index];
4275   /* Use segment start in original timescale for comparisons */
4276   seg_media_start_mov = seg->trak_media_start;
4277
4278   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4279       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4280       k_index, target_ts, seg_media_start_mov,
4281       GST_TIME_ARGS (seg->media_start));
4282
4283   /* Crawl back through segments to find the one containing this I frame */
4284   while (target_ts < seg_media_start_mov) {
4285     GST_DEBUG_OBJECT (qtdemux,
4286         "keyframe position (sample %u) is out of segment %u " " target %"
4287         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4288         ref_str->segment_index, target_ts, seg_media_start_mov);
4289
4290     if (G_UNLIKELY (!ref_str->segment_index)) {
4291       /* Reached first segment, let's consider it's EOS */
4292       goto eos;
4293     }
4294     ref_str->segment_index--;
4295     seg = &ref_str->segments[ref_str->segment_index];
4296     /* Use segment start in original timescale for comparisons */
4297     seg_media_start_mov = seg->trak_media_start;
4298   }
4299   /* Calculate time position of the keyframe and where we should stop */
4300   k_pos =
4301       QTSTREAMTIME_TO_GSTTIME (ref_str,
4302       target_ts - seg->trak_media_start) + seg->time;
4303   last_stop =
4304       QTSTREAMTIME_TO_GSTTIME (ref_str,
4305       ref_str->samples[ref_str->from_sample].timestamp -
4306       seg->trak_media_start) + seg->time;
4307
4308   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4309       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4310       k_index, GST_TIME_ARGS (k_pos));
4311
4312   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4313   qtdemux->segment.position = last_stop;
4314   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4315       GST_TIME_ARGS (last_stop));
4316
4317   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4318     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4319     goto eos;
4320   }
4321
4322   ref_seg_idx = ref_str->segment_index;
4323   ref_k_index = k_index;
4324
4325   /* Align them all on this */
4326   for (n = 0; n < qtdemux->n_streams; n++) {
4327     guint32 index = 0;
4328     GstClockTime seg_time = 0;
4329     QtDemuxStream *str = qtdemux->streams[n];
4330
4331     /* aligning reference stream again might lead to backing up to yet another
4332      * keyframe (due to timestamp rounding issues),
4333      * potentially putting more load on downstream; so let's try to avoid */
4334     if (str == ref_str) {
4335       seg_idx = ref_seg_idx;
4336       seg = &str->segments[seg_idx];
4337       k_index = ref_k_index;
4338       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4339           "sample at index %d", n, ref_str->segment_index, k_index);
4340     } else {
4341       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4342       GST_DEBUG_OBJECT (qtdemux,
4343           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4344           seg_idx, GST_TIME_ARGS (k_pos));
4345
4346       /* get segment and time in the segment */
4347       seg = &str->segments[seg_idx];
4348       seg_time = k_pos - seg->time;
4349
4350       /* get the media time in the segment.
4351        * No adjustment for empty "filler" segments */
4352       if (seg->media_start != GST_CLOCK_TIME_NONE)
4353         seg_time += seg->media_start;
4354
4355       /* get the index of the sample with media time */
4356       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4357       GST_DEBUG_OBJECT (qtdemux,
4358           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4359           GST_TIME_ARGS (seg_time), index);
4360
4361       /* find previous keyframe */
4362       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4363     }
4364
4365     /* Remember until where we want to go */
4366     str->to_sample = str->from_sample - 1;
4367     /* Define our time position */
4368     target_ts =
4369         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4370     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4371     if (seg->media_start != GST_CLOCK_TIME_NONE)
4372       str->time_position -= seg->media_start;
4373
4374     /* Now seek back in time */
4375     gst_qtdemux_move_stream (qtdemux, str, k_index);
4376     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4377         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4378         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4379   }
4380
4381   return GST_FLOW_OK;
4382
4383 eos:
4384   return GST_FLOW_EOS;
4385 }
4386
4387 /*
4388  * Gets the current qt segment start, stop and position for the
4389  * given time offset. This is used in update_segment()
4390  */
4391 static void
4392 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4393     QtDemuxStream * stream, GstClockTime offset,
4394     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4395 {
4396   GstClockTime seg_time;
4397   GstClockTime start, stop, time;
4398   QtDemuxSegment *segment;
4399
4400   segment = &stream->segments[stream->segment_index];
4401
4402   /* get time in this segment */
4403   seg_time = (offset - segment->time) * segment->rate;
4404
4405   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4406       GST_TIME_ARGS (seg_time));
4407
4408   if (G_UNLIKELY (seg_time > segment->duration)) {
4409     GST_LOG_OBJECT (stream->pad,
4410         "seg_time > segment->duration %" GST_TIME_FORMAT,
4411         GST_TIME_ARGS (segment->duration));
4412     seg_time = segment->duration;
4413   }
4414
4415   /* qtdemux->segment.stop is in outside-time-realm, whereas
4416    * segment->media_stop is in track-time-realm.
4417    *
4418    * In order to compare the two, we need to bring segment.stop
4419    * into the track-time-realm
4420    *
4421    * FIXME - does this comment still hold? Don't see any conversion here */
4422
4423   stop = qtdemux->segment.stop;
4424   if (stop == GST_CLOCK_TIME_NONE)
4425     stop = qtdemux->segment.duration;
4426   if (stop == GST_CLOCK_TIME_NONE)
4427     stop = segment->media_stop;
4428   else
4429     stop =
4430         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4431
4432   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4433     start = segment->time + seg_time;
4434     time = offset;
4435     stop = start - seg_time + segment->duration;
4436   } else if (qtdemux->segment.rate >= 0) {
4437     start = MIN (segment->media_start + seg_time, stop);
4438     time = offset;
4439   } else {
4440     if (segment->media_start >= qtdemux->segment.start) {
4441       time = segment->time;
4442     } else {
4443       time = segment->time + (qtdemux->segment.start - segment->media_start);
4444     }
4445
4446     start = MAX (segment->media_start, qtdemux->segment.start);
4447     stop = MIN (segment->media_start + seg_time, stop);
4448   }
4449
4450   *_start = start;
4451   *_stop = stop;
4452   *_time = time;
4453 }
4454
4455 /*
4456  * Updates the qt segment used for the stream and pushes a new segment event
4457  * downstream on this stream's pad.
4458  */
4459 static gboolean
4460 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4461     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4462     GstClockTime * _stop)
4463 {
4464   QtDemuxSegment *segment;
4465   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4466   gdouble rate;
4467   GstEvent *event;
4468
4469   /* update the current segment */
4470   stream->segment_index = seg_idx;
4471
4472   /* get the segment */
4473   segment = &stream->segments[seg_idx];
4474
4475   if (G_UNLIKELY (offset < segment->time)) {
4476     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4477         GST_TIME_ARGS (segment->time));
4478     return FALSE;
4479   }
4480
4481   /* segment lies beyond total indicated duration */
4482   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4483           segment->time > qtdemux->segment.duration)) {
4484     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4485         " < segment->time %" GST_TIME_FORMAT,
4486         GST_TIME_ARGS (qtdemux->segment.duration),
4487         GST_TIME_ARGS (segment->time));
4488     return FALSE;
4489   }
4490
4491   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4492       &start, &stop, &time);
4493
4494   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4495       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4496       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4497
4498   /* combine global rate with that of the segment */
4499   rate = segment->rate * qtdemux->segment.rate;
4500
4501   /* Copy flags from main segment */
4502   stream->segment.flags = qtdemux->segment.flags;
4503
4504   /* update the segment values used for clipping */
4505   stream->segment.offset = qtdemux->segment.offset;
4506   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4507   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4508   stream->segment.rate = rate;
4509   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4510       stream->cslg_shift);
4511   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4512       stream->cslg_shift);
4513   stream->segment.time = time;
4514   stream->segment.position = stream->segment.start;
4515
4516   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4517       &stream->segment);
4518
4519   /* now prepare and send the segment */
4520   if (stream->pad) {
4521     event = gst_event_new_segment (&stream->segment);
4522     if (qtdemux->segment_seqnum) {
4523       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4524     }
4525     gst_pad_push_event (stream->pad, event);
4526     /* assume we can send more data now */
4527     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4528     /* clear to send tags on this pad now */
4529     gst_qtdemux_push_tags (qtdemux, stream);
4530   }
4531
4532   if (_start)
4533     *_start = start;
4534   if (_stop)
4535     *_stop = stop;
4536
4537   return TRUE;
4538 }
4539
4540 /* activate the given segment number @seg_idx of @stream at time @offset.
4541  * @offset is an absolute global position over all the segments.
4542  *
4543  * This will push out a NEWSEGMENT event with the right values and
4544  * position the stream index to the first decodable sample before
4545  * @offset.
4546  */
4547 static gboolean
4548 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4549     guint32 seg_idx, GstClockTime offset)
4550 {
4551   QtDemuxSegment *segment;
4552   guint32 index, kf_index;
4553   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4554
4555   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4556       seg_idx, GST_TIME_ARGS (offset));
4557
4558   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4559           &start, &stop))
4560     return FALSE;
4561
4562   segment = &stream->segments[stream->segment_index];
4563
4564   /* in the fragmented case, we pick a fragment that starts before our
4565    * desired position and rely on downstream to wait for a keyframe
4566    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4567    * tfra entries tells us which trun/sample the key unit is in, but we don't
4568    * make use of this additional information at the moment) */
4569   if (qtdemux->fragmented) {
4570     stream->to_sample = G_MAXUINT32;
4571     return TRUE;
4572   }
4573
4574   /* We don't need to look for a sample in push-based */
4575   if (!qtdemux->pullbased)
4576     return TRUE;
4577
4578   /* and move to the keyframe before the indicated media time of the
4579    * segment */
4580   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4581     if (qtdemux->segment.rate >= 0) {
4582       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4583       stream->to_sample = G_MAXUINT32;
4584       GST_DEBUG_OBJECT (stream->pad,
4585           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4586           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4587           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4588     } else {
4589       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4590       stream->to_sample = index;
4591       GST_DEBUG_OBJECT (stream->pad,
4592           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4593           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4594           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4595     }
4596   } else {
4597     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4598         "this is an empty segment");
4599     return TRUE;
4600   }
4601
4602   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4603    * encountered an error and printed a message so we return appropriately */
4604   if (index == -1)
4605     return FALSE;
4606
4607   /* we're at the right spot */
4608   if (index == stream->sample_index) {
4609     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4610     return TRUE;
4611   }
4612
4613   /* find keyframe of the target index */
4614   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4615
4616 /* *INDENT-OFF* */
4617 /* indent does stupid stuff with stream->samples[].timestamp */
4618
4619   /* if we move forwards, we don't have to go back to the previous
4620    * keyframe since we already sent that. We can also just jump to
4621    * the keyframe right before the target index if there is one. */
4622   if (index > stream->sample_index) {
4623     /* moving forwards check if we move past a keyframe */
4624     if (kf_index > stream->sample_index) {
4625       GST_DEBUG_OBJECT (stream->pad,
4626            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4627            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4628            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4629       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4630     } else {
4631       GST_DEBUG_OBJECT (stream->pad,
4632           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4633           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4634           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4635     }
4636   } else {
4637     GST_DEBUG_OBJECT (stream->pad,
4638         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4639         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4640         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4641     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4642   }
4643
4644 /* *INDENT-ON* */
4645
4646   return TRUE;
4647 }
4648
4649 /* prepare to get the current sample of @stream, getting essential values.
4650  *
4651  * This function will also prepare and send the segment when needed.
4652  *
4653  * Return FALSE if the stream is EOS.
4654  *
4655  * PULL-BASED
4656  */
4657 static gboolean
4658 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4659     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4660     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4661     gboolean * keyframe)
4662 {
4663   QtDemuxSample *sample;
4664   GstClockTime time_position;
4665   guint32 seg_idx;
4666
4667   g_return_val_if_fail (stream != NULL, FALSE);
4668
4669   time_position = stream->time_position;
4670   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4671     goto eos;
4672
4673   seg_idx = stream->segment_index;
4674   if (G_UNLIKELY (seg_idx == -1)) {
4675     /* find segment corresponding to time_position if we are looking
4676      * for a segment. */
4677     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4678   }
4679
4680   /* different segment, activate it, sample_index will be set. */
4681   if (G_UNLIKELY (stream->segment_index != seg_idx))
4682     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4683
4684   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4685                   segment_index]))) {
4686     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4687
4688     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4689         " prepare empty sample");
4690
4691     *empty = TRUE;
4692     *pts = *dts = time_position;
4693     *duration = seg->duration - (time_position - seg->time);
4694
4695     return TRUE;
4696   }
4697
4698   *empty = FALSE;
4699
4700   if (stream->sample_index == -1)
4701     stream->sample_index = 0;
4702
4703   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4704       stream->sample_index, stream->n_samples);
4705
4706   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4707     if (!qtdemux->fragmented)
4708       goto eos;
4709
4710     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4711     do {
4712       GstFlowReturn flow;
4713
4714       GST_OBJECT_LOCK (qtdemux);
4715       flow = qtdemux_add_fragmented_samples (qtdemux);
4716       GST_OBJECT_UNLOCK (qtdemux);
4717
4718       if (flow != GST_FLOW_OK)
4719         goto eos;
4720     }
4721     while (stream->sample_index >= stream->n_samples);
4722   }
4723
4724   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4725     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4726         stream->sample_index);
4727     return FALSE;
4728   }
4729
4730   /* now get the info for the sample we're at */
4731   sample = &stream->samples[stream->sample_index];
4732
4733   *dts = QTSAMPLE_DTS (stream, sample);
4734   *pts = QTSAMPLE_PTS (stream, sample);
4735   *offset = sample->offset;
4736   *size = sample->size;
4737   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4738   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4739
4740   return TRUE;
4741
4742   /* special cases */
4743 eos:
4744   {
4745     stream->time_position = GST_CLOCK_TIME_NONE;
4746     return FALSE;
4747   }
4748 }
4749
4750 /* move to the next sample in @stream.
4751  *
4752  * Moves to the next segment when needed.
4753  */
4754 static void
4755 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4756 {
4757   QtDemuxSample *sample;
4758   QtDemuxSegment *segment;
4759
4760   /* get current segment */
4761   segment = &stream->segments[stream->segment_index];
4762
4763   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4764     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4765     goto next_segment;
4766   }
4767
4768   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4769     /* Mark the stream as EOS */
4770     GST_DEBUG_OBJECT (qtdemux,
4771         "reached max allowed sample %u, mark EOS", stream->to_sample);
4772     stream->time_position = GST_CLOCK_TIME_NONE;
4773     return;
4774   }
4775
4776   /* move to next sample */
4777   stream->sample_index++;
4778   stream->offset_in_sample = 0;
4779
4780   /* reached the last sample, we need the next segment */
4781   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4782     goto next_segment;
4783
4784   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4785     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4786         stream->sample_index);
4787     return;
4788   }
4789
4790   /* get next sample */
4791   sample = &stream->samples[stream->sample_index];
4792
4793   /* see if we are past the segment */
4794   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4795     goto next_segment;
4796
4797   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4798     /* inside the segment, update time_position, looks very familiar to
4799      * GStreamer segments, doesn't it? */
4800     stream->time_position =
4801         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4802   } else {
4803     /* not yet in segment, time does not yet increment. This means
4804      * that we are still prerolling keyframes to the decoder so it can
4805      * decode the first sample of the segment. */
4806     stream->time_position = segment->time;
4807   }
4808   return;
4809
4810   /* move to the next segment */
4811 next_segment:
4812   {
4813     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4814
4815     if (stream->segment_index == stream->n_segments - 1) {
4816       /* are we at the end of the last segment, we're EOS */
4817       stream->time_position = GST_CLOCK_TIME_NONE;
4818     } else {
4819       /* else we're only at the end of the current segment */
4820       stream->time_position = segment->stop_time;
4821     }
4822     /* make sure we select a new segment */
4823
4824     /* accumulate previous segments */
4825     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4826       stream->accumulated_base +=
4827           (stream->segment.stop -
4828           stream->segment.start) / ABS (stream->segment.rate);
4829
4830     stream->segment_index = -1;
4831   }
4832 }
4833
4834 static void
4835 gst_qtdemux_sync_streams (GstQTDemux * demux)
4836 {
4837   gint i;
4838
4839   if (demux->n_streams <= 1)
4840     return;
4841
4842   for (i = 0; i < demux->n_streams; i++) {
4843     QtDemuxStream *stream;
4844     GstClockTime end_time;
4845
4846     stream = demux->streams[i];
4847
4848     if (!stream->pad)
4849       continue;
4850
4851     /* TODO advance time on subtitle streams here, if any some day */
4852
4853     /* some clips/trailers may have unbalanced streams at the end,
4854      * so send EOS on shorter stream to prevent stalling others */
4855
4856     /* do not mess with EOS if SEGMENT seeking */
4857     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4858       continue;
4859
4860     if (demux->pullbased) {
4861       /* loop mode is sample time based */
4862       if (!STREAM_IS_EOS (stream))
4863         continue;
4864     } else {
4865       /* push mode is byte position based */
4866       if (stream->n_samples &&
4867           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4868         continue;
4869     }
4870
4871     if (stream->sent_eos)
4872       continue;
4873
4874     /* only act if some gap */
4875     end_time = stream->segments[stream->n_segments - 1].stop_time;
4876     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4877         ", stream end: %" GST_TIME_FORMAT,
4878         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4879     if (GST_CLOCK_TIME_IS_VALID (end_time)
4880         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4881       GstEvent *event;
4882
4883       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4884           GST_PAD_NAME (stream->pad));
4885       stream->sent_eos = TRUE;
4886       event = gst_event_new_eos ();
4887       if (demux->segment_seqnum)
4888         gst_event_set_seqnum (event, demux->segment_seqnum);
4889       gst_pad_push_event (stream->pad, event);
4890     }
4891   }
4892 }
4893
4894 /* EOS and NOT_LINKED need to be combined. This means that we return:
4895  *
4896  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4897  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4898  */
4899 static GstFlowReturn
4900 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4901     GstFlowReturn ret)
4902 {
4903   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4904
4905   if (stream->pad)
4906     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4907         ret);
4908   else
4909     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4910
4911   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4912   return ret;
4913 }
4914
4915 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4916  * completely clipped
4917  *
4918  * Should be used only with raw buffers */
4919 static GstBuffer *
4920 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4921     GstBuffer * buf)
4922 {
4923   guint64 start, stop, cstart, cstop, diff;
4924   GstClockTime pts, duration;
4925   gsize size, osize;
4926   gint num_rate, denom_rate;
4927   gint frame_size;
4928   gboolean clip_data;
4929   guint offset;
4930
4931   osize = size = gst_buffer_get_size (buf);
4932   offset = 0;
4933
4934   /* depending on the type, setup the clip parameters */
4935   if (stream->subtype == FOURCC_soun) {
4936     frame_size = stream->bytes_per_frame;
4937     num_rate = GST_SECOND;
4938     denom_rate = (gint) stream->rate;
4939     clip_data = TRUE;
4940   } else if (stream->subtype == FOURCC_vide) {
4941     frame_size = size;
4942     num_rate = stream->fps_n;
4943     denom_rate = stream->fps_d;
4944     clip_data = FALSE;
4945   } else
4946     goto wrong_type;
4947
4948   if (frame_size <= 0)
4949     goto bad_frame_size;
4950
4951   /* we can only clip if we have a valid pts */
4952   pts = GST_BUFFER_PTS (buf);
4953   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4954     goto no_pts;
4955
4956   duration = GST_BUFFER_DURATION (buf);
4957
4958   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4959     duration =
4960         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4961   }
4962
4963   start = pts;
4964   stop = start + duration;
4965
4966   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4967               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4968     goto clipped;
4969
4970   /* see if some clipping happened */
4971   diff = cstart - start;
4972   if (diff > 0) {
4973     pts += diff;
4974     duration -= diff;
4975
4976     if (clip_data) {
4977       /* bring clipped time to samples and to bytes */
4978       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4979       diff *= frame_size;
4980
4981       GST_DEBUG_OBJECT (qtdemux,
4982           "clipping start to %" GST_TIME_FORMAT " %"
4983           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4984
4985       offset = diff;
4986       size -= diff;
4987     }
4988   }
4989   diff = stop - cstop;
4990   if (diff > 0) {
4991     duration -= diff;
4992
4993     if (clip_data) {
4994       /* bring clipped time to samples and then to bytes */
4995       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4996       diff *= frame_size;
4997       GST_DEBUG_OBJECT (qtdemux,
4998           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4999           " bytes", GST_TIME_ARGS (cstop), diff);
5000       size -= diff;
5001     }
5002   }
5003
5004   if (offset != 0 || size != osize)
5005     gst_buffer_resize (buf, offset, size);
5006
5007   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5008   GST_BUFFER_PTS (buf) = pts;
5009   GST_BUFFER_DURATION (buf) = duration;
5010
5011   return buf;
5012
5013   /* dropped buffer */
5014 wrong_type:
5015   {
5016     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5017     return buf;
5018   }
5019 bad_frame_size:
5020   {
5021     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5022     return buf;
5023   }
5024 no_pts:
5025   {
5026     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5027     return buf;
5028   }
5029 clipped:
5030   {
5031     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5032     gst_buffer_unref (buf);
5033     return NULL;
5034   }
5035 }
5036
5037 /* the input buffer metadata must be writable,
5038  * but time/duration etc not yet set and need not be preserved */
5039 static GstBuffer *
5040 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5041     GstBuffer * buf)
5042 {
5043   GstMapInfo map;
5044   guint nsize = 0;
5045   gchar *str;
5046
5047   /* not many cases for now */
5048   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5049     /* send a one time dvd clut event */
5050     if (stream->pending_event && stream->pad)
5051       gst_pad_push_event (stream->pad, stream->pending_event);
5052     stream->pending_event = NULL;
5053   }
5054
5055   if (G_UNLIKELY (stream->subtype != FOURCC_text
5056           && stream->subtype != FOURCC_sbtl &&
5057           stream->subtype != FOURCC_subp)) {
5058     return buf;
5059   }
5060
5061   gst_buffer_map (buf, &map, GST_MAP_READ);
5062
5063   /* empty buffer is sent to terminate previous subtitle */
5064   if (map.size <= 2) {
5065     gst_buffer_unmap (buf, &map);
5066     gst_buffer_unref (buf);
5067     return NULL;
5068   }
5069   if (stream->subtype == FOURCC_subp) {
5070     /* That's all the processing needed for subpictures */
5071     gst_buffer_unmap (buf, &map);
5072     return buf;
5073   }
5074
5075   nsize = GST_READ_UINT16_BE (map.data);
5076   nsize = MIN (nsize, map.size - 2);
5077
5078   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5079       nsize, map.size);
5080
5081   /* takes care of UTF-8 validation or UTF-16 recognition,
5082    * no other encoding expected */
5083   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5084   gst_buffer_unmap (buf, &map);
5085   if (str) {
5086     gst_buffer_unref (buf);
5087     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5088   } else {
5089     /* this should not really happen unless the subtitle is corrupted */
5090     gst_buffer_unref (buf);
5091     buf = NULL;
5092   }
5093
5094   /* FIXME ? convert optional subsequent style info to markup */
5095
5096   return buf;
5097 }
5098
5099 /* Sets a buffer's attributes properly and pushes it downstream.
5100  * Also checks for additional actions and custom processing that may
5101  * need to be done first.
5102  */
5103 static GstFlowReturn
5104 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5105     QtDemuxStream * stream, GstBuffer * buf,
5106     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5107     gboolean keyframe, GstClockTime position, guint64 byte_position)
5108 {
5109   GstFlowReturn ret = GST_FLOW_OK;
5110
5111   /* offset the timestamps according to the edit list */
5112
5113   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5114     gchar *url;
5115     GstMapInfo map;
5116
5117     gst_buffer_map (buf, &map, GST_MAP_READ);
5118     url = g_strndup ((gchar *) map.data, map.size);
5119     gst_buffer_unmap (buf, &map);
5120     if (url != NULL && strlen (url) != 0) {
5121       /* we have RTSP redirect now */
5122       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5123           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5124               gst_structure_new ("redirect",
5125                   "new-location", G_TYPE_STRING, url, NULL)));
5126       qtdemux->posted_redirect = TRUE;
5127     } else {
5128       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5129           "posting");
5130     }
5131     g_free (url);
5132   }
5133
5134   /* position reporting */
5135   if (qtdemux->segment.rate >= 0) {
5136     qtdemux->segment.position = position;
5137     gst_qtdemux_sync_streams (qtdemux);
5138   }
5139
5140   if (G_UNLIKELY (!stream->pad)) {
5141     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5142     gst_buffer_unref (buf);
5143     goto exit;
5144   }
5145
5146   /* send out pending buffers */
5147   while (stream->buffers) {
5148     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5149
5150     if (G_UNLIKELY (stream->discont)) {
5151       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5152       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5153       stream->discont = FALSE;
5154     } else {
5155       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5156     }
5157
5158     gst_pad_push (stream->pad, buffer);
5159
5160     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5161   }
5162
5163   /* we're going to modify the metadata */
5164   buf = gst_buffer_make_writable (buf);
5165
5166   if (G_UNLIKELY (stream->need_process))
5167     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5168
5169   if (!buf) {
5170     goto exit;
5171   }
5172
5173   GST_BUFFER_DTS (buf) = dts;
5174   GST_BUFFER_PTS (buf) = pts;
5175   GST_BUFFER_DURATION (buf) = duration;
5176   GST_BUFFER_OFFSET (buf) = -1;
5177   GST_BUFFER_OFFSET_END (buf) = -1;
5178
5179   if (G_UNLIKELY (stream->rgb8_palette))
5180     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5181
5182   if (G_UNLIKELY (stream->padding)) {
5183     gst_buffer_resize (buf, stream->padding, -1);
5184   }
5185 #if 0
5186   if (G_UNLIKELY (qtdemux->element_index)) {
5187     GstClockTime stream_time;
5188
5189     stream_time =
5190         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5191         timestamp);
5192     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5193       GST_LOG_OBJECT (qtdemux,
5194           "adding association %" GST_TIME_FORMAT "-> %"
5195           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5196       gst_index_add_association (qtdemux->element_index,
5197           qtdemux->index_id,
5198           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5199           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5200           GST_FORMAT_BYTES, byte_position, NULL);
5201     }
5202   }
5203 #endif
5204
5205   if (stream->need_clip)
5206     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5207
5208   if (G_UNLIKELY (buf == NULL))
5209     goto exit;
5210
5211   if (G_UNLIKELY (stream->discont)) {
5212     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5213     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5214     stream->discont = FALSE;
5215   } else {
5216     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5217   }
5218
5219   if (!keyframe) {
5220     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5221     stream->on_keyframe = FALSE;
5222   } else {
5223     stream->on_keyframe = TRUE;
5224   }
5225
5226
5227   GST_LOG_OBJECT (qtdemux,
5228       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5229       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5230       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5231       GST_PAD_NAME (stream->pad));
5232
5233   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5234     GstStructure *crypto_info;
5235     QtDemuxCencSampleSetInfo *info =
5236         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5237     gint index;
5238     GstEvent *event;
5239
5240     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5241       gst_pad_push_event (stream->pad, event);
5242     }
5243
5244     if (qtdemux->cenc_aux_info_offset > 0 && info->crypto_info == NULL) {
5245       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5246       gst_buffer_unref (buf);
5247       goto exit;
5248     }
5249
5250     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5251     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5252       /* steal structure from array */
5253       crypto_info = g_ptr_array_index (info->crypto_info, index);
5254       g_ptr_array_index (info->crypto_info, index) = NULL;
5255       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5256       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5257         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5258     }
5259   }
5260
5261   ret = gst_pad_push (stream->pad, buf);
5262
5263   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5264     /* mark position in stream, we'll need this to know when to send GAP event */
5265     stream->segment.position = pts + duration;
5266   }
5267
5268 exit:
5269   return ret;
5270 }
5271
5272 static const QtDemuxRandomAccessEntry *
5273 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5274     GstClockTime pos, gboolean after)
5275 {
5276   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5277   guint n_entries = stream->n_ra_entries;
5278   guint i;
5279
5280   /* we assume the table is sorted */
5281   for (i = 0; i < n_entries; ++i) {
5282     if (entries[i].ts > pos)
5283       break;
5284   }
5285
5286   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5287    * probably okay to assume that the index lists the very first fragment */
5288   if (i == 0)
5289     return &entries[0];
5290
5291   if (after)
5292     return &entries[i];
5293   else
5294     return &entries[i - 1];
5295 }
5296
5297 static gboolean
5298 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5299 {
5300   const QtDemuxRandomAccessEntry *best_entry = NULL;
5301   guint i;
5302
5303   GST_OBJECT_LOCK (qtdemux);
5304
5305   g_assert (qtdemux->n_streams > 0);
5306
5307   for (i = 0; i < qtdemux->n_streams; i++) {
5308     const QtDemuxRandomAccessEntry *entry;
5309     QtDemuxStream *stream;
5310     gboolean is_audio_or_video;
5311
5312     stream = qtdemux->streams[i];
5313
5314     g_free (stream->samples);
5315     stream->samples = NULL;
5316     stream->n_samples = 0;
5317     stream->stbl_index = -1;    /* no samples have yet been parsed */
5318     stream->sample_index = -1;
5319
5320     if (stream->ra_entries == NULL)
5321       continue;
5322
5323     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5324       is_audio_or_video = TRUE;
5325     else
5326       is_audio_or_video = FALSE;
5327
5328     entry =
5329         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5330         stream->time_position, !is_audio_or_video);
5331
5332     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5333         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5334
5335     stream->pending_seek = entry;
5336
5337     /* decide position to jump to just based on audio/video tracks, not subs */
5338     if (!is_audio_or_video)
5339       continue;
5340
5341     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5342       best_entry = entry;
5343   }
5344
5345   if (best_entry == NULL) {
5346     GST_OBJECT_UNLOCK (qtdemux);
5347     return FALSE;
5348   }
5349
5350   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5351       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5352       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5353       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5354
5355   qtdemux->moof_offset = best_entry->moof_offset;
5356
5357   qtdemux_add_fragmented_samples (qtdemux);
5358
5359   GST_OBJECT_UNLOCK (qtdemux);
5360   return TRUE;
5361 }
5362
5363 static GstFlowReturn
5364 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5365 {
5366   GstFlowReturn ret = GST_FLOW_OK;
5367   GstBuffer *buf = NULL;
5368   QtDemuxStream *stream;
5369   GstClockTime min_time;
5370   guint64 offset = 0;
5371   GstClockTime dts = GST_CLOCK_TIME_NONE;
5372   GstClockTime pts = GST_CLOCK_TIME_NONE;
5373   GstClockTime duration = 0;
5374   gboolean keyframe = FALSE;
5375   guint sample_size = 0;
5376   gboolean empty = 0;
5377   guint size;
5378   gint index;
5379   gint i;
5380
5381   gst_qtdemux_push_pending_newsegment (qtdemux);
5382
5383   if (qtdemux->fragmented_seek_pending) {
5384     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5385     gst_qtdemux_do_fragmented_seek (qtdemux);
5386     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5387     qtdemux->fragmented_seek_pending = FALSE;
5388   }
5389
5390   /* Figure out the next stream sample to output, min_time is expressed in
5391    * global time and runs over the edit list segments. */
5392   min_time = G_MAXUINT64;
5393   index = -1;
5394   for (i = 0; i < qtdemux->n_streams; i++) {
5395     GstClockTime position;
5396
5397     stream = qtdemux->streams[i];
5398     position = stream->time_position;
5399
5400     /* position of -1 is EOS */
5401     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5402       min_time = position;
5403       index = i;
5404     }
5405   }
5406   /* all are EOS */
5407   if (G_UNLIKELY (index == -1)) {
5408     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5409     goto eos;
5410   }
5411
5412   /* check for segment end */
5413   if (G_UNLIKELY (qtdemux->segment.stop != -1
5414           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5415               || (qtdemux->segment.rate < 0
5416                   && qtdemux->segment.start > min_time))
5417           && qtdemux->streams[index]->on_keyframe)) {
5418     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5419     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5420     goto eos_stream;
5421   }
5422
5423   /* gap events for subtitle streams */
5424   for (i = 0; i < qtdemux->n_streams; i++) {
5425     stream = qtdemux->streams[i];
5426     if (stream->pad && (stream->subtype == FOURCC_subp
5427             || stream->subtype == FOURCC_text
5428             || stream->subtype == FOURCC_sbtl)) {
5429       /* send one second gap events until the stream catches up */
5430       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5431       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5432           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5433           stream->segment.position + GST_SECOND < min_time) {
5434         GstEvent *gap =
5435             gst_event_new_gap (stream->segment.position, GST_SECOND);
5436         gst_pad_push_event (stream->pad, gap);
5437         stream->segment.position += GST_SECOND;
5438       }
5439     }
5440   }
5441
5442   stream = qtdemux->streams[index];
5443   if (stream->new_caps) {
5444     gst_qtdemux_configure_stream (qtdemux, stream);
5445     qtdemux_do_allocation (qtdemux, stream);
5446   }
5447
5448   /* fetch info for the current sample of this stream */
5449   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5450               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5451     goto eos_stream;
5452
5453   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5454   if (G_UNLIKELY (qtdemux->
5455           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5456     if (stream->subtype == FOURCC_vide && !keyframe) {
5457       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5458       goto next;
5459     }
5460   }
5461
5462   GST_DEBUG_OBJECT (qtdemux,
5463       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5464       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5465       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5466       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5467
5468   if (G_UNLIKELY (empty)) {
5469     /* empty segment, push a gap and move to the next one */
5470     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5471     stream->segment.position = pts + duration;
5472     goto next;
5473   }
5474
5475   /* hmm, empty sample, skip and move to next sample */
5476   if (G_UNLIKELY (sample_size <= 0))
5477     goto next;
5478
5479   /* last pushed sample was out of boundary, goto next sample */
5480   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5481     goto next;
5482
5483   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5484     size = sample_size;
5485   } else {
5486     GST_DEBUG_OBJECT (qtdemux,
5487         "size %d larger than stream max_buffer_size %d, trimming",
5488         sample_size, stream->max_buffer_size);
5489     size =
5490         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5491   }
5492
5493   if (qtdemux->cenc_aux_info_offset > 0) {
5494     GstMapInfo map;
5495     GstByteReader br;
5496     GstBuffer *aux_info = NULL;
5497
5498     /* pull the data stored before the sample */
5499     ret =
5500         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5501         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5502     if (G_UNLIKELY (ret != GST_FLOW_OK))
5503       goto beach;
5504     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5505     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5506     gst_byte_reader_init (&br, map.data + 8, map.size);
5507     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5508             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5509       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5510       gst_buffer_unmap (aux_info, &map);
5511       gst_buffer_unref (aux_info);
5512       ret = GST_FLOW_ERROR;
5513       goto beach;
5514     }
5515     gst_buffer_unmap (aux_info, &map);
5516     gst_buffer_unref (aux_info);
5517   }
5518
5519   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5520       offset);
5521
5522   if (stream->use_allocator) {
5523     /* if we have a per-stream allocator, use it */
5524     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5525   }
5526
5527   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5528       size, &buf);
5529   if (G_UNLIKELY (ret != GST_FLOW_OK))
5530     goto beach;
5531
5532   if (size != sample_size) {
5533     pts += gst_util_uint64_scale_int (GST_SECOND,
5534         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5535     dts += gst_util_uint64_scale_int (GST_SECOND,
5536         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5537     duration = gst_util_uint64_scale_int (GST_SECOND,
5538         size / stream->bytes_per_frame, stream->timescale);
5539   }
5540
5541   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5542       dts, pts, duration, keyframe, min_time, offset);
5543
5544   if (size != sample_size) {
5545     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5546     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5547
5548     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5549         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5550     if (time_position >= segment->media_start) {
5551       /* inside the segment, update time_position, looks very familiar to
5552        * GStreamer segments, doesn't it? */
5553       stream->time_position = (time_position - segment->media_start) +
5554           segment->time;
5555     } else {
5556       /* not yet in segment, time does not yet increment. This means
5557        * that we are still prerolling keyframes to the decoder so it can
5558        * decode the first sample of the segment. */
5559       stream->time_position = segment->time;
5560     }
5561   }
5562
5563   /* combine flows */
5564   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5565   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5566    * we have no more data for the pad to push */
5567   if (ret == GST_FLOW_EOS)
5568     ret = GST_FLOW_OK;
5569
5570   stream->offset_in_sample += size;
5571   if (stream->offset_in_sample >= sample_size) {
5572     gst_qtdemux_advance_sample (qtdemux, stream);
5573   }
5574   goto beach;
5575
5576 next:
5577   gst_qtdemux_advance_sample (qtdemux, stream);
5578
5579 beach:
5580   return ret;
5581
5582   /* special cases */
5583 eos:
5584   {
5585     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5586     ret = GST_FLOW_EOS;
5587     goto beach;
5588   }
5589 eos_stream:
5590   {
5591     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5592     /* EOS will be raised if all are EOS */
5593     ret = GST_FLOW_OK;
5594     goto beach;
5595   }
5596 }
5597
5598 static void
5599 gst_qtdemux_loop (GstPad * pad)
5600 {
5601   GstQTDemux *qtdemux;
5602   guint64 cur_offset;
5603   GstFlowReturn ret;
5604
5605   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5606
5607   cur_offset = qtdemux->offset;
5608   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5609       cur_offset, qtdemux->state);
5610
5611   switch (qtdemux->state) {
5612     case QTDEMUX_STATE_INITIAL:
5613     case QTDEMUX_STATE_HEADER:
5614       ret = gst_qtdemux_loop_state_header (qtdemux);
5615       break;
5616     case QTDEMUX_STATE_MOVIE:
5617       ret = gst_qtdemux_loop_state_movie (qtdemux);
5618       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5619         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5620       }
5621       break;
5622     default:
5623       /* ouch */
5624       goto invalid_state;
5625   }
5626
5627   /* if something went wrong, pause */
5628   if (ret != GST_FLOW_OK)
5629     goto pause;
5630
5631 done:
5632   gst_object_unref (qtdemux);
5633   return;
5634
5635   /* ERRORS */
5636 invalid_state:
5637   {
5638     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5639         (NULL), ("streaming stopped, invalid state"));
5640     gst_pad_pause_task (pad);
5641     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5642     goto done;
5643   }
5644 pause:
5645   {
5646     const gchar *reason = gst_flow_get_name (ret);
5647
5648     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5649
5650     gst_pad_pause_task (pad);
5651
5652     /* fatal errors need special actions */
5653     /* check EOS */
5654     if (ret == GST_FLOW_EOS) {
5655       if (qtdemux->n_streams == 0) {
5656         /* we have no streams, post an error */
5657         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5658       }
5659       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5660         gint64 stop;
5661
5662         if ((stop = qtdemux->segment.stop) == -1)
5663           stop = qtdemux->segment.duration;
5664
5665         if (qtdemux->segment.rate >= 0) {
5666           GstMessage *message;
5667           GstEvent *event;
5668
5669           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5670           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5671               GST_FORMAT_TIME, stop);
5672           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5673           if (qtdemux->segment_seqnum) {
5674             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5675             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5676           }
5677           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5678           gst_qtdemux_push_event (qtdemux, event);
5679         } else {
5680           GstMessage *message;
5681           GstEvent *event;
5682
5683           /*  For Reverse Playback */
5684           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5685           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5686               GST_FORMAT_TIME, qtdemux->segment.start);
5687           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5688               qtdemux->segment.start);
5689           if (qtdemux->segment_seqnum) {
5690             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5691             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5692           }
5693           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5694           gst_qtdemux_push_event (qtdemux, event);
5695         }
5696       } else {
5697         GstEvent *event;
5698
5699         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5700         event = gst_event_new_eos ();
5701         if (qtdemux->segment_seqnum)
5702           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5703         gst_qtdemux_push_event (qtdemux, event);
5704       }
5705     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5706       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5707           (NULL), ("streaming stopped, reason %s", reason));
5708       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5709     }
5710     goto done;
5711   }
5712 }
5713
5714 /*
5715  * has_next_entry
5716  *
5717  * Returns if there are samples to be played.
5718  */
5719 static gboolean
5720 has_next_entry (GstQTDemux * demux)
5721 {
5722   QtDemuxStream *stream;
5723   int i;
5724
5725   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5726
5727   for (i = 0; i < demux->n_streams; i++) {
5728     stream = demux->streams[i];
5729
5730     if (stream->sample_index == -1) {
5731       stream->sample_index = 0;
5732       stream->offset_in_sample = 0;
5733     }
5734
5735     if (stream->sample_index >= stream->n_samples) {
5736       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5737       continue;
5738     }
5739     GST_DEBUG_OBJECT (demux, "Found a sample");
5740     return TRUE;
5741   }
5742
5743   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5744   return FALSE;
5745 }
5746
5747 /*
5748  * next_entry_size
5749  *
5750  * Returns the size of the first entry at the current offset.
5751  * If -1, there are none (which means EOS or empty file).
5752  */
5753 static guint64
5754 next_entry_size (GstQTDemux * demux)
5755 {
5756   QtDemuxStream *stream;
5757   int i;
5758   int smallidx = -1;
5759   guint64 smalloffs = (guint64) - 1;
5760   QtDemuxSample *sample;
5761
5762   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5763       demux->offset);
5764
5765   for (i = 0; i < demux->n_streams; i++) {
5766     stream = demux->streams[i];
5767
5768     if (stream->sample_index == -1) {
5769       stream->sample_index = 0;
5770       stream->offset_in_sample = 0;
5771     }
5772
5773     if (stream->sample_index >= stream->n_samples) {
5774       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5775       continue;
5776     }
5777
5778     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5779       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5780           stream->sample_index);
5781       return -1;
5782     }
5783
5784     sample = &stream->samples[stream->sample_index];
5785
5786     GST_LOG_OBJECT (demux,
5787         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5788         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5789         sample->offset, sample->size);
5790
5791     if (((smalloffs == -1)
5792             || (sample->offset < smalloffs)) && (sample->size)) {
5793       smallidx = i;
5794       smalloffs = sample->offset;
5795     }
5796   }
5797
5798   GST_LOG_OBJECT (demux,
5799       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5800       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5801
5802   if (smallidx == -1)
5803     return -1;
5804
5805   stream = demux->streams[smallidx];
5806   sample = &stream->samples[stream->sample_index];
5807
5808   if (sample->offset >= demux->offset) {
5809     demux->todrop = sample->offset - demux->offset;
5810     return sample->size + demux->todrop;
5811   }
5812
5813   GST_DEBUG_OBJECT (demux,
5814       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5815   return -1;
5816 }
5817
5818 static void
5819 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5820 {
5821   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5822
5823   gst_element_post_message (GST_ELEMENT_CAST (demux),
5824       gst_message_new_element (GST_OBJECT_CAST (demux),
5825           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5826 }
5827
5828 static gboolean
5829 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5830 {
5831   GstEvent *event;
5832   gboolean res = 0;
5833
5834   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5835
5836   event =
5837       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5838       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5839       GST_SEEK_TYPE_NONE, -1);
5840
5841   /* store seqnum to drop flush events, they don't need to reach downstream */
5842   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5843   res = gst_pad_push_event (demux->sinkpad, event);
5844   demux->offset_seek_seqnum = 0;
5845
5846   return res;
5847 }
5848
5849 /* check for seekable upstream, above and beyond a mere query */
5850 static void
5851 gst_qtdemux_check_seekability (GstQTDemux * demux)
5852 {
5853   GstQuery *query;
5854   gboolean seekable = FALSE;
5855   gint64 start = -1, stop = -1;
5856
5857   if (demux->upstream_size)
5858     return;
5859
5860   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5861   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5862     GST_DEBUG_OBJECT (demux, "seeking query failed");
5863     goto done;
5864   }
5865
5866   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5867
5868   /* try harder to query upstream size if we didn't get it the first time */
5869   if (seekable && stop == -1) {
5870     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5871     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5872   }
5873
5874   /* if upstream doesn't know the size, it's likely that it's not seekable in
5875    * practice even if it technically may be seekable */
5876   if (seekable && (start != 0 || stop <= start)) {
5877     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5878     seekable = FALSE;
5879   }
5880
5881 done:
5882   gst_query_unref (query);
5883
5884   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5885       G_GUINT64_FORMAT ")", seekable, start, stop);
5886   demux->upstream_seekable = seekable;
5887   demux->upstream_size = seekable ? stop : -1;
5888 }
5889
5890 static void
5891 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5892 {
5893   g_return_if_fail (bytes <= demux->todrop);
5894
5895   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5896   gst_adapter_flush (demux->adapter, bytes);
5897   demux->neededbytes -= bytes;
5898   demux->offset += bytes;
5899   demux->todrop -= bytes;
5900 }
5901
5902 static void
5903 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5904 {
5905   if (G_UNLIKELY (demux->pending_newsegment)) {
5906     gint i;
5907
5908     gst_qtdemux_push_pending_newsegment (demux);
5909     /* clear to send tags on all streams */
5910     for (i = 0; i < demux->n_streams; i++) {
5911       QtDemuxStream *stream;
5912       stream = demux->streams[i];
5913       gst_qtdemux_push_tags (demux, stream);
5914       if (stream->sparse) {
5915         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5916         gst_pad_push_event (stream->pad,
5917             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5918       }
5919     }
5920   }
5921 }
5922
5923 static void
5924 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5925     QtDemuxStream * stream)
5926 {
5927   gint i;
5928
5929   /* Push any initial gap segments before proceeding to the
5930    * 'real' data */
5931   for (i = 0; i < stream->n_segments; i++) {
5932     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
5933
5934     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
5935       GstClockTime ts, dur;
5936       GstEvent *gap;
5937
5938       ts = stream->time_position;
5939       dur =
5940           stream->segments[i].duration - (stream->time_position -
5941           stream->segments[i].time);
5942       gap = gst_event_new_gap (ts, dur);
5943       stream->time_position += dur;
5944
5945       GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5946           "segment: %" GST_PTR_FORMAT, gap);
5947       gst_pad_push_event (stream->pad, gap);
5948     } else {
5949       /* Only support empty segment at the beginning followed by
5950        * one non-empty segment, this was checked when parsing the
5951        * edts atom, arriving here is unexpected */
5952       g_assert (i + 1 == stream->n_segments);
5953       break;
5954     }
5955   }
5956 }
5957
5958 static GstFlowReturn
5959 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5960 {
5961   GstQTDemux *demux;
5962
5963   demux = GST_QTDEMUX (parent);
5964
5965   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5966     gint i;
5967
5968     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5969
5970     for (i = 0; i < demux->n_streams; i++) {
5971       demux->streams[i]->discont = TRUE;
5972     }
5973
5974     /* Reverse fragmented playback, need to flush all we have before
5975      * consuming a new fragment.
5976      * The samples array have the timestamps calculated by accumulating the
5977      * durations but this won't work for reverse playback of fragments as
5978      * the timestamps of a subsequent fragment should be smaller than the
5979      * previously received one. */
5980     if (demux->fragmented && demux->segment.rate < 0) {
5981       gst_qtdemux_process_adapter (demux, TRUE);
5982       for (i = 0; i < demux->n_streams; i++)
5983         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5984     }
5985   }
5986
5987   gst_adapter_push (demux->adapter, inbuf);
5988
5989   GST_DEBUG_OBJECT (demux,
5990       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5991       demux->neededbytes, gst_adapter_available (demux->adapter));
5992
5993   return gst_qtdemux_process_adapter (demux, FALSE);
5994 }
5995
5996 static GstFlowReturn
5997 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5998 {
5999   GstFlowReturn ret = GST_FLOW_OK;
6000
6001   /* we never really mean to buffer that much */
6002   if (demux->neededbytes == -1) {
6003     goto eos;
6004   }
6005
6006   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6007       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6008
6009     GST_DEBUG_OBJECT (demux,
6010         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
6011         demux->state, demux->neededbytes, demux->offset);
6012
6013     switch (demux->state) {
6014       case QTDEMUX_STATE_INITIAL:{
6015         const guint8 *data;
6016         guint32 fourcc;
6017         guint64 size;
6018
6019         gst_qtdemux_check_seekability (demux);
6020
6021         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6022
6023         /* get fourcc/length, set neededbytes */
6024         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6025             &size, &fourcc);
6026         gst_adapter_unmap (demux->adapter);
6027         data = NULL;
6028         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6029             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6030         if (size == 0) {
6031           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6032               (_("This file is invalid and cannot be played.")),
6033               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6034                   GST_FOURCC_ARGS (fourcc)));
6035           ret = GST_FLOW_ERROR;
6036           break;
6037         }
6038         if (fourcc == FOURCC_mdat) {
6039           gint next_entry = next_entry_size (demux);
6040           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6041             /* we have the headers, start playback */
6042             demux->state = QTDEMUX_STATE_MOVIE;
6043             demux->neededbytes = next_entry;
6044             demux->mdatleft = size;
6045           } else {
6046             /* no headers yet, try to get them */
6047             guint bs;
6048             gboolean res;
6049             guint64 old, target;
6050
6051           buffer_data:
6052             old = demux->offset;
6053             target = old + size;
6054
6055             /* try to jump over the atom with a seek */
6056             /* only bother if it seems worth doing so,
6057              * and avoids possible upstream/server problems */
6058             if (demux->upstream_seekable &&
6059                 demux->upstream_size > 4 * (1 << 20)) {
6060               res = qtdemux_seek_offset (demux, target);
6061             } else {
6062               GST_DEBUG_OBJECT (demux, "skipping seek");
6063               res = FALSE;
6064             }
6065
6066             if (res) {
6067               GST_DEBUG_OBJECT (demux, "seek success");
6068               /* remember the offset fo the first mdat so we can seek back to it
6069                * after we have the headers */
6070               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6071                 demux->first_mdat = old;
6072                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6073                     demux->first_mdat);
6074               }
6075               /* seek worked, continue reading */
6076               demux->offset = target;
6077               demux->neededbytes = 16;
6078               demux->state = QTDEMUX_STATE_INITIAL;
6079             } else {
6080               /* seek failed, need to buffer */
6081               demux->offset = old;
6082               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6083               /* there may be multiple mdat (or alike) buffers */
6084               /* sanity check */
6085               if (demux->mdatbuffer)
6086                 bs = gst_buffer_get_size (demux->mdatbuffer);
6087               else
6088                 bs = 0;
6089               if (size + bs > 10 * (1 << 20))
6090                 goto no_moov;
6091               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6092               demux->neededbytes = size;
6093               if (!demux->mdatbuffer)
6094                 demux->mdatoffset = demux->offset;
6095             }
6096           }
6097         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6098           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6099               (_("This file is invalid and cannot be played.")),
6100               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6101                   GST_FOURCC_ARGS (fourcc), size));
6102           ret = GST_FLOW_ERROR;
6103           break;
6104         } else {
6105           /* this means we already started buffering and still no moov header,
6106            * let's continue buffering everything till we get moov */
6107           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6108                   || fourcc == FOURCC_moof))
6109             goto buffer_data;
6110           demux->neededbytes = size;
6111           demux->state = QTDEMUX_STATE_HEADER;
6112         }
6113         break;
6114       }
6115       case QTDEMUX_STATE_HEADER:{
6116         const guint8 *data;
6117         guint32 fourcc;
6118
6119         GST_DEBUG_OBJECT (demux, "In header");
6120
6121         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6122
6123         /* parse the header */
6124         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6125             &fourcc);
6126         if (fourcc == FOURCC_moov) {
6127           gint n;
6128
6129           /* in usual fragmented setup we could try to scan for more
6130            * and end up at the the moov (after mdat) again */
6131           if (demux->got_moov && demux->n_streams > 0 &&
6132               (!demux->fragmented
6133                   || demux->last_moov_offset == demux->offset)) {
6134             GST_DEBUG_OBJECT (demux,
6135                 "Skipping moov atom as we have (this) one already");
6136           } else {
6137             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6138
6139             if (demux->got_moov && demux->fragmented) {
6140               GST_DEBUG_OBJECT (demux,
6141                   "Got a second moov, clean up data from old one");
6142               if (demux->moov_node)
6143                 g_node_destroy (demux->moov_node);
6144               demux->moov_node = NULL;
6145               demux->moov_node_compressed = NULL;
6146             } else {
6147               /* prepare newsegment to send when streaming actually starts */
6148               if (!demux->pending_newsegment)
6149                 demux->pending_newsegment =
6150                     gst_event_new_segment (&demux->segment);
6151             }
6152
6153             demux->last_moov_offset = demux->offset;
6154
6155             qtdemux_parse_moov (demux, data, demux->neededbytes);
6156             qtdemux_node_dump (demux, demux->moov_node);
6157             qtdemux_parse_tree (demux);
6158             qtdemux_prepare_streams (demux);
6159             if (!demux->got_moov)
6160               qtdemux_expose_streams (demux);
6161             else {
6162
6163               for (n = 0; n < demux->n_streams; n++) {
6164                 QtDemuxStream *stream = demux->streams[n];
6165
6166                 gst_qtdemux_configure_stream (demux, stream);
6167               }
6168             }
6169
6170             demux->got_moov = TRUE;
6171             gst_qtdemux_check_send_pending_segment (demux);
6172
6173             /* fragmented streams headers shouldn't contain edts atoms */
6174             if (!demux->fragmented) {
6175               for (n = 0; n < demux->n_streams; n++) {
6176                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6177                     demux->streams[n]);
6178               }
6179             }
6180
6181             g_node_destroy (demux->moov_node);
6182             demux->moov_node = NULL;
6183             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6184           }
6185         } else if (fourcc == FOURCC_moof) {
6186           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6187             guint64 dist = 0;
6188             GstClockTime prev_pts;
6189             guint64 prev_offset;
6190
6191             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6192
6193             /*
6194              * The timestamp of the moof buffer is relevant as some scenarios
6195              * won't have the initial timestamp in the atoms. Whenever a new
6196              * buffer has started, we get that buffer's PTS and use it as a base
6197              * timestamp for the trun entries.
6198              *
6199              * To keep track of the current buffer timestamp and starting point
6200              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6201              * from the beggining of the buffer, with the distance and demux->offset
6202              * we know if it is still the same buffer or not.
6203              */
6204             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6205             prev_offset = demux->offset - dist;
6206             if (demux->fragment_start_offset == -1
6207                 || prev_offset > demux->fragment_start_offset) {
6208               demux->fragment_start_offset = prev_offset;
6209               demux->fragment_start = prev_pts;
6210               GST_DEBUG_OBJECT (demux,
6211                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6212                   GST_TIME_FORMAT, demux->fragment_start_offset,
6213                   GST_TIME_ARGS (demux->fragment_start));
6214             }
6215
6216             demux->moof_offset = demux->offset;
6217             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6218                     demux->offset, NULL)) {
6219               gst_adapter_unmap (demux->adapter);
6220               ret = GST_FLOW_ERROR;
6221               goto done;
6222             }
6223             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6224             if (demux->mss_mode && !demux->exposed) {
6225               if (!demux->pending_newsegment) {
6226                 GstSegment segment;
6227                 gst_segment_init (&segment, GST_FORMAT_TIME);
6228                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6229                 demux->pending_newsegment = gst_event_new_segment (&segment);
6230               }
6231               qtdemux_expose_streams (demux);
6232             }
6233           } else {
6234             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6235           }
6236         } else if (fourcc == FOURCC_ftyp) {
6237           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6238           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6239         } else if (fourcc == FOURCC_uuid) {
6240           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6241           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6242         } else if (fourcc == FOURCC_sidx) {
6243           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6244           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6245         } else {
6246           GST_WARNING_OBJECT (demux,
6247               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6248               GST_FOURCC_ARGS (fourcc));
6249           /* Let's jump that one and go back to initial state */
6250         }
6251         gst_adapter_unmap (demux->adapter);
6252         data = NULL;
6253
6254         if (demux->mdatbuffer && demux->n_streams) {
6255           gsize remaining_data_size = 0;
6256
6257           /* the mdat was before the header */
6258           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6259               demux->n_streams, demux->mdatbuffer);
6260           /* restore our adapter/offset view of things with upstream;
6261            * put preceding buffered data ahead of current moov data.
6262            * This should also handle evil mdat, moov, mdat cases and alike */
6263           gst_adapter_flush (demux->adapter, demux->neededbytes);
6264
6265           /* Store any remaining data after the mdat for later usage */
6266           remaining_data_size = gst_adapter_available (demux->adapter);
6267           if (remaining_data_size > 0) {
6268             g_assert (demux->restoredata_buffer == NULL);
6269             demux->restoredata_buffer =
6270                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6271             demux->restoredata_offset = demux->offset + demux->neededbytes;
6272             GST_DEBUG_OBJECT (demux,
6273                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6274                 G_GUINT64_FORMAT, remaining_data_size,
6275                 demux->restoredata_offset);
6276           }
6277
6278           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6279           demux->mdatbuffer = NULL;
6280           demux->offset = demux->mdatoffset;
6281           demux->neededbytes = next_entry_size (demux);
6282           demux->state = QTDEMUX_STATE_MOVIE;
6283           demux->mdatleft = gst_adapter_available (demux->adapter);
6284         } else {
6285           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6286           gst_adapter_flush (demux->adapter, demux->neededbytes);
6287
6288           /* only go back to the mdat if there are samples to play */
6289           if (demux->got_moov && demux->first_mdat != -1
6290               && has_next_entry (demux)) {
6291             gboolean res;
6292
6293             /* we need to seek back */
6294             res = qtdemux_seek_offset (demux, demux->first_mdat);
6295             if (res) {
6296               demux->offset = demux->first_mdat;
6297             } else {
6298               GST_DEBUG_OBJECT (demux, "Seek back failed");
6299             }
6300           } else {
6301             demux->offset += demux->neededbytes;
6302           }
6303           demux->neededbytes = 16;
6304           demux->state = QTDEMUX_STATE_INITIAL;
6305         }
6306
6307         break;
6308       }
6309       case QTDEMUX_STATE_BUFFER_MDAT:{
6310         GstBuffer *buf;
6311         guint8 fourcc[4];
6312
6313         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6314             demux->offset);
6315         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6316         gst_buffer_extract (buf, 0, fourcc, 4);
6317         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6318             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6319         if (demux->mdatbuffer)
6320           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6321         else
6322           demux->mdatbuffer = buf;
6323         demux->offset += demux->neededbytes;
6324         demux->neededbytes = 16;
6325         demux->state = QTDEMUX_STATE_INITIAL;
6326         gst_qtdemux_post_progress (demux, 1, 1);
6327
6328         break;
6329       }
6330       case QTDEMUX_STATE_MOVIE:{
6331         QtDemuxStream *stream = NULL;
6332         QtDemuxSample *sample;
6333         int i = -1;
6334         GstClockTime dts, pts, duration;
6335         gboolean keyframe;
6336
6337         GST_DEBUG_OBJECT (demux,
6338             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6339
6340         if (demux->fragmented) {
6341           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6342               demux->mdatleft);
6343           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6344             /* if needed data starts within this atom,
6345              * then it should not exceed this atom */
6346             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6347               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6348                   (_("This file is invalid and cannot be played.")),
6349                   ("sample data crosses atom boundary"));
6350               ret = GST_FLOW_ERROR;
6351               break;
6352             }
6353             demux->mdatleft -= demux->neededbytes;
6354           } else {
6355             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6356             /* so we are dropping more than left in this atom */
6357             gst_qtdemux_drop_data (demux, demux->mdatleft);
6358             demux->mdatleft = 0;
6359
6360             /* need to resume atom parsing so we do not miss any other pieces */
6361             demux->state = QTDEMUX_STATE_INITIAL;
6362             demux->neededbytes = 16;
6363
6364             /* check if there was any stored post mdat data from previous buffers */
6365             if (demux->restoredata_buffer) {
6366               g_assert (gst_adapter_available (demux->adapter) == 0);
6367
6368               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6369               demux->restoredata_buffer = NULL;
6370               demux->offset = demux->restoredata_offset;
6371             }
6372
6373             break;
6374           }
6375         }
6376
6377         if (demux->todrop) {
6378           if (demux->cenc_aux_info_offset > 0) {
6379             GstByteReader br;
6380             const guint8 *data;
6381
6382             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6383             data = gst_adapter_map (demux->adapter, demux->todrop);
6384             gst_byte_reader_init (&br, data + 8, demux->todrop);
6385             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6386                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6387               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6388               ret = GST_FLOW_ERROR;
6389               gst_adapter_unmap (demux->adapter);
6390               g_free (demux->cenc_aux_info_sizes);
6391               demux->cenc_aux_info_sizes = NULL;
6392               goto done;
6393             }
6394             demux->cenc_aux_info_offset = 0;
6395             g_free (demux->cenc_aux_info_sizes);
6396             demux->cenc_aux_info_sizes = NULL;
6397             gst_adapter_unmap (demux->adapter);
6398           }
6399           gst_qtdemux_drop_data (demux, demux->todrop);
6400         }
6401
6402         /* first buffer? */
6403         /* initial newsegment sent here after having added pads,
6404          * possible others in sink_event */
6405         gst_qtdemux_check_send_pending_segment (demux);
6406
6407         /* Figure out which stream this packet belongs to */
6408         for (i = 0; i < demux->n_streams; i++) {
6409           stream = demux->streams[i];
6410           if (stream->sample_index >= stream->n_samples)
6411             continue;
6412           GST_LOG_OBJECT (demux,
6413               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6414               " / size:%d)", i, stream->sample_index,
6415               stream->samples[stream->sample_index].offset,
6416               stream->samples[stream->sample_index].size);
6417
6418           if (stream->samples[stream->sample_index].offset == demux->offset)
6419             break;
6420         }
6421
6422         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6423           goto unknown_stream;
6424
6425         if (stream->new_caps) {
6426           gst_qtdemux_configure_stream (demux, stream);
6427         }
6428
6429         /* Put data in a buffer, set timestamps, caps, ... */
6430         sample = &stream->samples[stream->sample_index];
6431
6432         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6433           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6434               GST_FOURCC_ARGS (stream->fourcc));
6435
6436           dts = QTSAMPLE_DTS (stream, sample);
6437           pts = QTSAMPLE_PTS (stream, sample);
6438           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6439           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6440
6441           /* check for segment end */
6442           if (G_UNLIKELY (demux->segment.stop != -1
6443                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6444             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6445             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6446
6447             /* skip this data, stream is EOS */
6448             gst_adapter_flush (demux->adapter, demux->neededbytes);
6449
6450             /* check if all streams are eos */
6451             ret = GST_FLOW_EOS;
6452             for (i = 0; i < demux->n_streams; i++) {
6453               if (!STREAM_IS_EOS (demux->streams[i])) {
6454                 ret = GST_FLOW_OK;
6455                 break;
6456               }
6457             }
6458
6459             if (ret == GST_FLOW_EOS) {
6460               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6461               goto eos;
6462             }
6463           } else {
6464             GstBuffer *outbuf;
6465
6466             outbuf =
6467                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6468
6469             /* FIXME: should either be an assert or a plain check */
6470             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6471
6472             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6473                 dts, pts, duration, keyframe, dts, demux->offset);
6474           }
6475
6476           /* combine flows */
6477           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6478           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6479             goto non_ok_unlinked_flow;
6480         } else {
6481           /* skip this data, stream is EOS */
6482           gst_adapter_flush (demux->adapter, demux->neededbytes);
6483         }
6484
6485         stream->sample_index++;
6486         stream->offset_in_sample = 0;
6487
6488         /* update current offset and figure out size of next buffer */
6489         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6490             demux->offset, demux->neededbytes);
6491         demux->offset += demux->neededbytes;
6492         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6493             demux->offset);
6494
6495         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6496           if (demux->fragmented) {
6497             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6498             /* there may be more to follow, only finish this atom */
6499             demux->todrop = demux->mdatleft;
6500             demux->neededbytes = demux->todrop;
6501             break;
6502           }
6503           goto eos;
6504         }
6505         break;
6506       }
6507       default:
6508         goto invalid_state;
6509     }
6510   }
6511
6512   /* when buffering movie data, at least show user something is happening */
6513   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6514       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6515     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6516         demux->neededbytes);
6517   }
6518 done:
6519
6520   return ret;
6521
6522   /* ERRORS */
6523 non_ok_unlinked_flow:
6524   {
6525     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6526         gst_flow_get_name (ret));
6527     return ret;
6528   }
6529 unknown_stream:
6530   {
6531     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6532     ret = GST_FLOW_ERROR;
6533     goto done;
6534   }
6535 eos:
6536   {
6537     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6538     ret = GST_FLOW_EOS;
6539     goto done;
6540   }
6541 invalid_state:
6542   {
6543     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6544         (NULL), ("qtdemuxer invalid state %d", demux->state));
6545     ret = GST_FLOW_ERROR;
6546     goto done;
6547   }
6548 no_moov:
6549   {
6550     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6551         (NULL), ("no 'moov' atom within the first 10 MB"));
6552     ret = GST_FLOW_ERROR;
6553     goto done;
6554   }
6555 }
6556
6557 static gboolean
6558 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6559 {
6560   GstQuery *query;
6561   gboolean pull_mode;
6562
6563   query = gst_query_new_scheduling ();
6564
6565   if (!gst_pad_peer_query (sinkpad, query)) {
6566     gst_query_unref (query);
6567     goto activate_push;
6568   }
6569
6570   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6571       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6572   gst_query_unref (query);
6573
6574   if (!pull_mode)
6575     goto activate_push;
6576
6577   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6578   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6579
6580 activate_push:
6581   {
6582     GST_DEBUG_OBJECT (sinkpad, "activating push");
6583     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6584   }
6585 }
6586
6587 static gboolean
6588 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6589     GstPadMode mode, gboolean active)
6590 {
6591   gboolean res;
6592   GstQTDemux *demux = GST_QTDEMUX (parent);
6593
6594   switch (mode) {
6595     case GST_PAD_MODE_PUSH:
6596       demux->pullbased = FALSE;
6597       res = TRUE;
6598       break;
6599     case GST_PAD_MODE_PULL:
6600       if (active) {
6601         demux->pullbased = TRUE;
6602         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6603             sinkpad, NULL);
6604       } else {
6605         res = gst_pad_stop_task (sinkpad);
6606       }
6607       break;
6608     default:
6609       res = FALSE;
6610       break;
6611   }
6612   return res;
6613 }
6614
6615 #ifdef HAVE_ZLIB
6616 static void *
6617 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6618 {
6619   return g_malloc (items * size);
6620 }
6621
6622 static void
6623 qtdemux_zfree (void *opaque, void *addr)
6624 {
6625   g_free (addr);
6626 }
6627
6628 static void *
6629 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6630 {
6631   guint8 *buffer;
6632   z_stream *z;
6633   int ret;
6634
6635   z = g_new0 (z_stream, 1);
6636   z->zalloc = qtdemux_zalloc;
6637   z->zfree = qtdemux_zfree;
6638   z->opaque = NULL;
6639
6640   z->next_in = z_buffer;
6641   z->avail_in = z_length;
6642
6643   buffer = (guint8 *) g_malloc (length);
6644   ret = inflateInit (z);
6645   while (z->avail_in > 0) {
6646     if (z->avail_out == 0) {
6647       length += 1024;
6648       buffer = (guint8 *) g_realloc (buffer, length);
6649       z->next_out = buffer + z->total_out;
6650       z->avail_out = 1024;
6651     }
6652     ret = inflate (z, Z_SYNC_FLUSH);
6653     if (ret != Z_OK)
6654       break;
6655   }
6656   if (ret != Z_STREAM_END) {
6657     g_warning ("inflate() returned %d", ret);
6658   }
6659
6660   g_free (z);
6661   return buffer;
6662 }
6663 #endif /* HAVE_ZLIB */
6664
6665 static gboolean
6666 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6667 {
6668   GNode *cmov;
6669
6670   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6671
6672   /* counts as header data */
6673   qtdemux->header_size += length;
6674
6675   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6676   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6677
6678   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6679   if (cmov) {
6680     guint32 method;
6681     GNode *dcom;
6682     GNode *cmvd;
6683
6684     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6685     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6686     if (dcom == NULL || cmvd == NULL)
6687       goto invalid_compression;
6688
6689     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6690     switch (method) {
6691 #ifdef HAVE_ZLIB
6692       case FOURCC_zlib:{
6693         guint uncompressed_length;
6694         guint compressed_length;
6695         guint8 *buf;
6696
6697         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6698         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6699         GST_LOG ("length = %u", uncompressed_length);
6700
6701         buf =
6702             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6703             compressed_length, uncompressed_length);
6704
6705         qtdemux->moov_node_compressed = qtdemux->moov_node;
6706         qtdemux->moov_node = g_node_new (buf);
6707
6708         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6709             uncompressed_length);
6710         break;
6711       }
6712 #endif /* HAVE_ZLIB */
6713       default:
6714         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6715             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6716         break;
6717     }
6718   }
6719   return TRUE;
6720
6721   /* ERRORS */
6722 invalid_compression:
6723   {
6724     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6725     return FALSE;
6726   }
6727 }
6728
6729 static gboolean
6730 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6731     const guint8 * end)
6732 {
6733   while (G_UNLIKELY (buf < end)) {
6734     GNode *child;
6735     guint32 len;
6736
6737     if (G_UNLIKELY (buf + 4 > end)) {
6738       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6739       break;
6740     }
6741     len = QT_UINT32 (buf);
6742     if (G_UNLIKELY (len == 0)) {
6743       GST_LOG_OBJECT (qtdemux, "empty container");
6744       break;
6745     }
6746     if (G_UNLIKELY (len < 8)) {
6747       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6748       break;
6749     }
6750     if (G_UNLIKELY (len > (end - buf))) {
6751       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6752           (gint) (end - buf));
6753       break;
6754     }
6755
6756     child = g_node_new ((guint8 *) buf);
6757     g_node_append (node, child);
6758     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6759     qtdemux_parse_node (qtdemux, child, buf, len);
6760
6761     buf += len;
6762   }
6763   return TRUE;
6764 }
6765
6766 static gboolean
6767 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6768     GNode * xdxt)
6769 {
6770   int len = QT_UINT32 (xdxt->data);
6771   guint8 *buf = xdxt->data;
6772   guint8 *end = buf + len;
6773   GstBuffer *buffer;
6774
6775   /* skip size and type */
6776   buf += 8;
6777   end -= 8;
6778
6779   while (buf < end) {
6780     gint size;
6781     guint32 type;
6782
6783     size = QT_UINT32 (buf);
6784     type = QT_FOURCC (buf + 4);
6785
6786     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6787
6788     if (buf + size > end || size <= 0)
6789       break;
6790
6791     buf += 8;
6792     size -= 8;
6793
6794     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6795         GST_FOURCC_ARGS (type));
6796
6797     switch (type) {
6798       case FOURCC_tCtH:
6799         buffer = gst_buffer_new_and_alloc (size);
6800         gst_buffer_fill (buffer, 0, buf, size);
6801         stream->buffers = g_slist_append (stream->buffers, buffer);
6802         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6803         break;
6804       case FOURCC_tCt_:
6805         buffer = gst_buffer_new_and_alloc (size);
6806         gst_buffer_fill (buffer, 0, buf, size);
6807         stream->buffers = g_slist_append (stream->buffers, buffer);
6808         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6809         break;
6810       case FOURCC_tCtC:
6811         buffer = gst_buffer_new_and_alloc (size);
6812         gst_buffer_fill (buffer, 0, buf, size);
6813         stream->buffers = g_slist_append (stream->buffers, buffer);
6814         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6815         break;
6816       default:
6817         GST_WARNING_OBJECT (qtdemux,
6818             "unknown theora cookie %" GST_FOURCC_FORMAT,
6819             GST_FOURCC_ARGS (type));
6820         break;
6821     }
6822     buf += size;
6823   }
6824   return TRUE;
6825 }
6826
6827 static gboolean
6828 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6829     guint length)
6830 {
6831   guint32 fourcc = 0;
6832   guint32 node_length = 0;
6833   const QtNodeType *type;
6834   const guint8 *end;
6835
6836   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6837
6838   if (G_UNLIKELY (length < 8))
6839     goto not_enough_data;
6840
6841   node_length = QT_UINT32 (buffer);
6842   fourcc = QT_FOURCC (buffer + 4);
6843
6844   /* ignore empty nodes */
6845   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6846     return TRUE;
6847
6848   type = qtdemux_type_get (fourcc);
6849
6850   end = buffer + length;
6851
6852   GST_LOG_OBJECT (qtdemux,
6853       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6854       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6855
6856   if (node_length > length)
6857     goto broken_atom_size;
6858
6859   if (type->flags & QT_FLAG_CONTAINER) {
6860     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6861   } else {
6862     switch (fourcc) {
6863       case FOURCC_stsd:
6864       {
6865         if (node_length < 20) {
6866           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6867           break;
6868         }
6869         GST_DEBUG_OBJECT (qtdemux,
6870             "parsing stsd (sample table, sample description) atom");
6871         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6872         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6873         break;
6874       }
6875       case FOURCC_mp4a:
6876       case FOURCC_alac:
6877       {
6878         guint32 version;
6879         guint32 offset;
6880         guint min_size;
6881
6882         /* also read alac (or whatever) in stead of mp4a in the following,
6883          * since a similar layout is used in other cases as well */
6884         if (fourcc == FOURCC_mp4a)
6885           min_size = 20;
6886         else
6887           min_size = 40;
6888
6889         /* There are two things we might encounter here: a true mp4a atom, and
6890            an mp4a entry in an stsd atom. The latter is what we're interested
6891            in, and it looks like an atom, but isn't really one. The true mp4a
6892            atom is short, so we detect it based on length here. */
6893         if (length < min_size) {
6894           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6895               GST_FOURCC_ARGS (fourcc));
6896           break;
6897         }
6898
6899         /* 'version' here is the sound sample description version. Types 0 and
6900            1 are documented in the QTFF reference, but type 2 is not: it's
6901            described in Apple header files instead (struct SoundDescriptionV2
6902            in Movies.h) */
6903         version = QT_UINT16 (buffer + 16);
6904
6905         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6906             GST_FOURCC_ARGS (fourcc), version);
6907
6908         /* parse any esds descriptors */
6909         switch (version) {
6910           case 0:
6911             offset = 0x24;
6912             break;
6913           case 1:
6914             offset = 0x34;
6915             break;
6916           case 2:
6917             offset = 0x48;
6918             break;
6919           default:
6920             GST_WARNING_OBJECT (qtdemux,
6921                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6922                 GST_FOURCC_ARGS (fourcc), version);
6923             offset = 0;
6924             break;
6925         }
6926         if (offset)
6927           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6928         break;
6929       }
6930       case FOURCC_mp4v:
6931       case FOURCC_MP4V:
6932       case FOURCC_fmp4:
6933       case FOURCC_FMP4:
6934       case FOURCC_apcs:
6935       case FOURCC_apch:
6936       case FOURCC_apcn:
6937       case FOURCC_apco:
6938       case FOURCC_ap4h:
6939       {
6940         const guint8 *buf;
6941         guint32 version;
6942         int tlen;
6943
6944         /* codec_data is contained inside these atoms, which all have
6945          * the same format. */
6946
6947         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6948             GST_FOURCC_ARGS (fourcc));
6949         version = QT_UINT32 (buffer + 16);
6950         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6951         if (1 || version == 0x00000000) {
6952           buf = buffer + 0x32;
6953
6954           /* FIXME Quicktime uses PASCAL string while
6955            * the iso format uses C strings. Check the file
6956            * type before attempting to parse the string here. */
6957           tlen = QT_UINT8 (buf);
6958           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6959           buf++;
6960           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6961           /* the string has a reserved space of 32 bytes so skip
6962            * the remaining 31 */
6963           buf += 31;
6964           buf += 4;             /* and 4 bytes reserved */
6965
6966           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6967
6968           qtdemux_parse_container (qtdemux, node, buf, end);
6969         }
6970         break;
6971       }
6972       case FOURCC_H264:
6973       {
6974         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6975         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6976         break;
6977       }
6978       case FOURCC_avc1:
6979       {
6980         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6981         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6982         break;
6983       }
6984       case FOURCC_avc3:
6985       {
6986         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6987         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6988         break;
6989       }
6990       case FOURCC_H265:
6991       {
6992         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6993         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6994         break;
6995       }
6996       case FOURCC_hvc1:
6997       {
6998         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6999         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7000         break;
7001       }
7002       case FOURCC_hev1:
7003       {
7004         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7005         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7006         break;
7007       }
7008       case FOURCC_mjp2:
7009       {
7010         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7011         break;
7012       }
7013       case FOURCC_meta:
7014       {
7015         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7016         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7017         break;
7018       }
7019       case FOURCC_mp4s:
7020       {
7021         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7022         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7023         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7024         break;
7025       }
7026       case FOURCC_XiTh:
7027       {
7028         guint32 version;
7029         guint32 offset;
7030
7031         version = QT_UINT32 (buffer + 12);
7032         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7033
7034         switch (version) {
7035           case 0x00000001:
7036             offset = 0x62;
7037             break;
7038           default:
7039             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7040             offset = 0;
7041             break;
7042         }
7043         if (offset)
7044           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7045         break;
7046       }
7047       case FOURCC_in24:
7048       {
7049         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7050         break;
7051       }
7052       case FOURCC_uuid:
7053       {
7054         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7055         break;
7056       }
7057       case FOURCC_encv:
7058       {
7059         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7060         break;
7061       }
7062       case FOURCC_enca:
7063       {
7064         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7065         break;
7066       }
7067       default:
7068         if (!strcmp (type->name, "unknown"))
7069           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7070         break;
7071     }
7072   }
7073   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7074       GST_FOURCC_ARGS (fourcc));
7075   return TRUE;
7076
7077 /* ERRORS */
7078 not_enough_data:
7079   {
7080     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7081         (_("This file is corrupt and cannot be played.")),
7082         ("Not enough data for an atom header, got only %u bytes", length));
7083     return FALSE;
7084   }
7085 broken_atom_size:
7086   {
7087     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7088         (_("This file is corrupt and cannot be played.")),
7089         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7090             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7091             length));
7092     return FALSE;
7093   }
7094 }
7095
7096 static GNode *
7097 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7098 {
7099   GNode *child;
7100   guint8 *buffer;
7101   guint32 child_fourcc;
7102
7103   for (child = g_node_first_child (node); child;
7104       child = g_node_next_sibling (child)) {
7105     buffer = (guint8 *) child->data;
7106
7107     child_fourcc = QT_FOURCC (buffer + 4);
7108
7109     if (G_UNLIKELY (child_fourcc == fourcc)) {
7110       return child;
7111     }
7112   }
7113   return NULL;
7114 }
7115
7116 static GNode *
7117 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7118     GstByteReader * parser)
7119 {
7120   GNode *child;
7121   guint8 *buffer;
7122   guint32 child_fourcc, child_len;
7123
7124   for (child = g_node_first_child (node); child;
7125       child = g_node_next_sibling (child)) {
7126     buffer = (guint8 *) child->data;
7127
7128     child_len = QT_UINT32 (buffer);
7129     child_fourcc = QT_FOURCC (buffer + 4);
7130
7131     if (G_UNLIKELY (child_fourcc == fourcc)) {
7132       if (G_UNLIKELY (child_len < (4 + 4)))
7133         return NULL;
7134       /* FIXME: must verify if atom length < parent atom length */
7135       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7136       return child;
7137     }
7138   }
7139   return NULL;
7140 }
7141
7142 static GNode *
7143 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7144     GstByteReader * parser)
7145 {
7146   GNode *child;
7147   guint8 *buffer;
7148   guint32 child_fourcc, child_len;
7149
7150   for (child = g_node_next_sibling (node); child;
7151       child = g_node_next_sibling (child)) {
7152     buffer = (guint8 *) child->data;
7153
7154     child_fourcc = QT_FOURCC (buffer + 4);
7155
7156     if (child_fourcc == fourcc) {
7157       if (parser) {
7158         child_len = QT_UINT32 (buffer);
7159         if (G_UNLIKELY (child_len < (4 + 4)))
7160           return NULL;
7161         /* FIXME: must verify if atom length < parent atom length */
7162         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7163       }
7164       return child;
7165     }
7166   }
7167   return NULL;
7168 }
7169
7170 static GNode *
7171 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7172 {
7173   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7174 }
7175
7176 static void
7177 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7178 {
7179 /* FIXME: This can only reliably work if demuxers have a
7180  * separate streaming thread per srcpad. This should be
7181  * done in a demuxer base class, which integrates parts
7182  * of multiqueue
7183  *
7184  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7185  */
7186 #if 0
7187   GstQuery *query;
7188
7189   query = gst_query_new_allocation (stream->caps, FALSE);
7190
7191   if (!gst_pad_peer_query (stream->pad, query)) {
7192     /* not a problem, just debug a little */
7193     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7194   }
7195
7196   if (stream->allocator)
7197     gst_object_unref (stream->allocator);
7198
7199   if (gst_query_get_n_allocation_params (query) > 0) {
7200     /* try the allocator */
7201     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7202         &stream->params);
7203     stream->use_allocator = TRUE;
7204   } else {
7205     stream->allocator = NULL;
7206     gst_allocation_params_init (&stream->params);
7207     stream->use_allocator = FALSE;
7208   }
7209   gst_query_unref (query);
7210 #endif
7211 }
7212
7213 static gboolean
7214 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7215     QtDemuxStream * stream)
7216 {
7217   GstStructure *s;
7218   const gchar *selected_system;
7219
7220   g_return_val_if_fail (qtdemux != NULL, FALSE);
7221   g_return_val_if_fail (stream != NULL, FALSE);
7222   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7223
7224   if (stream->protection_scheme_type != FOURCC_cenc) {
7225     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7226     return FALSE;
7227   }
7228   if (qtdemux->protection_system_ids == NULL) {
7229     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7230         "cenc protection system information has been found");
7231     return FALSE;
7232   }
7233   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7234   selected_system = gst_protection_select_system ((const gchar **)
7235       qtdemux->protection_system_ids->pdata);
7236   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7237       qtdemux->protection_system_ids->len - 1);
7238   if (!selected_system) {
7239     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7240         "suitable decryptor element has been found");
7241     return FALSE;
7242   }
7243
7244   s = gst_caps_get_structure (stream->caps, 0);
7245   if (!gst_structure_has_name (s, "application/x-cenc")) {
7246     gst_structure_set (s,
7247         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7248         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7249         NULL);
7250     gst_structure_set_name (s, "application/x-cenc");
7251   }
7252   return TRUE;
7253 }
7254
7255 static gboolean
7256 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7257 {
7258   if (stream->subtype == FOURCC_vide) {
7259     /* fps is calculated base on the duration of the average framerate since
7260      * qt does not have a fixed framerate. */
7261     gboolean fps_available = TRUE;
7262
7263     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7264       /* still frame */
7265       stream->fps_n = 0;
7266       stream->fps_d = 1;
7267     } else {
7268       if (stream->duration == 0 || stream->n_samples < 2) {
7269         stream->fps_n = stream->timescale;
7270         stream->fps_d = 1;
7271         fps_available = FALSE;
7272       } else {
7273         GstClockTime avg_duration;
7274         guint64 duration;
7275         guint32 n_samples;
7276
7277         /* duration and n_samples can be updated for fragmented format
7278          * so, framerate of fragmented format is calculated using data in a moof */
7279         if (qtdemux->fragmented && stream->n_samples_moof > 0
7280             && stream->duration_moof > 0) {
7281           n_samples = stream->n_samples_moof;
7282           duration = stream->duration_moof;
7283         } else {
7284           n_samples = stream->n_samples;
7285           duration = stream->duration;
7286         }
7287
7288         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7289         /* stream->duration is guint64, timescale, n_samples are guint32 */
7290         avg_duration =
7291             gst_util_uint64_scale_round (duration -
7292             stream->first_duration, GST_SECOND,
7293             (guint64) (stream->timescale) * (n_samples - 1));
7294
7295         GST_LOG_OBJECT (qtdemux,
7296             "Calculating avg sample duration based on stream (or moof) duration %"
7297             G_GUINT64_FORMAT
7298             " minus first sample %u, leaving %d samples gives %"
7299             GST_TIME_FORMAT, duration, stream->first_duration,
7300             n_samples - 1, GST_TIME_ARGS (avg_duration));
7301
7302         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7303             &stream->fps_d);
7304
7305         GST_DEBUG_OBJECT (qtdemux,
7306             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7307             stream->timescale, stream->fps_n, stream->fps_d);
7308       }
7309     }
7310
7311     if (stream->caps) {
7312       stream->caps = gst_caps_make_writable (stream->caps);
7313
7314       gst_caps_set_simple (stream->caps,
7315           "width", G_TYPE_INT, stream->width,
7316           "height", G_TYPE_INT, stream->height, NULL);
7317
7318       /* set framerate if calculated framerate is reliable */
7319       if (fps_available) {
7320         gst_caps_set_simple (stream->caps,
7321             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7322       }
7323
7324       /* calculate pixel-aspect-ratio using display width and height */
7325       GST_DEBUG_OBJECT (qtdemux,
7326           "video size %dx%d, target display size %dx%d", stream->width,
7327           stream->height, stream->display_width, stream->display_height);
7328       /* qt file might have pasp atom */
7329       if (stream->par_w > 0 && stream->par_h > 0) {
7330         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7331         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7332             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7333       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7334           stream->width > 0 && stream->height > 0) {
7335         gint n, d;
7336
7337         /* calculate the pixel aspect ratio using the display and pixel w/h */
7338         n = stream->display_width * stream->height;
7339         d = stream->display_height * stream->width;
7340         if (n == d)
7341           n = d = 1;
7342         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7343         stream->par_w = n;
7344         stream->par_h = d;
7345         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7346             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7347       }
7348
7349       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7350         guint par_w = 1, par_h = 1;
7351
7352         if (stream->par_w > 0 && stream->par_h > 0) {
7353           par_w = stream->par_w;
7354           par_h = stream->par_h;
7355         }
7356
7357         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7358                 stream->width, stream->height, par_w, par_h)) {
7359           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7360         }
7361
7362         gst_caps_set_simple (stream->caps,
7363             "multiview-mode", G_TYPE_STRING,
7364             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7365             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7366             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7367       }
7368     }
7369   }
7370
7371   else if (stream->subtype == FOURCC_soun) {
7372     if (stream->caps) {
7373       stream->caps = gst_caps_make_writable (stream->caps);
7374       if (stream->rate > 0)
7375         gst_caps_set_simple (stream->caps,
7376             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7377       if (stream->n_channels > 0)
7378         gst_caps_set_simple (stream->caps,
7379             "channels", G_TYPE_INT, stream->n_channels, NULL);
7380       if (stream->n_channels > 2) {
7381         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7382          * correctly; this is just the minimum we can do - assume
7383          * we don't actually have any channel positions. */
7384         gst_caps_set_simple (stream->caps,
7385             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7386       }
7387     }
7388   }
7389
7390   if (stream->pad) {
7391     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7392     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7393     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7394     gst_pad_set_active (stream->pad, TRUE);
7395
7396     gst_pad_use_fixed_caps (stream->pad);
7397
7398     if (stream->protected) {
7399       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7400         GST_ERROR_OBJECT (qtdemux,
7401             "Failed to configure protected stream caps.");
7402         return FALSE;
7403       }
7404     }
7405
7406     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7407     if (stream->new_stream) {
7408       gchar *stream_id;
7409       GstEvent *event;
7410       GstStreamFlags stream_flags;
7411
7412       event =
7413           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7414           0);
7415       if (event) {
7416         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7417           qtdemux->have_group_id = TRUE;
7418         else
7419           qtdemux->have_group_id = FALSE;
7420         gst_event_unref (event);
7421       } else if (!qtdemux->have_group_id) {
7422         qtdemux->have_group_id = TRUE;
7423         qtdemux->group_id = gst_util_group_id_next ();
7424       }
7425
7426       stream->new_stream = FALSE;
7427       stream_id =
7428           gst_pad_create_stream_id_printf (stream->pad,
7429           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7430       event = gst_event_new_stream_start (stream_id);
7431       if (qtdemux->have_group_id)
7432         gst_event_set_group_id (event, qtdemux->group_id);
7433       stream_flags = GST_STREAM_FLAG_NONE;
7434       if (stream->disabled)
7435         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7436       if (stream->sparse)
7437         stream_flags |= GST_STREAM_FLAG_SPARSE;
7438       gst_event_set_stream_flags (event, stream_flags);
7439       gst_pad_push_event (stream->pad, event);
7440       g_free (stream_id);
7441     }
7442     gst_pad_set_caps (stream->pad, stream->caps);
7443     stream->new_caps = FALSE;
7444   }
7445   return TRUE;
7446 }
7447
7448 static gboolean
7449 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7450     QtDemuxStream * stream, GstTagList * list)
7451 {
7452   gboolean ret = TRUE;
7453   /* consistent default for push based mode */
7454   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7455
7456   if (stream->subtype == FOURCC_vide) {
7457     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7458
7459     stream->pad =
7460         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7461     g_free (name);
7462
7463     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7464       gst_object_unref (stream->pad);
7465       stream->pad = NULL;
7466       ret = FALSE;
7467       goto done;
7468     }
7469
7470     qtdemux->n_video_streams++;
7471   } else if (stream->subtype == FOURCC_soun) {
7472     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7473
7474     stream->pad =
7475         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7476     g_free (name);
7477     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7478       gst_object_unref (stream->pad);
7479       stream->pad = NULL;
7480       ret = FALSE;
7481       goto done;
7482     }
7483     qtdemux->n_audio_streams++;
7484   } else if (stream->subtype == FOURCC_strm) {
7485     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7486   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7487       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7488     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7489
7490     stream->pad =
7491         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7492     g_free (name);
7493     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7494       gst_object_unref (stream->pad);
7495       stream->pad = NULL;
7496       ret = FALSE;
7497       goto done;
7498     }
7499     qtdemux->n_sub_streams++;
7500   } else if (stream->caps) {
7501     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7502
7503     stream->pad =
7504         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7505     g_free (name);
7506     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7507       gst_object_unref (stream->pad);
7508       stream->pad = NULL;
7509       ret = FALSE;
7510       goto done;
7511     }
7512     qtdemux->n_video_streams++;
7513   } else {
7514     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7515     goto done;
7516   }
7517
7518   if (stream->pad) {
7519     GList *l;
7520
7521     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7522         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7523     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7524     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7525
7526     if (stream->pending_tags)
7527       gst_tag_list_unref (stream->pending_tags);
7528     stream->pending_tags = list;
7529     list = NULL;
7530     /* global tags go on each pad anyway */
7531     stream->send_global_tags = TRUE;
7532     /* send upstream GST_EVENT_PROTECTION events that were received before
7533        this source pad was created */
7534     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7535       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7536   }
7537 done:
7538   if (list)
7539     gst_tag_list_unref (list);
7540   return ret;
7541 }
7542
7543 /* find next atom with @fourcc starting at @offset */
7544 static GstFlowReturn
7545 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7546     guint64 * length, guint32 fourcc)
7547 {
7548   GstFlowReturn ret;
7549   guint32 lfourcc;
7550   GstBuffer *buf;
7551
7552   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7553       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7554
7555   while (TRUE) {
7556     GstMapInfo map;
7557
7558     buf = NULL;
7559     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7560     if (G_UNLIKELY (ret != GST_FLOW_OK))
7561       goto locate_failed;
7562     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7563       /* likely EOF */
7564       ret = GST_FLOW_EOS;
7565       gst_buffer_unref (buf);
7566       goto locate_failed;
7567     }
7568     gst_buffer_map (buf, &map, GST_MAP_READ);
7569     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7570     gst_buffer_unmap (buf, &map);
7571     gst_buffer_unref (buf);
7572
7573     if (G_UNLIKELY (*length == 0)) {
7574       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7575       ret = GST_FLOW_ERROR;
7576       goto locate_failed;
7577     }
7578
7579     if (lfourcc == fourcc) {
7580       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7581           *offset);
7582       break;
7583     } else {
7584       GST_LOG_OBJECT (qtdemux,
7585           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7586           GST_FOURCC_ARGS (fourcc), *offset);
7587       *offset += *length;
7588     }
7589   }
7590
7591   return GST_FLOW_OK;
7592
7593 locate_failed:
7594   {
7595     /* might simply have had last one */
7596     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7597     return ret;
7598   }
7599 }
7600
7601 /* should only do something in pull mode */
7602 /* call with OBJECT lock */
7603 static GstFlowReturn
7604 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7605 {
7606   guint64 length, offset;
7607   GstBuffer *buf = NULL;
7608   GstFlowReturn ret = GST_FLOW_OK;
7609   GstFlowReturn res = GST_FLOW_OK;
7610   GstMapInfo map;
7611
7612   offset = qtdemux->moof_offset;
7613   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7614
7615   if (!offset) {
7616     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7617     return GST_FLOW_EOS;
7618   }
7619
7620   /* best not do pull etc with lock held */
7621   GST_OBJECT_UNLOCK (qtdemux);
7622
7623   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7624   if (ret != GST_FLOW_OK)
7625     goto flow_failed;
7626
7627   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7628   if (G_UNLIKELY (ret != GST_FLOW_OK))
7629     goto flow_failed;
7630   gst_buffer_map (buf, &map, GST_MAP_READ);
7631   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7632     gst_buffer_unmap (buf, &map);
7633     gst_buffer_unref (buf);
7634     buf = NULL;
7635     goto parse_failed;
7636   }
7637
7638   gst_buffer_unmap (buf, &map);
7639   gst_buffer_unref (buf);
7640   buf = NULL;
7641
7642   offset += length;
7643   /* look for next moof */
7644   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7645   if (G_UNLIKELY (ret != GST_FLOW_OK))
7646     goto flow_failed;
7647
7648 exit:
7649   GST_OBJECT_LOCK (qtdemux);
7650
7651   qtdemux->moof_offset = offset;
7652
7653   return res;
7654
7655 parse_failed:
7656   {
7657     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7658     offset = 0;
7659     res = GST_FLOW_ERROR;
7660     goto exit;
7661   }
7662 flow_failed:
7663   {
7664     /* maybe upstream temporarily flushing */
7665     if (ret != GST_FLOW_FLUSHING) {
7666       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7667       offset = 0;
7668     } else {
7669       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7670       /* resume at current position next time */
7671     }
7672     res = ret;
7673     goto exit;
7674   }
7675 }
7676
7677 /* initialise bytereaders for stbl sub-atoms */
7678 static gboolean
7679 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7680 {
7681   stream->stbl_index = -1;      /* no samples have yet been parsed */
7682   stream->sample_index = -1;
7683
7684   /* time-to-sample atom */
7685   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7686     goto corrupt_file;
7687
7688   /* copy atom data into a new buffer for later use */
7689   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7690
7691   /* skip version + flags */
7692   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7693       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7694     goto corrupt_file;
7695   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7696
7697   /* make sure there's enough data */
7698   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7699     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7700     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7701         stream->n_sample_times);
7702     if (!stream->n_sample_times)
7703       goto corrupt_file;
7704   }
7705
7706   /* sync sample atom */
7707   stream->stps_present = FALSE;
7708   if ((stream->stss_present =
7709           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7710               &stream->stss) ? TRUE : FALSE) == TRUE) {
7711     /* copy atom data into a new buffer for later use */
7712     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7713
7714     /* skip version + flags */
7715     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7716         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7717       goto corrupt_file;
7718
7719     if (stream->n_sample_syncs) {
7720       /* make sure there's enough data */
7721       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7722         goto corrupt_file;
7723     }
7724
7725     /* partial sync sample atom */
7726     if ((stream->stps_present =
7727             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7728                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7729       /* copy atom data into a new buffer for later use */
7730       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7731
7732       /* skip version + flags */
7733       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7734           !gst_byte_reader_get_uint32_be (&stream->stps,
7735               &stream->n_sample_partial_syncs))
7736         goto corrupt_file;
7737
7738       /* if there are no entries, the stss table contains the real
7739        * sync samples */
7740       if (stream->n_sample_partial_syncs) {
7741         /* make sure there's enough data */
7742         if (!qt_atom_parser_has_chunks (&stream->stps,
7743                 stream->n_sample_partial_syncs, 4))
7744           goto corrupt_file;
7745       }
7746     }
7747   }
7748
7749   /* sample size */
7750   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7751     goto no_samples;
7752
7753   /* copy atom data into a new buffer for later use */
7754   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7755
7756   /* skip version + flags */
7757   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7758       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7759     goto corrupt_file;
7760
7761   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7762     goto corrupt_file;
7763
7764   if (!stream->n_samples)
7765     goto no_samples;
7766
7767   /* sample-to-chunk atom */
7768   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7769     goto corrupt_file;
7770
7771   /* copy atom data into a new buffer for later use */
7772   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7773
7774   /* skip version + flags */
7775   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7776       !gst_byte_reader_get_uint32_be (&stream->stsc,
7777           &stream->n_samples_per_chunk))
7778     goto corrupt_file;
7779
7780   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7781       stream->n_samples_per_chunk);
7782
7783   /* make sure there's enough data */
7784   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7785           12))
7786     goto corrupt_file;
7787
7788
7789   /* chunk offset */
7790   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7791     stream->co_size = sizeof (guint32);
7792   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7793           &stream->stco))
7794     stream->co_size = sizeof (guint64);
7795   else
7796     goto corrupt_file;
7797
7798   /* copy atom data into a new buffer for later use */
7799   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7800
7801   /* skip version + flags */
7802   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7803     goto corrupt_file;
7804
7805   /* chunks_are_samples == TRUE means treat chunks as samples */
7806   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7807   if (stream->chunks_are_samples) {
7808     /* treat chunks as samples */
7809     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7810       goto corrupt_file;
7811   } else {
7812     /* skip number of entries */
7813     if (!gst_byte_reader_skip (&stream->stco, 4))
7814       goto corrupt_file;
7815
7816     /* make sure there are enough data in the stsz atom */
7817     if (!stream->sample_size) {
7818       /* different sizes for each sample */
7819       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7820         goto corrupt_file;
7821     }
7822   }
7823
7824   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7825       stream->n_samples, (guint) sizeof (QtDemuxSample),
7826       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7827
7828   if (stream->n_samples >=
7829       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7830     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7831         "be larger than %uMB (broken file?)", stream->n_samples,
7832         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7833     return FALSE;
7834   }
7835
7836   g_assert (stream->samples == NULL);
7837   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7838   if (!stream->samples) {
7839     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7840         stream->n_samples);
7841     return FALSE;
7842   }
7843
7844   /* composition time-to-sample */
7845   if ((stream->ctts_present =
7846           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7847               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7848     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7849
7850     /* copy atom data into a new buffer for later use */
7851     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7852
7853     /* skip version + flags */
7854     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7855         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7856             &stream->n_composition_times))
7857       goto corrupt_file;
7858
7859     /* make sure there's enough data */
7860     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7861             4 + 4))
7862       goto corrupt_file;
7863
7864     /* This is optional, if missing we iterate the ctts */
7865     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7866       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7867           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7868         g_free ((gpointer) cslg.data);
7869         goto corrupt_file;
7870       }
7871     } else {
7872       gint32 cslg_least = 0;
7873       guint num_entries, pos;
7874       gint i;
7875
7876       pos = gst_byte_reader_get_pos (&stream->ctts);
7877       num_entries = stream->n_composition_times;
7878
7879       stream->cslg_shift = 0;
7880
7881       for (i = 0; i < num_entries; i++) {
7882         gint32 offset;
7883
7884         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7885         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7886
7887         if (offset < cslg_least)
7888           cslg_least = offset;
7889       }
7890
7891       if (cslg_least < 0)
7892         stream->cslg_shift = ABS (cslg_least);
7893       else
7894         stream->cslg_shift = 0;
7895
7896       /* reset the reader so we can generate sample table */
7897       gst_byte_reader_set_pos (&stream->ctts, pos);
7898     }
7899   } else {
7900     /* Ensure the cslg_shift value is consistent so we can use it
7901      * unconditionnally to produce TS and Segment */
7902     stream->cslg_shift = 0;
7903   }
7904
7905   return TRUE;
7906
7907 corrupt_file:
7908   {
7909     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7910         (_("This file is corrupt and cannot be played.")), (NULL));
7911     return FALSE;
7912   }
7913 no_samples:
7914   {
7915     gst_qtdemux_stbl_free (stream);
7916     if (!qtdemux->fragmented) {
7917       /* not quite good */
7918       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7919       return FALSE;
7920     } else {
7921       /* may pick up samples elsewhere */
7922       return TRUE;
7923     }
7924   }
7925 }
7926
7927 /* collect samples from the next sample to be parsed up to sample @n for @stream
7928  * by reading the info from @stbl
7929  *
7930  * This code can be executed from both the streaming thread and the seeking
7931  * thread so it takes the object lock to protect itself
7932  */
7933 static gboolean
7934 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7935 {
7936   gint i, j, k;
7937   QtDemuxSample *samples, *first, *cur, *last;
7938   guint32 n_samples_per_chunk;
7939   guint32 n_samples;
7940
7941   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7942       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7943       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7944
7945   n_samples = stream->n_samples;
7946
7947   if (n >= n_samples)
7948     goto out_of_samples;
7949
7950   GST_OBJECT_LOCK (qtdemux);
7951   if (n <= stream->stbl_index)
7952     goto already_parsed;
7953
7954   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7955
7956   if (!stream->stsz.data) {
7957     /* so we already parsed and passed all the moov samples;
7958      * onto fragmented ones */
7959     g_assert (qtdemux->fragmented);
7960     goto done;
7961   }
7962
7963   /* pointer to the sample table */
7964   samples = stream->samples;
7965
7966   /* starts from -1, moves to the next sample index to parse */
7967   stream->stbl_index++;
7968
7969   /* keep track of the first and last sample to fill */
7970   first = &samples[stream->stbl_index];
7971   last = &samples[n];
7972
7973   if (!stream->chunks_are_samples) {
7974     /* set the sample sizes */
7975     if (stream->sample_size == 0) {
7976       /* different sizes for each sample */
7977       for (cur = first; cur <= last; cur++) {
7978         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7979         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7980             (guint) (cur - samples), cur->size);
7981       }
7982     } else {
7983       /* samples have the same size */
7984       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7985       for (cur = first; cur <= last; cur++)
7986         cur->size = stream->sample_size;
7987     }
7988   }
7989
7990   n_samples_per_chunk = stream->n_samples_per_chunk;
7991   cur = first;
7992
7993   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7994     guint32 last_chunk;
7995
7996     if (stream->stsc_chunk_index >= stream->last_chunk
7997         || stream->stsc_chunk_index < stream->first_chunk) {
7998       stream->first_chunk =
7999           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8000       stream->samples_per_chunk =
8001           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8002       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8003
8004       /* chunk numbers are counted from 1 it seems */
8005       if (G_UNLIKELY (stream->first_chunk == 0))
8006         goto corrupt_file;
8007
8008       --stream->first_chunk;
8009
8010       /* the last chunk of each entry is calculated by taking the first chunk
8011        * of the next entry; except if there is no next, where we fake it with
8012        * INT_MAX */
8013       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8014         stream->last_chunk = G_MAXUINT32;
8015       } else {
8016         stream->last_chunk =
8017             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8018         if (G_UNLIKELY (stream->last_chunk == 0))
8019           goto corrupt_file;
8020
8021         --stream->last_chunk;
8022       }
8023
8024       GST_LOG_OBJECT (qtdemux,
8025           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8026           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8027
8028       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8029         goto corrupt_file;
8030
8031       if (stream->last_chunk != G_MAXUINT32) {
8032         if (!qt_atom_parser_peek_sub (&stream->stco,
8033                 stream->first_chunk * stream->co_size,
8034                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8035                 &stream->co_chunk))
8036           goto corrupt_file;
8037
8038       } else {
8039         stream->co_chunk = stream->stco;
8040         if (!gst_byte_reader_skip (&stream->co_chunk,
8041                 stream->first_chunk * stream->co_size))
8042           goto corrupt_file;
8043       }
8044
8045       stream->stsc_chunk_index = stream->first_chunk;
8046     }
8047
8048     last_chunk = stream->last_chunk;
8049
8050     if (stream->chunks_are_samples) {
8051       cur = &samples[stream->stsc_chunk_index];
8052
8053       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8054         if (j > n) {
8055           /* save state */
8056           stream->stsc_chunk_index = j;
8057           goto done;
8058         }
8059
8060         cur->offset =
8061             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8062             stream->co_size);
8063
8064         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8065             "%" G_GUINT64_FORMAT, j, cur->offset);
8066
8067         if (stream->samples_per_frame * stream->bytes_per_frame) {
8068           cur->size =
8069               (stream->samples_per_chunk * stream->n_channels) /
8070               stream->samples_per_frame * stream->bytes_per_frame;
8071         } else {
8072           cur->size = stream->samples_per_chunk;
8073         }
8074
8075         GST_DEBUG_OBJECT (qtdemux,
8076             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8077             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8078                     stream->stco_sample_index)), cur->size);
8079
8080         cur->timestamp = stream->stco_sample_index;
8081         cur->duration = stream->samples_per_chunk;
8082         cur->keyframe = TRUE;
8083         cur++;
8084
8085         stream->stco_sample_index += stream->samples_per_chunk;
8086       }
8087       stream->stsc_chunk_index = j;
8088     } else {
8089       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8090         guint32 samples_per_chunk;
8091         guint64 chunk_offset;
8092
8093         if (!stream->stsc_sample_index
8094             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8095                 &stream->chunk_offset))
8096           goto corrupt_file;
8097
8098         samples_per_chunk = stream->samples_per_chunk;
8099         chunk_offset = stream->chunk_offset;
8100
8101         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8102           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8103               G_GUINT64_FORMAT " and size %d",
8104               (guint) (cur - samples), chunk_offset, cur->size);
8105
8106           cur->offset = chunk_offset;
8107           chunk_offset += cur->size;
8108           cur++;
8109
8110           if (G_UNLIKELY (cur > last)) {
8111             /* save state */
8112             stream->stsc_sample_index = k + 1;
8113             stream->chunk_offset = chunk_offset;
8114             stream->stsc_chunk_index = j;
8115             goto done2;
8116           }
8117         }
8118         stream->stsc_sample_index = 0;
8119       }
8120       stream->stsc_chunk_index = j;
8121     }
8122     stream->stsc_index++;
8123   }
8124
8125   if (stream->chunks_are_samples)
8126     goto ctts;
8127 done2:
8128   {
8129     guint32 n_sample_times;
8130
8131     n_sample_times = stream->n_sample_times;
8132     cur = first;
8133
8134     for (i = stream->stts_index; i < n_sample_times; i++) {
8135       guint32 stts_samples;
8136       gint32 stts_duration;
8137       gint64 stts_time;
8138
8139       if (stream->stts_sample_index >= stream->stts_samples
8140           || !stream->stts_sample_index) {
8141
8142         stream->stts_samples =
8143             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8144         stream->stts_duration =
8145             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8146
8147         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8148             i, stream->stts_samples, stream->stts_duration);
8149
8150         stream->stts_sample_index = 0;
8151       }
8152
8153       stts_samples = stream->stts_samples;
8154       stts_duration = stream->stts_duration;
8155       stts_time = stream->stts_time;
8156
8157       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8158         GST_DEBUG_OBJECT (qtdemux,
8159             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8160             (guint) (cur - samples), j,
8161             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8162
8163         cur->timestamp = stts_time;
8164         cur->duration = stts_duration;
8165
8166         /* avoid 32-bit wrap-around,
8167          * but still mind possible 'negative' duration */
8168         stts_time += (gint64) stts_duration;
8169         cur++;
8170
8171         if (G_UNLIKELY (cur > last)) {
8172           /* save values */
8173           stream->stts_time = stts_time;
8174           stream->stts_sample_index = j + 1;
8175           goto done3;
8176         }
8177       }
8178       stream->stts_sample_index = 0;
8179       stream->stts_time = stts_time;
8180       stream->stts_index++;
8181     }
8182     /* fill up empty timestamps with the last timestamp, this can happen when
8183      * the last samples do not decode and so we don't have timestamps for them.
8184      * We however look at the last timestamp to estimate the track length so we
8185      * need something in here. */
8186     for (; cur < last; cur++) {
8187       GST_DEBUG_OBJECT (qtdemux,
8188           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8189           (guint) (cur - samples),
8190           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8191       cur->timestamp = stream->stts_time;
8192       cur->duration = -1;
8193     }
8194   }
8195 done3:
8196   {
8197     /* sample sync, can be NULL */
8198     if (stream->stss_present == TRUE) {
8199       guint32 n_sample_syncs;
8200
8201       n_sample_syncs = stream->n_sample_syncs;
8202
8203       if (!n_sample_syncs) {
8204         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8205         stream->all_keyframe = TRUE;
8206       } else {
8207         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8208           /* note that the first sample is index 1, not 0 */
8209           guint32 index;
8210
8211           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8212
8213           if (G_LIKELY (index > 0 && index <= n_samples)) {
8214             index -= 1;
8215             samples[index].keyframe = TRUE;
8216             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8217             /* and exit if we have enough samples */
8218             if (G_UNLIKELY (index >= n)) {
8219               i++;
8220               break;
8221             }
8222           }
8223         }
8224         /* save state */
8225         stream->stss_index = i;
8226       }
8227
8228       /* stps marks partial sync frames like open GOP I-Frames */
8229       if (stream->stps_present == TRUE) {
8230         guint32 n_sample_partial_syncs;
8231
8232         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8233
8234         /* if there are no entries, the stss table contains the real
8235          * sync samples */
8236         if (n_sample_partial_syncs) {
8237           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8238             /* note that the first sample is index 1, not 0 */
8239             guint32 index;
8240
8241             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8242
8243             if (G_LIKELY (index > 0 && index <= n_samples)) {
8244               index -= 1;
8245               samples[index].keyframe = TRUE;
8246               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8247               /* and exit if we have enough samples */
8248               if (G_UNLIKELY (index >= n)) {
8249                 i++;
8250                 break;
8251               }
8252             }
8253           }
8254           /* save state */
8255           stream->stps_index = i;
8256         }
8257       }
8258     } else {
8259       /* no stss, all samples are keyframes */
8260       stream->all_keyframe = TRUE;
8261       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8262     }
8263   }
8264
8265 ctts:
8266   /* composition time to sample */
8267   if (stream->ctts_present == TRUE) {
8268     guint32 n_composition_times;
8269     guint32 ctts_count;
8270     gint32 ctts_soffset;
8271
8272     /* Fill in the pts_offsets */
8273     cur = first;
8274     n_composition_times = stream->n_composition_times;
8275
8276     for (i = stream->ctts_index; i < n_composition_times; i++) {
8277       if (stream->ctts_sample_index >= stream->ctts_count
8278           || !stream->ctts_sample_index) {
8279         stream->ctts_count =
8280             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8281         stream->ctts_soffset =
8282             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8283         stream->ctts_sample_index = 0;
8284       }
8285
8286       ctts_count = stream->ctts_count;
8287       ctts_soffset = stream->ctts_soffset;
8288
8289       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8290         cur->pts_offset = ctts_soffset;
8291         cur++;
8292
8293         if (G_UNLIKELY (cur > last)) {
8294           /* save state */
8295           stream->ctts_sample_index = j + 1;
8296           goto done;
8297         }
8298       }
8299       stream->ctts_sample_index = 0;
8300       stream->ctts_index++;
8301     }
8302   }
8303 done:
8304   stream->stbl_index = n;
8305   /* if index has been completely parsed, free data that is no-longer needed */
8306   if (n + 1 == stream->n_samples) {
8307     gst_qtdemux_stbl_free (stream);
8308     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8309     if (qtdemux->pullbased) {
8310       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8311       while (n + 1 == stream->n_samples)
8312         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8313           break;
8314     }
8315   }
8316   GST_OBJECT_UNLOCK (qtdemux);
8317
8318   return TRUE;
8319
8320   /* SUCCESS */
8321 already_parsed:
8322   {
8323     GST_LOG_OBJECT (qtdemux,
8324         "Tried to parse up to sample %u but this sample has already been parsed",
8325         n);
8326     /* if fragmented, there may be more */
8327     if (qtdemux->fragmented && n == stream->stbl_index)
8328       goto done;
8329     GST_OBJECT_UNLOCK (qtdemux);
8330     return TRUE;
8331   }
8332   /* ERRORS */
8333 out_of_samples:
8334   {
8335     GST_LOG_OBJECT (qtdemux,
8336         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8337         stream->n_samples);
8338     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8339         (_("This file is corrupt and cannot be played.")), (NULL));
8340     return FALSE;
8341   }
8342 corrupt_file:
8343   {
8344     GST_OBJECT_UNLOCK (qtdemux);
8345     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8346         (_("This file is corrupt and cannot be played.")), (NULL));
8347     return FALSE;
8348   }
8349 }
8350
8351 /* collect all segment info for @stream.
8352  */
8353 static gboolean
8354 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8355     GNode * trak)
8356 {
8357   GNode *edts;
8358   /* accept edts if they contain gaps at start and there is only
8359    * one media segment */
8360   gboolean allow_pushbased_edts = TRUE;
8361   gint media_segments_count = 0;
8362
8363   /* parse and prepare segment info from the edit list */
8364   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8365   stream->n_segments = 0;
8366   stream->segments = NULL;
8367   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8368     GNode *elst;
8369     gint n_segments;
8370     gint i, count;
8371     guint64 time;
8372     GstClockTime stime;
8373     guint8 *buffer;
8374
8375     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8376     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8377       goto done;
8378
8379     buffer = elst->data;
8380
8381     n_segments = QT_UINT32 (buffer + 12);
8382
8383     /* we might allocate a bit too much, at least allocate 1 segment */
8384     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8385
8386     /* segments always start from 0 */
8387     time = 0;
8388     stime = 0;
8389     count = 0;
8390     for (i = 0; i < n_segments; i++) {
8391       guint64 duration;
8392       guint64 media_time;
8393       QtDemuxSegment *segment;
8394       guint32 rate_int;
8395       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8396
8397       media_time = QT_UINT32 (buffer + 20 + i * 12);
8398       duration = QT_UINT32 (buffer + 16 + i * 12);
8399
8400       if (media_time != G_MAXUINT32)
8401         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8402
8403       segment = &stream->segments[count++];
8404
8405       /* time and duration expressed in global timescale */
8406       segment->time = stime;
8407       /* add non scaled values so we don't cause roundoff errors */
8408       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8409         time += duration;
8410         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8411         segment->duration = stime - segment->time;
8412       } else {
8413         /* zero duration does not imply media_start == media_stop
8414          * but, only specify media_start.*/
8415         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8416         if (GST_CLOCK_TIME_IS_VALID (stime) && media_time != G_MAXUINT32
8417             && stime >= media_start) {
8418           segment->duration = stime - media_start;
8419         } else {
8420           segment->duration = GST_CLOCK_TIME_NONE;
8421         }
8422       }
8423       segment->stop_time = stime;
8424
8425       segment->trak_media_start = media_time;
8426       /* media_time expressed in stream timescale */
8427       if (media_time != G_MAXUINT32) {
8428         segment->media_start = media_start;
8429         segment->media_stop = segment->media_start + segment->duration;
8430         media_segments_count++;
8431       } else {
8432         segment->media_start = GST_CLOCK_TIME_NONE;
8433         segment->media_stop = GST_CLOCK_TIME_NONE;
8434       }
8435       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
8436
8437       if (rate_int <= 1) {
8438         /* 0 is not allowed, some programs write 1 instead of the floating point
8439          * value */
8440         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8441             rate_int);
8442         segment->rate = 1;
8443       } else {
8444         segment->rate = rate_int / 65536.0;
8445       }
8446
8447       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8448           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8449           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8450           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8451           i, GST_TIME_ARGS (segment->time),
8452           GST_TIME_ARGS (segment->duration),
8453           GST_TIME_ARGS (segment->media_start), media_time,
8454           GST_TIME_ARGS (segment->media_stop),
8455           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8456           stream->timescale);
8457       if (segment->stop_time > qtdemux->segment.stop) {
8458         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8459             " extends to %" GST_TIME_FORMAT
8460             " past the end of the file duration %" GST_TIME_FORMAT
8461             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8462             GST_TIME_ARGS (qtdemux->segment.stop));
8463         qtdemux->segment.stop = segment->stop_time;
8464       }
8465     }
8466     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8467     stream->n_segments = count;
8468     if (media_segments_count != 1)
8469       allow_pushbased_edts = FALSE;
8470   }
8471 done:
8472
8473   /* push based does not handle segments, so act accordingly here,
8474    * and warn if applicable */
8475   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8476     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8477     /* remove and use default one below, we stream like it anyway */
8478     g_free (stream->segments);
8479     stream->segments = NULL;
8480     stream->n_segments = 0;
8481   }
8482
8483   /* no segments, create one to play the complete trak */
8484   if (stream->n_segments == 0) {
8485     GstClockTime stream_duration =
8486         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8487
8488     if (stream->segments == NULL)
8489       stream->segments = g_new (QtDemuxSegment, 1);
8490
8491     /* represent unknown our way */
8492     if (stream_duration == 0)
8493       stream_duration = GST_CLOCK_TIME_NONE;
8494
8495     stream->segments[0].time = 0;
8496     stream->segments[0].stop_time = stream_duration;
8497     stream->segments[0].duration = stream_duration;
8498     stream->segments[0].media_start = 0;
8499     stream->segments[0].media_stop = stream_duration;
8500     stream->segments[0].rate = 1.0;
8501     stream->segments[0].trak_media_start = 0;
8502
8503     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8504         GST_TIME_ARGS (stream_duration));
8505     stream->n_segments = 1;
8506     stream->dummy_segment = TRUE;
8507   }
8508   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8509
8510   return TRUE;
8511 }
8512
8513 /*
8514  * Parses the stsd atom of a svq3 trak looking for
8515  * the SMI and gama atoms.
8516  */
8517 static void
8518 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8519     guint8 ** gamma, GstBuffer ** seqh)
8520 {
8521   guint8 *_gamma = NULL;
8522   GstBuffer *_seqh = NULL;
8523   guint8 *stsd_data = stsd->data;
8524   guint32 length = QT_UINT32 (stsd_data);
8525   guint16 version;
8526
8527   if (length < 32) {
8528     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8529     goto end;
8530   }
8531
8532   stsd_data += 32;
8533   length -= 32;
8534   version = QT_UINT16 (stsd_data);
8535   if (version == 3) {
8536     if (length >= 70) {
8537       length -= 70;
8538       stsd_data += 70;
8539       while (length > 8) {
8540         guint32 fourcc, size;
8541         guint8 *data;
8542         size = QT_UINT32 (stsd_data);
8543         fourcc = QT_FOURCC (stsd_data + 4);
8544         data = stsd_data + 8;
8545
8546         if (size == 0) {
8547           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8548               "svq3 atom parsing");
8549           goto end;
8550         }
8551
8552         switch (fourcc) {
8553           case FOURCC_gama:{
8554             if (size == 12) {
8555               _gamma = data;
8556             } else {
8557               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8558                   " for gama atom, expected 12", size);
8559             }
8560             break;
8561           }
8562           case FOURCC_SMI_:{
8563             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8564               guint32 seqh_size;
8565               if (_seqh != NULL) {
8566                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8567                     " found, ignoring");
8568               } else {
8569                 seqh_size = QT_UINT32 (data + 4);
8570                 if (seqh_size > 0) {
8571                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8572                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8573                 }
8574               }
8575             }
8576             break;
8577           }
8578           default:{
8579             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8580                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8581           }
8582         }
8583
8584         if (size <= length) {
8585           length -= size;
8586           stsd_data += size;
8587         }
8588       }
8589     } else {
8590       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8591     }
8592   } else {
8593     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8594         G_GUINT16_FORMAT, version);
8595     goto end;
8596   }
8597
8598 end:
8599   if (gamma) {
8600     *gamma = _gamma;
8601   }
8602   if (seqh) {
8603     *seqh = _seqh;
8604   } else if (_seqh) {
8605     gst_buffer_unref (_seqh);
8606   }
8607 }
8608
8609 static gchar *
8610 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8611 {
8612   GNode *dinf;
8613   GstByteReader dref;
8614   gchar *uri = NULL;
8615
8616   /*
8617    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8618    * atom that might contain a 'data' atom with the rtsp uri.
8619    * This case was reported in bug #597497, some info about
8620    * the hndl atom can be found in TN1195
8621    */
8622   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8623   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8624
8625   if (dinf) {
8626     guint32 dref_num_entries = 0;
8627     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8628         gst_byte_reader_skip (&dref, 4) &&
8629         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8630       gint i;
8631
8632       /* search dref entries for hndl atom */
8633       for (i = 0; i < dref_num_entries; i++) {
8634         guint32 size = 0, type;
8635         guint8 string_len = 0;
8636         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8637             qt_atom_parser_get_fourcc (&dref, &type)) {
8638           if (type == FOURCC_hndl) {
8639             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8640
8641             /* skip data reference handle bytes and the
8642              * following pascal string and some extra 4
8643              * bytes I have no idea what are */
8644             if (!gst_byte_reader_skip (&dref, 4) ||
8645                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8646                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8647               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8648               break;
8649             }
8650
8651             /* iterate over the atoms to find the data atom */
8652             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8653               guint32 atom_size;
8654               guint32 atom_type;
8655
8656               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8657                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8658                 if (atom_type == FOURCC_data) {
8659                   const guint8 *uri_aux = NULL;
8660
8661                   /* found the data atom that might contain the rtsp uri */
8662                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8663                       "hndl atom, interpreting it as an URI");
8664                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8665                           &uri_aux)) {
8666                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8667                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8668                     else
8669                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8670                           "didn't contain a rtsp address");
8671                   } else {
8672                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8673                         "atom contents");
8674                   }
8675                   break;
8676                 }
8677                 /* skipping to the next entry */
8678                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8679                   break;
8680               } else {
8681                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8682                     "atom header");
8683                 break;
8684               }
8685             }
8686             break;
8687           }
8688           /* skip to the next entry */
8689           if (!gst_byte_reader_skip (&dref, size - 8))
8690             break;
8691         } else {
8692           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8693         }
8694       }
8695       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8696     }
8697   }
8698   return uri;
8699 }
8700
8701 #define AMR_NB_ALL_MODES        0x81ff
8702 #define AMR_WB_ALL_MODES        0x83ff
8703 static guint
8704 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8705 {
8706   /* The 'damr' atom is of the form:
8707    *
8708    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8709    *    32 b       8 b          16 b           8 b                 8 b
8710    *
8711    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8712    * represents the highest mode used in the stream (and thus the maximum
8713    * bitrate), with a couple of special cases as seen below.
8714    */
8715
8716   /* Map of frame type ID -> bitrate */
8717   static const guint nb_bitrates[] = {
8718     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8719   };
8720   static const guint wb_bitrates[] = {
8721     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8722   };
8723   GstMapInfo map;
8724   gsize max_mode;
8725   guint16 mode_set;
8726
8727   gst_buffer_map (buf, &map, GST_MAP_READ);
8728
8729   if (map.size != 0x11) {
8730     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8731     goto bad_data;
8732   }
8733
8734   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8735     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8736         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8737     goto bad_data;
8738   }
8739
8740   mode_set = QT_UINT16 (map.data + 13);
8741
8742   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8743     max_mode = 7 + (wb ? 1 : 0);
8744   else
8745     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8746     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8747
8748   if (max_mode == -1) {
8749     GST_DEBUG ("No mode indication was found (mode set) = %x",
8750         (guint) mode_set);
8751     goto bad_data;
8752   }
8753
8754   gst_buffer_unmap (buf, &map);
8755   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8756
8757 bad_data:
8758   gst_buffer_unmap (buf, &map);
8759   return 0;
8760 }
8761
8762 static gboolean
8763 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8764     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8765 {
8766   /*
8767    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8768    * [0 1 2]
8769    * [3 4 5]
8770    * [6 7 8]
8771    */
8772
8773   if (gst_byte_reader_get_remaining (reader) < 36)
8774     return FALSE;
8775
8776   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8777   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8778   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8779   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8780   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8781   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8782   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8783   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8784   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8785
8786   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8787   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8788       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8789       matrix[2] & 0xFF);
8790   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8791       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8792       matrix[5] & 0xFF);
8793   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8794       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8795       matrix[8] & 0xFF);
8796
8797   return TRUE;
8798 }
8799
8800 static void
8801 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8802     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8803 {
8804
8805 /* [a b c]
8806  * [d e f]
8807  * [g h i]
8808  *
8809  * This macro will only compare value abdegh, it expects cfi to have already
8810  * been checked
8811  */
8812 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8813                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8814
8815   /* only handle the cases where the last column has standard values */
8816   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8817     const gchar *rotation_tag = NULL;
8818
8819     /* no rotation needed */
8820     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8821       /* NOP */
8822     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8823       rotation_tag = "rotate-90";
8824     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8825       rotation_tag = "rotate-180";
8826     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8827       rotation_tag = "rotate-270";
8828     } else {
8829       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8830     }
8831
8832     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8833         rotation_tag);
8834     if (rotation_tag != NULL) {
8835       if (*taglist == NULL)
8836         *taglist = gst_tag_list_new_empty ();
8837       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8838           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8839     }
8840   } else {
8841     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8842   }
8843 }
8844
8845 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8846  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8847  * Common Encryption (cenc), the function will also parse the tenc box (defined
8848  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8849  * (typically an enc[v|a|t|s] sample entry); the function will set
8850  * @original_fmt to the fourcc of the original unencrypted stream format.
8851  * Returns TRUE if successful; FALSE otherwise. */
8852 static gboolean
8853 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8854     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8855 {
8856   GNode *sinf;
8857   GNode *frma;
8858   GNode *schm;
8859   GNode *schi;
8860
8861   g_return_val_if_fail (qtdemux != NULL, FALSE);
8862   g_return_val_if_fail (stream != NULL, FALSE);
8863   g_return_val_if_fail (container != NULL, FALSE);
8864   g_return_val_if_fail (original_fmt != NULL, FALSE);
8865
8866   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8867   if (G_UNLIKELY (!sinf)) {
8868     if (stream->protection_scheme_type == FOURCC_cenc) {
8869       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8870           "mandatory for Common Encryption");
8871       return FALSE;
8872     }
8873     return TRUE;
8874   }
8875
8876   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8877   if (G_UNLIKELY (!frma)) {
8878     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8879     return FALSE;
8880   }
8881
8882   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8883   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8884       GST_FOURCC_ARGS (*original_fmt));
8885
8886   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8887   if (!schm) {
8888     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8889     return FALSE;
8890   }
8891   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8892   stream->protection_scheme_version =
8893       QT_UINT32 ((const guint8 *) schm->data + 16);
8894
8895   GST_DEBUG_OBJECT (qtdemux,
8896       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8897       "protection_scheme_version: %#010x",
8898       GST_FOURCC_ARGS (stream->protection_scheme_type),
8899       stream->protection_scheme_version);
8900
8901   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8902   if (!schi) {
8903     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8904     return FALSE;
8905   }
8906   if (stream->protection_scheme_type == FOURCC_cenc) {
8907     QtDemuxCencSampleSetInfo *info;
8908     GNode *tenc;
8909     const guint8 *tenc_data;
8910     guint32 isEncrypted;
8911     guint8 iv_size;
8912     const guint8 *default_kid;
8913     GstBuffer *kid_buf;
8914
8915     if (G_UNLIKELY (!stream->protection_scheme_info))
8916       stream->protection_scheme_info =
8917           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8918
8919     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8920
8921     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8922     if (!tenc) {
8923       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8924           "which is mandatory for Common Encryption");
8925       return FALSE;
8926     }
8927     tenc_data = (const guint8 *) tenc->data + 12;
8928     isEncrypted = QT_UINT24 (tenc_data);
8929     iv_size = QT_UINT8 (tenc_data + 3);
8930     default_kid = (tenc_data + 4);
8931     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8932     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8933     if (info->default_properties)
8934       gst_structure_free (info->default_properties);
8935     info->default_properties =
8936         gst_structure_new ("application/x-cenc",
8937         "iv_size", G_TYPE_UINT, iv_size,
8938         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8939         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8940     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8941         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8942     gst_buffer_unref (kid_buf);
8943   }
8944   return TRUE;
8945 }
8946
8947 /* parse the traks.
8948  * With each track we associate a new QtDemuxStream that contains all the info
8949  * about the trak.
8950  * traks that do not decode to something (like strm traks) will not have a pad.
8951  */
8952 static gboolean
8953 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8954 {
8955   GstByteReader tkhd;
8956   int offset;
8957   GNode *mdia;
8958   GNode *mdhd;
8959   GNode *hdlr;
8960   GNode *minf;
8961   GNode *stbl;
8962   GNode *stsd;
8963   GNode *mp4a;
8964   GNode *mp4v;
8965   GNode *wave;
8966   GNode *esds;
8967   GNode *pasp;
8968   GNode *tref;
8969   GNode *udta;
8970   GNode *svmi;
8971
8972   QtDemuxStream *stream = NULL;
8973   gboolean new_stream = FALSE;
8974   gchar *codec = NULL;
8975   const guint8 *stsd_data;
8976   guint16 lang_code;            /* quicktime lang code or packed iso code */
8977   guint32 version;
8978   guint32 tkhd_flags = 0;
8979   guint8 tkhd_version = 0;
8980   guint32 fourcc;
8981   guint value_size, stsd_len, len;
8982   guint32 track_id;
8983   guint32 dummy;
8984
8985   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8986
8987   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8988       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8989       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8990     goto corrupt_file;
8991
8992   /* pick between 64 or 32 bits */
8993   value_size = tkhd_version == 1 ? 8 : 4;
8994   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8995       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8996     goto corrupt_file;
8997
8998   if (!qtdemux->got_moov) {
8999     if (qtdemux_find_stream (qtdemux, track_id))
9000       goto existing_stream;
9001     stream = _create_stream ();
9002     stream->track_id = track_id;
9003     new_stream = TRUE;
9004   } else {
9005     stream = qtdemux_find_stream (qtdemux, track_id);
9006     if (!stream) {
9007       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9008       goto skip_track;
9009     }
9010
9011     /* flush samples data from this track from previous moov */
9012     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9013     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9014   }
9015   /* need defaults for fragments */
9016   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9017
9018   if (stream->pending_tags == NULL)
9019     stream->pending_tags = gst_tag_list_new_empty ();
9020
9021   if ((tkhd_flags & 1) == 0)
9022     stream->disabled = TRUE;
9023
9024   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9025       tkhd_version, tkhd_flags, stream->track_id);
9026
9027   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9028     goto corrupt_file;
9029
9030   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9031     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9032     if (qtdemux->major_brand != FOURCC_mjp2 ||
9033         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9034       goto corrupt_file;
9035   }
9036
9037   len = QT_UINT32 ((guint8 *) mdhd->data);
9038   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9039   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9040   if (version == 0x01000000) {
9041     if (len < 38)
9042       goto corrupt_file;
9043     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9044     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9045     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9046   } else {
9047     if (len < 30)
9048       goto corrupt_file;
9049     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9050     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9051     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9052   }
9053
9054   if (lang_code < 0x400) {
9055     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9056   } else if (lang_code == 0x7fff) {
9057     stream->lang_id[0] = 0;     /* unspecified */
9058   } else {
9059     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9060     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9061     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9062     stream->lang_id[3] = 0;
9063   }
9064
9065   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9066       stream->timescale);
9067   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9068       stream->duration);
9069   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9070       lang_code, stream->lang_id);
9071
9072   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9073     goto corrupt_file;
9074
9075   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9076     /* chapters track reference */
9077     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9078     if (chap) {
9079       gsize length = GST_READ_UINT32_BE (chap->data);
9080       if (qtdemux->chapters_track_id)
9081         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9082
9083       if (length >= 12) {
9084         qtdemux->chapters_track_id =
9085             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9086       }
9087     }
9088   }
9089
9090   /* fragmented files may have bogus duration in moov */
9091   if (!qtdemux->fragmented &&
9092       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9093     guint64 tdur1, tdur2;
9094
9095     /* don't overflow */
9096     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9097     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9098
9099     /* HACK:
9100      * some of those trailers, nowadays, have prologue images that are
9101      * themselves vide tracks as well. I haven't really found a way to
9102      * identify those yet, except for just looking at their duration. */
9103     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9104       GST_WARNING_OBJECT (qtdemux,
9105           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9106           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9107           "found, assuming preview image or something; skipping track",
9108           stream->duration, stream->timescale, qtdemux->duration,
9109           qtdemux->timescale);
9110       if (new_stream)
9111         gst_qtdemux_stream_free (qtdemux, stream);
9112       return TRUE;
9113     }
9114   }
9115
9116   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9117     goto corrupt_file;
9118
9119   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9120       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9121
9122   len = QT_UINT32 ((guint8 *) hdlr->data);
9123   if (len >= 20)
9124     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9125   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9126       GST_FOURCC_ARGS (stream->subtype));
9127
9128   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9129     goto corrupt_file;
9130
9131   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9132     goto corrupt_file;
9133
9134   /*parse svmi header if existing */
9135   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9136   if (svmi) {
9137     len = QT_UINT32 ((guint8 *) svmi->data);
9138     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9139     if (!version) {
9140       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9141       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9142       guint8 frame_type, frame_layout;
9143
9144       /* MPEG-A stereo video */
9145       if (qtdemux->major_brand == FOURCC_ss02)
9146         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9147
9148       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9149       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9150       switch (frame_type) {
9151         case 0:
9152           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9153           break;
9154         case 1:
9155           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9156           break;
9157         case 2:
9158           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9159           break;
9160         case 3:
9161           /* mode 3 is primary/secondary view sequence, ie
9162            * left/right views in separate tracks. See section 7.2
9163            * of ISO/IEC 23000-11:2009 */
9164           GST_FIXME_OBJECT (qtdemux,
9165               "Implement stereo video in separate streams");
9166       }
9167
9168       if ((frame_layout & 0x1) == 0)
9169         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9170
9171       GST_LOG_OBJECT (qtdemux,
9172           "StereoVideo: composition type: %u, is_left_first: %u",
9173           frame_type, frame_layout);
9174       stream->multiview_mode = mode;
9175       stream->multiview_flags = flags;
9176     }
9177   }
9178
9179   /* parse stsd */
9180   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9181     goto corrupt_file;
9182   stsd_data = (const guint8 *) stsd->data;
9183
9184   /* stsd should at least have one entry */
9185   stsd_len = QT_UINT32 (stsd_data);
9186   if (stsd_len < 24) {
9187     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9188     if (stream->subtype == FOURCC_vivo) {
9189       if (new_stream)
9190         gst_qtdemux_stream_free (qtdemux, stream);
9191       return TRUE;
9192     } else {
9193       goto corrupt_file;
9194     }
9195   }
9196
9197   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9198
9199   /* and that entry should fit within stsd */
9200   len = QT_UINT32 (stsd_data + 16);
9201   if (len > stsd_len + 16)
9202     goto corrupt_file;
9203
9204   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9205   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9206       GST_FOURCC_ARGS (stream->fourcc));
9207   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9208
9209   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9210     goto error_encrypted;
9211
9212   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9213     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9214     stream->protected = TRUE;
9215     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9216       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9217   }
9218
9219   if (stream->subtype == FOURCC_vide) {
9220     guint32 w = 0, h = 0;
9221     gboolean gray;
9222     gint depth, palette_size, palette_count;
9223     guint32 matrix[9];
9224     guint32 *palette_data = NULL;
9225
9226     stream->sampled = TRUE;
9227
9228     /* version 1 uses some 64-bit ints */
9229     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9230       goto corrupt_file;
9231
9232     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9233       goto corrupt_file;
9234
9235     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9236         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9237       goto corrupt_file;
9238
9239     stream->display_width = w >> 16;
9240     stream->display_height = h >> 16;
9241
9242     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9243         &stream->pending_tags);
9244
9245     offset = 16;
9246     if (len < 86)
9247       goto corrupt_file;
9248
9249     stream->width = QT_UINT16 (stsd_data + offset + 32);
9250     stream->height = QT_UINT16 (stsd_data + offset + 34);
9251     stream->fps_n = 0;          /* this is filled in later */
9252     stream->fps_d = 0;          /* this is filled in later */
9253     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9254     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9255
9256     /* if color_table_id is 0, ctab atom must follow; however some files
9257      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9258      * if color table is not present we'll correct the value */
9259     if (stream->color_table_id == 0 &&
9260         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9261       stream->color_table_id = -1;
9262     }
9263
9264     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9265         stream->width, stream->height, stream->bits_per_sample,
9266         stream->color_table_id);
9267
9268     depth = stream->bits_per_sample;
9269
9270     /* more than 32 bits means grayscale */
9271     gray = (depth > 32);
9272     /* low 32 bits specify the depth  */
9273     depth &= 0x1F;
9274
9275     /* different number of palette entries is determined by depth. */
9276     palette_count = 0;
9277     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9278       palette_count = (1 << depth);
9279     palette_size = palette_count * 4;
9280
9281     if (stream->color_table_id) {
9282       switch (palette_count) {
9283         case 0:
9284           break;
9285         case 2:
9286           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9287           break;
9288         case 4:
9289           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9290           break;
9291         case 16:
9292           if (gray)
9293             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9294           else
9295             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9296           break;
9297         case 256:
9298           if (gray)
9299             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9300           else
9301             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9302           break;
9303         default:
9304           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9305               (_("The video in this file might not play correctly.")),
9306               ("unsupported palette depth %d", depth));
9307           break;
9308       }
9309     } else {
9310       gint i, j, start, end;
9311
9312       if (len < 94)
9313         goto corrupt_file;
9314
9315       /* read table */
9316       start = QT_UINT32 (stsd_data + offset + 86);
9317       palette_count = QT_UINT16 (stsd_data + offset + 90);
9318       end = QT_UINT16 (stsd_data + offset + 92);
9319
9320       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9321           start, end, palette_count);
9322
9323       if (end > 255)
9324         end = 255;
9325       if (start > end)
9326         start = end;
9327
9328       if (len < 94 + (end - start) * 8)
9329         goto corrupt_file;
9330
9331       /* palette is always the same size */
9332       palette_data = g_malloc0 (256 * 4);
9333       palette_size = 256 * 4;
9334
9335       for (j = 0, i = start; i <= end; j++, i++) {
9336         guint32 a, r, g, b;
9337
9338         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9339         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9340         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9341         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9342
9343         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9344             (g & 0xff00) | (b >> 8);
9345       }
9346     }
9347
9348     if (stream->caps)
9349       gst_caps_unref (stream->caps);
9350
9351     stream->caps =
9352         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9353     if (G_UNLIKELY (!stream->caps)) {
9354       g_free (palette_data);
9355       goto unknown_stream;
9356     }
9357
9358     if (codec) {
9359       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9360           GST_TAG_VIDEO_CODEC, codec, NULL);
9361       g_free (codec);
9362       codec = NULL;
9363     }
9364
9365
9366     if (palette_data) {
9367       GstStructure *s;
9368
9369       if (stream->rgb8_palette)
9370         gst_memory_unref (stream->rgb8_palette);
9371       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9372           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9373
9374       s = gst_caps_get_structure (stream->caps, 0);
9375
9376       /* non-raw video has a palette_data property. raw video has the palette as
9377        * an extra plane that we append to the output buffers before we push
9378        * them*/
9379       if (!gst_structure_has_name (s, "video/x-raw")) {
9380         GstBuffer *palette;
9381
9382         palette = gst_buffer_new ();
9383         gst_buffer_append_memory (palette, stream->rgb8_palette);
9384         stream->rgb8_palette = NULL;
9385
9386         gst_caps_set_simple (stream->caps, "palette_data",
9387             GST_TYPE_BUFFER, palette, NULL);
9388         gst_buffer_unref (palette);
9389       }
9390     } else if (palette_count != 0) {
9391       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9392           (NULL), ("Unsupported palette depth %d", depth));
9393     }
9394
9395     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9396         QT_UINT16 (stsd_data + offset + 48));
9397
9398     esds = NULL;
9399     pasp = NULL;
9400     /* pick 'the' stsd child */
9401     if (!stream->protected)
9402       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9403     else
9404       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9405
9406     if (mp4v) {
9407       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9408       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9409     }
9410
9411     if (pasp) {
9412       const guint8 *pasp_data = (const guint8 *) pasp->data;
9413
9414       stream->par_w = QT_UINT32 (pasp_data + 8);
9415       stream->par_h = QT_UINT32 (pasp_data + 12);
9416     } else {
9417       stream->par_w = 0;
9418       stream->par_h = 0;
9419     }
9420
9421     if (esds) {
9422       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9423     } else {
9424       switch (fourcc) {
9425         case FOURCC_H264:
9426         case FOURCC_avc1:
9427         case FOURCC_avc3:
9428         {
9429           gint len = QT_UINT32 (stsd_data) - 0x66;
9430           const guint8 *avc_data = stsd_data + 0x66;
9431
9432           /* find avcC */
9433           while (len >= 0x8) {
9434             gint size;
9435
9436             if (QT_UINT32 (avc_data) <= len)
9437               size = QT_UINT32 (avc_data) - 0x8;
9438             else
9439               size = len - 0x8;
9440
9441             if (size < 1)
9442               /* No real data, so break out */
9443               break;
9444
9445             switch (QT_FOURCC (avc_data + 0x4)) {
9446               case FOURCC_avcC:
9447               {
9448                 /* parse, if found */
9449                 GstBuffer *buf;
9450
9451                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9452
9453                 /* First 4 bytes are the length of the atom, the next 4 bytes
9454                  * are the fourcc, the next 1 byte is the version, and the
9455                  * subsequent bytes are profile_tier_level structure like data. */
9456                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9457                     avc_data + 8 + 1, size - 1);
9458                 buf = gst_buffer_new_and_alloc (size);
9459                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9460                 gst_caps_set_simple (stream->caps,
9461                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9462                 gst_buffer_unref (buf);
9463
9464                 break;
9465               }
9466               case FOURCC_strf:
9467               {
9468                 GstBuffer *buf;
9469
9470                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9471
9472                 /* First 4 bytes are the length of the atom, the next 4 bytes
9473                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9474                  * next 1 byte is the version, and the
9475                  * subsequent bytes are sequence parameter set like data. */
9476
9477                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9478                 if (size > 1) {
9479                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9480                       avc_data + 8 + 40 + 1, size - 1);
9481
9482                   buf = gst_buffer_new_and_alloc (size);
9483                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9484                   gst_caps_set_simple (stream->caps,
9485                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9486                   gst_buffer_unref (buf);
9487                 }
9488                 break;
9489               }
9490               case FOURCC_btrt:
9491               {
9492                 guint avg_bitrate, max_bitrate;
9493
9494                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9495                 if (size < 12)
9496                   break;
9497
9498                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9499                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9500
9501                 if (!max_bitrate && !avg_bitrate)
9502                   break;
9503
9504                 /* Some muxers seem to swap the average and maximum bitrates
9505                  * (I'm looking at you, YouTube), so we swap for sanity. */
9506                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9507                   guint temp = avg_bitrate;
9508
9509                   avg_bitrate = max_bitrate;
9510                   max_bitrate = temp;
9511                 }
9512
9513                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9514                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9515                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9516                 }
9517                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9518                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9519                       GST_TAG_BITRATE, avg_bitrate, NULL);
9520                 }
9521
9522                 break;
9523               }
9524
9525               default:
9526                 break;
9527             }
9528
9529             len -= size + 8;
9530             avc_data += size + 8;
9531           }
9532
9533           break;
9534         }
9535         case FOURCC_H265:
9536         case FOURCC_hvc1:
9537         case FOURCC_hev1:
9538         {
9539           gint len = QT_UINT32 (stsd_data) - 0x66;
9540           const guint8 *hevc_data = stsd_data + 0x66;
9541
9542           /* find hevc */
9543           while (len >= 0x8) {
9544             gint size;
9545
9546             if (QT_UINT32 (hevc_data) <= len)
9547               size = QT_UINT32 (hevc_data) - 0x8;
9548             else
9549               size = len - 0x8;
9550
9551             if (size < 1)
9552               /* No real data, so break out */
9553               break;
9554
9555             switch (QT_FOURCC (hevc_data + 0x4)) {
9556               case FOURCC_hvcC:
9557               {
9558                 /* parse, if found */
9559                 GstBuffer *buf;
9560
9561                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9562
9563                 /* First 4 bytes are the length of the atom, the next 4 bytes
9564                  * are the fourcc, the next 1 byte is the version, and the
9565                  * subsequent bytes are sequence parameter set like data. */
9566                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9567                     (stream->caps, hevc_data + 8 + 1, size - 1);
9568
9569                 buf = gst_buffer_new_and_alloc (size);
9570                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9571                 gst_caps_set_simple (stream->caps,
9572                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9573                 gst_buffer_unref (buf);
9574                 break;
9575               }
9576               default:
9577                 break;
9578             }
9579             len -= size + 8;
9580             hevc_data += size + 8;
9581           }
9582           break;
9583         }
9584         case FOURCC_mp4v:
9585         case FOURCC_MP4V:
9586         case FOURCC_fmp4:
9587         case FOURCC_FMP4:
9588         {
9589           GNode *glbl;
9590
9591           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9592               GST_FOURCC_ARGS (fourcc));
9593
9594           /* codec data might be in glbl extension atom */
9595           glbl = mp4v ?
9596               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9597           if (glbl) {
9598             guint8 *data;
9599             GstBuffer *buf;
9600             gint len;
9601
9602             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9603             data = glbl->data;
9604             len = QT_UINT32 (data);
9605             if (len > 0x8) {
9606               len -= 0x8;
9607               buf = gst_buffer_new_and_alloc (len);
9608               gst_buffer_fill (buf, 0, data + 8, len);
9609               gst_caps_set_simple (stream->caps,
9610                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9611               gst_buffer_unref (buf);
9612             }
9613           }
9614           break;
9615         }
9616         case FOURCC_mjp2:
9617         {
9618           /* see annex I of the jpeg2000 spec */
9619           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9620           const guint8 *data;
9621           const gchar *colorspace = NULL;
9622           gint ncomp = 0;
9623           guint32 ncomp_map = 0;
9624           gint32 *comp_map = NULL;
9625           guint32 nchan_def = 0;
9626           gint32 *chan_def = NULL;
9627
9628           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9629           /* some required atoms */
9630           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9631           if (!mjp2)
9632             break;
9633           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9634           if (!jp2h)
9635             break;
9636
9637           /* number of components; redundant with info in codestream, but useful
9638              to a muxer */
9639           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9640           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9641             break;
9642           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9643
9644           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9645           if (!colr)
9646             break;
9647           GST_DEBUG_OBJECT (qtdemux, "found colr");
9648           /* extract colour space info */
9649           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9650             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9651               case 16:
9652                 colorspace = "sRGB";
9653                 break;
9654               case 17:
9655                 colorspace = "GRAY";
9656                 break;
9657               case 18:
9658                 colorspace = "sYUV";
9659                 break;
9660               default:
9661                 colorspace = NULL;
9662                 break;
9663             }
9664           }
9665           if (!colorspace)
9666             /* colr is required, and only values 16, 17, and 18 are specified,
9667                so error if we have no colorspace */
9668             break;
9669
9670           /* extract component mapping */
9671           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9672           if (cmap) {
9673             guint32 cmap_len = 0;
9674             int i;
9675             cmap_len = QT_UINT32 (cmap->data);
9676             if (cmap_len >= 8) {
9677               /* normal box, subtract off header */
9678               cmap_len -= 8;
9679               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9680               if (cmap_len % 4 == 0) {
9681                 ncomp_map = (cmap_len / 4);
9682                 comp_map = g_new0 (gint32, ncomp_map);
9683                 for (i = 0; i < ncomp_map; i++) {
9684                   guint16 cmp;
9685                   guint8 mtyp, pcol;
9686                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9687                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9688                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9689                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9690                 }
9691               }
9692             }
9693           }
9694           /* extract channel definitions */
9695           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9696           if (cdef) {
9697             guint32 cdef_len = 0;
9698             int i;
9699             cdef_len = QT_UINT32 (cdef->data);
9700             if (cdef_len >= 10) {
9701               /* normal box, subtract off header and len */
9702               cdef_len -= 10;
9703               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9704               if (cdef_len % 6 == 0) {
9705                 nchan_def = (cdef_len / 6);
9706                 chan_def = g_new0 (gint32, nchan_def);
9707                 for (i = 0; i < nchan_def; i++)
9708                   chan_def[i] = -1;
9709                 for (i = 0; i < nchan_def; i++) {
9710                   guint16 cn, typ, asoc;
9711                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9712                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9713                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9714                   if (cn < nchan_def) {
9715                     switch (typ) {
9716                       case 0:
9717                         chan_def[cn] = asoc;
9718                         break;
9719                       case 1:
9720                         chan_def[cn] = 0;       /* alpha */
9721                         break;
9722                       default:
9723                         chan_def[cn] = -typ;
9724                     }
9725                   }
9726                 }
9727               }
9728             }
9729           }
9730
9731           gst_caps_set_simple (stream->caps,
9732               "num-components", G_TYPE_INT, ncomp, NULL);
9733           gst_caps_set_simple (stream->caps,
9734               "colorspace", G_TYPE_STRING, colorspace, NULL);
9735
9736           if (comp_map) {
9737             GValue arr = { 0, };
9738             GValue elt = { 0, };
9739             int i;
9740             g_value_init (&arr, GST_TYPE_ARRAY);
9741             g_value_init (&elt, G_TYPE_INT);
9742             for (i = 0; i < ncomp_map; i++) {
9743               g_value_set_int (&elt, comp_map[i]);
9744               gst_value_array_append_value (&arr, &elt);
9745             }
9746             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9747                 "component-map", &arr);
9748             g_value_unset (&elt);
9749             g_value_unset (&arr);
9750             g_free (comp_map);
9751           }
9752
9753           if (chan_def) {
9754             GValue arr = { 0, };
9755             GValue elt = { 0, };
9756             int i;
9757             g_value_init (&arr, GST_TYPE_ARRAY);
9758             g_value_init (&elt, G_TYPE_INT);
9759             for (i = 0; i < nchan_def; i++) {
9760               g_value_set_int (&elt, chan_def[i]);
9761               gst_value_array_append_value (&arr, &elt);
9762             }
9763             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9764                 "channel-definitions", &arr);
9765             g_value_unset (&elt);
9766             g_value_unset (&arr);
9767             g_free (chan_def);
9768           }
9769
9770           /* some optional atoms */
9771           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9772           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9773
9774           /* indicate possible fields in caps */
9775           if (field) {
9776             data = (guint8 *) field->data + 8;
9777             if (*data != 1)
9778               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9779                   (gint) * data, NULL);
9780           }
9781           /* add codec_data if provided */
9782           if (prefix) {
9783             GstBuffer *buf;
9784             gint len;
9785
9786             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9787             data = prefix->data;
9788             len = QT_UINT32 (data);
9789             if (len > 0x8) {
9790               len -= 0x8;
9791               buf = gst_buffer_new_and_alloc (len);
9792               gst_buffer_fill (buf, 0, data + 8, len);
9793               gst_caps_set_simple (stream->caps,
9794                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9795               gst_buffer_unref (buf);
9796             }
9797           }
9798           break;
9799         }
9800         case FOURCC_SVQ3:
9801         case FOURCC_VP31:
9802         {
9803           GstBuffer *buf;
9804           GstBuffer *seqh = NULL;
9805           guint8 *gamma_data = NULL;
9806           gint len = QT_UINT32 (stsd_data);
9807
9808           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9809           if (gamma_data) {
9810             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9811                 QT_FP32 (gamma_data), NULL);
9812           }
9813           if (seqh) {
9814             /* sorry for the bad name, but we don't know what this is, other
9815              * than its own fourcc */
9816             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9817                 NULL);
9818           }
9819
9820           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9821           buf = gst_buffer_new_and_alloc (len);
9822           gst_buffer_fill (buf, 0, stsd_data, len);
9823           gst_caps_set_simple (stream->caps,
9824               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9825           gst_buffer_unref (buf);
9826           break;
9827         }
9828         case FOURCC_rle_:
9829         case FOURCC_WRLE:
9830         {
9831           gst_caps_set_simple (stream->caps,
9832               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9833           break;
9834         }
9835         case FOURCC_XiTh:
9836         {
9837           GNode *xith, *xdxt;
9838
9839           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9840           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9841           if (!xith)
9842             break;
9843
9844           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9845           if (!xdxt)
9846             break;
9847
9848           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9849           /* collect the headers and store them in a stream list so that we can
9850            * send them out first */
9851           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9852           break;
9853         }
9854         case FOURCC_ovc1:
9855         {
9856           GNode *ovc1;
9857           guint8 *ovc1_data;
9858           guint ovc1_len;
9859           GstBuffer *buf;
9860
9861           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9862           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9863           if (!ovc1)
9864             break;
9865           ovc1_data = ovc1->data;
9866           ovc1_len = QT_UINT32 (ovc1_data);
9867           if (ovc1_len <= 198) {
9868             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9869             break;
9870           }
9871           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9872           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9873           gst_caps_set_simple (stream->caps,
9874               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9875           gst_buffer_unref (buf);
9876           break;
9877         }
9878         case FOURCC_vc_1:
9879         {
9880           gint len = QT_UINT32 (stsd_data) - 0x66;
9881           const guint8 *vc1_data = stsd_data + 0x66;
9882
9883           /* find dvc1 */
9884           while (len >= 8) {
9885             gint size;
9886
9887             if (QT_UINT32 (vc1_data) <= len)
9888               size = QT_UINT32 (vc1_data) - 8;
9889             else
9890               size = len - 8;
9891
9892             if (size < 1)
9893               /* No real data, so break out */
9894               break;
9895
9896             switch (QT_FOURCC (vc1_data + 0x4)) {
9897               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9898               {
9899                 GstBuffer *buf;
9900
9901                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9902                 buf = gst_buffer_new_and_alloc (size);
9903                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9904                 gst_caps_set_simple (stream->caps,
9905                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9906                 gst_buffer_unref (buf);
9907                 break;
9908               }
9909               default:
9910                 break;
9911             }
9912             len -= size + 8;
9913             vc1_data += size + 8;
9914           }
9915           break;
9916         }
9917         default:
9918           break;
9919       }
9920     }
9921
9922     GST_INFO_OBJECT (qtdemux,
9923         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9924         GST_FOURCC_ARGS (fourcc), stream->caps);
9925
9926   } else if (stream->subtype == FOURCC_soun) {
9927     int version, samplesize;
9928     guint16 compression_id;
9929     gboolean amrwb = FALSE;
9930
9931     offset = 32;
9932     /* sample description entry (16) + sound sample description v0 (20) */
9933     if (len < 36)
9934       goto corrupt_file;
9935
9936     version = QT_UINT32 (stsd_data + offset);
9937     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9938     samplesize = QT_UINT16 (stsd_data + offset + 10);
9939     compression_id = QT_UINT16 (stsd_data + offset + 12);
9940     stream->rate = QT_FP32 (stsd_data + offset + 16);
9941
9942     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9943     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9944         QT_UINT32 (stsd_data + offset + 4));
9945     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9946     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9947     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9948     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9949         QT_UINT16 (stsd_data + offset + 14));
9950     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9951
9952     if (compression_id == 0xfffe)
9953       stream->sampled = TRUE;
9954
9955     /* first assume uncompressed audio */
9956     stream->bytes_per_sample = samplesize / 8;
9957     stream->samples_per_frame = stream->n_channels;
9958     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9959     stream->samples_per_packet = stream->samples_per_frame;
9960     stream->bytes_per_packet = stream->bytes_per_sample;
9961
9962     offset = 52;
9963     switch (fourcc) {
9964         /* Yes, these have to be hard-coded */
9965       case FOURCC_MAC6:
9966       {
9967         stream->samples_per_packet = 6;
9968         stream->bytes_per_packet = 1;
9969         stream->bytes_per_frame = 1 * stream->n_channels;
9970         stream->bytes_per_sample = 1;
9971         stream->samples_per_frame = 6 * stream->n_channels;
9972         break;
9973       }
9974       case FOURCC_MAC3:
9975       {
9976         stream->samples_per_packet = 3;
9977         stream->bytes_per_packet = 1;
9978         stream->bytes_per_frame = 1 * stream->n_channels;
9979         stream->bytes_per_sample = 1;
9980         stream->samples_per_frame = 3 * stream->n_channels;
9981         break;
9982       }
9983       case FOURCC_ima4:
9984       {
9985         stream->samples_per_packet = 64;
9986         stream->bytes_per_packet = 34;
9987         stream->bytes_per_frame = 34 * stream->n_channels;
9988         stream->bytes_per_sample = 2;
9989         stream->samples_per_frame = 64 * stream->n_channels;
9990         break;
9991       }
9992       case FOURCC_ulaw:
9993       case FOURCC_alaw:
9994       {
9995         stream->samples_per_packet = 1;
9996         stream->bytes_per_packet = 1;
9997         stream->bytes_per_frame = 1 * stream->n_channels;
9998         stream->bytes_per_sample = 1;
9999         stream->samples_per_frame = 1 * stream->n_channels;
10000         break;
10001       }
10002       case FOURCC_agsm:
10003       {
10004         stream->samples_per_packet = 160;
10005         stream->bytes_per_packet = 33;
10006         stream->bytes_per_frame = 33 * stream->n_channels;
10007         stream->bytes_per_sample = 2;
10008         stream->samples_per_frame = 160 * stream->n_channels;
10009         break;
10010       }
10011       default:
10012         break;
10013     }
10014
10015     if (version == 0x00010000) {
10016       /* sample description entry (16) + sound sample description v1 (20+16) */
10017       if (len < 52)
10018         goto corrupt_file;
10019
10020       switch (fourcc) {
10021         case FOURCC_twos:
10022         case FOURCC_sowt:
10023         case FOURCC_raw_:
10024           break;
10025         default:
10026         {
10027           /* only parse extra decoding config for non-pcm audio */
10028           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10029           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10030           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10031           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10032
10033           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10034               stream->samples_per_packet);
10035           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10036               stream->bytes_per_packet);
10037           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10038               stream->bytes_per_frame);
10039           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10040               stream->bytes_per_sample);
10041
10042           if (!stream->sampled && stream->bytes_per_packet) {
10043             stream->samples_per_frame = (stream->bytes_per_frame /
10044                 stream->bytes_per_packet) * stream->samples_per_packet;
10045             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10046                 stream->samples_per_frame);
10047           }
10048           break;
10049         }
10050       }
10051     } else if (version == 0x00020000) {
10052       union
10053       {
10054         gdouble fp;
10055         guint64 val;
10056       } qtfp;
10057
10058       /* sample description entry (16) + sound sample description v2 (56) */
10059       if (len < 72)
10060         goto corrupt_file;
10061
10062       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10063       stream->rate = qtfp.fp;
10064       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10065
10066       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10067       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10068       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10069       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10070           QT_UINT32 (stsd_data + offset + 20));
10071       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10072           QT_UINT32 (stsd_data + offset + 24));
10073       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10074           QT_UINT32 (stsd_data + offset + 28));
10075       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10076           QT_UINT32 (stsd_data + offset + 32));
10077     } else if (version != 0x00000) {
10078       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10079     }
10080
10081     if (stream->caps)
10082       gst_caps_unref (stream->caps);
10083
10084     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10085         stsd_data + 32, len - 16, &codec);
10086
10087     switch (fourcc) {
10088       case FOURCC_in24:
10089       {
10090         GNode *enda;
10091         GNode *in24;
10092
10093         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10094
10095         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10096         if (!enda) {
10097           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10098           if (wave)
10099             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10100         }
10101         if (enda) {
10102           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10103           gst_caps_set_simple (stream->caps,
10104               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10105         }
10106         break;
10107       }
10108       case FOURCC_owma:
10109       {
10110         GNode *owma;
10111         const guint8 *owma_data;
10112         const gchar *codec_name = NULL;
10113         guint owma_len;
10114         GstBuffer *buf;
10115         gint version = 1;
10116         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10117         /* FIXME this should also be gst_riff_strf_auds,
10118          * but the latter one is actually missing bits-per-sample :( */
10119         typedef struct
10120         {
10121           gint16 wFormatTag;
10122           gint16 nChannels;
10123           gint32 nSamplesPerSec;
10124           gint32 nAvgBytesPerSec;
10125           gint16 nBlockAlign;
10126           gint16 wBitsPerSample;
10127           gint16 cbSize;
10128         } WAVEFORMATEX;
10129         WAVEFORMATEX *wfex;
10130
10131         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10132         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10133         if (!owma)
10134           break;
10135         owma_data = owma->data;
10136         owma_len = QT_UINT32 (owma_data);
10137         if (owma_len <= 54) {
10138           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10139           break;
10140         }
10141         wfex = (WAVEFORMATEX *) (owma_data + 36);
10142         buf = gst_buffer_new_and_alloc (owma_len - 54);
10143         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10144         if (wfex->wFormatTag == 0x0161) {
10145           codec_name = "Windows Media Audio";
10146           version = 2;
10147         } else if (wfex->wFormatTag == 0x0162) {
10148           codec_name = "Windows Media Audio 9 Pro";
10149           version = 3;
10150         } else if (wfex->wFormatTag == 0x0163) {
10151           codec_name = "Windows Media Audio 9 Lossless";
10152           /* is that correct? gstffmpegcodecmap.c is missing it, but
10153            * fluendo codec seems to support it */
10154           version = 4;
10155         }
10156
10157         gst_caps_set_simple (stream->caps,
10158             "codec_data", GST_TYPE_BUFFER, buf,
10159             "wmaversion", G_TYPE_INT, version,
10160             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10161             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10162             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10163             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10164             NULL);
10165         gst_buffer_unref (buf);
10166
10167         if (codec_name) {
10168           g_free (codec);
10169           codec = g_strdup (codec_name);
10170         }
10171         break;
10172       }
10173       case FOURCC_wma_:
10174       {
10175         gint len = QT_UINT32 (stsd_data) - offset;
10176         const guint8 *wfex_data = stsd_data + offset;
10177         const gchar *codec_name = NULL;
10178         gint version = 1;
10179         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10180         /* FIXME this should also be gst_riff_strf_auds,
10181          * but the latter one is actually missing bits-per-sample :( */
10182         typedef struct
10183         {
10184           gint16 wFormatTag;
10185           gint16 nChannels;
10186           gint32 nSamplesPerSec;
10187           gint32 nAvgBytesPerSec;
10188           gint16 nBlockAlign;
10189           gint16 wBitsPerSample;
10190           gint16 cbSize;
10191         } WAVEFORMATEX;
10192         WAVEFORMATEX wfex;
10193
10194         /* FIXME: unify with similar wavformatex parsing code above */
10195         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10196
10197         /* find wfex */
10198         while (len >= 8) {
10199           gint size;
10200
10201           if (QT_UINT32 (wfex_data) <= len)
10202             size = QT_UINT32 (wfex_data) - 8;
10203           else
10204             size = len - 8;
10205
10206           if (size < 1)
10207             /* No real data, so break out */
10208             break;
10209
10210           switch (QT_FOURCC (wfex_data + 4)) {
10211             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10212             {
10213               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10214
10215               if (size < 8 + 18)
10216                 break;
10217
10218               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10219               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10220               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10221               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10222               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10223               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10224               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10225
10226               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10227               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10228                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10229                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10230                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10231                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10232
10233               if (wfex.wFormatTag == 0x0161) {
10234                 codec_name = "Windows Media Audio";
10235                 version = 2;
10236               } else if (wfex.wFormatTag == 0x0162) {
10237                 codec_name = "Windows Media Audio 9 Pro";
10238                 version = 3;
10239               } else if (wfex.wFormatTag == 0x0163) {
10240                 codec_name = "Windows Media Audio 9 Lossless";
10241                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10242                  * fluendo codec seems to support it */
10243                 version = 4;
10244               }
10245
10246               gst_caps_set_simple (stream->caps,
10247                   "wmaversion", G_TYPE_INT, version,
10248                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10249                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10250                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10251                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10252
10253               if (size > wfex.cbSize) {
10254                 GstBuffer *buf;
10255
10256                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10257                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10258                     size - wfex.cbSize);
10259                 gst_caps_set_simple (stream->caps,
10260                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10261                 gst_buffer_unref (buf);
10262               } else {
10263                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10264               }
10265
10266               if (codec_name) {
10267                 g_free (codec);
10268                 codec = g_strdup (codec_name);
10269               }
10270               break;
10271             }
10272             default:
10273               break;
10274           }
10275           len -= size + 8;
10276           wfex_data += size + 8;
10277         }
10278         break;
10279       }
10280       case FOURCC_opus:
10281       {
10282         GNode *opus;
10283         const guint8 *opus_data;
10284         guint8 *channel_mapping = NULL;
10285         guint32 rate;
10286         guint8 channels;
10287         guint8 channel_mapping_family;
10288         guint8 stream_count;
10289         guint8 coupled_count;
10290         guint8 i;
10291
10292         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10293         opus_data = opus->data;
10294
10295         channels = GST_READ_UINT8 (opus_data + 45);
10296         rate = GST_READ_UINT32_LE (opus_data + 48);
10297         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10298         stream_count = GST_READ_UINT8 (opus_data + 55);
10299         coupled_count = GST_READ_UINT8 (opus_data + 56);
10300
10301         if (channels > 0) {
10302           channel_mapping = g_malloc (channels * sizeof (guint8));
10303           for (i = 0; i < channels; i++)
10304             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10305         }
10306
10307         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10308             channel_mapping_family, stream_count, coupled_count,
10309             channel_mapping);
10310         break;
10311       }
10312       default:
10313         break;
10314     }
10315
10316     if (codec) {
10317       GstStructure *s;
10318       gint bitrate = 0;
10319
10320       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10321           GST_TAG_AUDIO_CODEC, codec, NULL);
10322       g_free (codec);
10323       codec = NULL;
10324
10325       /* some bitrate info may have ended up in caps */
10326       s = gst_caps_get_structure (stream->caps, 0);
10327       gst_structure_get_int (s, "bitrate", &bitrate);
10328       if (bitrate > 0)
10329         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10330             GST_TAG_BITRATE, bitrate, NULL);
10331     }
10332
10333     if (stream->protected && fourcc == FOURCC_mp4a)
10334       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10335     else
10336       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10337
10338     wave = NULL;
10339     esds = NULL;
10340     if (mp4a) {
10341       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10342       if (wave)
10343         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10344       if (!esds)
10345         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10346     }
10347
10348
10349     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10350        16 bits is a byte-swapped wave-style codec identifier,
10351        and we can find a WAVE header internally to a 'wave' atom here.
10352        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10353        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10354        is big-endian).
10355      */
10356     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10357       if (len < offset + 20) {
10358         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10359       } else {
10360         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10361         const guint8 *data = stsd_data + offset + 16;
10362         GNode *wavenode;
10363         GNode *waveheadernode;
10364
10365         wavenode = g_node_new ((guint8 *) data);
10366         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10367           const guint8 *waveheader;
10368           guint32 headerlen;
10369
10370           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10371           if (waveheadernode) {
10372             waveheader = (const guint8 *) waveheadernode->data;
10373             headerlen = QT_UINT32 (waveheader);
10374
10375             if (headerlen > 8) {
10376               gst_riff_strf_auds *header = NULL;
10377               GstBuffer *headerbuf;
10378               GstBuffer *extra;
10379
10380               waveheader += 8;
10381               headerlen -= 8;
10382
10383               headerbuf = gst_buffer_new_and_alloc (headerlen);
10384               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10385
10386               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10387                       headerbuf, &header, &extra)) {
10388                 gst_caps_unref (stream->caps);
10389                 /* FIXME: Need to do something with the channel reorder map */
10390                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10391                     header, extra, NULL, NULL, NULL);
10392
10393                 if (extra)
10394                   gst_buffer_unref (extra);
10395                 g_free (header);
10396               }
10397             }
10398           } else
10399             GST_DEBUG ("Didn't find waveheadernode for this codec");
10400         }
10401         g_node_destroy (wavenode);
10402       }
10403     } else if (esds) {
10404       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10405     } else {
10406       switch (fourcc) {
10407 #if 0
10408           /* FIXME: what is in the chunk? */
10409         case FOURCC_QDMC:
10410         {
10411           gint len = QT_UINT32 (stsd_data);
10412
10413           /* seems to be always = 116 = 0x74 */
10414           break;
10415         }
10416 #endif
10417         case FOURCC_QDM2:
10418         {
10419           gint len = QT_UINT32 (stsd_data);
10420
10421           if (len > 0x4C) {
10422             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10423
10424             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10425             gst_caps_set_simple (stream->caps,
10426                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10427             gst_buffer_unref (buf);
10428           }
10429           gst_caps_set_simple (stream->caps,
10430               "samplesize", G_TYPE_INT, samplesize, NULL);
10431           break;
10432         }
10433         case FOURCC_alac:
10434         {
10435           GNode *alac, *wave = NULL;
10436
10437           /* apparently, m4a has this atom appended directly in the stsd entry,
10438            * while mov has it in a wave atom */
10439           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10440           if (alac) {
10441             /* alac now refers to stsd entry atom */
10442             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10443             if (wave)
10444               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10445             else
10446               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10447           }
10448           if (alac) {
10449             const guint8 *alac_data = alac->data;
10450             gint len = QT_UINT32 (alac->data);
10451             GstBuffer *buf;
10452
10453             if (len < 36) {
10454               GST_DEBUG_OBJECT (qtdemux,
10455                   "discarding alac atom with unexpected len %d", len);
10456             } else {
10457               /* codec-data contains alac atom size and prefix,
10458                * ffmpeg likes it that way, not quite gst-ish though ...*/
10459               buf = gst_buffer_new_and_alloc (len);
10460               gst_buffer_fill (buf, 0, alac->data, len);
10461               gst_caps_set_simple (stream->caps,
10462                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10463               gst_buffer_unref (buf);
10464
10465               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10466               stream->n_channels = QT_UINT8 (alac_data + 21);
10467               stream->rate = QT_UINT32 (alac_data + 32);
10468             }
10469           }
10470           gst_caps_set_simple (stream->caps,
10471               "samplesize", G_TYPE_INT, samplesize, NULL);
10472           break;
10473         }
10474         case FOURCC_sawb:
10475           /* Fallthrough! */
10476           amrwb = TRUE;
10477         case FOURCC_samr:
10478         {
10479           gint len = QT_UINT32 (stsd_data);
10480
10481           if (len > 0x34) {
10482             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10483             guint bitrate;
10484
10485             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10486
10487             /* If we have enough data, let's try to get the 'damr' atom. See
10488              * the 3GPP container spec (26.244) for more details. */
10489             if ((len - 0x34) > 8 &&
10490                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10491               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10492                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10493             }
10494
10495             gst_caps_set_simple (stream->caps,
10496                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10497             gst_buffer_unref (buf);
10498           }
10499           break;
10500         }
10501         case FOURCC_mp4a:
10502         {
10503           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10504           gint len = QT_UINT32 (stsd_data);
10505
10506           if (len >= 50) {
10507             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10508
10509             if (sound_version == 1) {
10510               guint16 channels = QT_UINT16 (stsd_data + 40);
10511               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10512               guint8 codec_data[2];
10513               GstBuffer *buf;
10514               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10515
10516               gint sample_rate_index =
10517                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10518
10519               /* build AAC codec data */
10520               codec_data[0] = profile << 3;
10521               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10522               codec_data[1] = (sample_rate_index & 0x01) << 7;
10523               codec_data[1] |= (channels & 0xF) << 3;
10524
10525               buf = gst_buffer_new_and_alloc (2);
10526               gst_buffer_fill (buf, 0, codec_data, 2);
10527               gst_caps_set_simple (stream->caps,
10528                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10529               gst_buffer_unref (buf);
10530             }
10531           }
10532           break;
10533         }
10534         default:
10535           GST_INFO_OBJECT (qtdemux,
10536               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10537           break;
10538       }
10539     }
10540     GST_INFO_OBJECT (qtdemux,
10541         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10542         GST_FOURCC_ARGS (fourcc), stream->caps);
10543
10544   } else if (stream->subtype == FOURCC_strm) {
10545     if (fourcc == FOURCC_rtsp) {
10546       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10547     } else {
10548       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10549           GST_FOURCC_ARGS (fourcc));
10550       goto unknown_stream;
10551     }
10552     stream->sampled = TRUE;
10553   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10554       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10555
10556     stream->sampled = TRUE;
10557     stream->sparse = TRUE;
10558
10559     stream->caps =
10560         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10561     if (codec) {
10562       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10563           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10564       g_free (codec);
10565       codec = NULL;
10566     }
10567
10568     /* hunt for sort-of codec data */
10569     switch (fourcc) {
10570       case FOURCC_mp4s:
10571       {
10572         GNode *mp4s = NULL;
10573         GNode *esds = NULL;
10574
10575         /* look for palette in a stsd->mp4s->esds sub-atom */
10576         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10577         if (mp4s)
10578           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10579         if (esds == NULL) {
10580           /* Invalid STSD */
10581           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10582           break;
10583         }
10584
10585         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10586         break;
10587       }
10588       default:
10589         GST_INFO_OBJECT (qtdemux,
10590             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10591         break;
10592     }
10593     GST_INFO_OBJECT (qtdemux,
10594         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10595         GST_FOURCC_ARGS (fourcc), stream->caps);
10596   } else {
10597     /* everything in 1 sample */
10598     stream->sampled = TRUE;
10599
10600     stream->caps =
10601         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10602
10603     if (stream->caps == NULL)
10604       goto unknown_stream;
10605
10606     if (codec) {
10607       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10608           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10609       g_free (codec);
10610       codec = NULL;
10611     }
10612   }
10613
10614   /* promote to sampled format */
10615   if (stream->fourcc == FOURCC_samr) {
10616     /* force mono 8000 Hz for AMR */
10617     stream->sampled = TRUE;
10618     stream->n_channels = 1;
10619     stream->rate = 8000;
10620   } else if (stream->fourcc == FOURCC_sawb) {
10621     /* force mono 16000 Hz for AMR-WB */
10622     stream->sampled = TRUE;
10623     stream->n_channels = 1;
10624     stream->rate = 16000;
10625   } else if (stream->fourcc == FOURCC_mp4a) {
10626     stream->sampled = TRUE;
10627   }
10628
10629   /* collect sample information */
10630   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10631     goto samples_failed;
10632
10633   if (qtdemux->fragmented) {
10634     guint64 offset;
10635
10636     /* need all moov samples as basis; probably not many if any at all */
10637     /* prevent moof parsing taking of at this time */
10638     offset = qtdemux->moof_offset;
10639     qtdemux->moof_offset = 0;
10640     if (stream->n_samples &&
10641         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10642       qtdemux->moof_offset = offset;
10643       goto samples_failed;
10644     }
10645     qtdemux->moof_offset = 0;
10646     /* movie duration more reliable in this case (e.g. mehd) */
10647     if (qtdemux->segment.duration &&
10648         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10649       stream->duration =
10650           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10651   }
10652
10653   /* configure segments */
10654   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10655     goto segments_failed;
10656
10657   /* add some language tag, if useful */
10658   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10659       strcmp (stream->lang_id, "und")) {
10660     const gchar *lang_code;
10661
10662     /* convert ISO 639-2 code to ISO 639-1 */
10663     lang_code = gst_tag_get_language_code (stream->lang_id);
10664     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10665         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10666   }
10667
10668   /* Check for UDTA tags */
10669   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10670     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10671   }
10672
10673   /* now we are ready to add the stream */
10674   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10675     goto too_many_streams;
10676
10677   if (!qtdemux->got_moov) {
10678     qtdemux->streams[qtdemux->n_streams] = stream;
10679     qtdemux->n_streams++;
10680     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10681   }
10682
10683   return TRUE;
10684
10685 /* ERRORS */
10686 skip_track:
10687   {
10688     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10689     if (new_stream)
10690       gst_qtdemux_stream_free (qtdemux, stream);
10691     return TRUE;
10692   }
10693 corrupt_file:
10694   {
10695     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10696         (_("This file is corrupt and cannot be played.")), (NULL));
10697     if (new_stream)
10698       gst_qtdemux_stream_free (qtdemux, stream);
10699     return FALSE;
10700   }
10701 error_encrypted:
10702   {
10703     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10704     if (new_stream)
10705       gst_qtdemux_stream_free (qtdemux, stream);
10706     return FALSE;
10707   }
10708 samples_failed:
10709 segments_failed:
10710   {
10711     /* we posted an error already */
10712     /* free stbl sub-atoms */
10713     gst_qtdemux_stbl_free (stream);
10714     if (new_stream)
10715       gst_qtdemux_stream_free (qtdemux, stream);
10716     return FALSE;
10717   }
10718 existing_stream:
10719   {
10720     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10721         track_id);
10722     if (new_stream)
10723       gst_qtdemux_stream_free (qtdemux, stream);
10724     return TRUE;
10725   }
10726 unknown_stream:
10727   {
10728     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10729         GST_FOURCC_ARGS (stream->subtype));
10730     if (new_stream)
10731       gst_qtdemux_stream_free (qtdemux, stream);
10732     return TRUE;
10733   }
10734 too_many_streams:
10735   {
10736     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10737         (_("This file contains too many streams. Only playing first %d"),
10738             GST_QTDEMUX_MAX_STREAMS), (NULL));
10739     return TRUE;
10740   }
10741 }
10742
10743 /* If we can estimate the overall bitrate, and don't have information about the
10744  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10745  * the overall bitrate minus the sum of the bitrates of all other streams. This
10746  * should be useful for the common case where we have one audio and one video
10747  * stream and can estimate the bitrate of one, but not the other. */
10748 static void
10749 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10750 {
10751   QtDemuxStream *stream = NULL;
10752   gint64 size, sys_bitrate, sum_bitrate = 0;
10753   GstClockTime duration;
10754   gint i;
10755   guint bitrate;
10756
10757   if (qtdemux->fragmented)
10758     return;
10759
10760   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10761
10762   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10763       || size <= 0) {
10764     GST_DEBUG_OBJECT (qtdemux,
10765         "Size in bytes of the stream not known - bailing");
10766     return;
10767   }
10768
10769   /* Subtract the header size */
10770   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10771       size, qtdemux->header_size);
10772
10773   if (size < qtdemux->header_size)
10774     return;
10775
10776   size = size - qtdemux->header_size;
10777
10778   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
10779     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10780     return;
10781   }
10782
10783   for (i = 0; i < qtdemux->n_streams; i++) {
10784     switch (qtdemux->streams[i]->subtype) {
10785       case FOURCC_soun:
10786       case FOURCC_vide:
10787         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10788             qtdemux->streams[i]->caps);
10789         /* retrieve bitrate, prefer avg then max */
10790         bitrate = 0;
10791         if (qtdemux->streams[i]->pending_tags) {
10792           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10793               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10794           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10795           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10796               GST_TAG_NOMINAL_BITRATE, &bitrate);
10797           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10798           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10799               GST_TAG_BITRATE, &bitrate);
10800           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10801         }
10802         if (bitrate)
10803           sum_bitrate += bitrate;
10804         else {
10805           if (stream) {
10806             GST_DEBUG_OBJECT (qtdemux,
10807                 ">1 stream with unknown bitrate - bailing");
10808             return;
10809           } else
10810             stream = qtdemux->streams[i];
10811         }
10812
10813       default:
10814         /* For other subtypes, we assume no significant impact on bitrate */
10815         break;
10816     }
10817   }
10818
10819   if (!stream) {
10820     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10821     return;
10822   }
10823
10824   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10825
10826   if (sys_bitrate < sum_bitrate) {
10827     /* This can happen, since sum_bitrate might be derived from maximum
10828      * bitrates and not average bitrates */
10829     GST_DEBUG_OBJECT (qtdemux,
10830         "System bitrate less than sum bitrate - bailing");
10831     return;
10832   }
10833
10834   bitrate = sys_bitrate - sum_bitrate;
10835   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10836       ", Stream bitrate = %u", sys_bitrate, bitrate);
10837
10838   if (!stream->pending_tags)
10839     stream->pending_tags = gst_tag_list_new_empty ();
10840
10841   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10842       GST_TAG_BITRATE, bitrate, NULL);
10843 }
10844
10845 static GstFlowReturn
10846 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10847 {
10848   gint i;
10849   GstFlowReturn ret = GST_FLOW_OK;
10850
10851   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10852
10853   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10854     QtDemuxStream *stream = qtdemux->streams[i];
10855     guint32 sample_num = 0;
10856
10857     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10858         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10859
10860     if (qtdemux->fragmented) {
10861       /* need all moov samples first */
10862       GST_OBJECT_LOCK (qtdemux);
10863       while (stream->n_samples == 0)
10864         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10865           break;
10866       GST_OBJECT_UNLOCK (qtdemux);
10867     } else {
10868       /* discard any stray moof */
10869       qtdemux->moof_offset = 0;
10870     }
10871
10872     /* prepare braking */
10873     if (ret != GST_FLOW_ERROR)
10874       ret = GST_FLOW_OK;
10875
10876     /* in pull mode, we should have parsed some sample info by now;
10877      * and quite some code will not handle no samples.
10878      * in push mode, we'll just have to deal with it */
10879     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10880       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10881       gst_qtdemux_remove_stream (qtdemux, i);
10882       i--;
10883       continue;
10884     }
10885
10886     /* parse the initial sample for use in setting the frame rate cap */
10887     while (sample_num == 0 && sample_num < stream->n_samples) {
10888       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10889         break;
10890       ++sample_num;
10891     }
10892     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10893       stream->first_duration = stream->samples[0].duration;
10894       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10895           stream->track_id, stream->first_duration);
10896     }
10897   }
10898
10899   return ret;
10900 }
10901
10902 static GstFlowReturn
10903 qtdemux_expose_streams (GstQTDemux * qtdemux)
10904 {
10905   gint i;
10906   GstFlowReturn ret = GST_FLOW_OK;
10907   GSList *oldpads = NULL;
10908   GSList *iter;
10909
10910   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10911
10912   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10913     QtDemuxStream *stream = qtdemux->streams[i];
10914     GstPad *oldpad = stream->pad;
10915     GstTagList *list;
10916
10917     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10918         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10919
10920     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10921         stream->track_id == qtdemux->chapters_track_id) {
10922       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10923          so that it doesn't look like a subtitle track */
10924       gst_qtdemux_remove_stream (qtdemux, i);
10925       i--;
10926       continue;
10927     }
10928
10929     /* now we have all info and can expose */
10930     list = stream->pending_tags;
10931     stream->pending_tags = NULL;
10932     if (oldpad)
10933       oldpads = g_slist_prepend (oldpads, oldpad);
10934     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
10935       return GST_FLOW_ERROR;
10936   }
10937
10938   gst_qtdemux_guess_bitrate (qtdemux);
10939
10940   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10941
10942   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10943     GstPad *oldpad = iter->data;
10944     GstEvent *event;
10945
10946     event = gst_event_new_eos ();
10947     if (qtdemux->segment_seqnum)
10948       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
10949
10950     gst_pad_push_event (oldpad, event);
10951     gst_pad_set_active (oldpad, FALSE);
10952     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10953     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10954     gst_object_unref (oldpad);
10955   }
10956
10957   /* check if we should post a redirect in case there is a single trak
10958    * and it is a redirecting trak */
10959   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10960     GstMessage *m;
10961
10962     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10963         "an external content");
10964     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10965         gst_structure_new ("redirect",
10966             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10967             NULL));
10968     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10969     qtdemux->posted_redirect = TRUE;
10970   }
10971
10972   for (i = 0; i < qtdemux->n_streams; i++) {
10973     QtDemuxStream *stream = qtdemux->streams[i];
10974
10975     qtdemux_do_allocation (qtdemux, stream);
10976   }
10977
10978   qtdemux->exposed = TRUE;
10979   return ret;
10980 }
10981
10982 /* check if major or compatible brand is 3GP */
10983 static inline gboolean
10984 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10985 {
10986   if (major) {
10987     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10988         FOURCC_3g__);
10989   } else if (qtdemux->comp_brands != NULL) {
10990     GstMapInfo map;
10991     guint8 *data;
10992     gsize size;
10993     gboolean res = FALSE;
10994
10995     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10996     data = map.data;
10997     size = map.size;
10998     while (size >= 4) {
10999       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11000           FOURCC_3g__);
11001       data += 4;
11002       size -= 4;
11003     }
11004     gst_buffer_unmap (qtdemux->comp_brands, &map);
11005     return res;
11006   } else {
11007     return FALSE;
11008   }
11009 }
11010
11011 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11012 static inline gboolean
11013 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11014 {
11015   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11016       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11017       || fourcc == FOURCC_albm;
11018 }
11019
11020 static void
11021 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11022     const char *tag, const char *dummy, GNode * node)
11023 {
11024   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11025   int offset;
11026   char *name;
11027   gchar *data;
11028   gdouble longitude, latitude, altitude;
11029   gint len;
11030
11031   len = QT_UINT32 (node->data);
11032   if (len <= 14)
11033     goto short_read;
11034
11035   data = node->data;
11036   offset = 14;
11037
11038   /* TODO: language code skipped */
11039
11040   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11041
11042   if (!name) {
11043     /* do not alarm in trivial case, but bail out otherwise */
11044     if (*(data + offset) != 0) {
11045       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11046           "giving up", tag);
11047     }
11048   } else {
11049     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11050         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11051     offset += strlen (name);
11052     g_free (name);
11053   }
11054
11055   if (len < offset + 2 + 4 + 4 + 4)
11056     goto short_read;
11057
11058   /* +1 +1 = skip null-terminator and location role byte */
11059   offset += 1 + 1;
11060   /* table in spec says unsigned, semantics say negative has meaning ... */
11061   longitude = QT_SFP32 (data + offset);
11062
11063   offset += 4;
11064   latitude = QT_SFP32 (data + offset);
11065
11066   offset += 4;
11067   altitude = QT_SFP32 (data + offset);
11068
11069   /* one invalid means all are invalid */
11070   if (longitude >= -180.0 && longitude <= 180.0 &&
11071       latitude >= -90.0 && latitude <= 90.0) {
11072     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11073         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11074         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11075         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11076   }
11077
11078   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11079
11080   return;
11081
11082   /* ERRORS */
11083 short_read:
11084   {
11085     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11086     return;
11087   }
11088 }
11089
11090
11091 static void
11092 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11093     const char *tag, const char *dummy, GNode * node)
11094 {
11095   guint16 y;
11096   GDate *date;
11097   gint len;
11098
11099   len = QT_UINT32 (node->data);
11100   if (len < 14)
11101     return;
11102
11103   y = QT_UINT16 ((guint8 *) node->data + 12);
11104   if (y == 0) {
11105     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11106     return;
11107   }
11108   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11109
11110   date = g_date_new_dmy (1, 1, y);
11111   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11112   g_date_free (date);
11113 }
11114
11115 static void
11116 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11117     const char *tag, const char *dummy, GNode * node)
11118 {
11119   int offset;
11120   char *tag_str = NULL;
11121   guint8 *entity;
11122   guint16 table;
11123   gint len;
11124
11125   len = QT_UINT32 (node->data);
11126   if (len <= 20)
11127     goto short_read;
11128
11129   offset = 12;
11130   entity = (guint8 *) node->data + offset;
11131   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11132     GST_DEBUG_OBJECT (qtdemux,
11133         "classification info: %c%c%c%c invalid classification entity",
11134         entity[0], entity[1], entity[2], entity[3]);
11135     return;
11136   }
11137
11138   offset += 4;
11139   table = QT_UINT16 ((guint8 *) node->data + offset);
11140
11141   /* Language code skipped */
11142
11143   offset += 4;
11144
11145   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11146    * XXXX: classification entity, fixed length 4 chars.
11147    * Y[YYYY]: classification table, max 5 chars.
11148    */
11149   tag_str = g_strdup_printf ("----://%u/%s",
11150       table, (char *) node->data + offset);
11151
11152   /* memcpy To be sure we're preserving byte order */
11153   memcpy (tag_str, entity, 4);
11154   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11155
11156   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11157
11158   g_free (tag_str);
11159
11160   return;
11161
11162   /* ERRORS */
11163 short_read:
11164   {
11165     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11166     return;
11167   }
11168 }
11169
11170 static gboolean
11171 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11172     const char *tag, const char *dummy, GNode * node)
11173 {
11174   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11175   GNode *data;
11176   char *s;
11177   int len;
11178   guint32 type;
11179   int offset;
11180   gboolean ret = TRUE;
11181   const gchar *charset = NULL;
11182
11183   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11184   if (data) {
11185     len = QT_UINT32 (data->data);
11186     type = QT_UINT32 ((guint8 *) data->data + 8);
11187     if (type == 0x00000001 && len > 16) {
11188       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11189           env_vars);
11190       if (s) {
11191         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11192         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11193         g_free (s);
11194       } else {
11195         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11196       }
11197     }
11198   } else {
11199     len = QT_UINT32 (node->data);
11200     type = QT_UINT32 ((guint8 *) node->data + 4);
11201     if ((type >> 24) == 0xa9) {
11202       gint str_len;
11203       gint lang_code;
11204
11205       /* Type starts with the (C) symbol, so the next data is a list
11206        * of (string size(16), language code(16), string) */
11207
11208       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11209       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11210
11211       /* the string + fourcc + size + 2 16bit fields,
11212        * means that there are more tags in this atom */
11213       if (len > str_len + 8 + 4) {
11214         /* TODO how to represent the same tag in different languages? */
11215         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11216             "text alternatives, reading only first one");
11217       }
11218
11219       offset = 12;
11220       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11221       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11222
11223       if (lang_code < 0x800) {  /* MAC encoded string */
11224         charset = "mac";
11225       }
11226     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11227             QT_FOURCC ((guint8 *) node->data + 4))) {
11228       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11229
11230       /* we go for 3GP style encoding if major brands claims so,
11231        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11232       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11233           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11234               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11235         offset = 14;
11236         /* 16-bit Language code is ignored here as well */
11237         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11238       } else {
11239         goto normal;
11240       }
11241     } else {
11242     normal:
11243       offset = 8;
11244       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11245       ret = FALSE;              /* may have to fallback */
11246     }
11247     if (charset) {
11248       GError *err = NULL;
11249
11250       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11251           charset, NULL, NULL, &err);
11252       if (err) {
11253         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11254             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11255             err->message);
11256         g_error_free (err);
11257       }
11258     } else {
11259       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11260           len - offset, env_vars);
11261     }
11262     if (s) {
11263       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11264       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11265       g_free (s);
11266       ret = TRUE;
11267     } else {
11268       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11269     }
11270   }
11271   return ret;
11272 }
11273
11274 static void
11275 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11276     const char *tag, const char *dummy, GNode * node)
11277 {
11278   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11279 }
11280
11281 static void
11282 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11283     const char *tag, const char *dummy, GNode * node)
11284 {
11285   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11286   guint8 *data;
11287   char *s, *t, *k = NULL;
11288   int len;
11289   int offset;
11290   int count;
11291
11292   /* first try normal string tag if major brand not 3GP */
11293   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11294     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11295       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11296        * let's try it 3gpp way after minor safety check */
11297       data = node->data;
11298       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11299         return;
11300     } else
11301       return;
11302   }
11303
11304   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11305
11306   data = node->data;
11307
11308   len = QT_UINT32 (data);
11309   if (len < 15)
11310     goto short_read;
11311
11312   count = QT_UINT8 (data + 14);
11313   offset = 15;
11314   for (; count; count--) {
11315     gint slen;
11316
11317     if (offset + 1 > len)
11318       goto short_read;
11319     slen = QT_UINT8 (data + offset);
11320     offset += 1;
11321     if (offset + slen > len)
11322       goto short_read;
11323     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11324         slen, env_vars);
11325     if (s) {
11326       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11327       if (k) {
11328         t = g_strjoin (",", k, s, NULL);
11329         g_free (s);
11330         g_free (k);
11331         k = t;
11332       } else {
11333         k = s;
11334       }
11335     } else {
11336       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11337     }
11338     offset += slen;
11339   }
11340
11341 done:
11342   if (k) {
11343     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11344     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11345   }
11346   g_free (k);
11347
11348   return;
11349
11350   /* ERRORS */
11351 short_read:
11352   {
11353     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11354     goto done;
11355   }
11356 }
11357
11358 static void
11359 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11360     const char *tag1, const char *tag2, GNode * node)
11361 {
11362   GNode *data;
11363   int len;
11364   int type;
11365   int n1, n2;
11366
11367   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11368   if (data) {
11369     len = QT_UINT32 (data->data);
11370     type = QT_UINT32 ((guint8 *) data->data + 8);
11371     if (type == 0x00000000 && len >= 22) {
11372       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11373       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11374       if (n1 > 0) {
11375         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11376         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11377       }
11378       if (n2 > 0) {
11379         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11380         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11381       }
11382     }
11383   }
11384 }
11385
11386 static void
11387 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11388     const char *tag1, const char *dummy, GNode * node)
11389 {
11390   GNode *data;
11391   int len;
11392   int type;
11393   int n1;
11394
11395   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11396   if (data) {
11397     len = QT_UINT32 (data->data);
11398     type = QT_UINT32 ((guint8 *) data->data + 8);
11399     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11400     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11401     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11402       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11403       if (n1) {
11404         /* do not add bpm=0 */
11405         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11406         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11407             NULL);
11408       }
11409     }
11410   }
11411 }
11412
11413 static void
11414 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11415     const char *tag1, const char *dummy, GNode * node)
11416 {
11417   GNode *data;
11418   int len;
11419   int type;
11420   guint32 num;
11421
11422   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11423   if (data) {
11424     len = QT_UINT32 (data->data);
11425     type = QT_UINT32 ((guint8 *) data->data + 8);
11426     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11427     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11428     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11429       num = QT_UINT32 ((guint8 *) data->data + 16);
11430       if (num) {
11431         /* do not add num=0 */
11432         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11433         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11434       }
11435     }
11436   }
11437 }
11438
11439 static void
11440 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11441     const char *tag1, const char *dummy, GNode * node)
11442 {
11443   GNode *data;
11444   int len;
11445   int type;
11446   GstSample *sample;
11447
11448   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11449   if (data) {
11450     len = QT_UINT32 (data->data);
11451     type = QT_UINT32 ((guint8 *) data->data + 8);
11452     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11453     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11454       if ((sample =
11455               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11456                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11457         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11458         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11459         gst_sample_unref (sample);
11460       }
11461     }
11462   }
11463 }
11464
11465 static void
11466 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11467     const char *tag, const char *dummy, GNode * node)
11468 {
11469   GNode *data;
11470   char *s;
11471   int len;
11472   int type;
11473
11474   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11475   if (data) {
11476     len = QT_UINT32 (data->data);
11477     type = QT_UINT32 ((guint8 *) data->data + 8);
11478     if (type == 0x00000001 && len > 16) {
11479       guint y, m = 1, d = 1;
11480       gint ret;
11481
11482       s = g_strndup ((char *) data->data + 16, len - 16);
11483       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11484       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11485       if (ret >= 1 && y > 1500 && y < 3000) {
11486         GDate *date;
11487
11488         date = g_date_new_dmy (d, m, y);
11489         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11490         g_date_free (date);
11491       } else {
11492         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11493       }
11494       g_free (s);
11495     }
11496   }
11497 }
11498
11499 static void
11500 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11501     const char *tag, const char *dummy, GNode * node)
11502 {
11503   GNode *data;
11504
11505   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11506
11507   /* re-route to normal string tag if major brand says so
11508    * or no data atom and compatible brand suggests so */
11509   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11510       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11511     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11512     return;
11513   }
11514
11515   if (data) {
11516     guint len, type, n;
11517
11518     len = QT_UINT32 (data->data);
11519     type = QT_UINT32 ((guint8 *) data->data + 8);
11520     if (type == 0x00000000 && len >= 18) {
11521       n = QT_UINT16 ((guint8 *) data->data + 16);
11522       if (n > 0) {
11523         const gchar *genre;
11524
11525         genre = gst_tag_id3_genre_get (n - 1);
11526         if (genre != NULL) {
11527           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11528           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11529         }
11530       }
11531     }
11532   }
11533 }
11534
11535 static void
11536 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11537     const gchar * tag, guint8 * data, guint32 datasize)
11538 {
11539   gdouble value;
11540   gchar *datacopy;
11541
11542   /* make a copy to have \0 at the end */
11543   datacopy = g_strndup ((gchar *) data, datasize);
11544
11545   /* convert the str to double */
11546   if (sscanf (datacopy, "%lf", &value) == 1) {
11547     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11548     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11549   } else {
11550     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11551         datacopy);
11552   }
11553   g_free (datacopy);
11554 }
11555
11556
11557 static void
11558 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11559     const char *tag, const char *tag_bis, GNode * node)
11560 {
11561   GNode *mean;
11562   GNode *name;
11563   GNode *data;
11564   guint32 meansize;
11565   guint32 namesize;
11566   guint32 datatype;
11567   guint32 datasize;
11568   const gchar *meanstr;
11569   const gchar *namestr;
11570
11571   /* checking the whole ---- atom size for consistency */
11572   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11573     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11574     return;
11575   }
11576
11577   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11578   if (!mean) {
11579     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11580     return;
11581   }
11582
11583   meansize = QT_UINT32 (mean->data);
11584   if (meansize <= 12) {
11585     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11586     return;
11587   }
11588   meanstr = ((gchar *) mean->data) + 12;
11589   meansize -= 12;
11590
11591   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11592   if (!name) {
11593     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11594     return;
11595   }
11596
11597   namesize = QT_UINT32 (name->data);
11598   if (namesize <= 12) {
11599     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11600     return;
11601   }
11602   namestr = ((gchar *) name->data) + 12;
11603   namesize -= 12;
11604
11605   /*
11606    * Data atom is:
11607    * uint32 - size
11608    * uint32 - name
11609    * uint8  - version
11610    * uint24 - data type
11611    * uint32 - all 0
11612    * rest   - the data
11613    */
11614   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11615   if (!data) {
11616     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11617     return;
11618   }
11619   datasize = QT_UINT32 (data->data);
11620   if (datasize <= 16) {
11621     GST_WARNING_OBJECT (demux, "Data atom too small");
11622     return;
11623   }
11624   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11625
11626   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11627       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11628     static const struct
11629     {
11630       const gchar name[28];
11631       const gchar tag[28];
11632     } tags[] = {
11633       {
11634       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11635       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11636       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11637       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11638       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11639       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11640       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11641       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11642     };
11643     int i;
11644
11645     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11646       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11647         switch (gst_tag_get_type (tags[i].tag)) {
11648           case G_TYPE_DOUBLE:
11649             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11650                 ((guint8 *) data->data) + 16, datasize - 16);
11651             break;
11652           case G_TYPE_STRING:
11653             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11654             break;
11655           default:
11656             /* not reached */
11657             break;
11658         }
11659         break;
11660       }
11661     }
11662     if (i == G_N_ELEMENTS (tags))
11663       goto unknown_tag;
11664   } else {
11665     goto unknown_tag;
11666   }
11667
11668   return;
11669
11670 /* errors */
11671 unknown_tag:
11672 #ifndef GST_DISABLE_GST_DEBUG
11673   {
11674     gchar *namestr_dbg;
11675     gchar *meanstr_dbg;
11676
11677     meanstr_dbg = g_strndup (meanstr, meansize);
11678     namestr_dbg = g_strndup (namestr, namesize);
11679
11680     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11681         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11682
11683     g_free (namestr_dbg);
11684     g_free (meanstr_dbg);
11685   }
11686 #endif
11687   return;
11688 }
11689
11690 static void
11691 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11692     const char *tag_bis, GNode * node)
11693 {
11694   guint8 *data;
11695   GstBuffer *buf;
11696   guint len;
11697   GstTagList *id32_taglist = NULL;
11698
11699   GST_LOG_OBJECT (demux, "parsing ID32");
11700
11701   data = node->data;
11702   len = GST_READ_UINT32_BE (data);
11703
11704   /* need at least full box and language tag */
11705   if (len < 12 + 2)
11706     return;
11707
11708   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11709   gst_buffer_fill (buf, 0, data + 14, len - 14);
11710
11711   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11712   if (id32_taglist) {
11713     GST_LOG_OBJECT (demux, "parsing ok");
11714     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11715     gst_tag_list_unref (id32_taglist);
11716   } else {
11717     GST_LOG_OBJECT (demux, "parsing failed");
11718   }
11719
11720   gst_buffer_unref (buf);
11721 }
11722
11723 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11724     const char *tag, const char *tag_bis, GNode * node);
11725
11726 /* unmapped tags
11727 FOURCC_pcst -> if media is a podcast -> bool
11728 FOURCC_cpil -> if media is part of a compilation -> bool
11729 FOURCC_pgap -> if media is part of a gapless context -> bool
11730 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11731 */
11732
11733 static const struct
11734 {
11735   guint32 fourcc;
11736   const gchar *gst_tag;
11737   const gchar *gst_tag_bis;
11738   const GstQTDemuxAddTagFunc func;
11739 } add_funcs[] = {
11740   {
11741   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11742   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11743   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11744   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11745   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11746   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11747   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11748   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11749   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11750   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11751   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11752   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11753   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11754   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11755   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11756   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11757   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11758   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11759   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11760   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11761   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11762   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11763   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11764         qtdemux_tag_add_num}, {
11765   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11766         qtdemux_tag_add_num}, {
11767   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11768   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11769   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11770   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11771   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11772   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11773   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11774   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11775   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11776   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11777   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11778   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11779   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11780   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11781   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11782   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11783   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11784   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11785         qtdemux_tag_add_classification}, {
11786   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11787   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11788   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11789
11790     /* This is a special case, some tags are stored in this
11791      * 'reverse dns naming', according to:
11792      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11793      * bug #614471
11794      */
11795   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11796     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11797   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11798 };
11799
11800 struct _GstQtDemuxTagList
11801 {
11802   GstQTDemux *demux;
11803   GstTagList *taglist;
11804 };
11805 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11806
11807 static void
11808 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11809 {
11810   gint len;
11811   guint8 *data;
11812   GstBuffer *buf;
11813   gchar *media_type;
11814   const gchar *style;
11815   GstSample *sample;
11816   GstStructure *s;
11817   guint i;
11818   guint8 ndata[4];
11819   GstQTDemux *demux = qtdemuxtaglist->demux;
11820   GstTagList *taglist = qtdemuxtaglist->taglist;
11821
11822   data = node->data;
11823   len = QT_UINT32 (data);
11824   buf = gst_buffer_new_and_alloc (len);
11825   gst_buffer_fill (buf, 0, data, len);
11826
11827   /* heuristic to determine style of tag */
11828   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11829       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11830     style = "itunes";
11831   else if (demux->major_brand == FOURCC_qt__)
11832     style = "quicktime";
11833   /* fall back to assuming iso/3gp tag style */
11834   else
11835     style = "iso";
11836
11837   /* santize the name for the caps. */
11838   for (i = 0; i < 4; i++) {
11839     guint8 d = data[4 + i];
11840     if (g_ascii_isalnum (d))
11841       ndata[i] = g_ascii_tolower (d);
11842     else
11843       ndata[i] = '_';
11844   }
11845
11846   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11847       ndata[0], ndata[1], ndata[2], ndata[3]);
11848   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11849
11850   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11851   sample = gst_sample_new (buf, NULL, NULL, s);
11852   gst_buffer_unref (buf);
11853   g_free (media_type);
11854
11855   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11856       len, s);
11857
11858   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11859       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11860
11861   gst_sample_unref (sample);
11862 }
11863
11864 static void
11865 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11866 {
11867   GNode *meta;
11868   GNode *ilst;
11869   GNode *xmp_;
11870   GNode *node;
11871   gint i;
11872   GstQtDemuxTagList demuxtaglist;
11873
11874   demuxtaglist.demux = qtdemux;
11875   demuxtaglist.taglist = taglist;
11876
11877   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11878   if (meta != NULL) {
11879     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11880     if (ilst == NULL) {
11881       GST_LOG_OBJECT (qtdemux, "no ilst");
11882       return;
11883     }
11884   } else {
11885     ilst = udta;
11886     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11887   }
11888
11889   i = 0;
11890   while (i < G_N_ELEMENTS (add_funcs)) {
11891     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11892     if (node) {
11893       gint len;
11894
11895       len = QT_UINT32 (node->data);
11896       if (len < 12) {
11897         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11898             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11899       } else {
11900         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11901             add_funcs[i].gst_tag_bis, node);
11902       }
11903       g_node_destroy (node);
11904     } else {
11905       i++;
11906     }
11907   }
11908
11909   /* parsed nodes have been removed, pass along remainder as blob */
11910   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11911       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11912
11913   /* parse up XMP_ node if existing */
11914   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11915   if (xmp_ != NULL) {
11916     GstBuffer *buf;
11917     GstTagList *xmptaglist;
11918
11919     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11920         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11921     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11922     gst_buffer_unref (buf);
11923
11924     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11925   } else {
11926     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11927   }
11928 }
11929
11930 typedef struct
11931 {
11932   GstStructure *structure;      /* helper for sort function */
11933   gchar *location;
11934   guint min_req_bitrate;
11935   guint min_req_qt_version;
11936 } GstQtReference;
11937
11938 static gint
11939 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11940 {
11941   GstQtReference *ref_a = (GstQtReference *) a;
11942   GstQtReference *ref_b = (GstQtReference *) b;
11943
11944   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11945     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11946
11947   /* known bitrates go before unknown; higher bitrates go first */
11948   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11949 }
11950
11951 /* sort the redirects and post a message for the application.
11952  */
11953 static void
11954 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11955 {
11956   GstQtReference *best;
11957   GstStructure *s;
11958   GstMessage *msg;
11959   GValue list_val = { 0, };
11960   GList *l;
11961
11962   g_assert (references != NULL);
11963
11964   references = g_list_sort (references, qtdemux_redirects_sort_func);
11965
11966   best = (GstQtReference *) references->data;
11967
11968   g_value_init (&list_val, GST_TYPE_LIST);
11969
11970   for (l = references; l != NULL; l = l->next) {
11971     GstQtReference *ref = (GstQtReference *) l->data;
11972     GValue struct_val = { 0, };
11973
11974     ref->structure = gst_structure_new ("redirect",
11975         "new-location", G_TYPE_STRING, ref->location, NULL);
11976
11977     if (ref->min_req_bitrate > 0) {
11978       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11979           ref->min_req_bitrate, NULL);
11980     }
11981
11982     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11983     g_value_set_boxed (&struct_val, ref->structure);
11984     gst_value_list_append_value (&list_val, &struct_val);
11985     g_value_unset (&struct_val);
11986     /* don't free anything here yet, since we need best->structure below */
11987   }
11988
11989   g_assert (best != NULL);
11990   s = gst_structure_copy (best->structure);
11991
11992   if (g_list_length (references) > 1) {
11993     gst_structure_set_value (s, "locations", &list_val);
11994   }
11995
11996   g_value_unset (&list_val);
11997
11998   for (l = references; l != NULL; l = l->next) {
11999     GstQtReference *ref = (GstQtReference *) l->data;
12000
12001     gst_structure_free (ref->structure);
12002     g_free (ref->location);
12003     g_free (ref);
12004   }
12005   g_list_free (references);
12006
12007   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12008   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12009   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12010   qtdemux->posted_redirect = TRUE;
12011 }
12012
12013 /* look for redirect nodes, collect all redirect information and
12014  * process it.
12015  */
12016 static gboolean
12017 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12018 {
12019   GNode *rmra, *rmda, *rdrf;
12020
12021   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12022   if (rmra) {
12023     GList *redirects = NULL;
12024
12025     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12026     while (rmda) {
12027       GstQtReference ref = { NULL, NULL, 0, 0 };
12028       GNode *rmdr, *rmvc;
12029
12030       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12031         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12032         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12033             ref.min_req_bitrate);
12034       }
12035
12036       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12037         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12038         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12039
12040 #ifndef GST_DISABLE_GST_DEBUG
12041         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12042 #endif
12043         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12044
12045         GST_LOG_OBJECT (qtdemux,
12046             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12047             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12048             bitmask, check_type);
12049         if (package == FOURCC_qtim && check_type == 0) {
12050           ref.min_req_qt_version = version;
12051         }
12052       }
12053
12054       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12055       if (rdrf) {
12056         guint32 ref_type;
12057         guint8 *ref_data;
12058         guint ref_len;
12059
12060         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12061         if (ref_len > 20) {
12062           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12063           ref_data = (guint8 *) rdrf->data + 20;
12064           if (ref_type == FOURCC_alis) {
12065             guint record_len, record_version, fn_len;
12066
12067             if (ref_len > 70) {
12068               /* MacOSX alias record, google for alias-layout.txt */
12069               record_len = QT_UINT16 (ref_data + 4);
12070               record_version = QT_UINT16 (ref_data + 4 + 2);
12071               fn_len = QT_UINT8 (ref_data + 50);
12072               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12073                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12074               }
12075             } else {
12076               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12077                   ref_len);
12078             }
12079           } else if (ref_type == FOURCC_url_) {
12080             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12081           } else {
12082             GST_DEBUG_OBJECT (qtdemux,
12083                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12084                 GST_FOURCC_ARGS (ref_type));
12085           }
12086           if (ref.location != NULL) {
12087             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12088             redirects =
12089                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12090           } else {
12091             GST_WARNING_OBJECT (qtdemux,
12092                 "Failed to extract redirect location from rdrf atom");
12093           }
12094         } else {
12095           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12096         }
12097       }
12098
12099       /* look for others */
12100       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12101     }
12102
12103     if (redirects != NULL) {
12104       qtdemux_process_redirects (qtdemux, redirects);
12105     }
12106   }
12107   return TRUE;
12108 }
12109
12110 static GstTagList *
12111 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12112 {
12113   const gchar *fmt;
12114
12115   if (tags == NULL) {
12116     tags = gst_tag_list_new_empty ();
12117     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12118   }
12119
12120   if (qtdemux->major_brand == FOURCC_mjp2)
12121     fmt = "Motion JPEG 2000";
12122   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12123     fmt = "3GP";
12124   else if (qtdemux->major_brand == FOURCC_qt__)
12125     fmt = "Quicktime";
12126   else if (qtdemux->fragmented)
12127     fmt = "ISO fMP4";
12128   else
12129     fmt = "ISO MP4/M4A";
12130
12131   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12132       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12133
12134   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12135       fmt, NULL);
12136
12137   return tags;
12138 }
12139
12140 /* we have read th complete moov node now.
12141  * This function parses all of the relevant info, creates the traks and
12142  * prepares all data structures for playback
12143  */
12144 static gboolean
12145 qtdemux_parse_tree (GstQTDemux * qtdemux)
12146 {
12147   GNode *mvhd;
12148   GNode *trak;
12149   GNode *udta;
12150   GNode *mvex;
12151   GstClockTime duration;
12152   GNode *pssh;
12153   guint64 creation_time;
12154   GstDateTime *datetime = NULL;
12155   gint version;
12156
12157   /* make sure we have a usable taglist */
12158   if (!qtdemux->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   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12166   if (mvhd == NULL) {
12167     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12168     return qtdemux_parse_redirects (qtdemux);
12169   }
12170
12171   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12172   if (version == 1) {
12173     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12174     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12175     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12176   } else if (version == 0) {
12177     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12178     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12179     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12180   } else {
12181     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12182     return FALSE;
12183   }
12184
12185   /* Moving qt creation time (secs since 1904) to unix time */
12186   if (creation_time != 0) {
12187     /* Try to use epoch first as it should be faster and more commonly found */
12188     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12189       GTimeVal now;
12190
12191       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12192       /* some data cleansing sanity */
12193       g_get_current_time (&now);
12194       if (now.tv_sec + 24 * 3600 < creation_time) {
12195         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12196       } else {
12197         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12198       }
12199     } else {
12200       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12201       GDateTime *dt, *dt_local;
12202
12203       dt = g_date_time_add_seconds (base_dt, creation_time);
12204       dt_local = g_date_time_to_local (dt);
12205       datetime = gst_date_time_new_from_g_date_time (dt_local);
12206
12207       g_date_time_unref (base_dt);
12208       g_date_time_unref (dt);
12209     }
12210   }
12211   if (datetime) {
12212     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12213     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12214         datetime, NULL);
12215     gst_date_time_unref (datetime);
12216   }
12217
12218   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12219   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12220
12221   /* check for fragmented file and get some (default) data */
12222   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12223   if (mvex) {
12224     GNode *mehd;
12225     GstByteReader mehd_data;
12226
12227     /* let track parsing or anyone know weird stuff might happen ... */
12228     qtdemux->fragmented = TRUE;
12229
12230     /* compensate for total duration */
12231     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12232     if (mehd)
12233       qtdemux_parse_mehd (qtdemux, &mehd_data);
12234   }
12235
12236   /* set duration in the segment info */
12237   gst_qtdemux_get_duration (qtdemux, &duration);
12238   if (duration) {
12239     qtdemux->segment.duration = duration;
12240     /* also do not exceed duration; stop is set that way post seek anyway,
12241      * and segment activation falls back to duration,
12242      * whereas loop only checks stop, so let's align this here as well */
12243     qtdemux->segment.stop = duration;
12244   }
12245
12246   /* parse all traks */
12247   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12248   while (trak) {
12249     qtdemux_parse_trak (qtdemux, trak);
12250     /* iterate all siblings */
12251     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12252   }
12253
12254   if (!qtdemux->tag_list) {
12255     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12256     qtdemux->tag_list = gst_tag_list_new_empty ();
12257     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12258   } else {
12259     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12260   }
12261
12262   /* find tags */
12263   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12264   if (udta) {
12265     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12266   } else {
12267     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12268   }
12269
12270   /* maybe also some tags in meta box */
12271   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12272   if (udta) {
12273     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12274     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12275   } else {
12276     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12277   }
12278
12279   /* parse any protection system info */
12280   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12281   while (pssh) {
12282     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12283     qtdemux_parse_pssh (qtdemux, pssh);
12284     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12285   }
12286
12287   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12288
12289   return TRUE;
12290 }
12291
12292 /* taken from ffmpeg */
12293 static int
12294 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12295 {
12296   int count = 4;
12297   int len = 0;
12298
12299   while (count--) {
12300     int c;
12301
12302     if (ptr >= end)
12303       return -1;
12304
12305     c = *ptr++;
12306     len = (len << 7) | (c & 0x7f);
12307     if (!(c & 0x80))
12308       break;
12309   }
12310   *end_out = ptr;
12311   return len;
12312 }
12313
12314 /* this can change the codec originally present in @list */
12315 static void
12316 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12317     GNode * esds, GstTagList * list)
12318 {
12319   int len = QT_UINT32 (esds->data);
12320   guint8 *ptr = esds->data;
12321   guint8 *end = ptr + len;
12322   int tag;
12323   guint8 *data_ptr = NULL;
12324   int data_len = 0;
12325   guint8 object_type_id = 0;
12326   const char *codec_name = NULL;
12327   GstCaps *caps = NULL;
12328
12329   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12330   ptr += 8;
12331   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12332   ptr += 4;
12333   while (ptr + 1 < end) {
12334     tag = QT_UINT8 (ptr);
12335     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12336     ptr++;
12337     len = read_descr_size (ptr, end, &ptr);
12338     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12339
12340     /* Check the stated amount of data is available for reading */
12341     if (len < 0 || ptr + len > end)
12342       break;
12343
12344     switch (tag) {
12345       case ES_DESCRIPTOR_TAG:
12346         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12347         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12348         ptr += 3;
12349         break;
12350       case DECODER_CONFIG_DESC_TAG:{
12351         guint max_bitrate, avg_bitrate;
12352
12353         object_type_id = QT_UINT8 (ptr);
12354         max_bitrate = QT_UINT32 (ptr + 5);
12355         avg_bitrate = QT_UINT32 (ptr + 9);
12356         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12357         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12358         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12359         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12360         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12361         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12362           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12363               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12364         }
12365         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12366           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12367               avg_bitrate, NULL);
12368         }
12369         ptr += 13;
12370         break;
12371       }
12372       case DECODER_SPECIFIC_INFO_TAG:
12373         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12374         if (object_type_id == 0xe0 && len == 0x40) {
12375           guint8 *data;
12376           GstStructure *s;
12377           guint32 clut[16];
12378           gint i;
12379
12380           GST_DEBUG_OBJECT (qtdemux,
12381               "Have VOBSUB palette. Creating palette event");
12382           /* move to decConfigDescr data and read palette */
12383           data = ptr;
12384           for (i = 0; i < 16; i++) {
12385             clut[i] = QT_UINT32 (data);
12386             data += 4;
12387           }
12388
12389           s = gst_structure_new ("application/x-gst-dvd", "event",
12390               G_TYPE_STRING, "dvd-spu-clut-change",
12391               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12392               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12393               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12394               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12395               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12396               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12397               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12398               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12399               NULL);
12400
12401           /* store event and trigger custom processing */
12402           stream->pending_event =
12403               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12404         } else {
12405           /* Generic codec_data handler puts it on the caps */
12406           data_ptr = ptr;
12407           data_len = len;
12408         }
12409
12410         ptr += len;
12411         break;
12412       case SL_CONFIG_DESC_TAG:
12413         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12414         ptr += 1;
12415         break;
12416       default:
12417         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12418             tag);
12419         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12420         ptr += len;
12421         break;
12422     }
12423   }
12424
12425   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12426    * in use, and should also be used to override some other parameters for some
12427    * codecs. */
12428   switch (object_type_id) {
12429     case 0x20:                 /* MPEG-4 */
12430       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12431        * profile_and_level_indication */
12432       if (data_ptr != NULL && data_len >= 5 &&
12433           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12434         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12435             data_ptr + 4, data_len - 4);
12436       }
12437       break;                    /* Nothing special needed here */
12438     case 0x21:                 /* H.264 */
12439       codec_name = "H.264 / AVC";
12440       caps = gst_caps_new_simple ("video/x-h264",
12441           "stream-format", G_TYPE_STRING, "avc",
12442           "alignment", G_TYPE_STRING, "au", NULL);
12443       break;
12444     case 0x40:                 /* AAC (any) */
12445     case 0x66:                 /* AAC Main */
12446     case 0x67:                 /* AAC LC */
12447     case 0x68:                 /* AAC SSR */
12448       /* Override channels and rate based on the codec_data, as it's often
12449        * wrong. */
12450       /* Only do so for basic setup without HE-AAC extension */
12451       if (data_ptr && data_len == 2) {
12452         guint channels, rate;
12453
12454         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12455         if (channels > 0)
12456           stream->n_channels = channels;
12457
12458         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12459         if (rate > 0)
12460           stream->rate = rate;
12461       }
12462
12463       /* Set level and profile if possible */
12464       if (data_ptr != NULL && data_len >= 2) {
12465         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12466             data_ptr, data_len);
12467       }
12468       break;
12469     case 0x60:                 /* MPEG-2, various profiles */
12470     case 0x61:
12471     case 0x62:
12472     case 0x63:
12473     case 0x64:
12474     case 0x65:
12475       codec_name = "MPEG-2 video";
12476       caps = gst_caps_new_simple ("video/mpeg",
12477           "mpegversion", G_TYPE_INT, 2,
12478           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12479       break;
12480     case 0x69:                 /* MPEG-2 BC audio */
12481     case 0x6B:                 /* MPEG-1 audio */
12482       caps = gst_caps_new_simple ("audio/mpeg",
12483           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12484       codec_name = "MPEG-1 audio";
12485       break;
12486     case 0x6A:                 /* MPEG-1 */
12487       codec_name = "MPEG-1 video";
12488       caps = gst_caps_new_simple ("video/mpeg",
12489           "mpegversion", G_TYPE_INT, 1,
12490           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12491       break;
12492     case 0x6C:                 /* MJPEG */
12493       caps =
12494           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12495           NULL);
12496       codec_name = "Motion-JPEG";
12497       break;
12498     case 0x6D:                 /* PNG */
12499       caps =
12500           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12501           NULL);
12502       codec_name = "PNG still images";
12503       break;
12504     case 0x6E:                 /* JPEG2000 */
12505       codec_name = "JPEG-2000";
12506       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12507       break;
12508     case 0xA4:                 /* Dirac */
12509       codec_name = "Dirac";
12510       caps = gst_caps_new_empty_simple ("video/x-dirac");
12511       break;
12512     case 0xA5:                 /* AC3 */
12513       codec_name = "AC-3 audio";
12514       caps = gst_caps_new_simple ("audio/x-ac3",
12515           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12516       break;
12517     case 0xA9:                 /* AC3 */
12518       codec_name = "DTS audio";
12519       caps = gst_caps_new_simple ("audio/x-dts",
12520           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12521       break;
12522     case 0xE1:                 /* QCELP */
12523       /* QCELP, the codec_data is a riff tag (little endian) with
12524        * 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). */
12525       caps = gst_caps_new_empty_simple ("audio/qcelp");
12526       codec_name = "QCELP";
12527       break;
12528     default:
12529       break;
12530   }
12531
12532   /* If we have a replacement caps, then change our caps for this stream */
12533   if (caps) {
12534     gst_caps_unref (stream->caps);
12535     stream->caps = caps;
12536   }
12537
12538   if (codec_name && list)
12539     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12540         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12541
12542   /* Add the codec_data attribute to caps, if we have it */
12543   if (data_ptr) {
12544     GstBuffer *buffer;
12545
12546     buffer = gst_buffer_new_and_alloc (data_len);
12547     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12548
12549     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12550     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12551
12552     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12553         buffer, NULL);
12554     gst_buffer_unref (buffer);
12555   }
12556
12557 }
12558
12559 #define _codec(name) \
12560   do { \
12561     if (codec_name) { \
12562       *codec_name = g_strdup (name); \
12563     } \
12564   } while (0)
12565
12566 static GstCaps *
12567 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12568     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12569 {
12570   GstCaps *caps = NULL;
12571   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12572
12573   switch (fourcc) {
12574     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12575       _codec ("PNG still images");
12576       caps = gst_caps_new_empty_simple ("image/png");
12577       break;
12578     case FOURCC_jpeg:
12579       _codec ("JPEG still images");
12580       caps =
12581           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12582           NULL);
12583       break;
12584     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12585     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12586     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12587     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12588       _codec ("Motion-JPEG");
12589       caps =
12590           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12591           NULL);
12592       break;
12593     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12594       _codec ("Motion-JPEG format B");
12595       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12596       break;
12597     case FOURCC_mjp2:
12598       _codec ("JPEG-2000");
12599       /* override to what it should be according to spec, avoid palette_data */
12600       stream->bits_per_sample = 24;
12601       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12602       break;
12603     case FOURCC_SVQ3:
12604       _codec ("Sorensen video v.3");
12605       caps = gst_caps_new_simple ("video/x-svq",
12606           "svqversion", G_TYPE_INT, 3, NULL);
12607       break;
12608     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12609     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12610       _codec ("Sorensen video v.1");
12611       caps = gst_caps_new_simple ("video/x-svq",
12612           "svqversion", G_TYPE_INT, 1, NULL);
12613       break;
12614     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12615       caps = gst_caps_new_empty_simple ("video/x-raw");
12616       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12617       _codec ("Windows Raw RGB");
12618       break;
12619     case FOURCC_raw_:
12620     {
12621       guint16 bps;
12622
12623       bps = QT_UINT16 (stsd_data + 98);
12624       switch (bps) {
12625         case 15:
12626           format = GST_VIDEO_FORMAT_RGB15;
12627           break;
12628         case 16:
12629           format = GST_VIDEO_FORMAT_RGB16;
12630           break;
12631         case 24:
12632           format = GST_VIDEO_FORMAT_RGB;
12633           break;
12634         case 32:
12635           format = GST_VIDEO_FORMAT_ARGB;
12636           break;
12637         default:
12638           /* unknown */
12639           break;
12640       }
12641       break;
12642     }
12643     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12644       format = GST_VIDEO_FORMAT_I420;
12645       break;
12646     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12647     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12648       format = GST_VIDEO_FORMAT_I420;
12649       break;
12650     case FOURCC_2vuy:
12651     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12652       format = GST_VIDEO_FORMAT_UYVY;
12653       break;
12654     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12655       format = GST_VIDEO_FORMAT_v308;
12656       break;
12657     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12658       format = GST_VIDEO_FORMAT_v216;
12659       break;
12660     case FOURCC_v210:
12661       format = GST_VIDEO_FORMAT_v210;
12662       break;
12663     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12664       format = GST_VIDEO_FORMAT_r210;
12665       break;
12666       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12667          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12668          format = GST_VIDEO_FORMAT_v410;
12669          break;
12670        */
12671       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12672        * but different order than AYUV
12673        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12674        format = GST_VIDEO_FORMAT_v408;
12675        break;
12676        */
12677     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12678     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12679       _codec ("MPEG-1 video");
12680       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12681           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12682       break;
12683     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12684     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12685     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12686     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12687     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12688     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12689     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12690     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12691     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12692     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12693     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12694     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12695     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12696     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12697     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12698     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12699     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12700     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12701     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12702     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12703     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12704     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12705     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12706     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12707     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12708     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12709     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12710     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12711     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12712     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12713     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12714     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12715     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12716     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12717     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12718     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12719     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12720     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12721     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12722     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12723     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12724     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12725     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12726     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12727     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12728     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12729       _codec ("MPEG-2 video");
12730       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12731           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12732       break;
12733     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12734       _codec ("GIF still images");
12735       caps = gst_caps_new_empty_simple ("image/gif");
12736       break;
12737     case FOURCC_h263:
12738     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12739     case FOURCC_s263:
12740     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12741       _codec ("H.263");
12742       /* ffmpeg uses the height/width props, don't know why */
12743       caps = gst_caps_new_simple ("video/x-h263",
12744           "variant", G_TYPE_STRING, "itu", NULL);
12745       break;
12746     case FOURCC_mp4v:
12747     case FOURCC_MP4V:
12748       _codec ("MPEG-4 video");
12749       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12750           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12751       break;
12752     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12753     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12754       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12755       caps = gst_caps_new_simple ("video/x-msmpeg",
12756           "msmpegversion", G_TYPE_INT, 43, NULL);
12757       break;
12758     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12759       _codec ("DivX 3");
12760       caps = gst_caps_new_simple ("video/x-divx",
12761           "divxversion", G_TYPE_INT, 3, NULL);
12762       break;
12763     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12764     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12765       _codec ("DivX 4");
12766       caps = gst_caps_new_simple ("video/x-divx",
12767           "divxversion", G_TYPE_INT, 4, NULL);
12768       break;
12769     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12770       _codec ("DivX 5");
12771       caps = gst_caps_new_simple ("video/x-divx",
12772           "divxversion", G_TYPE_INT, 5, NULL);
12773       break;
12774
12775     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12776       _codec ("FFV1");
12777       caps = gst_caps_new_simple ("video/x-ffv",
12778           "ffvversion", G_TYPE_INT, 1, NULL);
12779       break;
12780
12781     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12782     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12783     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12784     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12785     case FOURCC_FMP4:
12786     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12787       caps = gst_caps_new_simple ("video/mpeg",
12788           "mpegversion", G_TYPE_INT, 4, NULL);
12789       _codec ("MPEG-4");
12790       break;
12791
12792     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12793       _codec ("Cinepak");
12794       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12795       break;
12796     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12797       _codec ("Apple QuickDraw");
12798       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12799       break;
12800     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12801       _codec ("Apple video");
12802       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12803       break;
12804     case FOURCC_H264:
12805     case FOURCC_avc1:
12806       _codec ("H.264 / AVC");
12807       caps = gst_caps_new_simple ("video/x-h264",
12808           "stream-format", G_TYPE_STRING, "avc",
12809           "alignment", G_TYPE_STRING, "au", NULL);
12810       break;
12811     case FOURCC_avc3:
12812       _codec ("H.264 / AVC");
12813       caps = gst_caps_new_simple ("video/x-h264",
12814           "stream-format", G_TYPE_STRING, "avc3",
12815           "alignment", G_TYPE_STRING, "au", NULL);
12816       break;
12817     case FOURCC_H265:
12818     case FOURCC_hvc1:
12819       _codec ("H.265 / HEVC");
12820       caps = gst_caps_new_simple ("video/x-h265",
12821           "stream-format", G_TYPE_STRING, "hvc1",
12822           "alignment", G_TYPE_STRING, "au", NULL);
12823       break;
12824     case FOURCC_hev1:
12825       _codec ("H.265 / HEVC");
12826       caps = gst_caps_new_simple ("video/x-h265",
12827           "stream-format", G_TYPE_STRING, "hev1",
12828           "alignment", G_TYPE_STRING, "au", NULL);
12829       break;
12830     case FOURCC_rle_:
12831       _codec ("Run-length encoding");
12832       caps = gst_caps_new_simple ("video/x-rle",
12833           "layout", G_TYPE_STRING, "quicktime", NULL);
12834       break;
12835     case FOURCC_WRLE:
12836       _codec ("Run-length encoding");
12837       caps = gst_caps_new_simple ("video/x-rle",
12838           "layout", G_TYPE_STRING, "microsoft", NULL);
12839       break;
12840     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12841     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12842       _codec ("Indeo Video 3");
12843       caps = gst_caps_new_simple ("video/x-indeo",
12844           "indeoversion", G_TYPE_INT, 3, NULL);
12845       break;
12846     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12847     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12848       _codec ("Intel Video 4");
12849       caps = gst_caps_new_simple ("video/x-indeo",
12850           "indeoversion", G_TYPE_INT, 4, NULL);
12851       break;
12852     case FOURCC_dvcp:
12853     case FOURCC_dvc_:
12854     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12855     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12856     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12857     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12858     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12859     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12860       _codec ("DV Video");
12861       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12862           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12863       break;
12864     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12865     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12866       _codec ("DVCPro50 Video");
12867       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12868           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12869       break;
12870     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12871     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12872       _codec ("DVCProHD Video");
12873       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12874           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12875       break;
12876     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12877       _codec ("Apple Graphics (SMC)");
12878       caps = gst_caps_new_empty_simple ("video/x-smc");
12879       break;
12880     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12881       _codec ("VP3");
12882       caps = gst_caps_new_empty_simple ("video/x-vp3");
12883       break;
12884     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12885       _codec ("VP6 Flash");
12886       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12887       break;
12888     case FOURCC_XiTh:
12889       _codec ("Theora");
12890       caps = gst_caps_new_empty_simple ("video/x-theora");
12891       /* theora uses one byte of padding in the data stream because it does not
12892        * allow 0 sized packets while theora does */
12893       stream->padding = 1;
12894       break;
12895     case FOURCC_drac:
12896       _codec ("Dirac");
12897       caps = gst_caps_new_empty_simple ("video/x-dirac");
12898       break;
12899     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12900       _codec ("TIFF still images");
12901       caps = gst_caps_new_empty_simple ("image/tiff");
12902       break;
12903     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12904       _codec ("Apple Intermediate Codec");
12905       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12906       break;
12907     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12908       _codec ("AVID DNxHD");
12909       caps = gst_caps_from_string ("video/x-dnxhd");
12910       break;
12911     case FOURCC_VP80:
12912       _codec ("On2 VP8");
12913       caps = gst_caps_from_string ("video/x-vp8");
12914       break;
12915     case FOURCC_apcs:
12916       _codec ("Apple ProRes LT");
12917       caps =
12918           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12919           NULL);
12920       break;
12921     case FOURCC_apch:
12922       _codec ("Apple ProRes HQ");
12923       caps =
12924           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12925           NULL);
12926       break;
12927     case FOURCC_apcn:
12928       _codec ("Apple ProRes");
12929       caps =
12930           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12931           "standard", NULL);
12932       break;
12933     case FOURCC_apco:
12934       _codec ("Apple ProRes Proxy");
12935       caps =
12936           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12937           "proxy", NULL);
12938       break;
12939     case FOURCC_ap4h:
12940       _codec ("Apple ProRes 4444");
12941       caps =
12942           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12943           "4444", NULL);
12944       break;
12945     case FOURCC_vc_1:
12946     case FOURCC_ovc1:
12947       _codec ("VC-1");
12948       caps = gst_caps_new_simple ("video/x-wmv",
12949           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12950       break;
12951     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12952     default:
12953     {
12954       char *s, fourstr[5];
12955
12956       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12957       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12958       caps = gst_caps_new_empty_simple (s);
12959       g_free (s);
12960       break;
12961     }
12962   }
12963
12964   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12965     GstVideoInfo info;
12966
12967     gst_video_info_init (&info);
12968     gst_video_info_set_format (&info, format, stream->width, stream->height);
12969
12970     caps = gst_video_info_to_caps (&info);
12971     *codec_name = gst_pb_utils_get_codec_description (caps);
12972
12973     /* enable clipping for raw video streams */
12974     stream->need_clip = TRUE;
12975   }
12976
12977   return caps;
12978 }
12979
12980 static GstCaps *
12981 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12982     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12983 {
12984   GstCaps *caps;
12985   const GstStructure *s;
12986   const gchar *name;
12987   gint endian = 0;
12988   GstAudioFormat format = 0;
12989   gint depth;
12990
12991   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12992
12993   depth = stream->bytes_per_packet * 8;
12994
12995   switch (fourcc) {
12996     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12997     case FOURCC_raw_:
12998       /* 8-bit audio is unsigned */
12999       if (depth == 8)
13000         format = GST_AUDIO_FORMAT_U8;
13001       /* otherwise it's signed and big-endian just like 'twos' */
13002     case FOURCC_twos:
13003       endian = G_BIG_ENDIAN;
13004       /* fall-through */
13005     case FOURCC_sowt:
13006     {
13007       gchar *str;
13008
13009       if (!endian)
13010         endian = G_LITTLE_ENDIAN;
13011
13012       if (!format)
13013         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13014
13015       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13016       _codec (str);
13017       g_free (str);
13018
13019       caps = gst_caps_new_simple ("audio/x-raw",
13020           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13021           "layout", G_TYPE_STRING, "interleaved", NULL);
13022       break;
13023     }
13024     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13025       _codec ("Raw 64-bit floating-point audio");
13026       caps = gst_caps_new_simple ("audio/x-raw",
13027           "format", G_TYPE_STRING, "F64BE",
13028           "layout", G_TYPE_STRING, "interleaved", NULL);
13029       break;
13030     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13031       _codec ("Raw 32-bit floating-point audio");
13032       caps = gst_caps_new_simple ("audio/x-raw",
13033           "format", G_TYPE_STRING, "F32BE",
13034           "layout", G_TYPE_STRING, "interleaved", NULL);
13035       break;
13036     case FOURCC_in24:
13037       _codec ("Raw 24-bit PCM audio");
13038       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13039        * endian later */
13040       caps = gst_caps_new_simple ("audio/x-raw",
13041           "format", G_TYPE_STRING, "S24BE",
13042           "layout", G_TYPE_STRING, "interleaved", NULL);
13043       break;
13044     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13045       _codec ("Raw 32-bit PCM audio");
13046       caps = gst_caps_new_simple ("audio/x-raw",
13047           "format", G_TYPE_STRING, "S32BE",
13048           "layout", G_TYPE_STRING, "interleaved", NULL);
13049       break;
13050     case FOURCC_ulaw:
13051       _codec ("Mu-law audio");
13052       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13053       break;
13054     case FOURCC_alaw:
13055       _codec ("A-law audio");
13056       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13057       break;
13058     case 0x0200736d:
13059     case 0x6d730002:
13060       _codec ("Microsoft ADPCM");
13061       /* Microsoft ADPCM-ACM code 2 */
13062       caps = gst_caps_new_simple ("audio/x-adpcm",
13063           "layout", G_TYPE_STRING, "microsoft", NULL);
13064       break;
13065     case 0x1100736d:
13066     case 0x6d730011:
13067       _codec ("DVI/IMA ADPCM");
13068       caps = gst_caps_new_simple ("audio/x-adpcm",
13069           "layout", G_TYPE_STRING, "dvi", NULL);
13070       break;
13071     case 0x1700736d:
13072     case 0x6d730017:
13073       _codec ("DVI/Intel IMA ADPCM");
13074       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13075       caps = gst_caps_new_simple ("audio/x-adpcm",
13076           "layout", G_TYPE_STRING, "quicktime", NULL);
13077       break;
13078     case 0x5500736d:
13079     case 0x6d730055:
13080       /* MPEG layer 3, CBR only (pre QT4.1) */
13081     case FOURCC__mp3:
13082       _codec ("MPEG-1 layer 3");
13083       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13084       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13085           "mpegversion", G_TYPE_INT, 1, NULL);
13086       break;
13087     case 0x20736d:
13088     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13089       _codec ("EAC-3 audio");
13090       caps = gst_caps_new_simple ("audio/x-eac3",
13091           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13092       stream->sampled = TRUE;
13093       break;
13094     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13095     case FOURCC_ac_3:
13096       _codec ("AC-3 audio");
13097       caps = gst_caps_new_simple ("audio/x-ac3",
13098           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13099       stream->sampled = TRUE;
13100       break;
13101     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13102     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13103       _codec ("DTS audio");
13104       caps = gst_caps_new_simple ("audio/x-dts",
13105           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13106       stream->sampled = TRUE;
13107       break;
13108     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13109     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13110       _codec ("DTS-HD audio");
13111       caps = gst_caps_new_simple ("audio/x-dts",
13112           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13113       stream->sampled = TRUE;
13114       break;
13115     case FOURCC_MAC3:
13116       _codec ("MACE-3");
13117       caps = gst_caps_new_simple ("audio/x-mace",
13118           "maceversion", G_TYPE_INT, 3, NULL);
13119       break;
13120     case FOURCC_MAC6:
13121       _codec ("MACE-6");
13122       caps = gst_caps_new_simple ("audio/x-mace",
13123           "maceversion", G_TYPE_INT, 6, NULL);
13124       break;
13125     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13126       /* ogg/vorbis */
13127       caps = gst_caps_new_empty_simple ("application/ogg");
13128       break;
13129     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13130       _codec ("DV audio");
13131       caps = gst_caps_new_empty_simple ("audio/x-dv");
13132       break;
13133     case FOURCC_mp4a:
13134       _codec ("MPEG-4 AAC audio");
13135       caps = gst_caps_new_simple ("audio/mpeg",
13136           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13137           "stream-format", G_TYPE_STRING, "raw", NULL);
13138       break;
13139     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13140       _codec ("QDesign Music");
13141       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13142       break;
13143     case FOURCC_QDM2:
13144       _codec ("QDesign Music v.2");
13145       /* FIXME: QDesign music version 2 (no constant) */
13146       if (FALSE && data) {
13147         caps = gst_caps_new_simple ("audio/x-qdm2",
13148             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13149             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13150             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13151       } else {
13152         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13153       }
13154       break;
13155     case FOURCC_agsm:
13156       _codec ("GSM audio");
13157       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13158       break;
13159     case FOURCC_samr:
13160       _codec ("AMR audio");
13161       caps = gst_caps_new_empty_simple ("audio/AMR");
13162       break;
13163     case FOURCC_sawb:
13164       _codec ("AMR-WB audio");
13165       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13166       break;
13167     case FOURCC_ima4:
13168       _codec ("Quicktime IMA ADPCM");
13169       caps = gst_caps_new_simple ("audio/x-adpcm",
13170           "layout", G_TYPE_STRING, "quicktime", NULL);
13171       break;
13172     case FOURCC_alac:
13173       _codec ("Apple lossless audio");
13174       caps = gst_caps_new_empty_simple ("audio/x-alac");
13175       break;
13176     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13177       _codec ("QualComm PureVoice");
13178       caps = gst_caps_from_string ("audio/qcelp");
13179       break;
13180     case FOURCC_wma_:
13181     case FOURCC_owma:
13182       _codec ("WMA");
13183       caps = gst_caps_new_empty_simple ("audio/x-wma");
13184       break;
13185     case FOURCC_opus:
13186       _codec ("Opus");
13187       caps = gst_caps_new_empty_simple ("audio/x-opus");
13188       break;
13189     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13190     {
13191       guint32 flags = 0;
13192       guint32 depth = 0;
13193       guint32 width = 0;
13194       GstAudioFormat format;
13195       enum
13196       {
13197         FLAG_IS_FLOAT = 0x1,
13198         FLAG_IS_BIG_ENDIAN = 0x2,
13199         FLAG_IS_SIGNED = 0x4,
13200         FLAG_IS_PACKED = 0x8,
13201         FLAG_IS_ALIGNED_HIGH = 0x10,
13202         FLAG_IS_NON_INTERLEAVED = 0x20
13203       };
13204       _codec ("Raw LPCM audio");
13205
13206       if (data && len >= 56) {
13207         depth = QT_UINT32 (data + 40);
13208         flags = QT_UINT32 (data + 44);
13209         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13210       }
13211       if ((flags & FLAG_IS_FLOAT) == 0) {
13212         if (depth == 0)
13213           depth = 16;
13214         if (width == 0)
13215           width = 16;
13216         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13217             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13218             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13219         caps = gst_caps_new_simple ("audio/x-raw",
13220             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13221             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13222             "non-interleaved" : "interleaved", NULL);
13223       } else {
13224         if (width == 0)
13225           width = 32;
13226         if (width == 64) {
13227           if (flags & FLAG_IS_BIG_ENDIAN)
13228             format = GST_AUDIO_FORMAT_F64BE;
13229           else
13230             format = GST_AUDIO_FORMAT_F64LE;
13231         } else {
13232           if (flags & FLAG_IS_BIG_ENDIAN)
13233             format = GST_AUDIO_FORMAT_F32BE;
13234           else
13235             format = GST_AUDIO_FORMAT_F32LE;
13236         }
13237         caps = gst_caps_new_simple ("audio/x-raw",
13238             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13239             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13240             "non-interleaved" : "interleaved", NULL);
13241       }
13242       break;
13243     }
13244     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13245       /* ? */
13246     default:
13247     {
13248       char *s, fourstr[5];
13249
13250       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13251       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13252       caps = gst_caps_new_empty_simple (s);
13253       g_free (s);
13254       break;
13255     }
13256   }
13257
13258   if (caps) {
13259     GstCaps *templ_caps =
13260         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13261     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13262     gst_caps_unref (caps);
13263     gst_caps_unref (templ_caps);
13264     caps = intersection;
13265   }
13266
13267   /* enable clipping for raw audio streams */
13268   s = gst_caps_get_structure (caps, 0);
13269   name = gst_structure_get_name (s);
13270   if (g_str_has_prefix (name, "audio/x-raw")) {
13271     stream->need_clip = TRUE;
13272     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13273     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13274   }
13275   return caps;
13276 }
13277
13278 static GstCaps *
13279 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13280     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13281 {
13282   GstCaps *caps;
13283
13284   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13285
13286   switch (fourcc) {
13287     case FOURCC_mp4s:
13288       _codec ("DVD subtitle");
13289       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13290       stream->need_process = TRUE;
13291       break;
13292     case FOURCC_text:
13293       _codec ("Quicktime timed text");
13294       goto text;
13295     case FOURCC_tx3g:
13296       _codec ("3GPP timed text");
13297     text:
13298       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13299           "utf8", NULL);
13300       /* actual text piece needs to be extracted */
13301       stream->need_process = TRUE;
13302       break;
13303     case FOURCC_stpp:
13304       _codec ("XML subtitles");
13305       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13306       break;
13307     default:
13308     {
13309       char *s, fourstr[5];
13310
13311       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13312       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13313       caps = gst_caps_new_empty_simple (s);
13314       g_free (s);
13315       break;
13316     }
13317   }
13318   return caps;
13319 }
13320
13321 static GstCaps *
13322 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13323     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13324 {
13325   GstCaps *caps;
13326
13327   switch (fourcc) {
13328     case FOURCC_m1v:
13329       _codec ("MPEG 1 video");
13330       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13331           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13332       break;
13333     default:
13334       caps = NULL;
13335       break;
13336   }
13337   return caps;
13338 }
13339
13340 static void
13341 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13342     const gchar * system_id)
13343 {
13344   gint i;
13345
13346   if (!qtdemux->protection_system_ids)
13347     qtdemux->protection_system_ids =
13348         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13349   /* Check whether we already have an entry for this system ID. */
13350   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13351     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13352     if (g_ascii_strcasecmp (system_id, id) == 0) {
13353       return;
13354     }
13355   }
13356   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13357   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13358           -1));
13359 }