qtdemux: Add support for FLAC encapsulated in ISOBMFF
[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  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * 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
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
98
99 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
100
101 GST_DEBUG_CATEGORY (qtdemux_debug);
102
103 typedef struct _QtDemuxSegment QtDemuxSegment;
104 typedef struct _QtDemuxSample QtDemuxSample;
105
106 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
107
108 struct _QtDemuxSample
109 {
110   guint32 size;
111   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
112   guint64 offset;
113   guint64 timestamp;            /* DTS In mov time */
114   guint32 duration;             /* In mov time */
115   gboolean keyframe;            /* TRUE when this packet is a keyframe */
116 };
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset is the PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + duration - dts is the duration */
130 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
131
132 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
133
134 /*
135  * Quicktime has tracks and segments. A track is a continuous piece of
136  * multimedia content. The track is not always played from start to finish but
137  * instead, pieces of the track are 'cut out' and played in sequence. This is
138  * what the segments do.
139  *
140  * Inside the track we have keyframes (K) and delta frames. The track has its
141  * own timing, which starts from 0 and extends to end. The position in the track
142  * is called the media_time.
143  *
144  * The segments now describe the pieces that should be played from this track
145  * and are basically tuples of media_time/duration/rate entries. We can have
146  * multiple segments and they are all played after one another. An example:
147  *
148  * segment 1: media_time: 1 second, duration: 1 second, rate 1
149  * segment 2: media_time: 3 second, duration: 2 second, rate 2
150  *
151  * To correctly play back this track, one must play: 1 second of media starting
152  * from media_time 1 followed by 2 seconds of media starting from media_time 3
153  * at a rate of 2.
154  *
155  * Each of the segments will be played at a specific time, the first segment at
156  * time 0, the second one after the duration of the first one, etc.. Note that
157  * the time in resulting playback is not identical to the media_time of the
158  * track anymore.
159  *
160  * Visually, assuming the track has 4 second of media_time:
161  *
162  *                (a)                   (b)          (c)              (d)
163  *         .-----------------------------------------------------------.
164  * track:  | K.....K.........K........K.......K.......K...........K... |
165  *         '-----------------------------------------------------------'
166  *         0              1              2              3              4
167  *           .------------^              ^   .----------^              ^
168  *          /              .-------------'  /       .------------------'
169  *         /              /          .-----'       /
170  *         .--------------.         .--------------.
171  *         | segment 1    |         | segment 2    |
172  *         '--------------'         '--------------'
173  *
174  * The challenge here is to cut out the right pieces of the track for each of
175  * the playback segments. This fortunately can easily be done with the SEGMENT
176  * events of GStreamer.
177  *
178  * For playback of segment 1, we need to provide the decoder with the keyframe
179  * (a), in the above figure, but we must instruct it only to output the decoded
180  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
181  * position set to the time of the segment: 0.
182  *
183  * We then proceed to push data from keyframe (a) to frame (b). The decoder
184  * decodes but clips all before media_time 1.
185  *
186  * After finishing a segment, we push out a new SEGMENT event with the clipping
187  * boundaries of the new data.
188  *
189  * This is a good usecase for the GStreamer accumulated SEGMENT events.
190  */
191
192 struct _QtDemuxSegment
193 {
194   /* global time and duration, all gst time */
195   GstClockTime time;
196   GstClockTime stop_time;
197   GstClockTime duration;
198   /* media time of trak, all gst time */
199   GstClockTime media_start;
200   GstClockTime media_stop;
201   gdouble rate;
202   /* Media start time in trak timescale units */
203   guint32 trak_media_start;
204 };
205
206 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
207
208 /* Used with fragmented MP4 files (mfra atom) */
209 typedef struct
210 {
211   GstClockTime ts;
212   guint64 moof_offset;
213 } QtDemuxRandomAccessEntry;
214
215 struct _QtDemuxStream
216 {
217   GstPad *pad;
218
219   /* stream type */
220   guint32 subtype;
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   gboolean new_caps;            /* If TRUE, caps need to be generated (by
226                                  * calling _configure_stream()) This happens
227                                  * for MSS and fragmented streams */
228
229   gboolean new_stream;          /* signals that a stream_start is required */
230   gboolean on_keyframe;         /* if this stream last pushed buffer was a
231                                  * keyframe. This is important to identify
232                                  * where to stop pushing buffers after a
233                                  * segment stop time */
234
235   /* if the stream has a redirect URI in its headers, we store it here */
236   gchar *redirect_uri;
237
238   /* track id */
239   guint track_id;
240
241   /* duration/scale */
242   guint64 duration;             /* in timescale units */
243   guint32 timescale;
244
245   /* language */
246   gchar lang_id[4];             /* ISO 639-2T language code */
247
248   /* our samples */
249   guint32 n_samples;
250   QtDemuxSample *samples;
251   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
252   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
253                                    the framerate */
254   guint32 n_samples_moof;       /* sample count in a moof */
255   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
256                                  * the framerate of fragmented format stream */
257   guint64 duration_last_moof;
258
259   guint32 offset_in_sample;     /* Offset in the current sample, used for
260                                  * streams which have got exceedingly big
261                                  * sample size (such as 24s of raw audio).
262                                  * Only used when max_buffer_size is non-NULL */
263   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
264                                  * Currently only set for raw audio streams*/
265
266   /* if we use chunks or samples */
267   gboolean sampled;
268   guint padding;
269
270   /* video info */
271   gint width;
272   gint height;
273   /* aspect ratio */
274   gint display_width;
275   gint display_height;
276   gint par_w;
277   gint par_h;
278   /* Numerator/denominator framerate */
279   gint fps_n;
280   gint fps_d;
281   GstVideoColorimetry colorimetry;
282   guint16 bits_per_sample;
283   guint16 color_table_id;
284   GstMemory *rgb8_palette;
285
286   /* audio info */
287   gdouble rate;
288   gint n_channels;
289   guint samples_per_packet;
290   guint samples_per_frame;
291   guint bytes_per_packet;
292   guint bytes_per_sample;
293   guint bytes_per_frame;
294   guint compression;
295
296   /* allocation */
297   gboolean use_allocator;
298   GstAllocator *allocator;
299   GstAllocationParams params;
300
301   /* when a discontinuity is pending */
302   gboolean discont;
303
304   /* list of buffers to push first */
305   GSList *buffers;
306
307   /* if we need to clip this buffer. This is only needed for uncompressed
308    * data */
309   gboolean need_clip;
310
311   /* buffer needs some custom processing, e.g. subtitles */
312   gboolean need_process;
313
314   /* current position */
315   guint32 segment_index;
316   guint32 sample_index;
317   GstClockTime time_position;   /* in gst time */
318   guint64 accumulated_base;
319
320   /* the Gst segment we are processing out, used for clipping */
321   GstSegment segment;
322
323   /* quicktime segments */
324   guint32 n_segments;
325   QtDemuxSegment *segments;
326   gboolean dummy_segment;
327   guint32 from_sample;
328   guint32 to_sample;
329
330   gboolean sent_eos;
331   GstTagList *pending_tags;
332   gboolean send_global_tags;
333
334   GstEvent *pending_event;
335
336   GstByteReader stco;
337   GstByteReader stsz;
338   GstByteReader stsc;
339   GstByteReader stts;
340   GstByteReader stss;
341   GstByteReader stps;
342   GstByteReader ctts;
343
344   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
345   gint64 stbl_index;
346   /* stco */
347   guint co_size;
348   GstByteReader co_chunk;
349   guint32 first_chunk;
350   guint32 current_chunk;
351   guint32 last_chunk;
352   guint32 samples_per_chunk;
353   guint32 stco_sample_index;
354   /* stsz */
355   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
356   /* stsc */
357   guint32 stsc_index;
358   guint32 n_samples_per_chunk;
359   guint32 stsc_chunk_index;
360   guint32 stsc_sample_index;
361   guint64 chunk_offset;
362   /* stts */
363   guint32 stts_index;
364   guint32 stts_samples;
365   guint32 n_sample_times;
366   guint32 stts_sample_index;
367   guint64 stts_time;
368   guint32 stts_duration;
369   /* stss */
370   gboolean stss_present;
371   guint32 n_sample_syncs;
372   guint32 stss_index;
373   /* stps */
374   gboolean stps_present;
375   guint32 n_sample_partial_syncs;
376   guint32 stps_index;
377   QtDemuxRandomAccessEntry *ra_entries;
378   guint n_ra_entries;
379
380   const QtDemuxRandomAccessEntry *pending_seek;
381
382   /* ctts */
383   gboolean ctts_present;
384   guint32 n_composition_times;
385   guint32 ctts_index;
386   guint32 ctts_sample_index;
387   guint32 ctts_count;
388   gint32 ctts_soffset;
389
390   /* cslg */
391   guint32 cslg_shift;
392
393   /* fragmented */
394   gboolean parsed_trex;
395   guint32 def_sample_duration;
396   guint32 def_sample_size;
397   guint32 def_sample_flags;
398
399   gboolean disabled;
400
401   /* stereoscopic video streams */
402   GstVideoMultiviewMode multiview_mode;
403   GstVideoMultiviewFlags multiview_flags;
404
405   /* protected streams */
406   gboolean protected;
407   guint32 protection_scheme_type;
408   guint32 protection_scheme_version;
409   gpointer protection_scheme_info;      /* specific to the protection scheme */
410   GQueue protection_scheme_event_queue;
411 };
412
413 /* Contains properties and cryptographic info for a set of samples from a
414  * track protected using Common Encryption (cenc) */
415 struct _QtDemuxCencSampleSetInfo
416 {
417   GstStructure *default_properties;
418
419   /* @crypto_info holds one GstStructure per sample */
420   GPtrArray *crypto_info;
421 };
422
423 static const gchar *
424 qt_demux_state_string (enum QtDemuxState state)
425 {
426   switch (state) {
427     case QTDEMUX_STATE_INITIAL:
428       return "<INITIAL>";
429     case QTDEMUX_STATE_HEADER:
430       return "<HEADER>";
431     case QTDEMUX_STATE_MOVIE:
432       return "<MOVIE>";
433     case QTDEMUX_STATE_BUFFER_MDAT:
434       return "<BUFFER_MDAT>";
435     default:
436       return "<UNKNOWN>";
437   }
438 }
439
440 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
441 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
442     guint32 fourcc, GstByteReader * parser);
443 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
444 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
445     guint32 fourcc, GstByteReader * parser);
446
447 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
448
449 static GstStaticPadTemplate gst_qtdemux_sink_template =
450     GST_STATIC_PAD_TEMPLATE ("sink",
451     GST_PAD_SINK,
452     GST_PAD_ALWAYS,
453     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
454         "application/x-3gp")
455     );
456
457 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
458 GST_STATIC_PAD_TEMPLATE ("video_%u",
459     GST_PAD_SRC,
460     GST_PAD_SOMETIMES,
461     GST_STATIC_CAPS_ANY);
462
463 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
464 GST_STATIC_PAD_TEMPLATE ("audio_%u",
465     GST_PAD_SRC,
466     GST_PAD_SOMETIMES,
467     GST_STATIC_CAPS_ANY);
468
469 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
470 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
471     GST_PAD_SRC,
472     GST_PAD_SOMETIMES,
473     GST_STATIC_CAPS_ANY);
474
475 #define gst_qtdemux_parent_class parent_class
476 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
477
478 static void gst_qtdemux_dispose (GObject * object);
479
480 static guint32
481 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
482     GstClockTime media_time);
483 static guint32
484 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
485     QtDemuxStream * str, gint64 media_offset);
486
487 #if 0
488 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
489 static GstIndex *gst_qtdemux_get_index (GstElement * element);
490 #endif
491 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
492     GstStateChange transition);
493 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
494 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
495     GstObject * parent, GstPadMode mode, gboolean active);
496
497 static void gst_qtdemux_loop (GstPad * pad);
498 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
499     GstBuffer * inbuf);
500 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
501     GstEvent * event);
502 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
503 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
504     QtDemuxStream * stream);
505 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
506     gboolean force);
507
508 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
509     const guint8 * buffer, guint length);
510 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
511     const guint8 * buffer, guint length);
512 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
513 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
514     GNode * udta);
515
516 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
517     QtDemuxStream * stream, GNode * esds, GstTagList * list);
518 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
519     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
520     gchar ** codec_name);
521 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
522     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
523     gchar ** codec_name);
524 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
525     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
526     gchar ** codec_name);
527 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
528     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
529     gchar ** codec_name);
530
531 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
532     QtDemuxStream * stream, guint32 n);
533 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
534 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
535     QtDemuxStream * stream);
536 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
537     QtDemuxStream * stream);
538 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
539 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
540 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
541     QtDemuxStream * stream);
542 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
543     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
544 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
545     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
546     GstClockTime * _start, GstClockTime * _stop);
547 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
548     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
549
550 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
551 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
552
553 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
554
555 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
556     QtDemuxStream * stream, guint sample_index);
557 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
558     const gchar * id);
559 static void qtdemux_gst_structure_free (GstStructure * gststructure);
560
561 static void
562 gst_qtdemux_class_init (GstQTDemuxClass * klass)
563 {
564   GObjectClass *gobject_class;
565   GstElementClass *gstelement_class;
566
567   gobject_class = (GObjectClass *) klass;
568   gstelement_class = (GstElementClass *) klass;
569
570   parent_class = g_type_class_peek_parent (klass);
571
572   gobject_class->dispose = gst_qtdemux_dispose;
573
574   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
575 #if 0
576   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
577   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
578 #endif
579
580   gst_tag_register_musicbrainz_tags ();
581
582   gst_element_class_add_static_pad_template (gstelement_class,
583       &gst_qtdemux_sink_template);
584   gst_element_class_add_static_pad_template (gstelement_class,
585       &gst_qtdemux_videosrc_template);
586   gst_element_class_add_static_pad_template (gstelement_class,
587       &gst_qtdemux_audiosrc_template);
588   gst_element_class_add_static_pad_template (gstelement_class,
589       &gst_qtdemux_subsrc_template);
590   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
591       "Codec/Demuxer",
592       "Demultiplex a QuickTime file into audio and video streams",
593       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
594
595   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
596
597 }
598
599 static void
600 gst_qtdemux_init (GstQTDemux * qtdemux)
601 {
602   qtdemux->sinkpad =
603       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
604   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
605   gst_pad_set_activatemode_function (qtdemux->sinkpad,
606       qtdemux_sink_activate_mode);
607   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
608   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
609   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
610
611   qtdemux->state = QTDEMUX_STATE_INITIAL;
612   qtdemux->pullbased = FALSE;
613   qtdemux->posted_redirect = FALSE;
614   qtdemux->neededbytes = 16;
615   qtdemux->todrop = 0;
616   qtdemux->adapter = gst_adapter_new ();
617   qtdemux->offset = 0;
618   qtdemux->first_mdat = -1;
619   qtdemux->got_moov = FALSE;
620   qtdemux->mdatoffset = -1;
621   qtdemux->mdatbuffer = NULL;
622   qtdemux->restoredata_buffer = NULL;
623   qtdemux->restoredata_offset = -1;
624   qtdemux->fragment_start = -1;
625   qtdemux->fragment_start_offset = -1;
626   qtdemux->media_caps = NULL;
627   qtdemux->exposed = FALSE;
628   qtdemux->mss_mode = FALSE;
629   qtdemux->pending_newsegment = NULL;
630   qtdemux->upstream_format_is_time = FALSE;
631   qtdemux->have_group_id = FALSE;
632   qtdemux->group_id = G_MAXUINT;
633   qtdemux->cenc_aux_info_offset = 0;
634   qtdemux->cenc_aux_info_sizes = NULL;
635   qtdemux->cenc_aux_sample_count = 0;
636   qtdemux->protection_system_ids = NULL;
637   g_queue_init (&qtdemux->protection_event_queue);
638   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
639   qtdemux->flowcombiner = gst_flow_combiner_new ();
640
641   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
642 }
643
644 static void
645 gst_qtdemux_dispose (GObject * object)
646 {
647   GstQTDemux *qtdemux = GST_QTDEMUX (object);
648
649   if (qtdemux->adapter) {
650     g_object_unref (G_OBJECT (qtdemux->adapter));
651     qtdemux->adapter = NULL;
652   }
653   gst_flow_combiner_free (qtdemux->flowcombiner);
654   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
655       NULL);
656   g_queue_clear (&qtdemux->protection_event_queue);
657
658   g_free (qtdemux->cenc_aux_info_sizes);
659   qtdemux->cenc_aux_info_sizes = NULL;
660
661   G_OBJECT_CLASS (parent_class)->dispose (object);
662 }
663
664 static void
665 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
666 {
667   if (qtdemux->posted_redirect) {
668     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
669         (_("This file contains no playable streams.")),
670         ("no known streams found, a redirect message has been posted"));
671   } else {
672     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
673         (_("This file contains no playable streams.")),
674         ("no known streams found"));
675   }
676 }
677
678 static GstBuffer *
679 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
680 {
681   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
682       mem, size, 0, size, mem, free_func);
683 }
684
685 static GstFlowReturn
686 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
687     GstBuffer ** buf)
688 {
689   GstFlowReturn flow;
690   GstMapInfo map;
691   gsize bsize;
692
693   if (G_UNLIKELY (size == 0)) {
694     GstFlowReturn ret;
695     GstBuffer *tmp = NULL;
696
697     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
698     if (ret != GST_FLOW_OK)
699       return ret;
700
701     gst_buffer_map (tmp, &map, GST_MAP_READ);
702     size = QT_UINT32 (map.data);
703     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
704
705     gst_buffer_unmap (tmp, &map);
706     gst_buffer_unref (tmp);
707   }
708
709   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
710   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
711     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
712       /* we're pulling header but already got most interesting bits,
713        * so never mind the rest (e.g. tags) (that much) */
714       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
715           size);
716       return GST_FLOW_EOS;
717     } else {
718       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
719           (_("This file is invalid and cannot be played.")),
720           ("atom has bogus size %" G_GUINT64_FORMAT, size));
721       return GST_FLOW_ERROR;
722     }
723   }
724
725   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
726
727   if (G_UNLIKELY (flow != GST_FLOW_OK))
728     return flow;
729
730   bsize = gst_buffer_get_size (*buf);
731   /* Catch short reads - we don't want any partial atoms */
732   if (G_UNLIKELY (bsize < size)) {
733     GST_WARNING_OBJECT (qtdemux,
734         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
735     gst_buffer_unref (*buf);
736     *buf = NULL;
737     return GST_FLOW_EOS;
738   }
739
740   return flow;
741 }
742
743 #if 1
744 static gboolean
745 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
746     GstFormat src_format, gint64 src_value, GstFormat dest_format,
747     gint64 * dest_value)
748 {
749   gboolean res = TRUE;
750   QtDemuxStream *stream = gst_pad_get_element_private (pad);
751   gint32 index;
752
753   if (stream->subtype != FOURCC_vide) {
754     res = FALSE;
755     goto done;
756   }
757
758   switch (src_format) {
759     case GST_FORMAT_TIME:
760       switch (dest_format) {
761         case GST_FORMAT_BYTES:{
762           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
763           if (-1 == index) {
764             res = FALSE;
765             goto done;
766           }
767
768           *dest_value = stream->samples[index].offset;
769
770           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
771               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
772               GST_TIME_ARGS (src_value), *dest_value);
773           break;
774         }
775         default:
776           res = FALSE;
777           break;
778       }
779       break;
780     case GST_FORMAT_BYTES:
781       switch (dest_format) {
782         case GST_FORMAT_TIME:{
783           index =
784               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
785               stream, src_value);
786
787           if (-1 == index) {
788             res = FALSE;
789             goto done;
790           }
791
792           *dest_value =
793               QTSTREAMTIME_TO_GSTTIME (stream,
794               stream->samples[index].timestamp);
795           GST_DEBUG_OBJECT (qtdemux,
796               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
797               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
798           break;
799         }
800         default:
801           res = FALSE;
802           break;
803       }
804       break;
805     default:
806       res = FALSE;
807       break;
808   }
809
810 done:
811   return res;
812 }
813 #endif
814
815 static gboolean
816 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
817 {
818   gboolean res = FALSE;
819
820   *duration = GST_CLOCK_TIME_NONE;
821
822   if (qtdemux->duration != 0 &&
823       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
824     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
825     res = TRUE;
826   } else {
827     *duration = GST_CLOCK_TIME_NONE;
828   }
829
830   return res;
831 }
832
833 static gboolean
834 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
835     GstQuery * query)
836 {
837   gboolean res = FALSE;
838   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
839
840   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
841
842   switch (GST_QUERY_TYPE (query)) {
843     case GST_QUERY_POSITION:{
844       GstFormat fmt;
845
846       gst_query_parse_position (query, &fmt, NULL);
847       if (fmt == GST_FORMAT_TIME
848           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
849         gst_query_set_position (query, GST_FORMAT_TIME,
850             qtdemux->segment.position);
851         res = TRUE;
852       }
853     }
854       break;
855     case GST_QUERY_DURATION:{
856       GstFormat fmt;
857
858       gst_query_parse_duration (query, &fmt, NULL);
859       if (fmt == GST_FORMAT_TIME) {
860         /* First try to query upstream */
861         res = gst_pad_query_default (pad, parent, query);
862         if (!res) {
863           GstClockTime duration;
864           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
865             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
866             res = TRUE;
867           }
868         }
869       }
870       break;
871     }
872     case GST_QUERY_CONVERT:{
873       GstFormat src_fmt, dest_fmt;
874       gint64 src_value, dest_value = 0;
875
876       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
877
878       res = gst_qtdemux_src_convert (qtdemux, pad,
879           src_fmt, src_value, dest_fmt, &dest_value);
880       if (res) {
881         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
882         res = TRUE;
883       }
884       break;
885     }
886     case GST_QUERY_FORMATS:
887       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
888       res = TRUE;
889       break;
890     case GST_QUERY_SEEKING:{
891       GstFormat fmt;
892       gboolean seekable;
893
894       /* try upstream first */
895       res = gst_pad_query_default (pad, parent, query);
896
897       if (!res) {
898         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
899         if (fmt == GST_FORMAT_TIME) {
900           GstClockTime duration;
901
902           gst_qtdemux_get_duration (qtdemux, &duration);
903           seekable = TRUE;
904           if (!qtdemux->pullbased) {
905             GstQuery *q;
906
907             /* we might be able with help from upstream */
908             seekable = FALSE;
909             q = gst_query_new_seeking (GST_FORMAT_BYTES);
910             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
911               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
912               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
913             }
914             gst_query_unref (q);
915           }
916           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
917           res = TRUE;
918         }
919       }
920       break;
921     }
922     case GST_QUERY_SEGMENT:
923     {
924       GstFormat format;
925       gint64 start, stop;
926
927       format = qtdemux->segment.format;
928
929       start =
930           gst_segment_to_stream_time (&qtdemux->segment, format,
931           qtdemux->segment.start);
932       if ((stop = qtdemux->segment.stop) == -1)
933         stop = qtdemux->segment.duration;
934       else
935         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
936
937       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
938       res = TRUE;
939       break;
940     }
941     default:
942       res = gst_pad_query_default (pad, parent, query);
943       break;
944   }
945
946   return res;
947 }
948
949 static void
950 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
951 {
952   if (G_LIKELY (stream->pad)) {
953     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
954         GST_DEBUG_PAD_NAME (stream->pad));
955
956     if (G_UNLIKELY (stream->pending_tags)) {
957       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
958           stream->pending_tags);
959       gst_pad_push_event (stream->pad,
960           gst_event_new_tag (stream->pending_tags));
961       stream->pending_tags = NULL;
962     }
963
964     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
965       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
966           qtdemux->tag_list);
967       gst_pad_push_event (stream->pad,
968           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
969       stream->send_global_tags = FALSE;
970     }
971   }
972 }
973
974 /* push event on all source pads; takes ownership of the event */
975 static void
976 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
977 {
978   guint n;
979   gboolean has_valid_stream = FALSE;
980   GstEventType etype = GST_EVENT_TYPE (event);
981
982   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
983       GST_EVENT_TYPE_NAME (event));
984
985   for (n = 0; n < qtdemux->n_streams; n++) {
986     GstPad *pad;
987     QtDemuxStream *stream = qtdemux->streams[n];
988     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
989
990     if ((pad = stream->pad)) {
991       has_valid_stream = TRUE;
992
993       if (etype == GST_EVENT_EOS) {
994         /* let's not send twice */
995         if (stream->sent_eos)
996           continue;
997         stream->sent_eos = TRUE;
998       }
999
1000       gst_pad_push_event (pad, gst_event_ref (event));
1001     }
1002   }
1003
1004   gst_event_unref (event);
1005
1006   /* if it is EOS and there are no pads, post an error */
1007   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1008     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1009   }
1010 }
1011
1012 /* push a pending newsegment event, if any from the streaming thread */
1013 static void
1014 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1015 {
1016   if (qtdemux->pending_newsegment) {
1017     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1018     qtdemux->pending_newsegment = NULL;
1019   }
1020 }
1021
1022 typedef struct
1023 {
1024   guint64 media_time;
1025 } FindData;
1026
1027 static gint
1028 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1029 {
1030   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1031     return 1;
1032   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1033     return 0;
1034
1035   return -1;
1036 }
1037
1038 /* find the index of the sample that includes the data for @media_time using a
1039  * binary search.  Only to be called in optimized cases of linear search below.
1040  *
1041  * Returns the index of the sample.
1042  */
1043 static guint32
1044 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1045     guint64 media_time)
1046 {
1047   QtDemuxSample *result;
1048   guint32 index;
1049
1050   /* convert media_time to mov format */
1051   media_time =
1052       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1053
1054   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1055       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1056       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1057
1058   if (G_LIKELY (result))
1059     index = result - str->samples;
1060   else
1061     index = 0;
1062
1063   return index;
1064 }
1065
1066
1067
1068 /* find the index of the sample that includes the data for @media_offset using a
1069  * linear search
1070  *
1071  * Returns the index of the sample.
1072  */
1073 static guint32
1074 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1075     QtDemuxStream * str, gint64 media_offset)
1076 {
1077   QtDemuxSample *result = str->samples;
1078   guint32 index = 0;
1079
1080   if (result == NULL || str->n_samples == 0)
1081     return -1;
1082
1083   if (media_offset == result->offset)
1084     return index;
1085
1086   result++;
1087   while (index < str->n_samples - 1) {
1088     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1089       goto parse_failed;
1090
1091     if (media_offset < result->offset)
1092       break;
1093
1094     index++;
1095     result++;
1096   }
1097   return index;
1098
1099   /* ERRORS */
1100 parse_failed:
1101   {
1102     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1103     return -1;
1104   }
1105 }
1106
1107 /* find the index of the sample that includes the data for @media_time using a
1108  * linear search, and keeping in mind that not all samples may have been parsed
1109  * yet.  If possible, it will delegate to binary search.
1110  *
1111  * Returns the index of the sample.
1112  */
1113 static guint32
1114 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1115     GstClockTime media_time)
1116 {
1117   guint32 index = 0;
1118   guint64 mov_time;
1119   QtDemuxSample *sample;
1120
1121   /* convert media_time to mov format */
1122   mov_time =
1123       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1124
1125   sample = str->samples;
1126   if (mov_time == sample->timestamp + sample->pts_offset)
1127     return index;
1128
1129   /* use faster search if requested time in already parsed range */
1130   sample = str->samples + str->stbl_index;
1131   if (str->stbl_index >= 0 &&
1132       mov_time <= (sample->timestamp + sample->pts_offset))
1133     return gst_qtdemux_find_index (qtdemux, str, media_time);
1134
1135   while (index < str->n_samples - 1) {
1136     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1137       goto parse_failed;
1138
1139     sample = str->samples + index + 1;
1140     if (mov_time < (sample->timestamp + sample->pts_offset))
1141       break;
1142
1143     index++;
1144   }
1145   return index;
1146
1147   /* ERRORS */
1148 parse_failed:
1149   {
1150     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1151     return -1;
1152   }
1153 }
1154
1155 /* find the index of the keyframe needed to decode the sample at @index
1156  * of stream @str.
1157  *
1158  * Returns the index of the keyframe.
1159  */
1160 static guint32
1161 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1162     guint32 index)
1163 {
1164   guint32 new_index = index;
1165
1166   if (index >= str->n_samples) {
1167     new_index = str->n_samples;
1168     goto beach;
1169   }
1170
1171   /* all keyframes, return index */
1172   if (str->all_keyframe) {
1173     new_index = index;
1174     goto beach;
1175   }
1176
1177   /* else go back until we have a keyframe */
1178   while (TRUE) {
1179     if (str->samples[new_index].keyframe)
1180       break;
1181
1182     if (new_index == 0)
1183       break;
1184
1185     new_index--;
1186   }
1187
1188 beach:
1189   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1190       "gave %u", index, new_index);
1191
1192   return new_index;
1193 }
1194
1195 /* find the segment for @time_position for @stream
1196  *
1197  * Returns the index of the segment containing @time_position.
1198  * Returns the last segment and sets the @eos variable to TRUE
1199  * if the time is beyond the end. @eos may be NULL
1200  */
1201 static guint32
1202 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1203     GstClockTime time_position)
1204 {
1205   gint i;
1206   guint32 seg_idx;
1207
1208   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1209       GST_TIME_ARGS (time_position));
1210
1211   seg_idx = -1;
1212   for (i = 0; i < stream->n_segments; i++) {
1213     QtDemuxSegment *segment = &stream->segments[i];
1214
1215     GST_LOG_OBJECT (stream->pad,
1216         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1217         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1218
1219     /* For the last segment we include stop_time in the last segment */
1220     if (i < stream->n_segments - 1) {
1221       if (segment->time <= time_position && time_position < segment->stop_time) {
1222         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1223         seg_idx = i;
1224         break;
1225       }
1226     } else {
1227       /* Last segment always matches */
1228       seg_idx = i;
1229       break;
1230     }
1231   }
1232   return seg_idx;
1233 }
1234
1235 /* move the stream @str to the sample position @index.
1236  *
1237  * Updates @str->sample_index and marks discontinuity if needed.
1238  */
1239 static void
1240 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1241     guint32 index)
1242 {
1243   /* no change needed */
1244   if (index == str->sample_index)
1245     return;
1246
1247   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1248       str->n_samples);
1249
1250   /* position changed, we have a discont */
1251   str->sample_index = index;
1252   str->offset_in_sample = 0;
1253   /* Each time we move in the stream we store the position where we are
1254    * starting from */
1255   str->from_sample = index;
1256   str->discont = TRUE;
1257 }
1258
1259 static void
1260 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1261     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1262 {
1263   guint64 min_offset;
1264   gint64 min_byte_offset = -1;
1265   gint n;
1266
1267   min_offset = desired_time;
1268
1269   /* for each stream, find the index of the sample in the segment
1270    * and move back to the previous keyframe. */
1271   for (n = 0; n < qtdemux->n_streams; n++) {
1272     QtDemuxStream *str;
1273     guint32 index, kindex;
1274     guint32 seg_idx;
1275     GstClockTime media_start;
1276     GstClockTime media_time;
1277     GstClockTime seg_time;
1278     QtDemuxSegment *seg;
1279     gboolean empty_segment = FALSE;
1280
1281     str = qtdemux->streams[n];
1282
1283     if (str->sparse && !use_sparse)
1284       continue;
1285
1286     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1287     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1288
1289     /* get segment and time in the segment */
1290     seg = &str->segments[seg_idx];
1291     seg_time = (desired_time - seg->time) * seg->rate;
1292
1293     while (QTSEGMENT_IS_EMPTY (seg)) {
1294       seg_time = 0;
1295       empty_segment = TRUE;
1296       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1297           seg_idx);
1298       seg_idx++;
1299       if (seg_idx == str->n_segments)
1300         break;
1301       seg = &str->segments[seg_idx];
1302     }
1303
1304     if (seg_idx == str->n_segments) {
1305       /* FIXME track shouldn't have the last segment as empty, but if it
1306        * happens we better handle it */
1307       continue;
1308     }
1309
1310     /* get the media time in the segment */
1311     media_start = seg->media_start + seg_time;
1312
1313     /* get the index of the sample with media time */
1314     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1315     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1316         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1317         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1318         empty_segment);
1319
1320     if (!empty_segment) {
1321       /* find previous keyframe */
1322       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1323
1324       /* if the keyframe is at a different position, we need to update the
1325        * requested seek time */
1326       if (index != kindex) {
1327         index = kindex;
1328
1329         /* get timestamp of keyframe */
1330         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1331         GST_DEBUG_OBJECT (qtdemux,
1332             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1333             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1334             str->samples[kindex].offset);
1335
1336         /* keyframes in the segment get a chance to change the
1337          * desired_offset. keyframes out of the segment are
1338          * ignored. */
1339         if (media_time >= seg->media_start) {
1340           GstClockTime seg_time;
1341
1342           /* this keyframe is inside the segment, convert back to
1343            * segment time */
1344           seg_time = (media_time - seg->media_start) + seg->time;
1345           if (seg_time < min_offset)
1346             min_offset = seg_time;
1347         }
1348       }
1349     }
1350
1351     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1352       min_byte_offset = str->samples[index].offset;
1353   }
1354
1355   if (key_time)
1356     *key_time = min_offset;
1357   if (key_offset)
1358     *key_offset = min_byte_offset;
1359 }
1360
1361 static gboolean
1362 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1363     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1364 {
1365   gboolean res;
1366
1367   g_return_val_if_fail (format != NULL, FALSE);
1368   g_return_val_if_fail (cur != NULL, FALSE);
1369   g_return_val_if_fail (stop != NULL, FALSE);
1370
1371   if (*format == GST_FORMAT_TIME)
1372     return TRUE;
1373
1374   res = TRUE;
1375   if (cur_type != GST_SEEK_TYPE_NONE)
1376     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1377   if (res && stop_type != GST_SEEK_TYPE_NONE)
1378     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1379
1380   if (res)
1381     *format = GST_FORMAT_TIME;
1382
1383   return res;
1384 }
1385
1386 /* perform seek in push based mode:
1387    find BYTE position to move to based on time and delegate to upstream
1388 */
1389 static gboolean
1390 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1391 {
1392   gdouble rate;
1393   GstFormat format;
1394   GstSeekFlags flags;
1395   GstSeekType cur_type, stop_type;
1396   gint64 cur, stop, key_cur;
1397   gboolean res;
1398   gint64 byte_cur;
1399   gint64 original_stop;
1400   guint32 seqnum;
1401
1402   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1403
1404   gst_event_parse_seek (event, &rate, &format, &flags,
1405       &cur_type, &cur, &stop_type, &stop);
1406   seqnum = gst_event_get_seqnum (event);
1407
1408   /* only forward streaming and seeking is possible */
1409   if (rate <= 0)
1410     goto unsupported_seek;
1411
1412   /* convert to TIME if needed and possible */
1413   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1414           stop_type, &stop))
1415     goto no_format;
1416
1417   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1418    * the original stop position to use when upstream pushes the new segment
1419    * for this seek */
1420   original_stop = stop;
1421   stop = -1;
1422
1423   /* find reasonable corresponding BYTE position,
1424    * also try to mind about keyframes, since we can not go back a bit for them
1425    * later on */
1426   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1427
1428   if (byte_cur == -1)
1429     goto abort_seek;
1430
1431   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1432       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1433       stop);
1434
1435   GST_OBJECT_LOCK (qtdemux);
1436   qtdemux->seek_offset = byte_cur;
1437   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1438     qtdemux->push_seek_start = cur;
1439   } else {
1440     qtdemux->push_seek_start = key_cur;
1441   }
1442
1443   if (stop_type == GST_SEEK_TYPE_NONE) {
1444     qtdemux->push_seek_stop = qtdemux->segment.stop;
1445   } else {
1446     qtdemux->push_seek_stop = original_stop;
1447   }
1448   GST_OBJECT_UNLOCK (qtdemux);
1449
1450   /* BYTE seek event */
1451   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1452       stop_type, stop);
1453   gst_event_set_seqnum (event, seqnum);
1454   res = gst_pad_push_event (qtdemux->sinkpad, event);
1455
1456   return res;
1457
1458   /* ERRORS */
1459 abort_seek:
1460   {
1461     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1462         "seek aborted.");
1463     return FALSE;
1464   }
1465 unsupported_seek:
1466   {
1467     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1468     return FALSE;
1469   }
1470 no_format:
1471   {
1472     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1473     return FALSE;
1474   }
1475 }
1476
1477 /* perform the seek.
1478  *
1479  * We set all segment_indexes in the streams to unknown and
1480  * adjust the time_position to the desired position. this is enough
1481  * to trigger a segment switch in the streaming thread to start
1482  * streaming from the desired position.
1483  *
1484  * Keyframe seeking is a little more complicated when dealing with
1485  * segments. Ideally we want to move to the previous keyframe in
1486  * the segment but there might not be a keyframe in the segment. In
1487  * fact, none of the segments could contain a keyframe. We take a
1488  * practical approach: seek to the previous keyframe in the segment,
1489  * if there is none, seek to the beginning of the segment.
1490  *
1491  * Called with STREAM_LOCK
1492  */
1493 static gboolean
1494 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1495     guint32 seqnum, GstSeekFlags flags)
1496 {
1497   gint64 desired_offset;
1498   gint n;
1499
1500   desired_offset = segment->position;
1501
1502   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1503       GST_TIME_ARGS (desired_offset));
1504
1505   /* may not have enough fragmented info to do this adjustment,
1506    * and we can't scan (and probably should not) at this time with
1507    * possibly flushing upstream */
1508   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1509     gint64 min_offset;
1510
1511     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1512     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1513         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1514     desired_offset = min_offset;
1515   }
1516
1517   /* and set all streams to the final position */
1518   gst_flow_combiner_reset (qtdemux->flowcombiner);
1519   qtdemux->segment_seqnum = seqnum;
1520   for (n = 0; n < qtdemux->n_streams; n++) {
1521     QtDemuxStream *stream = qtdemux->streams[n];
1522
1523     stream->time_position = desired_offset;
1524     stream->accumulated_base = 0;
1525     stream->sample_index = -1;
1526     stream->offset_in_sample = 0;
1527     stream->segment_index = -1;
1528     stream->sent_eos = FALSE;
1529
1530     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1531       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1532   }
1533   segment->position = desired_offset;
1534   segment->time = desired_offset;
1535   if (segment->rate >= 0) {
1536     segment->start = desired_offset;
1537
1538     /* we stop at the end */
1539     if (segment->stop == -1)
1540       segment->stop = segment->duration;
1541   } else {
1542     segment->stop = desired_offset;
1543   }
1544
1545   if (qtdemux->fragmented)
1546     qtdemux->fragmented_seek_pending = TRUE;
1547
1548   return TRUE;
1549 }
1550
1551 /* do a seek in pull based mode */
1552 static gboolean
1553 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1554 {
1555   gdouble rate;
1556   GstFormat format;
1557   GstSeekFlags flags;
1558   GstSeekType cur_type, stop_type;
1559   gint64 cur, stop;
1560   gboolean flush;
1561   gboolean update;
1562   GstSegment seeksegment;
1563   guint32 seqnum = 0;
1564   GstEvent *flush_event;
1565
1566   if (event) {
1567     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1568
1569     gst_event_parse_seek (event, &rate, &format, &flags,
1570         &cur_type, &cur, &stop_type, &stop);
1571     seqnum = gst_event_get_seqnum (event);
1572
1573     /* we have to have a format as the segment format. Try to convert
1574      * if not. */
1575     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1576             stop_type, &stop))
1577       goto no_format;
1578
1579     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1580   } else {
1581     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1582     flags = 0;
1583   }
1584
1585   flush = flags & GST_SEEK_FLAG_FLUSH;
1586
1587   /* stop streaming, either by flushing or by pausing the task */
1588   if (flush) {
1589     flush_event = gst_event_new_flush_start ();
1590     if (seqnum)
1591       gst_event_set_seqnum (flush_event, seqnum);
1592     /* unlock upstream pull_range */
1593     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1594     /* make sure out loop function exits */
1595     gst_qtdemux_push_event (qtdemux, flush_event);
1596   } else {
1597     /* non flushing seek, pause the task */
1598     gst_pad_pause_task (qtdemux->sinkpad);
1599   }
1600
1601   /* wait for streaming to finish */
1602   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1603
1604   /* copy segment, we need this because we still need the old
1605    * segment when we close the current segment. */
1606   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1607
1608   if (event) {
1609     /* configure the segment with the seek variables */
1610     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1611     gst_segment_do_seek (&seeksegment, rate, format, flags,
1612         cur_type, cur, stop_type, stop, &update);
1613   }
1614
1615   /* now do the seek, this actually never returns FALSE */
1616   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1617
1618   /* prepare for streaming again */
1619   if (flush) {
1620     flush_event = gst_event_new_flush_stop (TRUE);
1621     if (seqnum)
1622       gst_event_set_seqnum (flush_event, seqnum);
1623
1624     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1625     gst_qtdemux_push_event (qtdemux, flush_event);
1626   }
1627
1628   /* commit the new segment */
1629   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1630
1631   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1632     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1633         qtdemux->segment.format, qtdemux->segment.position);
1634     if (seqnum)
1635       gst_message_set_seqnum (msg, seqnum);
1636     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1637   }
1638
1639   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1640   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1641       qtdemux->sinkpad, NULL);
1642
1643   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1644
1645   return TRUE;
1646
1647   /* ERRORS */
1648 no_format:
1649   {
1650     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1651     return FALSE;
1652   }
1653 }
1654
1655 static gboolean
1656 qtdemux_ensure_index (GstQTDemux * qtdemux)
1657 {
1658   guint i;
1659
1660   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1661
1662   /* Build complete index */
1663   for (i = 0; i < qtdemux->n_streams; i++) {
1664     QtDemuxStream *stream = qtdemux->streams[i];
1665
1666     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1667       goto parse_error;
1668   }
1669   return TRUE;
1670
1671   /* ERRORS */
1672 parse_error:
1673   {
1674     GST_LOG_OBJECT (qtdemux,
1675         "Building complete index of stream %u for seeking failed!", i);
1676     return FALSE;
1677   }
1678 }
1679
1680 static gboolean
1681 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1682     GstEvent * event)
1683 {
1684   gboolean res = TRUE;
1685   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1686
1687   switch (GST_EVENT_TYPE (event)) {
1688     case GST_EVENT_SEEK:
1689     {
1690 #ifndef GST_DISABLE_GST_DEBUG
1691       GstClockTime ts = gst_util_get_timestamp ();
1692 #endif
1693
1694       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1695         /* seek should be handled by upstream, we might need to re-download fragments */
1696         GST_DEBUG_OBJECT (qtdemux,
1697             "let upstream handle seek for fragmented playback");
1698         goto upstream;
1699       }
1700
1701       /* Build complete index for seeking;
1702        * if not a fragmented file at least */
1703       if (!qtdemux->fragmented)
1704         if (!qtdemux_ensure_index (qtdemux))
1705           goto index_failed;
1706 #ifndef GST_DISABLE_GST_DEBUG
1707       ts = gst_util_get_timestamp () - ts;
1708       GST_INFO_OBJECT (qtdemux,
1709           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1710 #endif
1711     }
1712       if (qtdemux->pullbased) {
1713         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1714       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1715         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1716         res = TRUE;
1717       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1718           && !qtdemux->fragmented) {
1719         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1720       } else {
1721         GST_DEBUG_OBJECT (qtdemux,
1722             "ignoring seek in push mode in current state");
1723         res = FALSE;
1724       }
1725       gst_event_unref (event);
1726       break;
1727     default:
1728     upstream:
1729       res = gst_pad_event_default (pad, parent, event);
1730       break;
1731   }
1732
1733 done:
1734   return res;
1735
1736   /* ERRORS */
1737 index_failed:
1738   {
1739     GST_ERROR_OBJECT (qtdemux, "Index failed");
1740     gst_event_unref (event);
1741     res = FALSE;
1742     goto done;
1743   }
1744 }
1745
1746 /* stream/index return sample that is min/max w.r.t. byte position,
1747  * time is min/max w.r.t. time of samples,
1748  * the latter need not be time of the former sample */
1749 static void
1750 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1751     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1752 {
1753   gint i, n, index;
1754   gint64 time, min_time;
1755   QtDemuxStream *stream;
1756
1757   min_time = -1;
1758   stream = NULL;
1759   index = -1;
1760
1761   for (n = 0; n < qtdemux->n_streams; ++n) {
1762     QtDemuxStream *str;
1763     gint inc;
1764     gboolean set_sample;
1765
1766     str = qtdemux->streams[n];
1767     set_sample = !set;
1768
1769     if (fw) {
1770       i = 0;
1771       inc = 1;
1772     } else {
1773       i = str->n_samples - 1;
1774       inc = -1;
1775     }
1776
1777     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1778       if (str->samples[i].size == 0)
1779         continue;
1780
1781       if (fw && (str->samples[i].offset < byte_pos))
1782         continue;
1783
1784       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1785         continue;
1786
1787       /* move stream to first available sample */
1788       if (set) {
1789         gst_qtdemux_move_stream (qtdemux, str, i);
1790         set_sample = TRUE;
1791       }
1792
1793       /* avoid index from sparse streams since they might be far away */
1794       if (!str->sparse) {
1795         /* determine min/max time */
1796         time = QTSAMPLE_PTS (str, &str->samples[i]);
1797         if (min_time == -1 || (!fw && time > min_time) ||
1798             (fw && time < min_time)) {
1799           min_time = time;
1800         }
1801
1802         /* determine stream with leading sample, to get its position */
1803         if (!stream ||
1804             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1805             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1806           stream = str;
1807           index = i;
1808         }
1809       }
1810       break;
1811     }
1812
1813     /* no sample for this stream, mark eos */
1814     if (!set_sample)
1815       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1816   }
1817
1818   if (_time)
1819     *_time = min_time;
1820   if (_stream)
1821     *_stream = stream;
1822   if (_index)
1823     *_index = index;
1824 }
1825
1826 static QtDemuxStream *
1827 _create_stream (void)
1828 {
1829   QtDemuxStream *stream;
1830
1831   stream = g_new0 (QtDemuxStream, 1);
1832   /* new streams always need a discont */
1833   stream->discont = TRUE;
1834   /* we enable clipping for raw audio/video streams */
1835   stream->need_clip = FALSE;
1836   stream->need_process = FALSE;
1837   stream->segment_index = -1;
1838   stream->time_position = 0;
1839   stream->sample_index = -1;
1840   stream->offset_in_sample = 0;
1841   stream->new_stream = TRUE;
1842   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1843   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1844   stream->protected = FALSE;
1845   stream->protection_scheme_type = 0;
1846   stream->protection_scheme_version = 0;
1847   stream->protection_scheme_info = NULL;
1848   stream->n_samples_moof = 0;
1849   stream->duration_moof = 0;
1850   stream->duration_last_moof = 0;
1851   g_queue_init (&stream->protection_scheme_event_queue);
1852   return stream;
1853 }
1854
1855 static gboolean
1856 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1857 {
1858   GstStructure *structure;
1859   const gchar *variant;
1860   const GstCaps *mediacaps = NULL;
1861
1862   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1863
1864   structure = gst_caps_get_structure (caps, 0);
1865   variant = gst_structure_get_string (structure, "variant");
1866
1867   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1868     QtDemuxStream *stream;
1869     const GValue *value;
1870
1871     demux->fragmented = TRUE;
1872     demux->mss_mode = TRUE;
1873
1874     if (demux->n_streams > 1) {
1875       /* can't do this, we can only renegotiate for another mss format */
1876       return FALSE;
1877     }
1878
1879     value = gst_structure_get_value (structure, "media-caps");
1880     /* create stream */
1881     if (value) {
1882       const GValue *timescale_v;
1883
1884       /* TODO update when stream changes during playback */
1885
1886       if (demux->n_streams == 0) {
1887         stream = _create_stream ();
1888         demux->streams[demux->n_streams] = stream;
1889         demux->n_streams = 1;
1890       } else {
1891         stream = demux->streams[0];
1892       }
1893
1894       timescale_v = gst_structure_get_value (structure, "timescale");
1895       if (timescale_v) {
1896         stream->timescale = g_value_get_uint64 (timescale_v);
1897       } else {
1898         /* default mss timescale */
1899         stream->timescale = 10000000;
1900       }
1901       demux->timescale = stream->timescale;
1902
1903       mediacaps = gst_value_get_caps (value);
1904       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1905         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1906             mediacaps);
1907         stream->new_caps = TRUE;
1908       }
1909       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1910       structure = gst_caps_get_structure (mediacaps, 0);
1911       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1912         stream->subtype = FOURCC_vide;
1913
1914         gst_structure_get_int (structure, "width", &stream->width);
1915         gst_structure_get_int (structure, "height", &stream->height);
1916         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1917             &stream->fps_d);
1918       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1919         gint rate = 0;
1920         stream->subtype = FOURCC_soun;
1921         gst_structure_get_int (structure, "channels", &stream->n_channels);
1922         gst_structure_get_int (structure, "rate", &rate);
1923         stream->rate = rate;
1924       }
1925     }
1926     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1927   } else {
1928     demux->mss_mode = FALSE;
1929   }
1930
1931   return TRUE;
1932 }
1933
1934 static void
1935 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1936 {
1937   gint n;
1938
1939   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1940   gst_pad_stop_task (qtdemux->sinkpad);
1941
1942   if (hard || qtdemux->upstream_format_is_time) {
1943     qtdemux->state = QTDEMUX_STATE_INITIAL;
1944     qtdemux->neededbytes = 16;
1945     qtdemux->todrop = 0;
1946     qtdemux->pullbased = FALSE;
1947     qtdemux->posted_redirect = FALSE;
1948     qtdemux->first_mdat = -1;
1949     qtdemux->header_size = 0;
1950     qtdemux->mdatoffset = -1;
1951     qtdemux->restoredata_offset = -1;
1952     if (qtdemux->mdatbuffer)
1953       gst_buffer_unref (qtdemux->mdatbuffer);
1954     if (qtdemux->restoredata_buffer)
1955       gst_buffer_unref (qtdemux->restoredata_buffer);
1956     qtdemux->mdatbuffer = NULL;
1957     qtdemux->restoredata_buffer = NULL;
1958     qtdemux->mdatleft = 0;
1959     if (qtdemux->comp_brands)
1960       gst_buffer_unref (qtdemux->comp_brands);
1961     qtdemux->comp_brands = NULL;
1962     qtdemux->last_moov_offset = -1;
1963     if (qtdemux->moov_node)
1964       g_node_destroy (qtdemux->moov_node);
1965     qtdemux->moov_node = NULL;
1966     qtdemux->moov_node_compressed = NULL;
1967     if (qtdemux->tag_list)
1968       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1969     qtdemux->tag_list = NULL;
1970 #if 0
1971     if (qtdemux->element_index)
1972       gst_object_unref (qtdemux->element_index);
1973     qtdemux->element_index = NULL;
1974 #endif
1975     qtdemux->major_brand = 0;
1976     if (qtdemux->pending_newsegment)
1977       gst_event_unref (qtdemux->pending_newsegment);
1978     qtdemux->pending_newsegment = NULL;
1979     qtdemux->upstream_format_is_time = FALSE;
1980     qtdemux->upstream_seekable = FALSE;
1981     qtdemux->upstream_size = 0;
1982
1983     qtdemux->fragment_start = -1;
1984     qtdemux->fragment_start_offset = -1;
1985     qtdemux->duration = 0;
1986     qtdemux->moof_offset = 0;
1987     qtdemux->chapters_track_id = 0;
1988     qtdemux->have_group_id = FALSE;
1989     qtdemux->group_id = G_MAXUINT;
1990
1991     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1992         NULL);
1993     g_queue_clear (&qtdemux->protection_event_queue);
1994   }
1995   qtdemux->offset = 0;
1996   gst_adapter_clear (qtdemux->adapter);
1997   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1998   qtdemux->segment_seqnum = 0;
1999
2000   if (hard) {
2001     for (n = 0; n < qtdemux->n_streams; n++) {
2002       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2003       qtdemux->streams[n] = NULL;
2004     }
2005     qtdemux->n_streams = 0;
2006     qtdemux->n_video_streams = 0;
2007     qtdemux->n_audio_streams = 0;
2008     qtdemux->n_sub_streams = 0;
2009     qtdemux->exposed = FALSE;
2010     qtdemux->fragmented = FALSE;
2011     qtdemux->mss_mode = FALSE;
2012     gst_caps_replace (&qtdemux->media_caps, NULL);
2013     qtdemux->timescale = 0;
2014     qtdemux->got_moov = FALSE;
2015     if (qtdemux->protection_system_ids) {
2016       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2017       qtdemux->protection_system_ids = NULL;
2018     }
2019   } else if (qtdemux->mss_mode) {
2020     gst_flow_combiner_reset (qtdemux->flowcombiner);
2021     for (n = 0; n < qtdemux->n_streams; n++)
2022       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2023   } else {
2024     gst_flow_combiner_reset (qtdemux->flowcombiner);
2025     for (n = 0; n < qtdemux->n_streams; n++) {
2026       qtdemux->streams[n]->sent_eos = FALSE;
2027       qtdemux->streams[n]->time_position = 0;
2028       qtdemux->streams[n]->accumulated_base = 0;
2029     }
2030     if (!qtdemux->pending_newsegment) {
2031       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2032       if (qtdemux->segment_seqnum)
2033         gst_event_set_seqnum (qtdemux->pending_newsegment,
2034             qtdemux->segment_seqnum);
2035     }
2036   }
2037 }
2038
2039
2040 /* Maps the @segment to the qt edts internal segments and pushes
2041  * the correspnding segment event.
2042  *
2043  * If it ends up being at a empty segment, a gap will be pushed and the next
2044  * edts segment will be activated in sequence.
2045  *
2046  * To be used in push-mode only */
2047 static void
2048 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2049 {
2050   gint n, i;
2051
2052   for (n = 0; n < qtdemux->n_streams; n++) {
2053     QtDemuxStream *stream = qtdemux->streams[n];
2054
2055     stream->time_position = segment->start;
2056
2057     /* in push mode we should be guaranteed that we will have empty segments
2058      * at the beginning and then one segment after, other scenarios are not
2059      * supported and are discarded when parsing the edts */
2060     for (i = 0; i < stream->n_segments; i++) {
2061       if (stream->segments[i].stop_time > segment->start) {
2062         gst_qtdemux_activate_segment (qtdemux, stream, i,
2063             stream->time_position);
2064         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2065           /* push the empty segment and move to the next one */
2066           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2067               stream->time_position);
2068           continue;
2069         }
2070
2071         g_assert (i == stream->n_segments - 1);
2072       }
2073     }
2074   }
2075 }
2076
2077 static gboolean
2078 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2079     GstEvent * event)
2080 {
2081   GstQTDemux *demux = GST_QTDEMUX (parent);
2082   gboolean res = TRUE;
2083
2084   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2085
2086   switch (GST_EVENT_TYPE (event)) {
2087     case GST_EVENT_SEGMENT:
2088     {
2089       gint64 offset = 0;
2090       QtDemuxStream *stream;
2091       gint idx;
2092       GstSegment segment;
2093
2094       /* some debug output */
2095       gst_event_copy_segment (event, &segment);
2096       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2097           &segment);
2098
2099       /* erase any previously set segment */
2100       gst_event_replace (&demux->pending_newsegment, NULL);
2101
2102       if (segment.format == GST_FORMAT_TIME) {
2103         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2104         gst_event_replace (&demux->pending_newsegment, event);
2105         demux->upstream_format_is_time = TRUE;
2106       } else {
2107         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2108             "not in time format");
2109
2110         /* chain will send initial newsegment after pads have been added */
2111         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2112           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2113           goto exit;
2114         }
2115       }
2116
2117       /* check if this matches a time seek we received previously
2118        * FIXME for backwards compatibility reasons we use the
2119        * seek_offset here to compare. In the future we might want to
2120        * change this to use the seqnum as it uniquely should identify
2121        * the segment that corresponds to the seek. */
2122       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2123           ", received segment offset %" G_GINT64_FORMAT,
2124           demux->seek_offset, segment.start);
2125       if (segment.format == GST_FORMAT_BYTES
2126           && demux->seek_offset == segment.start) {
2127         GST_OBJECT_LOCK (demux);
2128         offset = segment.start;
2129
2130         segment.format = GST_FORMAT_TIME;
2131         segment.start = demux->push_seek_start;
2132         segment.stop = demux->push_seek_stop;
2133         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2134             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2135             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2136         GST_OBJECT_UNLOCK (demux);
2137       }
2138
2139       /* we only expect a BYTE segment, e.g. following a seek */
2140       if (segment.format == GST_FORMAT_BYTES) {
2141         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2142           offset = segment.start;
2143
2144           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2145               NULL, (gint64 *) & segment.start);
2146           if ((gint64) segment.start < 0)
2147             segment.start = 0;
2148         }
2149         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2150           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2151               NULL, (gint64 *) & segment.stop);
2152           /* keyframe seeking should already arrange for start >= stop,
2153            * but make sure in other rare cases */
2154           segment.stop = MAX (segment.stop, segment.start);
2155         }
2156       } else if (segment.format == GST_FORMAT_TIME) {
2157         /* push all data on the adapter before starting this
2158          * new segment */
2159         gst_qtdemux_process_adapter (demux, TRUE);
2160       } else {
2161         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2162         goto exit;
2163       }
2164
2165       /* We shouldn't modify upstream driven TIME FORMAT segment */
2166       if (!demux->upstream_format_is_time) {
2167         /* accept upstream's notion of segment and distribute along */
2168         segment.format = GST_FORMAT_TIME;
2169         segment.position = segment.time = segment.start;
2170         segment.duration = demux->segment.duration;
2171         segment.base = gst_segment_to_running_time (&demux->segment,
2172             GST_FORMAT_TIME, demux->segment.position);
2173       }
2174
2175       gst_segment_copy_into (&segment, &demux->segment);
2176       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2177
2178       /* map segment to internal qt segments and push on each stream */
2179       if (demux->n_streams) {
2180         if (demux->fragmented) {
2181           GstEvent *segment_event = gst_event_new_segment (&segment);
2182
2183           gst_event_replace (&demux->pending_newsegment, NULL);
2184           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2185           gst_qtdemux_push_event (demux, segment_event);
2186         } else {
2187           gst_event_replace (&demux->pending_newsegment, NULL);
2188           gst_qtdemux_map_and_push_segments (demux, &segment);
2189         }
2190       }
2191
2192       /* clear leftover in current segment, if any */
2193       gst_adapter_clear (demux->adapter);
2194
2195       /* set up streaming thread */
2196       demux->offset = offset;
2197       if (demux->upstream_format_is_time) {
2198         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2199             "set values to restart reading from a new atom");
2200         demux->neededbytes = 16;
2201         demux->todrop = 0;
2202       } else {
2203         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2204             NULL);
2205         if (stream) {
2206           demux->todrop = stream->samples[idx].offset - offset;
2207           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2208         } else {
2209           /* set up for EOS */
2210           demux->neededbytes = -1;
2211           demux->todrop = 0;
2212         }
2213       }
2214     exit:
2215       gst_event_unref (event);
2216       res = TRUE;
2217       goto drop;
2218     }
2219     case GST_EVENT_FLUSH_START:
2220     {
2221       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2222         gst_event_unref (event);
2223         goto drop;
2224       }
2225       break;
2226     }
2227     case GST_EVENT_FLUSH_STOP:
2228     {
2229       guint64 dur;
2230
2231       dur = demux->segment.duration;
2232       gst_qtdemux_reset (demux, FALSE);
2233       demux->segment.duration = dur;
2234
2235       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2236         gst_event_unref (event);
2237         goto drop;
2238       }
2239       break;
2240     }
2241     case GST_EVENT_EOS:
2242       /* If we are in push mode, and get an EOS before we've seen any streams,
2243        * then error out - we have nowhere to send the EOS */
2244       if (!demux->pullbased) {
2245         gint i;
2246         gboolean has_valid_stream = FALSE;
2247         for (i = 0; i < demux->n_streams; i++) {
2248           if (demux->streams[i]->pad != NULL) {
2249             has_valid_stream = TRUE;
2250             break;
2251           }
2252         }
2253         if (!has_valid_stream)
2254           gst_qtdemux_post_no_playable_stream_error (demux);
2255         else {
2256           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2257               (guint) gst_adapter_available (demux->adapter));
2258           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2259             res = FALSE;
2260           }
2261         }
2262       }
2263       break;
2264     case GST_EVENT_CAPS:{
2265       GstCaps *caps = NULL;
2266
2267       gst_event_parse_caps (event, &caps);
2268       gst_qtdemux_setcaps (demux, caps);
2269       res = TRUE;
2270       gst_event_unref (event);
2271       goto drop;
2272     }
2273     case GST_EVENT_PROTECTION:
2274     {
2275       const gchar *system_id = NULL;
2276
2277       gst_event_parse_protection (event, &system_id, NULL, NULL);
2278       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2279           system_id);
2280       gst_qtdemux_append_protection_system_id (demux, system_id);
2281       /* save the event for later, for source pads that have not been created */
2282       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2283       /* send it to all pads that already exist */
2284       gst_qtdemux_push_event (demux, event);
2285       res = TRUE;
2286       goto drop;
2287     }
2288     default:
2289       break;
2290   }
2291
2292   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2293
2294 drop:
2295   return res;
2296 }
2297
2298 #if 0
2299 static void
2300 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2301 {
2302   GstQTDemux *demux = GST_QTDEMUX (element);
2303
2304   GST_OBJECT_LOCK (demux);
2305   if (demux->element_index)
2306     gst_object_unref (demux->element_index);
2307   if (index) {
2308     demux->element_index = gst_object_ref (index);
2309   } else {
2310     demux->element_index = NULL;
2311   }
2312   GST_OBJECT_UNLOCK (demux);
2313   /* object lock might be taken again */
2314   if (index)
2315     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2316   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2317       demux->element_index, demux->index_id);
2318 }
2319
2320 static GstIndex *
2321 gst_qtdemux_get_index (GstElement * element)
2322 {
2323   GstIndex *result = NULL;
2324   GstQTDemux *demux = GST_QTDEMUX (element);
2325
2326   GST_OBJECT_LOCK (demux);
2327   if (demux->element_index)
2328     result = gst_object_ref (demux->element_index);
2329   GST_OBJECT_UNLOCK (demux);
2330
2331   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2332
2333   return result;
2334 }
2335 #endif
2336
2337 static void
2338 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2339 {
2340   g_free ((gpointer) stream->stco.data);
2341   stream->stco.data = NULL;
2342   g_free ((gpointer) stream->stsz.data);
2343   stream->stsz.data = NULL;
2344   g_free ((gpointer) stream->stsc.data);
2345   stream->stsc.data = NULL;
2346   g_free ((gpointer) stream->stts.data);
2347   stream->stts.data = NULL;
2348   g_free ((gpointer) stream->stss.data);
2349   stream->stss.data = NULL;
2350   g_free ((gpointer) stream->stps.data);
2351   stream->stps.data = NULL;
2352   g_free ((gpointer) stream->ctts.data);
2353   stream->ctts.data = NULL;
2354 }
2355
2356 static void
2357 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2358     QtDemuxStream * stream)
2359 {
2360   g_free (stream->segments);
2361   stream->segments = NULL;
2362   stream->segment_index = -1;
2363   stream->accumulated_base = 0;
2364 }
2365
2366 static void
2367 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2368     QtDemuxStream * stream)
2369 {
2370   g_free (stream->samples);
2371   stream->samples = NULL;
2372   gst_qtdemux_stbl_free (stream);
2373
2374   /* fragments */
2375   g_free (stream->ra_entries);
2376   stream->ra_entries = NULL;
2377   stream->n_ra_entries = 0;
2378
2379   stream->sample_index = -1;
2380   stream->stbl_index = -1;
2381   stream->n_samples = 0;
2382   stream->time_position = 0;
2383
2384   stream->n_samples_moof = 0;
2385   stream->duration_moof = 0;
2386   stream->duration_last_moof = 0;
2387 }
2388
2389 static void
2390 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2391 {
2392   if (stream->allocator)
2393     gst_object_unref (stream->allocator);
2394   while (stream->buffers) {
2395     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2396     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2397   }
2398   if (stream->rgb8_palette) {
2399     gst_memory_unref (stream->rgb8_palette);
2400     stream->rgb8_palette = NULL;
2401   }
2402
2403   if (stream->pending_tags)
2404     gst_tag_list_unref (stream->pending_tags);
2405   stream->pending_tags = NULL;
2406   g_free (stream->redirect_uri);
2407   stream->redirect_uri = NULL;
2408   stream->sent_eos = FALSE;
2409   stream->sparse = FALSE;
2410   stream->protected = FALSE;
2411   if (stream->protection_scheme_info) {
2412     if (stream->protection_scheme_type == FOURCC_cenc) {
2413       QtDemuxCencSampleSetInfo *info =
2414           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2415       if (info->default_properties)
2416         gst_structure_free (info->default_properties);
2417       if (info->crypto_info)
2418         g_ptr_array_free (info->crypto_info, TRUE);
2419     }
2420     g_free (stream->protection_scheme_info);
2421     stream->protection_scheme_info = NULL;
2422   }
2423   stream->protection_scheme_type = 0;
2424   stream->protection_scheme_version = 0;
2425   g_queue_foreach (&stream->protection_scheme_event_queue,
2426       (GFunc) gst_event_unref, NULL);
2427   g_queue_clear (&stream->protection_scheme_event_queue);
2428   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2429   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2430 }
2431
2432 static void
2433 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2434 {
2435   gst_qtdemux_stream_clear (qtdemux, stream);
2436   if (stream->caps)
2437     gst_caps_unref (stream->caps);
2438   stream->caps = NULL;
2439   if (stream->pad) {
2440     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2441     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2442   }
2443   g_free (stream);
2444 }
2445
2446 static void
2447 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2448 {
2449   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2450
2451   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2452   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2453   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2454   qtdemux->n_streams--;
2455 }
2456
2457 static GstStateChangeReturn
2458 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2459 {
2460   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2461   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2462
2463   switch (transition) {
2464     case GST_STATE_CHANGE_PAUSED_TO_READY:
2465       break;
2466     default:
2467       break;
2468   }
2469
2470   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2471
2472   switch (transition) {
2473     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2474       gst_qtdemux_reset (qtdemux, TRUE);
2475       break;
2476     }
2477     default:
2478       break;
2479   }
2480
2481   return result;
2482 }
2483
2484 static void
2485 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2486 {
2487   /* counts as header data */
2488   qtdemux->header_size += length;
2489
2490   /* only consider at least a sufficiently complete ftyp atom */
2491   if (length >= 20) {
2492     GstBuffer *buf;
2493
2494     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2495     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2496         GST_FOURCC_ARGS (qtdemux->major_brand));
2497     if (qtdemux->comp_brands)
2498       gst_buffer_unref (qtdemux->comp_brands);
2499     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2500     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2501   }
2502 }
2503
2504 static void
2505 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2506     GstTagList * xmptaglist)
2507 {
2508   /* Strip out bogus fields */
2509   if (xmptaglist) {
2510     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2511       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2512       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2513     } else {
2514       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2515     }
2516
2517     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2518
2519     /* prioritize native tags using _KEEP mode */
2520     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2521     gst_tag_list_unref (xmptaglist);
2522   }
2523 }
2524
2525 static void
2526 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2527     guint offset)
2528 {
2529   GstByteReader br;
2530   guint8 version;
2531   guint32 flags = 0;
2532   guint i;
2533   guint8 iv_size = 8;
2534   QtDemuxStream *stream;
2535   GstStructure *structure;
2536   QtDemuxCencSampleSetInfo *ss_info = NULL;
2537   const gchar *system_id;
2538   gboolean uses_sub_sample_encryption = FALSE;
2539
2540   if (qtdemux->n_streams == 0)
2541     return;
2542
2543   stream = qtdemux->streams[0];
2544
2545   structure = gst_caps_get_structure (stream->caps, 0);
2546   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2547     GST_WARNING_OBJECT (qtdemux,
2548         "Attempting PIFF box parsing on an unencrypted stream.");
2549     return;
2550   }
2551
2552   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2553       G_TYPE_STRING, &system_id, NULL);
2554   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2555
2556   stream->protected = TRUE;
2557   stream->protection_scheme_type = FOURCC_cenc;
2558
2559   if (!stream->protection_scheme_info)
2560     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2561
2562   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2563
2564   if (ss_info->default_properties)
2565     gst_structure_free (ss_info->default_properties);
2566
2567   ss_info->default_properties =
2568       gst_structure_new ("application/x-cenc",
2569       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2570
2571   if (ss_info->crypto_info) {
2572     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2573     g_ptr_array_free (ss_info->crypto_info, TRUE);
2574     ss_info->crypto_info = NULL;
2575   }
2576
2577   /* skip UUID */
2578   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2579
2580   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2581     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2582     return;
2583   }
2584
2585   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2586     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2587     return;
2588   }
2589
2590   if ((flags & 0x000001)) {
2591     guint32 algorithm_id = 0;
2592     const guint8 *kid;
2593     GstBuffer *kid_buf;
2594     gboolean is_encrypted = TRUE;
2595
2596     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2597       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2598       return;
2599     }
2600
2601     algorithm_id >>= 8;
2602     if (algorithm_id == 0) {
2603       is_encrypted = FALSE;
2604     } else if (algorithm_id == 1) {
2605       /* FIXME: maybe store this in properties? */
2606       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2607     } else if (algorithm_id == 2) {
2608       /* FIXME: maybe store this in properties? */
2609       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2610     }
2611
2612     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2613       return;
2614
2615     if (!gst_byte_reader_get_data (&br, 16, &kid))
2616       return;
2617
2618     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2619     gst_buffer_fill (kid_buf, 0, kid, 16);
2620     if (ss_info->default_properties)
2621       gst_structure_free (ss_info->default_properties);
2622     ss_info->default_properties =
2623         gst_structure_new ("application/x-cenc",
2624         "iv_size", G_TYPE_UINT, iv_size,
2625         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2626         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2627     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2628         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2629     gst_buffer_unref (kid_buf);
2630   } else if ((flags & 0x000002)) {
2631     uses_sub_sample_encryption = TRUE;
2632   }
2633
2634   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2635     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2636     return;
2637   }
2638
2639   ss_info->crypto_info =
2640       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2641       (GDestroyNotify) qtdemux_gst_structure_free);
2642
2643   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2644     GstStructure *properties;
2645     guint8 *data;
2646     GstBuffer *buf;
2647
2648     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2649     if (properties == NULL) {
2650       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2651       return;
2652     }
2653
2654     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2655       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2656       gst_structure_free (properties);
2657       return;
2658     }
2659     buf = gst_buffer_new_wrapped (data, iv_size);
2660     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2661     gst_buffer_unref (buf);
2662
2663     if (uses_sub_sample_encryption) {
2664       guint16 n_subsamples;
2665
2666       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2667           || n_subsamples == 0) {
2668         GST_ERROR_OBJECT (qtdemux,
2669             "failed to get subsample count for sample %u", i);
2670         gst_structure_free (properties);
2671         return;
2672       }
2673       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2674       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2675         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2676             i);
2677         gst_structure_free (properties);
2678         return;
2679       }
2680       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2681       gst_structure_set (properties,
2682           "subsample_count", G_TYPE_UINT, n_subsamples,
2683           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2684       gst_buffer_unref (buf);
2685     } else {
2686       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2687     }
2688
2689     g_ptr_array_add (ss_info->crypto_info, properties);
2690   }
2691 }
2692
2693 static void
2694 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2695 {
2696   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2697     0x97, 0xA9, 0x42, 0xE8,
2698     0x9C, 0x71, 0x99, 0x94,
2699     0x91, 0xE3, 0xAF, 0xAC
2700   };
2701   static const guint8 playready_uuid[] = {
2702     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2703     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2704   };
2705
2706   static const guint8 piff_sample_encryption_uuid[] = {
2707     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2708     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2709   };
2710
2711   guint offset;
2712
2713   /* counts as header data */
2714   qtdemux->header_size += length;
2715
2716   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2717
2718   if (length <= offset + 16) {
2719     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2720     return;
2721   }
2722
2723   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2724     GstBuffer *buf;
2725     GstTagList *taglist;
2726
2727     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2728         length - offset - 16, NULL);
2729     taglist = gst_tag_list_from_xmp_buffer (buf);
2730     gst_buffer_unref (buf);
2731
2732     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2733
2734   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2735     int len;
2736     const gunichar2 *s_utf16;
2737     char *contents;
2738
2739     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2740     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2741     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2742     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2743
2744     g_free (contents);
2745
2746     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2747         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2748         (NULL));
2749   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2750     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2751   } else {
2752     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2753         GST_READ_UINT32_LE (buffer + offset),
2754         GST_READ_UINT32_LE (buffer + offset + 4),
2755         GST_READ_UINT32_LE (buffer + offset + 8),
2756         GST_READ_UINT32_LE (buffer + offset + 12));
2757   }
2758 }
2759
2760 static void
2761 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2762 {
2763   GstSidxParser sidx_parser;
2764   GstIsoffParserResult res;
2765   guint consumed;
2766
2767   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2768
2769   res =
2770       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2771       &consumed);
2772   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2773   if (res == GST_ISOFF_QT_PARSER_DONE) {
2774     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2775   }
2776   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2777 }
2778
2779 /* caller verifies at least 8 bytes in buf */
2780 static void
2781 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2782     guint64 * plength, guint32 * pfourcc)
2783 {
2784   guint64 length;
2785   guint32 fourcc;
2786
2787   length = QT_UINT32 (data);
2788   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2789   fourcc = QT_FOURCC (data + 4);
2790   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2791
2792   if (length == 0) {
2793     length = G_MAXUINT64;
2794   } else if (length == 1 && size >= 16) {
2795     /* this means we have an extended size, which is the 64 bit value of
2796      * the next 8 bytes */
2797     length = QT_UINT64 (data + 8);
2798     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2799   }
2800
2801   if (plength)
2802     *plength = length;
2803   if (pfourcc)
2804     *pfourcc = fourcc;
2805 }
2806
2807 static gboolean
2808 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2809 {
2810   guint32 version = 0;
2811   GstClockTime duration = 0;
2812
2813   if (!gst_byte_reader_get_uint32_be (br, &version))
2814     goto failed;
2815
2816   version >>= 24;
2817   if (version == 1) {
2818     if (!gst_byte_reader_get_uint64_be (br, &duration))
2819       goto failed;
2820   } else {
2821     guint32 dur = 0;
2822
2823     if (!gst_byte_reader_get_uint32_be (br, &dur))
2824       goto failed;
2825     duration = dur;
2826   }
2827
2828   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2829   qtdemux->duration = duration;
2830
2831   return TRUE;
2832
2833 failed:
2834   {
2835     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2836     return FALSE;
2837   }
2838 }
2839
2840 static gboolean
2841 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2842     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2843 {
2844   if (!stream->parsed_trex && qtdemux->moov_node) {
2845     GNode *mvex, *trex;
2846     GstByteReader trex_data;
2847
2848     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2849     if (mvex) {
2850       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2851           &trex_data);
2852       while (trex) {
2853         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2854
2855         /* skip version/flags */
2856         if (!gst_byte_reader_skip (&trex_data, 4))
2857           goto next;
2858         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2859           goto next;
2860         if (id != stream->track_id)
2861           goto next;
2862         /* sample description index; ignore */
2863         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2864           goto next;
2865         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2866           goto next;
2867         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2868           goto next;
2869         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2870           goto next;
2871
2872         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2873             "duration %d,  size %d, flags 0x%x", stream->track_id,
2874             dur, size, flags);
2875
2876         stream->parsed_trex = TRUE;
2877         stream->def_sample_duration = dur;
2878         stream->def_sample_size = size;
2879         stream->def_sample_flags = flags;
2880
2881       next:
2882         /* iterate all siblings */
2883         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2884             &trex_data);
2885       }
2886     }
2887   }
2888
2889   *ds_duration = stream->def_sample_duration;
2890   *ds_size = stream->def_sample_size;
2891   *ds_flags = stream->def_sample_flags;
2892
2893   /* even then, above values are better than random ... */
2894   if (G_UNLIKELY (!stream->parsed_trex)) {
2895     GST_WARNING_OBJECT (qtdemux,
2896         "failed to find fragment defaults for stream %d", stream->track_id);
2897     return FALSE;
2898   }
2899
2900   return TRUE;
2901 }
2902
2903 /* This method should be called whenever a more accurate duration might
2904  * have been found. It will update all relevant variables if/where needed
2905  */
2906 static void
2907 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2908 {
2909   guint i;
2910   guint64 movdur;
2911   GstClockTime prevdur;
2912
2913   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2914
2915   if (movdur > qtdemux->duration) {
2916     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2917     GST_DEBUG_OBJECT (qtdemux,
2918         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2919         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2920     qtdemux->duration = movdur;
2921     GST_DEBUG_OBJECT (qtdemux,
2922         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2923         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2924         GST_TIME_ARGS (qtdemux->segment.stop));
2925     if (qtdemux->segment.duration == prevdur) {
2926       /* If the current segment has duration/stop identical to previous duration
2927        * update them also (because they were set at that point in time with
2928        * the wrong duration */
2929       /* We convert the value *from* the timescale version to avoid rounding errors */
2930       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2931       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2932       qtdemux->segment.duration = fixeddur;
2933       qtdemux->segment.stop = fixeddur;
2934     }
2935   }
2936   for (i = 0; i < qtdemux->n_streams; i++) {
2937     QtDemuxStream *stream = qtdemux->streams[i];
2938     if (stream) {
2939       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2940       if (movdur > stream->duration) {
2941         GST_DEBUG_OBJECT (qtdemux,
2942             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2943             GST_TIME_ARGS (duration));
2944         stream->duration = movdur;
2945         if (stream->dummy_segment) {
2946           /* Update all dummy values to new duration */
2947           stream->segments[0].stop_time = duration;
2948           stream->segments[0].duration = duration;
2949           stream->segments[0].media_stop = duration;
2950
2951           /* let downstream know we possibly have a new stop time */
2952           if (stream->segment_index != -1) {
2953             GstClockTime pos;
2954
2955             if (qtdemux->segment.rate >= 0) {
2956               pos = stream->segment.start;
2957             } else {
2958               pos = stream->segment.stop;
2959             }
2960
2961             gst_qtdemux_stream_update_segment (qtdemux, stream,
2962                 stream->segment_index, pos, NULL, NULL);
2963           }
2964         }
2965       }
2966     }
2967   }
2968 }
2969
2970 static gboolean
2971 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2972     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2973     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2974     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2975 {
2976   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2977   guint64 timestamp;
2978   gint32 data_offset = 0;
2979   guint32 flags = 0, first_flags = 0, samples_count = 0;
2980   gint i;
2981   guint8 *data;
2982   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2983   QtDemuxSample *sample;
2984   gboolean ismv = FALSE;
2985   gint64 initial_offset;
2986
2987   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2988       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2989       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2990       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2991
2992   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2993     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2994     return TRUE;
2995   }
2996
2997   /* presence of stss or not can't really tell us much,
2998    * and flags and so on tend to be marginally reliable in these files */
2999   if (stream->subtype == FOURCC_soun) {
3000     GST_DEBUG_OBJECT (qtdemux,
3001         "sound track in fragmented file; marking all keyframes");
3002     stream->all_keyframe = TRUE;
3003   }
3004
3005   if (!gst_byte_reader_skip (trun, 1) ||
3006       !gst_byte_reader_get_uint24_be (trun, &flags))
3007     goto fail;
3008
3009   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3010     goto fail;
3011
3012   if (flags & TR_DATA_OFFSET) {
3013     /* note this is really signed */
3014     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3015       goto fail;
3016     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3017     /* default base offset = first byte of moof */
3018     if (*base_offset == -1) {
3019       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3020       *base_offset = moof_offset;
3021     }
3022     *running_offset = *base_offset + data_offset;
3023   } else {
3024     /* if no offset at all, that would mean data starts at moof start,
3025      * which is a bit wrong and is ismv crappy way, so compensate
3026      * assuming data is in mdat following moof */
3027     if (*base_offset == -1) {
3028       *base_offset = moof_offset + moof_length + 8;
3029       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3030       ismv = TRUE;
3031     }
3032     if (*running_offset == -1)
3033       *running_offset = *base_offset;
3034   }
3035
3036   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3037       *running_offset);
3038   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3039       data_offset, flags, samples_count);
3040
3041   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3042     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3043       GST_DEBUG_OBJECT (qtdemux,
3044           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3045       flags ^= TR_FIRST_SAMPLE_FLAGS;
3046     } else {
3047       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3048         goto fail;
3049       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3050     }
3051   }
3052
3053   /* FIXME ? spec says other bits should also be checked to determine
3054    * entry size (and prefix size for that matter) */
3055   entry_size = 0;
3056   dur_offset = size_offset = 0;
3057   if (flags & TR_SAMPLE_DURATION) {
3058     GST_LOG_OBJECT (qtdemux, "entry duration present");
3059     dur_offset = entry_size;
3060     entry_size += 4;
3061   }
3062   if (flags & TR_SAMPLE_SIZE) {
3063     GST_LOG_OBJECT (qtdemux, "entry size present");
3064     size_offset = entry_size;
3065     entry_size += 4;
3066   }
3067   if (flags & TR_SAMPLE_FLAGS) {
3068     GST_LOG_OBJECT (qtdemux, "entry flags present");
3069     flags_offset = entry_size;
3070     entry_size += 4;
3071   }
3072   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3073     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3074     ct_offset = entry_size;
3075     entry_size += 4;
3076   }
3077
3078   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3079     goto fail;
3080   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3081
3082   if (stream->n_samples + samples_count >=
3083       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3084     goto index_too_big;
3085
3086   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3087       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3088       (stream->n_samples + samples_count) *
3089       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3090
3091   /* create a new array of samples if it's the first sample parsed */
3092   if (stream->n_samples == 0) {
3093     g_assert (stream->samples == NULL);
3094     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3095     /* or try to reallocate it with space enough to insert the new samples */
3096   } else
3097     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3098         stream->n_samples + samples_count);
3099   if (stream->samples == NULL)
3100     goto out_of_memory;
3101
3102   if (qtdemux->fragment_start != -1) {
3103     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3104     qtdemux->fragment_start = -1;
3105   } else {
3106     if (stream->n_samples == 0) {
3107       if (decode_ts > 0) {
3108         timestamp = decode_ts;
3109       } else if (stream->pending_seek != NULL) {
3110         /* if we don't have a timestamp from a tfdt box, we'll use the one
3111          * from the mfra seek table */
3112         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3113             GST_TIME_ARGS (stream->pending_seek->ts));
3114
3115         /* FIXME: this is not fully correct, the timestamp refers to the random
3116          * access sample refered to in the tfra entry, which may not necessarily
3117          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3118         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3119       } else {
3120         timestamp = 0;
3121       }
3122
3123       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3124       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3125           GST_TIME_ARGS (gst_ts));
3126     } else {
3127       /* subsequent fragments extend stream */
3128       timestamp =
3129           stream->samples[stream->n_samples - 1].timestamp +
3130           stream->samples[stream->n_samples - 1].duration;
3131
3132       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3133        * difference (1 sec.) between decode_ts and timestamp, prefer the
3134        * former */
3135       if (!qtdemux->upstream_format_is_time
3136           && ABSDIFF (decode_ts, timestamp) >
3137           MAX (stream->duration_last_moof / 2,
3138               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3139         GST_INFO_OBJECT (qtdemux,
3140             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3141             ") are significantly different (more than %" GST_TIME_FORMAT
3142             "), using decode_ts",
3143             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3144             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3145             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3146                     MAX (stream->duration_last_moof / 2,
3147                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3148         timestamp = decode_ts;
3149       }
3150
3151       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3152       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3153           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3154     }
3155   }
3156
3157   initial_offset = *running_offset;
3158
3159   sample = stream->samples + stream->n_samples;
3160   for (i = 0; i < samples_count; i++) {
3161     guint32 dur, size, sflags, ct;
3162
3163     /* first read sample data */
3164     if (flags & TR_SAMPLE_DURATION) {
3165       dur = QT_UINT32 (data + dur_offset);
3166     } else {
3167       dur = d_sample_duration;
3168     }
3169     if (flags & TR_SAMPLE_SIZE) {
3170       size = QT_UINT32 (data + size_offset);
3171     } else {
3172       size = d_sample_size;
3173     }
3174     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3175       if (i == 0) {
3176         sflags = first_flags;
3177       } else {
3178         sflags = d_sample_flags;
3179       }
3180     } else if (flags & TR_SAMPLE_FLAGS) {
3181       sflags = QT_UINT32 (data + flags_offset);
3182     } else {
3183       sflags = d_sample_flags;
3184     }
3185     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3186       ct = QT_UINT32 (data + ct_offset);
3187     } else {
3188       ct = 0;
3189     }
3190     data += entry_size;
3191
3192     /* fill the sample information */
3193     sample->offset = *running_offset;
3194     sample->pts_offset = ct;
3195     sample->size = size;
3196     sample->timestamp = timestamp;
3197     sample->duration = dur;
3198     /* sample-is-difference-sample */
3199     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3200      * now idea how it relates to bitfield other than massive LE/BE confusion */
3201     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3202     *running_offset += size;
3203     timestamp += dur;
3204     stream->duration_moof += dur;
3205     sample++;
3206   }
3207
3208   /* Update total duration if needed */
3209   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3210
3211   /* Pre-emptively figure out size of mdat based on trun information.
3212    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3213    * size, else we will still be able to use this when dealing with gap'ed
3214    * input */
3215   qtdemux->mdatleft = *running_offset - initial_offset;
3216
3217   stream->n_samples += samples_count;
3218   stream->n_samples_moof += samples_count;
3219
3220   if (stream->pending_seek != NULL)
3221     stream->pending_seek = NULL;
3222
3223   return TRUE;
3224
3225 fail:
3226   {
3227     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3228     return FALSE;
3229   }
3230 out_of_memory:
3231   {
3232     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3233         stream->n_samples);
3234     return FALSE;
3235   }
3236 index_too_big:
3237   {
3238     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3239         "be larger than %uMB (broken file?)", stream->n_samples,
3240         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3241     return FALSE;
3242   }
3243 }
3244
3245 /* find stream with @id */
3246 static inline QtDemuxStream *
3247 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3248 {
3249   QtDemuxStream *stream;
3250   gint i;
3251
3252   /* check */
3253   if (G_UNLIKELY (!id)) {
3254     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3255     return NULL;
3256   }
3257
3258   /* try to get it fast and simple */
3259   if (G_LIKELY (id <= qtdemux->n_streams)) {
3260     stream = qtdemux->streams[id - 1];
3261     if (G_LIKELY (stream->track_id == id))
3262       return stream;
3263   }
3264
3265   /* linear search otherwise */
3266   for (i = 0; i < qtdemux->n_streams; i++) {
3267     stream = qtdemux->streams[i];
3268     if (stream->track_id == id)
3269       return stream;
3270   }
3271   if (qtdemux->mss_mode) {
3272     /* mss should have only 1 stream anyway */
3273     return qtdemux->streams[0];
3274   }
3275
3276   return NULL;
3277 }
3278
3279 static gboolean
3280 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3281     guint32 * fragment_number)
3282 {
3283   if (!gst_byte_reader_skip (mfhd, 4))
3284     goto fail;
3285   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3286     goto fail;
3287   return TRUE;
3288 fail:
3289   {
3290     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3291     return FALSE;
3292   }
3293 }
3294
3295 static gboolean
3296 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3297     QtDemuxStream ** stream, guint32 * default_sample_duration,
3298     guint32 * default_sample_size, guint32 * default_sample_flags,
3299     gint64 * base_offset)
3300 {
3301   guint32 flags = 0;
3302   guint32 track_id = 0;
3303
3304   if (!gst_byte_reader_skip (tfhd, 1) ||
3305       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3306     goto invalid_track;
3307
3308   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3309     goto invalid_track;
3310
3311   *stream = qtdemux_find_stream (qtdemux, track_id);
3312   if (G_UNLIKELY (!*stream))
3313     goto unknown_stream;
3314
3315   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3316     *base_offset = qtdemux->moof_offset;
3317
3318   if (flags & TF_BASE_DATA_OFFSET)
3319     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3320       goto invalid_track;
3321
3322   /* obtain stream defaults */
3323   qtdemux_parse_trex (qtdemux, *stream,
3324       default_sample_duration, default_sample_size, default_sample_flags);
3325
3326   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3327   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3328     if (!gst_byte_reader_skip (tfhd, 4))
3329       goto invalid_track;
3330
3331   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3332     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3333       goto invalid_track;
3334
3335   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3336     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3337       goto invalid_track;
3338
3339   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3340     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3341       goto invalid_track;
3342
3343   return TRUE;
3344
3345 invalid_track:
3346   {
3347     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3348     return FALSE;
3349   }
3350 unknown_stream:
3351   {
3352     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3353     return TRUE;
3354   }
3355 }
3356
3357 static gboolean
3358 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3359     guint64 * decode_time)
3360 {
3361   guint32 version = 0;
3362
3363   if (!gst_byte_reader_get_uint32_be (br, &version))
3364     return FALSE;
3365
3366   version >>= 24;
3367   if (version == 1) {
3368     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3369       goto failed;
3370   } else {
3371     guint32 dec_time = 0;
3372     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3373       goto failed;
3374     *decode_time = dec_time;
3375   }
3376
3377   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3378       *decode_time);
3379
3380   return TRUE;
3381
3382 failed:
3383   {
3384     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3385     return FALSE;
3386   }
3387 }
3388
3389 /* Returns a pointer to a GstStructure containing the properties of
3390  * the stream sample identified by @sample_index. The caller must unref
3391  * the returned object after use. Returns NULL if unsuccessful. */
3392 static GstStructure *
3393 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3394     QtDemuxStream * stream, guint sample_index)
3395 {
3396   QtDemuxCencSampleSetInfo *info = NULL;
3397
3398   g_return_val_if_fail (stream != NULL, NULL);
3399   g_return_val_if_fail (stream->protected, NULL);
3400   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3401
3402   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3403
3404   /* Currently, cenc properties for groups of samples are not supported, so
3405    * simply return a copy of the default sample properties */
3406   return gst_structure_copy (info->default_properties);
3407 }
3408
3409 /* Parses the sizes of sample auxiliary information contained within a stream,
3410  * as given in a saiz box. Returns array of sample_count guint8 size values,
3411  * or NULL on failure */
3412 static guint8 *
3413 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3414     GstByteReader * br, guint32 * sample_count)
3415 {
3416   guint32 flags = 0;
3417   guint8 *info_sizes;
3418   guint8 default_info_size;
3419
3420   g_return_val_if_fail (qtdemux != NULL, NULL);
3421   g_return_val_if_fail (stream != NULL, NULL);
3422   g_return_val_if_fail (br != NULL, NULL);
3423   g_return_val_if_fail (sample_count != NULL, NULL);
3424
3425   if (!gst_byte_reader_get_uint32_be (br, &flags))
3426     return NULL;
3427
3428   if (flags & 0x1) {
3429     /* aux_info_type and aux_info_type_parameter are ignored */
3430     if (!gst_byte_reader_skip (br, 8))
3431       return NULL;
3432   }
3433
3434   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3435     return NULL;
3436   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3437
3438   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3439     return NULL;
3440   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3441
3442
3443   if (default_info_size == 0) {
3444     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3445       return NULL;
3446     }
3447   } else {
3448     info_sizes = g_new (guint8, *sample_count);
3449     memset (info_sizes, default_info_size, *sample_count);
3450   }
3451
3452   return info_sizes;
3453 }
3454
3455 /* Parses the offset of sample auxiliary information contained within a stream,
3456  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3457 static gboolean
3458 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3459     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3460     guint64 * offset)
3461 {
3462   guint8 version = 0;
3463   guint32 flags = 0;
3464   guint32 aux_info_type = 0;
3465   guint32 aux_info_type_parameter = 0;
3466   guint32 entry_count;
3467   guint32 off_32;
3468   guint64 off_64;
3469   const guint8 *aux_info_type_data = NULL;
3470
3471   g_return_val_if_fail (qtdemux != NULL, FALSE);
3472   g_return_val_if_fail (stream != NULL, FALSE);
3473   g_return_val_if_fail (br != NULL, FALSE);
3474   g_return_val_if_fail (offset != NULL, FALSE);
3475
3476   if (!gst_byte_reader_get_uint8 (br, &version))
3477     return FALSE;
3478
3479   if (!gst_byte_reader_get_uint24_be (br, &flags))
3480     return FALSE;
3481
3482   if (flags & 0x1) {
3483
3484     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3485       return FALSE;
3486     aux_info_type = QT_FOURCC (aux_info_type_data);
3487
3488     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3489       return FALSE;
3490   } else if (stream->protected) {
3491     aux_info_type = stream->protection_scheme_type;
3492   } else {
3493     aux_info_type = stream->fourcc;
3494   }
3495
3496   if (info_type)
3497     *info_type = aux_info_type;
3498   if (info_type_parameter)
3499     *info_type_parameter = aux_info_type_parameter;
3500
3501   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3502       "aux_info_type_parameter:  %#06x",
3503       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3504
3505   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3506     return FALSE;
3507
3508   if (entry_count != 1) {
3509     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3510     return FALSE;
3511   }
3512
3513   if (version == 0) {
3514     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3515       return FALSE;
3516     *offset = (guint64) off_32;
3517   } else {
3518     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3519       return FALSE;
3520     *offset = off_64;
3521   }
3522
3523   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3524   return TRUE;
3525 }
3526
3527 static void
3528 qtdemux_gst_structure_free (GstStructure * gststructure)
3529 {
3530   if (gststructure) {
3531     gst_structure_free (gststructure);
3532   }
3533 }
3534
3535 /* Parses auxiliary information relating to samples protected using Common
3536  * Encryption (cenc); the format of this information is defined in
3537  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3538 static gboolean
3539 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3540     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3541 {
3542   QtDemuxCencSampleSetInfo *ss_info = NULL;
3543   guint8 size;
3544   gint i;
3545
3546   g_return_val_if_fail (qtdemux != NULL, FALSE);
3547   g_return_val_if_fail (stream != NULL, FALSE);
3548   g_return_val_if_fail (br != NULL, FALSE);
3549   g_return_val_if_fail (stream->protected, FALSE);
3550   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3551
3552   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3553
3554   if (ss_info->crypto_info) {
3555     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3556     g_ptr_array_free (ss_info->crypto_info, TRUE);
3557   }
3558
3559   ss_info->crypto_info =
3560       g_ptr_array_new_full (sample_count,
3561       (GDestroyNotify) qtdemux_gst_structure_free);
3562
3563   for (i = 0; i < sample_count; ++i) {
3564     GstStructure *properties;
3565     guint16 n_subsamples = 0;
3566     guint8 *data;
3567     guint iv_size;
3568     GstBuffer *buf;
3569
3570     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3571     if (properties == NULL) {
3572       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3573       return FALSE;
3574     }
3575     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3576       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3577       gst_structure_free (properties);
3578       return FALSE;
3579     }
3580     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3581       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3582       gst_structure_free (properties);
3583       return FALSE;
3584     }
3585     buf = gst_buffer_new_wrapped (data, iv_size);
3586     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3587     gst_buffer_unref (buf);
3588     size = info_sizes[i];
3589     if (size > iv_size) {
3590       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3591           || !(n_subsamples > 0)) {
3592         gst_structure_free (properties);
3593         GST_ERROR_OBJECT (qtdemux,
3594             "failed to get subsample count for sample %u", i);
3595         return FALSE;
3596       }
3597       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3598       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3599         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3600             i);
3601         gst_structure_free (properties);
3602         return FALSE;
3603       }
3604       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3605       if (!buf) {
3606         gst_structure_free (properties);
3607         return FALSE;
3608       }
3609       gst_structure_set (properties,
3610           "subsample_count", G_TYPE_UINT, n_subsamples,
3611           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3612       gst_buffer_unref (buf);
3613     } else {
3614       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3615     }
3616     g_ptr_array_add (ss_info->crypto_info, properties);
3617   }
3618   return TRUE;
3619 }
3620
3621 /* Converts a UUID in raw byte form to a string representation, as defined in
3622  * RFC 4122. The caller takes ownership of the returned string and is
3623  * responsible for freeing it after use. */
3624 static gchar *
3625 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3626 {
3627   const guint8 *uuid = (const guint8 *) uuid_bytes;
3628
3629   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3630       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3631       uuid[0], uuid[1], uuid[2], uuid[3],
3632       uuid[4], uuid[5], uuid[6], uuid[7],
3633       uuid[8], uuid[9], uuid[10], uuid[11],
3634       uuid[12], uuid[13], uuid[14], uuid[15]);
3635 }
3636
3637 /* Parses a Protection System Specific Header box (pssh), as defined in the
3638  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3639  * information needed by a specific content protection system in order to
3640  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3641  * otherwise. */
3642 static gboolean
3643 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3644 {
3645   gchar *sysid_string;
3646   guint32 pssh_size = QT_UINT32 (node->data);
3647   GstBuffer *pssh = NULL;
3648   GstEvent *event = NULL;
3649   guint32 parent_box_type;
3650   gint i;
3651
3652   if (G_UNLIKELY (pssh_size < 32U)) {
3653     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3654     return FALSE;
3655   }
3656
3657   sysid_string =
3658       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3659
3660   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3661
3662   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3663   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3664       gst_buffer_get_size (pssh));
3665
3666   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3667
3668   /* Push an event containing the pssh box onto the queues of all streams. */
3669   event = gst_event_new_protection (sysid_string, pssh,
3670       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3671   for (i = 0; i < qtdemux->n_streams; ++i) {
3672     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3673         gst_event_ref (event));
3674   }
3675   g_free (sysid_string);
3676   gst_event_unref (event);
3677   gst_buffer_unref (pssh);
3678   return TRUE;
3679 }
3680
3681 static gboolean
3682 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3683     guint64 moof_offset, QtDemuxStream * stream)
3684 {
3685   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3686   GNode *uuid_node;
3687   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3688   GNode *saiz_node, *saio_node, *pssh_node;
3689   GstByteReader saiz_data, saio_data;
3690   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3691   gint64 base_offset, running_offset;
3692   guint32 frag_num;
3693
3694   /* NOTE @stream ignored */
3695
3696   moof_node = g_node_new ((guint8 *) buffer);
3697   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3698   qtdemux_node_dump (qtdemux, moof_node);
3699
3700   /* Get fragment number from mfhd and check it's valid */
3701   mfhd_node =
3702       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3703   if (mfhd_node == NULL)
3704     goto missing_mfhd;
3705   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3706     goto fail;
3707   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3708
3709   /* unknown base_offset to start with */
3710   base_offset = running_offset = -1;
3711   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3712   while (traf_node) {
3713     guint64 decode_time = 0;
3714
3715     /* Fragment Header node */
3716     tfhd_node =
3717         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3718         &tfhd_data);
3719     if (!tfhd_node)
3720       goto missing_tfhd;
3721     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3722             &ds_size, &ds_flags, &base_offset))
3723       goto missing_tfhd;
3724
3725     /* The following code assumes at most a single set of sample auxiliary
3726      * data in the fragment (consisting of a saiz box and a corresponding saio
3727      * box); in theory, however, there could be multiple sets of sample
3728      * auxiliary data in a fragment. */
3729     saiz_node =
3730         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3731         &saiz_data);
3732     if (saiz_node) {
3733       guint32 info_type = 0;
3734       guint64 offset = 0;
3735       guint32 info_type_parameter = 0;
3736
3737       g_free (qtdemux->cenc_aux_info_sizes);
3738
3739       qtdemux->cenc_aux_info_sizes =
3740           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3741           &qtdemux->cenc_aux_sample_count);
3742       if (qtdemux->cenc_aux_info_sizes == NULL) {
3743         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3744         goto fail;
3745       }
3746       saio_node =
3747           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3748           &saio_data);
3749       if (!saio_node) {
3750         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3751         g_free (qtdemux->cenc_aux_info_sizes);
3752         qtdemux->cenc_aux_info_sizes = NULL;
3753         goto fail;
3754       }
3755
3756       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3757                   &info_type, &info_type_parameter, &offset))) {
3758         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3759         g_free (qtdemux->cenc_aux_info_sizes);
3760         qtdemux->cenc_aux_info_sizes = NULL;
3761         goto fail;
3762       }
3763       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3764         offset += (guint64) (base_offset - qtdemux->moof_offset);
3765       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3766         GstByteReader br;
3767         if (offset > length) {
3768           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3769           qtdemux->cenc_aux_info_offset = offset;
3770         } else {
3771           gst_byte_reader_init (&br, buffer + offset, length - offset);
3772           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3773                   qtdemux->cenc_aux_info_sizes,
3774                   qtdemux->cenc_aux_sample_count)) {
3775             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3776             g_free (qtdemux->cenc_aux_info_sizes);
3777             qtdemux->cenc_aux_info_sizes = NULL;
3778             goto fail;
3779           }
3780         }
3781       }
3782     }
3783
3784     tfdt_node =
3785         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3786         &tfdt_data);
3787     if (tfdt_node) {
3788       /* We'll use decode_time to interpolate timestamps
3789        * in case the input timestamps are missing */
3790       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3791
3792       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3793           " (%" GST_TIME_FORMAT ")", decode_time,
3794           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3795
3796       /* Discard the fragment buffer timestamp info to avoid using it.
3797        * Rely on tfdt instead as it is more accurate than the timestamp
3798        * that is fetched from a manifest/playlist and is usually
3799        * less accurate. */
3800       qtdemux->fragment_start = -1;
3801     }
3802
3803     if (G_UNLIKELY (!stream)) {
3804       /* we lost track of offset, we'll need to regain it,
3805        * but can delay complaining until later or avoid doing so altogether */
3806       base_offset = -2;
3807       goto next;
3808     }
3809     if (G_UNLIKELY (base_offset < -1))
3810       goto lost_offset;
3811
3812     if (qtdemux->upstream_format_is_time)
3813       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3814
3815     /* initialise moof sample data */
3816     stream->n_samples_moof = 0;
3817     stream->duration_last_moof = stream->duration_moof;
3818     stream->duration_moof = 0;
3819
3820     /* Track Run node */
3821     trun_node =
3822         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3823         &trun_data);
3824     while (trun_node) {
3825       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3826           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3827           &running_offset, decode_time);
3828       /* iterate all siblings */
3829       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3830           &trun_data);
3831     }
3832
3833     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3834     if (uuid_node) {
3835       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3836       guint32 box_length = QT_UINT32 (uuid_buffer);
3837
3838       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3839     }
3840
3841     /* if no new base_offset provided for next traf,
3842      * base is end of current traf */
3843     base_offset = running_offset;
3844     running_offset = -1;
3845
3846     if (stream->n_samples_moof && stream->duration_moof)
3847       stream->new_caps = TRUE;
3848
3849   next:
3850     /* iterate all siblings */
3851     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3852   }
3853
3854   /* parse any protection system info */
3855   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3856   while (pssh_node) {
3857     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3858     qtdemux_parse_pssh (qtdemux, pssh_node);
3859     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3860   }
3861
3862   g_node_destroy (moof_node);
3863   return TRUE;
3864
3865 missing_tfhd:
3866   {
3867     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3868     goto fail;
3869   }
3870 missing_mfhd:
3871   {
3872     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3873     goto fail;
3874   }
3875 lost_offset:
3876   {
3877     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3878     goto fail;
3879   }
3880 fail:
3881   {
3882     g_node_destroy (moof_node);
3883     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3884         (_("This file is corrupt and cannot be played.")), (NULL));
3885     return FALSE;
3886   }
3887 }
3888
3889 #if 0
3890 /* might be used if some day we actually use mfra & co
3891  * for random access to fragments,
3892  * but that will require quite some modifications and much less relying
3893  * on a sample array */
3894 #endif
3895
3896 static gboolean
3897 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3898 {
3899   QtDemuxStream *stream;
3900   guint32 ver_flags, track_id, len, num_entries, i;
3901   guint value_size, traf_size, trun_size, sample_size;
3902   guint64 time = 0, moof_offset = 0;
3903 #if 0
3904   GstBuffer *buf = NULL;
3905   GstFlowReturn ret;
3906 #endif
3907   GstByteReader tfra;
3908
3909   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3910
3911   if (!gst_byte_reader_skip (&tfra, 8))
3912     return FALSE;
3913
3914   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3915     return FALSE;
3916
3917   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3918       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3919       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3920     return FALSE;
3921
3922   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3923
3924   stream = qtdemux_find_stream (qtdemux, track_id);
3925   if (stream == NULL)
3926     goto unknown_trackid;
3927
3928   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3929   sample_size = (len & 3) + 1;
3930   trun_size = ((len & 12) >> 2) + 1;
3931   traf_size = ((len & 48) >> 4) + 1;
3932
3933   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3934       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3935
3936   if (num_entries == 0)
3937     goto no_samples;
3938
3939   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3940           value_size + value_size + traf_size + trun_size + sample_size))
3941     goto corrupt_file;
3942
3943   g_free (stream->ra_entries);
3944   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3945   stream->n_ra_entries = num_entries;
3946
3947   for (i = 0; i < num_entries; i++) {
3948     qt_atom_parser_get_offset (&tfra, value_size, &time);
3949     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3950     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3951     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3952     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3953
3954     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3955
3956     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3957         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3958
3959     stream->ra_entries[i].ts = time;
3960     stream->ra_entries[i].moof_offset = moof_offset;
3961
3962     /* don't want to go through the entire file and read all moofs at startup */
3963 #if 0
3964     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3965     if (ret != GST_FLOW_OK)
3966       goto corrupt_file;
3967     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3968         moof_offset, stream);
3969     gst_buffer_unref (buf);
3970 #endif
3971   }
3972
3973   check_update_duration (qtdemux, time);
3974
3975   return TRUE;
3976
3977 /* ERRORS */
3978 unknown_trackid:
3979   {
3980     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3981     return FALSE;
3982   }
3983 corrupt_file:
3984   {
3985     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3986     return FALSE;
3987   }
3988 no_samples:
3989   {
3990     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3991     return FALSE;
3992   }
3993 }
3994
3995 static gboolean
3996 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3997 {
3998   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3999   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4000   GstBuffer *mfro = NULL, *mfra = NULL;
4001   GstFlowReturn flow;
4002   gboolean ret = FALSE;
4003   GNode *mfra_node, *tfra_node;
4004   guint64 mfra_offset = 0;
4005   guint32 fourcc, mfra_size;
4006   gint64 len;
4007
4008   /* query upstream size in bytes */
4009   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4010     goto size_query_failed;
4011
4012   /* mfro box should be at the very end of the file */
4013   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4014   if (flow != GST_FLOW_OK)
4015     goto exit;
4016
4017   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4018
4019   fourcc = QT_FOURCC (mfro_map.data + 4);
4020   if (fourcc != FOURCC_mfro)
4021     goto exit;
4022
4023   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4024   if (mfro_map.size < 16)
4025     goto invalid_mfro_size;
4026
4027   mfra_size = QT_UINT32 (mfro_map.data + 12);
4028   if (mfra_size >= len)
4029     goto invalid_mfra_size;
4030
4031   mfra_offset = len - mfra_size;
4032
4033   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4034       mfra_offset, mfra_size);
4035
4036   /* now get and parse mfra box */
4037   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4038   if (flow != GST_FLOW_OK)
4039     goto broken_file;
4040
4041   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4042
4043   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4044   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4045
4046   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4047
4048   while (tfra_node) {
4049     qtdemux_parse_tfra (qtdemux, tfra_node);
4050     /* iterate all siblings */
4051     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4052   }
4053   g_node_destroy (mfra_node);
4054
4055   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4056   ret = TRUE;
4057
4058 exit:
4059
4060   if (mfro) {
4061     if (mfro_map.memory != NULL)
4062       gst_buffer_unmap (mfro, &mfro_map);
4063     gst_buffer_unref (mfro);
4064   }
4065   if (mfra) {
4066     if (mfra_map.memory != NULL)
4067       gst_buffer_unmap (mfra, &mfra_map);
4068     gst_buffer_unref (mfra);
4069   }
4070   return ret;
4071
4072 /* ERRORS */
4073 size_query_failed:
4074   {
4075     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4076     goto exit;
4077   }
4078 invalid_mfro_size:
4079   {
4080     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4081     goto exit;
4082   }
4083 invalid_mfra_size:
4084   {
4085     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4086     goto exit;
4087   }
4088 broken_file:
4089   {
4090     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4091     goto exit;
4092   }
4093 }
4094
4095 static guint64
4096 add_offset (guint64 offset, guint64 advance)
4097 {
4098   /* Avoid 64-bit overflow by clamping */
4099   if (offset > G_MAXUINT64 - advance)
4100     return G_MAXUINT64;
4101   return offset + advance;
4102 }
4103
4104 static GstFlowReturn
4105 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4106 {
4107   guint64 length = 0;
4108   guint32 fourcc = 0;
4109   GstBuffer *buf = NULL;
4110   GstFlowReturn ret = GST_FLOW_OK;
4111   guint64 cur_offset = qtdemux->offset;
4112   GstMapInfo map;
4113
4114   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4115   if (G_UNLIKELY (ret != GST_FLOW_OK))
4116     goto beach;
4117   gst_buffer_map (buf, &map, GST_MAP_READ);
4118   if (G_LIKELY (map.size >= 8))
4119     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4120   gst_buffer_unmap (buf, &map);
4121   gst_buffer_unref (buf);
4122
4123   /* maybe we already got most we needed, so only consider this eof */
4124   if (G_UNLIKELY (length == 0)) {
4125     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4126         (_("Invalid atom size.")),
4127         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4128             GST_FOURCC_ARGS (fourcc)));
4129     ret = GST_FLOW_EOS;
4130     goto beach;
4131   }
4132
4133   switch (fourcc) {
4134     case FOURCC_moof:
4135       /* record for later parsing when needed */
4136       if (!qtdemux->moof_offset) {
4137         qtdemux->moof_offset = qtdemux->offset;
4138       }
4139       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4140         /* FIXME */
4141       } else {
4142         qtdemux->offset += length;      /* skip moof and keep going */
4143       }
4144       if (qtdemux->got_moov) {
4145         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4146         ret = GST_FLOW_EOS;
4147         goto beach;
4148       }
4149       break;
4150     case FOURCC_mdat:
4151     case FOURCC_free:
4152     case FOURCC_wide:
4153     case FOURCC_PICT:
4154     case FOURCC_pnot:
4155     {
4156       GST_LOG_OBJECT (qtdemux,
4157           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4158           GST_FOURCC_ARGS (fourcc), cur_offset);
4159       qtdemux->offset = add_offset (qtdemux->offset, length);
4160       break;
4161     }
4162     case FOURCC_moov:
4163     {
4164       GstBuffer *moov = NULL;
4165
4166       if (qtdemux->got_moov) {
4167         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4168         qtdemux->offset = add_offset (qtdemux->offset, length);
4169         goto beach;
4170       }
4171
4172       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4173       if (ret != GST_FLOW_OK)
4174         goto beach;
4175       gst_buffer_map (moov, &map, GST_MAP_READ);
4176
4177       if (length != map.size) {
4178         /* Some files have a 'moov' atom at the end of the file which contains
4179          * a terminal 'free' atom where the body of the atom is missing.
4180          * Check for, and permit, this special case.
4181          */
4182         if (map.size >= 8) {
4183           guint8 *final_data = map.data + (map.size - 8);
4184           guint32 final_length = QT_UINT32 (final_data);
4185           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4186
4187           if (final_fourcc == FOURCC_free
4188               && map.size + final_length - 8 == length) {
4189             /* Ok, we've found that special case. Allocate a new buffer with
4190              * that free atom actually present. */
4191             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4192             gst_buffer_fill (newmoov, 0, map.data, map.size);
4193             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4194             gst_buffer_unmap (moov, &map);
4195             gst_buffer_unref (moov);
4196             moov = newmoov;
4197             gst_buffer_map (moov, &map, GST_MAP_READ);
4198           }
4199         }
4200       }
4201
4202       if (length != map.size) {
4203         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4204             (_("This file is incomplete and cannot be played.")),
4205             ("We got less than expected (received %" G_GSIZE_FORMAT
4206                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4207                 (guint) length, cur_offset));
4208         gst_buffer_unmap (moov, &map);
4209         gst_buffer_unref (moov);
4210         ret = GST_FLOW_ERROR;
4211         goto beach;
4212       }
4213       qtdemux->offset += length;
4214
4215       qtdemux_parse_moov (qtdemux, map.data, length);
4216       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4217
4218       qtdemux_parse_tree (qtdemux);
4219       g_node_destroy (qtdemux->moov_node);
4220       gst_buffer_unmap (moov, &map);
4221       gst_buffer_unref (moov);
4222       qtdemux->moov_node = NULL;
4223       qtdemux->got_moov = TRUE;
4224
4225       break;
4226     }
4227     case FOURCC_ftyp:
4228     {
4229       GstBuffer *ftyp = NULL;
4230
4231       /* extract major brand; might come in handy for ISO vs QT issues */
4232       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4233       if (ret != GST_FLOW_OK)
4234         goto beach;
4235       qtdemux->offset += length;
4236       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4237       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4238       gst_buffer_unmap (ftyp, &map);
4239       gst_buffer_unref (ftyp);
4240       break;
4241     }
4242     case FOURCC_uuid:
4243     {
4244       GstBuffer *uuid = NULL;
4245
4246       /* uuid are extension atoms */
4247       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4248       if (ret != GST_FLOW_OK)
4249         goto beach;
4250       qtdemux->offset += length;
4251       gst_buffer_map (uuid, &map, GST_MAP_READ);
4252       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4253       gst_buffer_unmap (uuid, &map);
4254       gst_buffer_unref (uuid);
4255       break;
4256     }
4257     case FOURCC_sidx:
4258     {
4259       GstBuffer *sidx = NULL;
4260       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4261       if (ret != GST_FLOW_OK)
4262         goto beach;
4263       qtdemux->offset += length;
4264       gst_buffer_map (sidx, &map, GST_MAP_READ);
4265       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4266       gst_buffer_unmap (sidx, &map);
4267       gst_buffer_unref (sidx);
4268       break;
4269     }
4270     default:
4271     {
4272       GstBuffer *unknown = NULL;
4273
4274       GST_LOG_OBJECT (qtdemux,
4275           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4276           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4277           cur_offset);
4278       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4279       if (ret != GST_FLOW_OK)
4280         goto beach;
4281       gst_buffer_map (unknown, &map, GST_MAP_READ);
4282       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4283       gst_buffer_unmap (unknown, &map);
4284       gst_buffer_unref (unknown);
4285       qtdemux->offset += length;
4286       break;
4287     }
4288   }
4289
4290 beach:
4291   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4292     /* digested all data, show what we have */
4293     qtdemux_prepare_streams (qtdemux);
4294     ret = qtdemux_expose_streams (qtdemux);
4295
4296     qtdemux->state = QTDEMUX_STATE_MOVIE;
4297     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4298         qtdemux->state);
4299     return ret;
4300   }
4301   return ret;
4302 }
4303
4304 /* Seeks to the previous keyframe of the indexed stream and
4305  * aligns other streams with respect to the keyframe timestamp
4306  * of indexed stream. Only called in case of Reverse Playback
4307  */
4308 static GstFlowReturn
4309 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4310 {
4311   guint8 n = 0;
4312   guint32 seg_idx = 0, k_index = 0;
4313   guint32 ref_seg_idx, ref_k_index;
4314   GstClockTime k_pos = 0, last_stop = 0;
4315   QtDemuxSegment *seg = NULL;
4316   QtDemuxStream *ref_str = NULL;
4317   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4318   guint64 target_ts;
4319
4320   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4321    * and finally align all the other streams on that timestamp with their
4322    * respective keyframes */
4323   for (n = 0; n < qtdemux->n_streams; n++) {
4324     QtDemuxStream *str = qtdemux->streams[n];
4325
4326     /* No candidate yet, take the first stream */
4327     if (!ref_str) {
4328       ref_str = str;
4329       continue;
4330     }
4331
4332     /* So that stream has a segment, we prefer video streams */
4333     if (str->subtype == FOURCC_vide) {
4334       ref_str = str;
4335       break;
4336     }
4337   }
4338
4339   if (G_UNLIKELY (!ref_str)) {
4340     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4341     goto eos;
4342   }
4343
4344   if (G_UNLIKELY (!ref_str->from_sample)) {
4345     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4346     goto eos;
4347   }
4348
4349   /* So that stream has been playing from from_sample to to_sample. We will
4350    * get the timestamp of the previous sample and search for a keyframe before
4351    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4352   if (ref_str->subtype == FOURCC_vide) {
4353     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4354         ref_str->from_sample - 1);
4355   } else {
4356     if (ref_str->from_sample >= 10)
4357       k_index = ref_str->from_sample - 10;
4358     else
4359       k_index = 0;
4360   }
4361
4362   target_ts =
4363       ref_str->samples[k_index].timestamp +
4364       ref_str->samples[k_index].pts_offset;
4365
4366   /* get current segment for that stream */
4367   seg = &ref_str->segments[ref_str->segment_index];
4368   /* Use segment start in original timescale for comparisons */
4369   seg_media_start_mov = seg->trak_media_start;
4370
4371   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4372       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4373       k_index, target_ts, seg_media_start_mov,
4374       GST_TIME_ARGS (seg->media_start));
4375
4376   /* Crawl back through segments to find the one containing this I frame */
4377   while (target_ts < seg_media_start_mov) {
4378     GST_DEBUG_OBJECT (qtdemux,
4379         "keyframe position (sample %u) is out of segment %u " " target %"
4380         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4381         ref_str->segment_index, target_ts, seg_media_start_mov);
4382
4383     if (G_UNLIKELY (!ref_str->segment_index)) {
4384       /* Reached first segment, let's consider it's EOS */
4385       goto eos;
4386     }
4387     ref_str->segment_index--;
4388     seg = &ref_str->segments[ref_str->segment_index];
4389     /* Use segment start in original timescale for comparisons */
4390     seg_media_start_mov = seg->trak_media_start;
4391   }
4392   /* Calculate time position of the keyframe and where we should stop */
4393   k_pos =
4394       QTSTREAMTIME_TO_GSTTIME (ref_str,
4395       target_ts - seg->trak_media_start) + seg->time;
4396   last_stop =
4397       QTSTREAMTIME_TO_GSTTIME (ref_str,
4398       ref_str->samples[ref_str->from_sample].timestamp -
4399       seg->trak_media_start) + seg->time;
4400
4401   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4402       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4403       k_index, GST_TIME_ARGS (k_pos));
4404
4405   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4406   qtdemux->segment.position = last_stop;
4407   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4408       GST_TIME_ARGS (last_stop));
4409
4410   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4411     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4412     goto eos;
4413   }
4414
4415   ref_seg_idx = ref_str->segment_index;
4416   ref_k_index = k_index;
4417
4418   /* Align them all on this */
4419   for (n = 0; n < qtdemux->n_streams; n++) {
4420     guint32 index = 0;
4421     GstClockTime seg_time = 0;
4422     QtDemuxStream *str = qtdemux->streams[n];
4423
4424     /* aligning reference stream again might lead to backing up to yet another
4425      * keyframe (due to timestamp rounding issues),
4426      * potentially putting more load on downstream; so let's try to avoid */
4427     if (str == ref_str) {
4428       seg_idx = ref_seg_idx;
4429       seg = &str->segments[seg_idx];
4430       k_index = ref_k_index;
4431       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4432           "sample at index %d", n, ref_str->segment_index, k_index);
4433     } else {
4434       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4435       GST_DEBUG_OBJECT (qtdemux,
4436           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4437           seg_idx, GST_TIME_ARGS (k_pos));
4438
4439       /* get segment and time in the segment */
4440       seg = &str->segments[seg_idx];
4441       seg_time = k_pos - seg->time;
4442
4443       /* get the media time in the segment.
4444        * No adjustment for empty "filler" segments */
4445       if (seg->media_start != GST_CLOCK_TIME_NONE)
4446         seg_time += seg->media_start;
4447
4448       /* get the index of the sample with media time */
4449       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4450       GST_DEBUG_OBJECT (qtdemux,
4451           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4452           GST_TIME_ARGS (seg_time), index);
4453
4454       /* find previous keyframe */
4455       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4456     }
4457
4458     /* Remember until where we want to go */
4459     str->to_sample = str->from_sample - 1;
4460     /* Define our time position */
4461     target_ts =
4462         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4463     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4464     if (seg->media_start != GST_CLOCK_TIME_NONE)
4465       str->time_position -= seg->media_start;
4466
4467     /* Now seek back in time */
4468     gst_qtdemux_move_stream (qtdemux, str, k_index);
4469     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4470         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4471         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4472   }
4473
4474   return GST_FLOW_OK;
4475
4476 eos:
4477   return GST_FLOW_EOS;
4478 }
4479
4480 /*
4481  * Gets the current qt segment start, stop and position for the
4482  * given time offset. This is used in update_segment()
4483  */
4484 static void
4485 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4486     QtDemuxStream * stream, GstClockTime offset,
4487     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4488 {
4489   GstClockTime seg_time;
4490   GstClockTime start, stop, time;
4491   QtDemuxSegment *segment;
4492
4493   segment = &stream->segments[stream->segment_index];
4494
4495   /* get time in this segment */
4496   seg_time = (offset - segment->time) * segment->rate;
4497
4498   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4499       GST_TIME_ARGS (seg_time));
4500
4501   if (G_UNLIKELY (seg_time > segment->duration)) {
4502     GST_LOG_OBJECT (stream->pad,
4503         "seg_time > segment->duration %" GST_TIME_FORMAT,
4504         GST_TIME_ARGS (segment->duration));
4505     seg_time = segment->duration;
4506   }
4507
4508   /* qtdemux->segment.stop is in outside-time-realm, whereas
4509    * segment->media_stop is in track-time-realm.
4510    *
4511    * In order to compare the two, we need to bring segment.stop
4512    * into the track-time-realm
4513    *
4514    * FIXME - does this comment still hold? Don't see any conversion here */
4515
4516   stop = qtdemux->segment.stop;
4517   if (stop == GST_CLOCK_TIME_NONE)
4518     stop = qtdemux->segment.duration;
4519   if (stop == GST_CLOCK_TIME_NONE)
4520     stop = segment->media_stop;
4521   else
4522     stop =
4523         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4524
4525   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4526     start = segment->time + seg_time;
4527     time = offset;
4528     stop = start - seg_time + segment->duration;
4529   } else if (qtdemux->segment.rate >= 0) {
4530     start = MIN (segment->media_start + seg_time, stop);
4531     time = offset;
4532   } else {
4533     if (segment->media_start >= qtdemux->segment.start) {
4534       time = segment->time;
4535     } else {
4536       time = segment->time + (qtdemux->segment.start - segment->media_start);
4537     }
4538
4539     start = MAX (segment->media_start, qtdemux->segment.start);
4540     stop = MIN (segment->media_start + seg_time, stop);
4541   }
4542
4543   *_start = start;
4544   *_stop = stop;
4545   *_time = time;
4546 }
4547
4548 /*
4549  * Updates the qt segment used for the stream and pushes a new segment event
4550  * downstream on this stream's pad.
4551  */
4552 static gboolean
4553 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4554     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4555     GstClockTime * _stop)
4556 {
4557   QtDemuxSegment *segment;
4558   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4559   gdouble rate;
4560   GstEvent *event;
4561
4562   /* update the current segment */
4563   stream->segment_index = seg_idx;
4564
4565   /* get the segment */
4566   segment = &stream->segments[seg_idx];
4567
4568   if (G_UNLIKELY (offset < segment->time)) {
4569     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4570         GST_TIME_ARGS (segment->time));
4571     return FALSE;
4572   }
4573
4574   /* segment lies beyond total indicated duration */
4575   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4576           segment->time > qtdemux->segment.duration)) {
4577     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4578         " < segment->time %" GST_TIME_FORMAT,
4579         GST_TIME_ARGS (qtdemux->segment.duration),
4580         GST_TIME_ARGS (segment->time));
4581     return FALSE;
4582   }
4583
4584   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4585       &start, &stop, &time);
4586
4587   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4588       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4589       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4590
4591   /* combine global rate with that of the segment */
4592   rate = segment->rate * qtdemux->segment.rate;
4593
4594   /* Copy flags from main segment */
4595   stream->segment.flags = qtdemux->segment.flags;
4596
4597   /* update the segment values used for clipping */
4598   stream->segment.offset = qtdemux->segment.offset;
4599   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4600   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4601   stream->segment.rate = rate;
4602   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4603       stream->cslg_shift);
4604   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4605       stream->cslg_shift);
4606   stream->segment.time = time;
4607   stream->segment.position = stream->segment.start;
4608
4609   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4610       &stream->segment);
4611
4612   /* now prepare and send the segment */
4613   if (stream->pad) {
4614     event = gst_event_new_segment (&stream->segment);
4615     if (qtdemux->segment_seqnum) {
4616       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4617     }
4618     gst_pad_push_event (stream->pad, event);
4619     /* assume we can send more data now */
4620     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4621     /* clear to send tags on this pad now */
4622     gst_qtdemux_push_tags (qtdemux, stream);
4623   }
4624
4625   if (_start)
4626     *_start = start;
4627   if (_stop)
4628     *_stop = stop;
4629
4630   return TRUE;
4631 }
4632
4633 /* activate the given segment number @seg_idx of @stream at time @offset.
4634  * @offset is an absolute global position over all the segments.
4635  *
4636  * This will push out a NEWSEGMENT event with the right values and
4637  * position the stream index to the first decodable sample before
4638  * @offset.
4639  */
4640 static gboolean
4641 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4642     guint32 seg_idx, GstClockTime offset)
4643 {
4644   QtDemuxSegment *segment;
4645   guint32 index, kf_index;
4646   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4647
4648   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4649       seg_idx, GST_TIME_ARGS (offset));
4650
4651   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4652           &start, &stop))
4653     return FALSE;
4654
4655   segment = &stream->segments[stream->segment_index];
4656
4657   /* in the fragmented case, we pick a fragment that starts before our
4658    * desired position and rely on downstream to wait for a keyframe
4659    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4660    * tfra entries tells us which trun/sample the key unit is in, but we don't
4661    * make use of this additional information at the moment) */
4662   if (qtdemux->fragmented) {
4663     stream->to_sample = G_MAXUINT32;
4664     return TRUE;
4665   }
4666
4667   /* We don't need to look for a sample in push-based */
4668   if (!qtdemux->pullbased)
4669     return TRUE;
4670
4671   /* and move to the keyframe before the indicated media time of the
4672    * segment */
4673   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4674     if (qtdemux->segment.rate >= 0) {
4675       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4676       stream->to_sample = G_MAXUINT32;
4677       GST_DEBUG_OBJECT (stream->pad,
4678           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4679           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4680           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4681     } else {
4682       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4683       stream->to_sample = index;
4684       GST_DEBUG_OBJECT (stream->pad,
4685           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4686           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4687           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4688     }
4689   } else {
4690     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4691         "this is an empty segment");
4692     return TRUE;
4693   }
4694
4695   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4696    * encountered an error and printed a message so we return appropriately */
4697   if (index == -1)
4698     return FALSE;
4699
4700   /* we're at the right spot */
4701   if (index == stream->sample_index) {
4702     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4703     return TRUE;
4704   }
4705
4706   /* find keyframe of the target index */
4707   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4708
4709 /* *INDENT-OFF* */
4710 /* indent does stupid stuff with stream->samples[].timestamp */
4711
4712   /* if we move forwards, we don't have to go back to the previous
4713    * keyframe since we already sent that. We can also just jump to
4714    * the keyframe right before the target index if there is one. */
4715   if (index > stream->sample_index) {
4716     /* moving forwards check if we move past a keyframe */
4717     if (kf_index > stream->sample_index) {
4718       GST_DEBUG_OBJECT (stream->pad,
4719            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4720            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4721            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4722       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4723     } else {
4724       GST_DEBUG_OBJECT (stream->pad,
4725           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4726           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4727           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4728     }
4729   } else {
4730     GST_DEBUG_OBJECT (stream->pad,
4731         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4732         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4733         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4734     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4735   }
4736
4737 /* *INDENT-ON* */
4738
4739   return TRUE;
4740 }
4741
4742 /* prepare to get the current sample of @stream, getting essential values.
4743  *
4744  * This function will also prepare and send the segment when needed.
4745  *
4746  * Return FALSE if the stream is EOS.
4747  *
4748  * PULL-BASED
4749  */
4750 static gboolean
4751 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4752     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4753     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4754     gboolean * keyframe)
4755 {
4756   QtDemuxSample *sample;
4757   GstClockTime time_position;
4758   guint32 seg_idx;
4759
4760   g_return_val_if_fail (stream != NULL, FALSE);
4761
4762   time_position = stream->time_position;
4763   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4764     goto eos;
4765
4766   seg_idx = stream->segment_index;
4767   if (G_UNLIKELY (seg_idx == -1)) {
4768     /* find segment corresponding to time_position if we are looking
4769      * for a segment. */
4770     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4771   }
4772
4773   /* different segment, activate it, sample_index will be set. */
4774   if (G_UNLIKELY (stream->segment_index != seg_idx))
4775     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4776
4777   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4778                   segment_index]))) {
4779     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4780
4781     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4782         " prepare empty sample");
4783
4784     *empty = TRUE;
4785     *pts = *dts = time_position;
4786     *duration = seg->duration - (time_position - seg->time);
4787
4788     return TRUE;
4789   }
4790
4791   *empty = FALSE;
4792
4793   if (stream->sample_index == -1)
4794     stream->sample_index = 0;
4795
4796   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4797       stream->sample_index, stream->n_samples);
4798
4799   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4800     if (!qtdemux->fragmented)
4801       goto eos;
4802
4803     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4804     do {
4805       GstFlowReturn flow;
4806
4807       GST_OBJECT_LOCK (qtdemux);
4808       flow = qtdemux_add_fragmented_samples (qtdemux);
4809       GST_OBJECT_UNLOCK (qtdemux);
4810
4811       if (flow != GST_FLOW_OK)
4812         goto eos;
4813     }
4814     while (stream->sample_index >= stream->n_samples);
4815   }
4816
4817   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4818     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4819         stream->sample_index);
4820     return FALSE;
4821   }
4822
4823   /* now get the info for the sample we're at */
4824   sample = &stream->samples[stream->sample_index];
4825
4826   *dts = QTSAMPLE_DTS (stream, sample);
4827   *pts = QTSAMPLE_PTS (stream, sample);
4828   *offset = sample->offset;
4829   *size = sample->size;
4830   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4831   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4832
4833   return TRUE;
4834
4835   /* special cases */
4836 eos:
4837   {
4838     stream->time_position = GST_CLOCK_TIME_NONE;
4839     return FALSE;
4840   }
4841 }
4842
4843 /* move to the next sample in @stream.
4844  *
4845  * Moves to the next segment when needed.
4846  */
4847 static void
4848 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4849 {
4850   QtDemuxSample *sample;
4851   QtDemuxSegment *segment;
4852
4853   /* get current segment */
4854   segment = &stream->segments[stream->segment_index];
4855
4856   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4857     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4858     goto next_segment;
4859   }
4860
4861   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4862     /* Mark the stream as EOS */
4863     GST_DEBUG_OBJECT (qtdemux,
4864         "reached max allowed sample %u, mark EOS", stream->to_sample);
4865     stream->time_position = GST_CLOCK_TIME_NONE;
4866     return;
4867   }
4868
4869   /* move to next sample */
4870   stream->sample_index++;
4871   stream->offset_in_sample = 0;
4872
4873   /* reached the last sample, we need the next segment */
4874   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4875     goto next_segment;
4876
4877   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4878     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4879         stream->sample_index);
4880     return;
4881   }
4882
4883   /* get next sample */
4884   sample = &stream->samples[stream->sample_index];
4885
4886   /* see if we are past the segment */
4887   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4888     goto next_segment;
4889
4890   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4891     /* inside the segment, update time_position, looks very familiar to
4892      * GStreamer segments, doesn't it? */
4893     stream->time_position =
4894         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4895   } else {
4896     /* not yet in segment, time does not yet increment. This means
4897      * that we are still prerolling keyframes to the decoder so it can
4898      * decode the first sample of the segment. */
4899     stream->time_position = segment->time;
4900   }
4901   return;
4902
4903   /* move to the next segment */
4904 next_segment:
4905   {
4906     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4907
4908     if (stream->segment_index == stream->n_segments - 1) {
4909       /* are we at the end of the last segment, we're EOS */
4910       stream->time_position = GST_CLOCK_TIME_NONE;
4911     } else {
4912       /* else we're only at the end of the current segment */
4913       stream->time_position = segment->stop_time;
4914     }
4915     /* make sure we select a new segment */
4916
4917     /* accumulate previous segments */
4918     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4919       stream->accumulated_base +=
4920           (stream->segment.stop -
4921           stream->segment.start) / ABS (stream->segment.rate);
4922
4923     stream->segment_index = -1;
4924   }
4925 }
4926
4927 static void
4928 gst_qtdemux_sync_streams (GstQTDemux * demux)
4929 {
4930   gint i;
4931
4932   if (demux->n_streams <= 1)
4933     return;
4934
4935   for (i = 0; i < demux->n_streams; i++) {
4936     QtDemuxStream *stream;
4937     GstClockTime end_time;
4938
4939     stream = demux->streams[i];
4940
4941     if (!stream->pad)
4942       continue;
4943
4944     /* TODO advance time on subtitle streams here, if any some day */
4945
4946     /* some clips/trailers may have unbalanced streams at the end,
4947      * so send EOS on shorter stream to prevent stalling others */
4948
4949     /* do not mess with EOS if SEGMENT seeking */
4950     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4951       continue;
4952
4953     if (demux->pullbased) {
4954       /* loop mode is sample time based */
4955       if (!STREAM_IS_EOS (stream))
4956         continue;
4957     } else {
4958       /* push mode is byte position based */
4959       if (stream->n_samples &&
4960           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4961         continue;
4962     }
4963
4964     if (stream->sent_eos)
4965       continue;
4966
4967     /* only act if some gap */
4968     end_time = stream->segments[stream->n_segments - 1].stop_time;
4969     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4970         ", stream end: %" GST_TIME_FORMAT,
4971         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4972     if (GST_CLOCK_TIME_IS_VALID (end_time)
4973         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4974       GstEvent *event;
4975
4976       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4977           GST_PAD_NAME (stream->pad));
4978       stream->sent_eos = TRUE;
4979       event = gst_event_new_eos ();
4980       if (demux->segment_seqnum)
4981         gst_event_set_seqnum (event, demux->segment_seqnum);
4982       gst_pad_push_event (stream->pad, event);
4983     }
4984   }
4985 }
4986
4987 /* EOS and NOT_LINKED need to be combined. This means that we return:
4988  *
4989  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4990  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4991  */
4992 static GstFlowReturn
4993 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4994     GstFlowReturn ret)
4995 {
4996   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4997
4998   if (stream->pad)
4999     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5000         ret);
5001   else
5002     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5003
5004   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5005   return ret;
5006 }
5007
5008 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5009  * completely clipped
5010  *
5011  * Should be used only with raw buffers */
5012 static GstBuffer *
5013 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5014     GstBuffer * buf)
5015 {
5016   guint64 start, stop, cstart, cstop, diff;
5017   GstClockTime pts, duration;
5018   gsize size, osize;
5019   gint num_rate, denom_rate;
5020   gint frame_size;
5021   gboolean clip_data;
5022   guint offset;
5023
5024   osize = size = gst_buffer_get_size (buf);
5025   offset = 0;
5026
5027   /* depending on the type, setup the clip parameters */
5028   if (stream->subtype == FOURCC_soun) {
5029     frame_size = stream->bytes_per_frame;
5030     num_rate = GST_SECOND;
5031     denom_rate = (gint) stream->rate;
5032     clip_data = TRUE;
5033   } else if (stream->subtype == FOURCC_vide) {
5034     frame_size = size;
5035     num_rate = stream->fps_n;
5036     denom_rate = stream->fps_d;
5037     clip_data = FALSE;
5038   } else
5039     goto wrong_type;
5040
5041   if (frame_size <= 0)
5042     goto bad_frame_size;
5043
5044   /* we can only clip if we have a valid pts */
5045   pts = GST_BUFFER_PTS (buf);
5046   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5047     goto no_pts;
5048
5049   duration = GST_BUFFER_DURATION (buf);
5050
5051   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5052     duration =
5053         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5054   }
5055
5056   start = pts;
5057   stop = start + duration;
5058
5059   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5060               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5061     goto clipped;
5062
5063   /* see if some clipping happened */
5064   diff = cstart - start;
5065   if (diff > 0) {
5066     pts += diff;
5067     duration -= diff;
5068
5069     if (clip_data) {
5070       /* bring clipped time to samples and to bytes */
5071       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5072       diff *= frame_size;
5073
5074       GST_DEBUG_OBJECT (qtdemux,
5075           "clipping start to %" GST_TIME_FORMAT " %"
5076           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5077
5078       offset = diff;
5079       size -= diff;
5080     }
5081   }
5082   diff = stop - cstop;
5083   if (diff > 0) {
5084     duration -= diff;
5085
5086     if (clip_data) {
5087       /* bring clipped time to samples and then to bytes */
5088       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5089       diff *= frame_size;
5090       GST_DEBUG_OBJECT (qtdemux,
5091           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5092           " bytes", GST_TIME_ARGS (cstop), diff);
5093       size -= diff;
5094     }
5095   }
5096
5097   if (offset != 0 || size != osize)
5098     gst_buffer_resize (buf, offset, size);
5099
5100   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5101   GST_BUFFER_PTS (buf) = pts;
5102   GST_BUFFER_DURATION (buf) = duration;
5103
5104   return buf;
5105
5106   /* dropped buffer */
5107 wrong_type:
5108   {
5109     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5110     return buf;
5111   }
5112 bad_frame_size:
5113   {
5114     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5115     return buf;
5116   }
5117 no_pts:
5118   {
5119     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5120     return buf;
5121   }
5122 clipped:
5123   {
5124     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5125     gst_buffer_unref (buf);
5126     return NULL;
5127   }
5128 }
5129
5130 /* the input buffer metadata must be writable,
5131  * but time/duration etc not yet set and need not be preserved */
5132 static GstBuffer *
5133 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5134     GstBuffer * buf)
5135 {
5136   GstMapInfo map;
5137   guint nsize = 0;
5138   gchar *str;
5139
5140   /* not many cases for now */
5141   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5142     /* send a one time dvd clut event */
5143     if (stream->pending_event && stream->pad)
5144       gst_pad_push_event (stream->pad, stream->pending_event);
5145     stream->pending_event = NULL;
5146   }
5147
5148   if (G_UNLIKELY (stream->subtype != FOURCC_text
5149           && stream->subtype != FOURCC_sbtl &&
5150           stream->subtype != FOURCC_subp)) {
5151     return buf;
5152   }
5153
5154   gst_buffer_map (buf, &map, GST_MAP_READ);
5155
5156   /* empty buffer is sent to terminate previous subtitle */
5157   if (map.size <= 2) {
5158     gst_buffer_unmap (buf, &map);
5159     gst_buffer_unref (buf);
5160     return NULL;
5161   }
5162   if (stream->subtype == FOURCC_subp) {
5163     /* That's all the processing needed for subpictures */
5164     gst_buffer_unmap (buf, &map);
5165     return buf;
5166   }
5167
5168   nsize = GST_READ_UINT16_BE (map.data);
5169   nsize = MIN (nsize, map.size - 2);
5170
5171   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5172       nsize, map.size);
5173
5174   /* takes care of UTF-8 validation or UTF-16 recognition,
5175    * no other encoding expected */
5176   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5177   gst_buffer_unmap (buf, &map);
5178   if (str) {
5179     gst_buffer_unref (buf);
5180     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5181   } else {
5182     /* this should not really happen unless the subtitle is corrupted */
5183     gst_buffer_unref (buf);
5184     buf = NULL;
5185   }
5186
5187   /* FIXME ? convert optional subsequent style info to markup */
5188
5189   return buf;
5190 }
5191
5192 /* Sets a buffer's attributes properly and pushes it downstream.
5193  * Also checks for additional actions and custom processing that may
5194  * need to be done first.
5195  */
5196 static GstFlowReturn
5197 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5198     QtDemuxStream * stream, GstBuffer * buf,
5199     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5200     gboolean keyframe, GstClockTime position, guint64 byte_position)
5201 {
5202   GstFlowReturn ret = GST_FLOW_OK;
5203
5204   /* offset the timestamps according to the edit list */
5205
5206   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5207     gchar *url;
5208     GstMapInfo map;
5209
5210     gst_buffer_map (buf, &map, GST_MAP_READ);
5211     url = g_strndup ((gchar *) map.data, map.size);
5212     gst_buffer_unmap (buf, &map);
5213     if (url != NULL && strlen (url) != 0) {
5214       /* we have RTSP redirect now */
5215       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5216           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5217               gst_structure_new ("redirect",
5218                   "new-location", G_TYPE_STRING, url, NULL)));
5219       qtdemux->posted_redirect = TRUE;
5220     } else {
5221       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5222           "posting");
5223     }
5224     g_free (url);
5225   }
5226
5227   /* position reporting */
5228   if (qtdemux->segment.rate >= 0) {
5229     qtdemux->segment.position = position;
5230     gst_qtdemux_sync_streams (qtdemux);
5231   }
5232
5233   if (G_UNLIKELY (!stream->pad)) {
5234     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5235     gst_buffer_unref (buf);
5236     goto exit;
5237   }
5238
5239   /* send out pending buffers */
5240   while (stream->buffers) {
5241     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5242
5243     if (G_UNLIKELY (stream->discont)) {
5244       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5245       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5246       stream->discont = FALSE;
5247     } else {
5248       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5249     }
5250
5251     gst_pad_push (stream->pad, buffer);
5252
5253     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5254   }
5255
5256   /* we're going to modify the metadata */
5257   buf = gst_buffer_make_writable (buf);
5258
5259   if (G_UNLIKELY (stream->need_process))
5260     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5261
5262   if (!buf) {
5263     goto exit;
5264   }
5265
5266   GST_BUFFER_DTS (buf) = dts;
5267   GST_BUFFER_PTS (buf) = pts;
5268   GST_BUFFER_DURATION (buf) = duration;
5269   GST_BUFFER_OFFSET (buf) = -1;
5270   GST_BUFFER_OFFSET_END (buf) = -1;
5271
5272   if (G_UNLIKELY (stream->rgb8_palette))
5273     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5274
5275   if (G_UNLIKELY (stream->padding)) {
5276     gst_buffer_resize (buf, stream->padding, -1);
5277   }
5278 #if 0
5279   if (G_UNLIKELY (qtdemux->element_index)) {
5280     GstClockTime stream_time;
5281
5282     stream_time =
5283         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5284         timestamp);
5285     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5286       GST_LOG_OBJECT (qtdemux,
5287           "adding association %" GST_TIME_FORMAT "-> %"
5288           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5289       gst_index_add_association (qtdemux->element_index,
5290           qtdemux->index_id,
5291           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5292           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5293           GST_FORMAT_BYTES, byte_position, NULL);
5294     }
5295   }
5296 #endif
5297
5298   if (stream->need_clip)
5299     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5300
5301   if (G_UNLIKELY (buf == NULL))
5302     goto exit;
5303
5304   if (G_UNLIKELY (stream->discont)) {
5305     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5306     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5307     stream->discont = FALSE;
5308   } else {
5309     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5310   }
5311
5312   if (!keyframe) {
5313     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5314     stream->on_keyframe = FALSE;
5315   } else {
5316     stream->on_keyframe = TRUE;
5317   }
5318
5319
5320   GST_LOG_OBJECT (qtdemux,
5321       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5322       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5323       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5324       GST_PAD_NAME (stream->pad));
5325
5326   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5327     GstStructure *crypto_info;
5328     QtDemuxCencSampleSetInfo *info =
5329         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5330     gint index;
5331     GstEvent *event;
5332
5333     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5334       gst_pad_push_event (stream->pad, event);
5335     }
5336
5337     if (info->crypto_info == NULL) {
5338       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5339       gst_buffer_unref (buf);
5340       goto exit;
5341     }
5342
5343     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5344     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5345       /* steal structure from array */
5346       crypto_info = g_ptr_array_index (info->crypto_info, index);
5347       g_ptr_array_index (info->crypto_info, index) = NULL;
5348       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5349       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5350         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5351     }
5352   }
5353
5354   ret = gst_pad_push (stream->pad, buf);
5355
5356   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5357     /* mark position in stream, we'll need this to know when to send GAP event */
5358     stream->segment.position = pts + duration;
5359   }
5360
5361 exit:
5362   return ret;
5363 }
5364
5365 static const QtDemuxRandomAccessEntry *
5366 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5367     GstClockTime pos, gboolean after)
5368 {
5369   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5370   guint n_entries = stream->n_ra_entries;
5371   guint i;
5372
5373   /* we assume the table is sorted */
5374   for (i = 0; i < n_entries; ++i) {
5375     if (entries[i].ts > pos)
5376       break;
5377   }
5378
5379   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5380    * probably okay to assume that the index lists the very first fragment */
5381   if (i == 0)
5382     return &entries[0];
5383
5384   if (after)
5385     return &entries[i];
5386   else
5387     return &entries[i - 1];
5388 }
5389
5390 static gboolean
5391 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5392 {
5393   const QtDemuxRandomAccessEntry *best_entry = NULL;
5394   guint i;
5395
5396   GST_OBJECT_LOCK (qtdemux);
5397
5398   g_assert (qtdemux->n_streams > 0);
5399
5400   for (i = 0; i < qtdemux->n_streams; i++) {
5401     const QtDemuxRandomAccessEntry *entry;
5402     QtDemuxStream *stream;
5403     gboolean is_audio_or_video;
5404
5405     stream = qtdemux->streams[i];
5406
5407     g_free (stream->samples);
5408     stream->samples = NULL;
5409     stream->n_samples = 0;
5410     stream->stbl_index = -1;    /* no samples have yet been parsed */
5411     stream->sample_index = -1;
5412
5413     if (stream->ra_entries == NULL)
5414       continue;
5415
5416     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5417       is_audio_or_video = TRUE;
5418     else
5419       is_audio_or_video = FALSE;
5420
5421     entry =
5422         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5423         stream->time_position, !is_audio_or_video);
5424
5425     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5426         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5427
5428     stream->pending_seek = entry;
5429
5430     /* decide position to jump to just based on audio/video tracks, not subs */
5431     if (!is_audio_or_video)
5432       continue;
5433
5434     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5435       best_entry = entry;
5436   }
5437
5438   if (best_entry == NULL) {
5439     GST_OBJECT_UNLOCK (qtdemux);
5440     return FALSE;
5441   }
5442
5443   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5444       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5445       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5446       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5447
5448   qtdemux->moof_offset = best_entry->moof_offset;
5449
5450   qtdemux_add_fragmented_samples (qtdemux);
5451
5452   GST_OBJECT_UNLOCK (qtdemux);
5453   return TRUE;
5454 }
5455
5456 static GstFlowReturn
5457 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5458 {
5459   GstFlowReturn ret = GST_FLOW_OK;
5460   GstBuffer *buf = NULL;
5461   QtDemuxStream *stream;
5462   GstClockTime min_time;
5463   guint64 offset = 0;
5464   GstClockTime dts = GST_CLOCK_TIME_NONE;
5465   GstClockTime pts = GST_CLOCK_TIME_NONE;
5466   GstClockTime duration = 0;
5467   gboolean keyframe = FALSE;
5468   guint sample_size = 0;
5469   gboolean empty = 0;
5470   guint size;
5471   gint index;
5472   gint i;
5473
5474   gst_qtdemux_push_pending_newsegment (qtdemux);
5475
5476   if (qtdemux->fragmented_seek_pending) {
5477     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5478     gst_qtdemux_do_fragmented_seek (qtdemux);
5479     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5480     qtdemux->fragmented_seek_pending = FALSE;
5481   }
5482
5483   /* Figure out the next stream sample to output, min_time is expressed in
5484    * global time and runs over the edit list segments. */
5485   min_time = G_MAXUINT64;
5486   index = -1;
5487   for (i = 0; i < qtdemux->n_streams; i++) {
5488     GstClockTime position;
5489
5490     stream = qtdemux->streams[i];
5491     position = stream->time_position;
5492
5493     /* position of -1 is EOS */
5494     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5495       min_time = position;
5496       index = i;
5497     }
5498   }
5499   /* all are EOS */
5500   if (G_UNLIKELY (index == -1)) {
5501     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5502     goto eos;
5503   }
5504
5505   /* check for segment end */
5506   if (G_UNLIKELY (qtdemux->segment.stop != -1
5507           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5508               || (qtdemux->segment.rate < 0
5509                   && qtdemux->segment.start > min_time))
5510           && qtdemux->streams[index]->on_keyframe)) {
5511     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5512     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5513     goto eos_stream;
5514   }
5515
5516   /* gap events for subtitle streams */
5517   for (i = 0; i < qtdemux->n_streams; i++) {
5518     stream = qtdemux->streams[i];
5519     if (stream->pad && (stream->subtype == FOURCC_subp
5520             || stream->subtype == FOURCC_text
5521             || stream->subtype == FOURCC_sbtl)) {
5522       /* send one second gap events until the stream catches up */
5523       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5524       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5525           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5526           stream->segment.position + GST_SECOND < min_time) {
5527         GstEvent *gap =
5528             gst_event_new_gap (stream->segment.position, GST_SECOND);
5529         gst_pad_push_event (stream->pad, gap);
5530         stream->segment.position += GST_SECOND;
5531       }
5532     }
5533   }
5534
5535   stream = qtdemux->streams[index];
5536   if (stream->new_caps) {
5537     gst_qtdemux_configure_stream (qtdemux, stream);
5538     qtdemux_do_allocation (qtdemux, stream);
5539   }
5540
5541   /* fetch info for the current sample of this stream */
5542   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5543               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5544     goto eos_stream;
5545
5546   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5547   if (G_UNLIKELY (qtdemux->
5548           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5549     if (stream->subtype == FOURCC_vide && !keyframe) {
5550       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5551       goto next;
5552     }
5553   }
5554
5555   GST_DEBUG_OBJECT (qtdemux,
5556       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5557       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5558       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5559       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5560
5561   if (G_UNLIKELY (empty)) {
5562     /* empty segment, push a gap and move to the next one */
5563     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5564     stream->segment.position = pts + duration;
5565     goto next;
5566   }
5567
5568   /* hmm, empty sample, skip and move to next sample */
5569   if (G_UNLIKELY (sample_size <= 0))
5570     goto next;
5571
5572   /* last pushed sample was out of boundary, goto next sample */
5573   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5574     goto next;
5575
5576   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5577     size = sample_size;
5578   } else {
5579     GST_DEBUG_OBJECT (qtdemux,
5580         "size %d larger than stream max_buffer_size %d, trimming",
5581         sample_size, stream->max_buffer_size);
5582     size =
5583         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5584   }
5585
5586   if (qtdemux->cenc_aux_info_offset > 0) {
5587     GstMapInfo map;
5588     GstByteReader br;
5589     GstBuffer *aux_info = NULL;
5590
5591     /* pull the data stored before the sample */
5592     ret =
5593         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5594         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5595     if (G_UNLIKELY (ret != GST_FLOW_OK))
5596       goto beach;
5597     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5598     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5599     gst_byte_reader_init (&br, map.data + 8, map.size);
5600     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5601             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5602       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5603       gst_buffer_unmap (aux_info, &map);
5604       gst_buffer_unref (aux_info);
5605       ret = GST_FLOW_ERROR;
5606       goto beach;
5607     }
5608     gst_buffer_unmap (aux_info, &map);
5609     gst_buffer_unref (aux_info);
5610   }
5611
5612   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5613       offset);
5614
5615   if (stream->use_allocator) {
5616     /* if we have a per-stream allocator, use it */
5617     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5618   }
5619
5620   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5621       size, &buf);
5622   if (G_UNLIKELY (ret != GST_FLOW_OK))
5623     goto beach;
5624
5625   if (size != sample_size) {
5626     pts += gst_util_uint64_scale_int (GST_SECOND,
5627         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5628     dts += gst_util_uint64_scale_int (GST_SECOND,
5629         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5630     duration = gst_util_uint64_scale_int (GST_SECOND,
5631         size / stream->bytes_per_frame, stream->timescale);
5632   }
5633
5634   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5635       dts, pts, duration, keyframe, min_time, offset);
5636
5637   if (size != sample_size) {
5638     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5639     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5640
5641     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5642         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5643     if (time_position >= segment->media_start) {
5644       /* inside the segment, update time_position, looks very familiar to
5645        * GStreamer segments, doesn't it? */
5646       stream->time_position = (time_position - segment->media_start) +
5647           segment->time;
5648     } else {
5649       /* not yet in segment, time does not yet increment. This means
5650        * that we are still prerolling keyframes to the decoder so it can
5651        * decode the first sample of the segment. */
5652       stream->time_position = segment->time;
5653     }
5654   }
5655
5656   /* combine flows */
5657   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5658   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5659    * we have no more data for the pad to push */
5660   if (ret == GST_FLOW_EOS)
5661     ret = GST_FLOW_OK;
5662
5663   stream->offset_in_sample += size;
5664   if (stream->offset_in_sample >= sample_size) {
5665     gst_qtdemux_advance_sample (qtdemux, stream);
5666   }
5667   goto beach;
5668
5669 next:
5670   gst_qtdemux_advance_sample (qtdemux, stream);
5671
5672 beach:
5673   return ret;
5674
5675   /* special cases */
5676 eos:
5677   {
5678     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5679     ret = GST_FLOW_EOS;
5680     goto beach;
5681   }
5682 eos_stream:
5683   {
5684     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5685     /* EOS will be raised if all are EOS */
5686     ret = GST_FLOW_OK;
5687     goto beach;
5688   }
5689 }
5690
5691 static void
5692 gst_qtdemux_loop (GstPad * pad)
5693 {
5694   GstQTDemux *qtdemux;
5695   guint64 cur_offset;
5696   GstFlowReturn ret;
5697
5698   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5699
5700   cur_offset = qtdemux->offset;
5701   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5702       cur_offset, qt_demux_state_string (qtdemux->state));
5703
5704   switch (qtdemux->state) {
5705     case QTDEMUX_STATE_INITIAL:
5706     case QTDEMUX_STATE_HEADER:
5707       ret = gst_qtdemux_loop_state_header (qtdemux);
5708       break;
5709     case QTDEMUX_STATE_MOVIE:
5710       ret = gst_qtdemux_loop_state_movie (qtdemux);
5711       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5712         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5713       }
5714       break;
5715     default:
5716       /* ouch */
5717       goto invalid_state;
5718   }
5719
5720   /* if something went wrong, pause */
5721   if (ret != GST_FLOW_OK)
5722     goto pause;
5723
5724 done:
5725   gst_object_unref (qtdemux);
5726   return;
5727
5728   /* ERRORS */
5729 invalid_state:
5730   {
5731     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5732         (NULL), ("streaming stopped, invalid state"));
5733     gst_pad_pause_task (pad);
5734     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5735     goto done;
5736   }
5737 pause:
5738   {
5739     const gchar *reason = gst_flow_get_name (ret);
5740
5741     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5742
5743     gst_pad_pause_task (pad);
5744
5745     /* fatal errors need special actions */
5746     /* check EOS */
5747     if (ret == GST_FLOW_EOS) {
5748       if (qtdemux->n_streams == 0) {
5749         /* we have no streams, post an error */
5750         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5751       }
5752       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5753         gint64 stop;
5754
5755         if ((stop = qtdemux->segment.stop) == -1)
5756           stop = qtdemux->segment.duration;
5757
5758         if (qtdemux->segment.rate >= 0) {
5759           GstMessage *message;
5760           GstEvent *event;
5761
5762           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5763           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5764               GST_FORMAT_TIME, stop);
5765           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5766           if (qtdemux->segment_seqnum) {
5767             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5768             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5769           }
5770           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5771           gst_qtdemux_push_event (qtdemux, event);
5772         } else {
5773           GstMessage *message;
5774           GstEvent *event;
5775
5776           /*  For Reverse Playback */
5777           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5778           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5779               GST_FORMAT_TIME, qtdemux->segment.start);
5780           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5781               qtdemux->segment.start);
5782           if (qtdemux->segment_seqnum) {
5783             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5784             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5785           }
5786           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5787           gst_qtdemux_push_event (qtdemux, event);
5788         }
5789       } else {
5790         GstEvent *event;
5791
5792         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5793         event = gst_event_new_eos ();
5794         if (qtdemux->segment_seqnum)
5795           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5796         gst_qtdemux_push_event (qtdemux, event);
5797       }
5798     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5799       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
5800       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5801     }
5802     goto done;
5803   }
5804 }
5805
5806 /*
5807  * has_next_entry
5808  *
5809  * Returns if there are samples to be played.
5810  */
5811 static gboolean
5812 has_next_entry (GstQTDemux * demux)
5813 {
5814   QtDemuxStream *stream;
5815   int i;
5816
5817   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5818
5819   for (i = 0; i < demux->n_streams; i++) {
5820     stream = demux->streams[i];
5821
5822     if (stream->sample_index == -1) {
5823       stream->sample_index = 0;
5824       stream->offset_in_sample = 0;
5825     }
5826
5827     if (stream->sample_index >= stream->n_samples) {
5828       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5829       continue;
5830     }
5831     GST_DEBUG_OBJECT (demux, "Found a sample");
5832     return TRUE;
5833   }
5834
5835   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5836   return FALSE;
5837 }
5838
5839 /*
5840  * next_entry_size
5841  *
5842  * Returns the size of the first entry at the current offset.
5843  * If -1, there are none (which means EOS or empty file).
5844  */
5845 static guint64
5846 next_entry_size (GstQTDemux * demux)
5847 {
5848   QtDemuxStream *stream;
5849   int i;
5850   int smallidx = -1;
5851   guint64 smalloffs = (guint64) - 1;
5852   QtDemuxSample *sample;
5853
5854   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5855       demux->offset);
5856
5857   for (i = 0; i < demux->n_streams; i++) {
5858     stream = demux->streams[i];
5859
5860     if (stream->sample_index == -1) {
5861       stream->sample_index = 0;
5862       stream->offset_in_sample = 0;
5863     }
5864
5865     if (stream->sample_index >= stream->n_samples) {
5866       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5867       continue;
5868     }
5869
5870     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5871       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5872           stream->sample_index);
5873       return -1;
5874     }
5875
5876     sample = &stream->samples[stream->sample_index];
5877
5878     GST_LOG_OBJECT (demux,
5879         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5880         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5881         sample->offset, sample->size);
5882
5883     if (((smalloffs == -1)
5884             || (sample->offset < smalloffs)) && (sample->size)) {
5885       smallidx = i;
5886       smalloffs = sample->offset;
5887     }
5888   }
5889
5890   GST_LOG_OBJECT (demux,
5891       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5892       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5893
5894   if (smallidx == -1)
5895     return -1;
5896
5897   stream = demux->streams[smallidx];
5898   sample = &stream->samples[stream->sample_index];
5899
5900   if (sample->offset >= demux->offset) {
5901     demux->todrop = sample->offset - demux->offset;
5902     return sample->size + demux->todrop;
5903   }
5904
5905   GST_DEBUG_OBJECT (demux,
5906       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5907   return -1;
5908 }
5909
5910 static void
5911 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5912 {
5913   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5914
5915   gst_element_post_message (GST_ELEMENT_CAST (demux),
5916       gst_message_new_element (GST_OBJECT_CAST (demux),
5917           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5918 }
5919
5920 static gboolean
5921 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5922 {
5923   GstEvent *event;
5924   gboolean res = 0;
5925
5926   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5927
5928   event =
5929       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5930       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5931       GST_SEEK_TYPE_NONE, -1);
5932
5933   /* store seqnum to drop flush events, they don't need to reach downstream */
5934   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5935   res = gst_pad_push_event (demux->sinkpad, event);
5936   demux->offset_seek_seqnum = 0;
5937
5938   return res;
5939 }
5940
5941 /* check for seekable upstream, above and beyond a mere query */
5942 static void
5943 gst_qtdemux_check_seekability (GstQTDemux * demux)
5944 {
5945   GstQuery *query;
5946   gboolean seekable = FALSE;
5947   gint64 start = -1, stop = -1;
5948
5949   if (demux->upstream_size)
5950     return;
5951
5952   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5953   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5954     GST_DEBUG_OBJECT (demux, "seeking query failed");
5955     goto done;
5956   }
5957
5958   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5959
5960   /* try harder to query upstream size if we didn't get it the first time */
5961   if (seekable && stop == -1) {
5962     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5963     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5964   }
5965
5966   /* if upstream doesn't know the size, it's likely that it's not seekable in
5967    * practice even if it technically may be seekable */
5968   if (seekable && (start != 0 || stop <= start)) {
5969     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5970     seekable = FALSE;
5971   }
5972
5973 done:
5974   gst_query_unref (query);
5975
5976   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5977       G_GUINT64_FORMAT ")", seekable, start, stop);
5978   demux->upstream_seekable = seekable;
5979   demux->upstream_size = seekable ? stop : -1;
5980 }
5981
5982 static void
5983 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5984 {
5985   g_return_if_fail (bytes <= demux->todrop);
5986
5987   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5988   gst_adapter_flush (demux->adapter, bytes);
5989   demux->neededbytes -= bytes;
5990   demux->offset += bytes;
5991   demux->todrop -= bytes;
5992 }
5993
5994 static void
5995 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5996 {
5997   if (G_UNLIKELY (demux->pending_newsegment)) {
5998     gint i;
5999
6000     gst_qtdemux_push_pending_newsegment (demux);
6001     /* clear to send tags on all streams */
6002     for (i = 0; i < demux->n_streams; i++) {
6003       QtDemuxStream *stream;
6004       stream = demux->streams[i];
6005       gst_qtdemux_push_tags (demux, stream);
6006       if (stream->sparse) {
6007         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6008         gst_pad_push_event (stream->pad,
6009             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6010       }
6011     }
6012   }
6013 }
6014
6015 static void
6016 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6017     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6018 {
6019   GstClockTime ts, dur;
6020   GstEvent *gap;
6021
6022   ts = pos;
6023   dur =
6024       stream->segments[segment_index].duration - (pos -
6025       stream->segments[segment_index].time);
6026   gap = gst_event_new_gap (ts, dur);
6027   stream->time_position += dur;
6028
6029   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6030       "segment: %" GST_PTR_FORMAT, gap);
6031   gst_pad_push_event (stream->pad, gap);
6032 }
6033
6034 static void
6035 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6036     QtDemuxStream * stream)
6037 {
6038   gint i;
6039
6040   /* Push any initial gap segments before proceeding to the
6041    * 'real' data */
6042   for (i = 0; i < stream->n_segments; i++) {
6043     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6044
6045     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6046       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6047           stream->time_position);
6048     } else {
6049       /* Only support empty segment at the beginning followed by
6050        * one non-empty segment, this was checked when parsing the
6051        * edts atom, arriving here is unexpected */
6052       g_assert (i + 1 == stream->n_segments);
6053       break;
6054     }
6055   }
6056 }
6057
6058 static GstFlowReturn
6059 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6060 {
6061   GstQTDemux *demux;
6062
6063   demux = GST_QTDEMUX (parent);
6064
6065   GST_DEBUG_OBJECT (demux,
6066       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6067       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6068       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6069       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6070       gst_buffer_get_size (inbuf), demux->offset);
6071
6072   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6073     gboolean is_gap_input = FALSE;
6074     gint i;
6075
6076     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6077
6078     for (i = 0; i < demux->n_streams; i++) {
6079       demux->streams[i]->discont = TRUE;
6080     }
6081
6082     /* Check if we can land back on our feet in the case where upstream is
6083      * handling the seeking/pushing of samples with gaps in between (like
6084      * in the case of trick-mode DASH for example) */
6085     if (demux->upstream_format_is_time
6086         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6087       gint i;
6088       for (i = 0; i < demux->n_streams; i++) {
6089         guint32 res;
6090         GST_LOG_OBJECT (demux,
6091             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6092             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6093         res =
6094             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6095             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6096         if (res != -1) {
6097           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6098           GST_LOG_OBJECT (demux,
6099               "Checking if sample %d from stream %d is valid (offset:%"
6100               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6101               sample->offset, sample->size);
6102           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6103             GST_LOG_OBJECT (demux,
6104                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6105                 res);
6106             is_gap_input = TRUE;
6107             /* We can go back to standard playback mode */
6108             demux->state = QTDEMUX_STATE_MOVIE;
6109             /* Remember which sample this stream is at */
6110             demux->streams[i]->sample_index = res;
6111             /* Finally update all push-based values to the expected values */
6112             demux->neededbytes = demux->streams[i]->samples[res].size;
6113             demux->todrop = 0;
6114             demux->offset = GST_BUFFER_OFFSET (inbuf);
6115           }
6116         }
6117       }
6118       if (!is_gap_input) {
6119         /* Reset state if it's a real discont */
6120         demux->neededbytes = 16;
6121         demux->state = QTDEMUX_STATE_INITIAL;
6122         demux->offset = GST_BUFFER_OFFSET (inbuf);
6123       }
6124     }
6125     /* Reverse fragmented playback, need to flush all we have before
6126      * consuming a new fragment.
6127      * The samples array have the timestamps calculated by accumulating the
6128      * durations but this won't work for reverse playback of fragments as
6129      * the timestamps of a subsequent fragment should be smaller than the
6130      * previously received one. */
6131     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6132       gst_qtdemux_process_adapter (demux, TRUE);
6133       for (i = 0; i < demux->n_streams; i++)
6134         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6135     }
6136   }
6137
6138   gst_adapter_push (demux->adapter, inbuf);
6139
6140   GST_DEBUG_OBJECT (demux,
6141       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6142       demux->neededbytes, gst_adapter_available (demux->adapter));
6143
6144   return gst_qtdemux_process_adapter (demux, FALSE);
6145 }
6146
6147 static GstFlowReturn
6148 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6149 {
6150   GstFlowReturn ret = GST_FLOW_OK;
6151
6152   /* we never really mean to buffer that much */
6153   if (demux->neededbytes == -1) {
6154     goto eos;
6155   }
6156
6157   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6158       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6159
6160 #ifndef GST_DISABLE_GST_DEBUG
6161     {
6162       guint64 discont_offset, distance_from_discont;
6163
6164       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6165       distance_from_discont =
6166           gst_adapter_distance_from_discont (demux->adapter);
6167
6168       GST_DEBUG_OBJECT (demux,
6169           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6170           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6171           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6172           demux->offset, discont_offset, distance_from_discont);
6173     }
6174 #endif
6175
6176     switch (demux->state) {
6177       case QTDEMUX_STATE_INITIAL:{
6178         const guint8 *data;
6179         guint32 fourcc;
6180         guint64 size;
6181
6182         gst_qtdemux_check_seekability (demux);
6183
6184         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6185
6186         /* get fourcc/length, set neededbytes */
6187         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6188             &size, &fourcc);
6189         gst_adapter_unmap (demux->adapter);
6190         data = NULL;
6191         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6192             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6193         if (size == 0) {
6194           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6195               (_("This file is invalid and cannot be played.")),
6196               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6197                   GST_FOURCC_ARGS (fourcc)));
6198           ret = GST_FLOW_ERROR;
6199           break;
6200         }
6201         if (fourcc == FOURCC_mdat) {
6202           gint next_entry = next_entry_size (demux);
6203           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6204             /* we have the headers, start playback */
6205             demux->state = QTDEMUX_STATE_MOVIE;
6206             demux->neededbytes = next_entry;
6207             demux->mdatleft = size;
6208           } else {
6209             /* no headers yet, try to get them */
6210             guint bs;
6211             gboolean res;
6212             guint64 old, target;
6213
6214           buffer_data:
6215             old = demux->offset;
6216             target = old + size;
6217
6218             /* try to jump over the atom with a seek */
6219             /* only bother if it seems worth doing so,
6220              * and avoids possible upstream/server problems */
6221             if (demux->upstream_seekable &&
6222                 demux->upstream_size > 4 * (1 << 20)) {
6223               res = qtdemux_seek_offset (demux, target);
6224             } else {
6225               GST_DEBUG_OBJECT (demux, "skipping seek");
6226               res = FALSE;
6227             }
6228
6229             if (res) {
6230               GST_DEBUG_OBJECT (demux, "seek success");
6231               /* remember the offset fo the first mdat so we can seek back to it
6232                * after we have the headers */
6233               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6234                 demux->first_mdat = old;
6235                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6236                     demux->first_mdat);
6237               }
6238               /* seek worked, continue reading */
6239               demux->offset = target;
6240               demux->neededbytes = 16;
6241               demux->state = QTDEMUX_STATE_INITIAL;
6242             } else {
6243               /* seek failed, need to buffer */
6244               demux->offset = old;
6245               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6246               /* there may be multiple mdat (or alike) buffers */
6247               /* sanity check */
6248               if (demux->mdatbuffer)
6249                 bs = gst_buffer_get_size (demux->mdatbuffer);
6250               else
6251                 bs = 0;
6252               if (size + bs > 10 * (1 << 20))
6253                 goto no_moov;
6254               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6255               demux->neededbytes = size;
6256               if (!demux->mdatbuffer)
6257                 demux->mdatoffset = demux->offset;
6258             }
6259           }
6260         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6261           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6262               (_("This file is invalid and cannot be played.")),
6263               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6264                   GST_FOURCC_ARGS (fourcc), size));
6265           ret = GST_FLOW_ERROR;
6266           break;
6267         } else {
6268           /* this means we already started buffering and still no moov header,
6269            * let's continue buffering everything till we get moov */
6270           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6271                   || fourcc == FOURCC_moof))
6272             goto buffer_data;
6273           demux->neededbytes = size;
6274           demux->state = QTDEMUX_STATE_HEADER;
6275         }
6276         break;
6277       }
6278       case QTDEMUX_STATE_HEADER:{
6279         const guint8 *data;
6280         guint32 fourcc;
6281
6282         GST_DEBUG_OBJECT (demux, "In header");
6283
6284         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6285
6286         /* parse the header */
6287         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6288             &fourcc);
6289         if (fourcc == FOURCC_moov) {
6290           gint n;
6291
6292           /* in usual fragmented setup we could try to scan for more
6293            * and end up at the the moov (after mdat) again */
6294           if (demux->got_moov && demux->n_streams > 0 &&
6295               (!demux->fragmented
6296                   || demux->last_moov_offset == demux->offset)) {
6297             GST_DEBUG_OBJECT (demux,
6298                 "Skipping moov atom as we have (this) one already");
6299           } else {
6300             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6301
6302             if (demux->got_moov && demux->fragmented) {
6303               GST_DEBUG_OBJECT (demux,
6304                   "Got a second moov, clean up data from old one");
6305               if (demux->moov_node)
6306                 g_node_destroy (demux->moov_node);
6307               demux->moov_node = NULL;
6308               demux->moov_node_compressed = NULL;
6309             } else {
6310               /* prepare newsegment to send when streaming actually starts */
6311               if (!demux->pending_newsegment) {
6312                 demux->pending_newsegment =
6313                     gst_event_new_segment (&demux->segment);
6314                 if (demux->segment_seqnum)
6315                   gst_event_set_seqnum (demux->pending_newsegment,
6316                       demux->segment_seqnum);
6317               }
6318             }
6319
6320             demux->last_moov_offset = demux->offset;
6321
6322             qtdemux_parse_moov (demux, data, demux->neededbytes);
6323             qtdemux_node_dump (demux, demux->moov_node);
6324             qtdemux_parse_tree (demux);
6325             qtdemux_prepare_streams (demux);
6326             if (!demux->got_moov)
6327               qtdemux_expose_streams (demux);
6328             else {
6329
6330               for (n = 0; n < demux->n_streams; n++) {
6331                 QtDemuxStream *stream = demux->streams[n];
6332
6333                 gst_qtdemux_configure_stream (demux, stream);
6334               }
6335             }
6336
6337             demux->got_moov = TRUE;
6338             gst_qtdemux_check_send_pending_segment (demux);
6339
6340             /* fragmented streams headers shouldn't contain edts atoms */
6341             if (!demux->fragmented) {
6342               for (n = 0; n < demux->n_streams; n++) {
6343                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6344                     demux->streams[n]);
6345               }
6346             }
6347
6348             g_node_destroy (demux->moov_node);
6349             demux->moov_node = NULL;
6350             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6351           }
6352         } else if (fourcc == FOURCC_moof) {
6353           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6354             guint64 dist = 0;
6355             GstClockTime prev_pts;
6356             guint64 prev_offset;
6357             guint64 adapter_discont_offset, adapter_discont_dist;
6358
6359             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6360
6361             /*
6362              * The timestamp of the moof buffer is relevant as some scenarios
6363              * won't have the initial timestamp in the atoms. Whenever a new
6364              * buffer has started, we get that buffer's PTS and use it as a base
6365              * timestamp for the trun entries.
6366              *
6367              * To keep track of the current buffer timestamp and starting point
6368              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6369              * from the beggining of the buffer, with the distance and demux->offset
6370              * we know if it is still the same buffer or not.
6371              */
6372             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6373             prev_offset = demux->offset - dist;
6374             if (demux->fragment_start_offset == -1
6375                 || prev_offset > demux->fragment_start_offset) {
6376               demux->fragment_start_offset = prev_offset;
6377               demux->fragment_start = prev_pts;
6378               GST_DEBUG_OBJECT (demux,
6379                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6380                   GST_TIME_FORMAT, demux->fragment_start_offset,
6381                   GST_TIME_ARGS (demux->fragment_start));
6382             }
6383
6384             /* We can't use prev_offset() here because this would require
6385              * upstream to set consistent and correct offsets on all buffers
6386              * since the discont. Nothing ever did that in the past and we
6387              * would break backwards compatibility here then.
6388              * Instead take the offset we had at the last discont and count
6389              * the bytes from there. This works with old code as there would
6390              * be no discont between moov and moof, and also works with
6391              * adaptivedemux which correctly sets offset and will set the
6392              * DISCONT flag accordingly when needed.
6393              *
6394              * We also only do this for upstream TIME segments as otherwise
6395              * there are potential backwards compatibility problems with
6396              * seeking in PUSH mode and upstream providing inconsistent
6397              * timestamps. */
6398             adapter_discont_offset =
6399                 gst_adapter_offset_at_discont (demux->adapter);
6400             adapter_discont_dist =
6401                 gst_adapter_distance_from_discont (demux->adapter);
6402
6403             GST_DEBUG_OBJECT (demux,
6404                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6405                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6406                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6407
6408             if (demux->upstream_format_is_time) {
6409               demux->moof_offset = adapter_discont_offset;
6410               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6411                 demux->moof_offset += adapter_discont_dist;
6412               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6413                 demux->moof_offset = demux->offset;
6414             } else {
6415               demux->moof_offset = demux->offset;
6416             }
6417
6418             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6419                     demux->moof_offset, NULL)) {
6420               gst_adapter_unmap (demux->adapter);
6421               ret = GST_FLOW_ERROR;
6422               goto done;
6423             }
6424             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6425             if (demux->mss_mode && !demux->exposed) {
6426               if (!demux->pending_newsegment) {
6427                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6428                 demux->pending_newsegment =
6429                     gst_event_new_segment (&demux->segment);
6430                 if (demux->segment_seqnum)
6431                   gst_event_set_seqnum (demux->pending_newsegment,
6432                       demux->segment_seqnum);
6433               }
6434               qtdemux_expose_streams (demux);
6435             }
6436           } else {
6437             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6438           }
6439         } else if (fourcc == FOURCC_ftyp) {
6440           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6441           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6442         } else if (fourcc == FOURCC_uuid) {
6443           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6444           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6445         } else if (fourcc == FOURCC_sidx) {
6446           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6447           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6448         } else {
6449           GST_WARNING_OBJECT (demux,
6450               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6451               GST_FOURCC_ARGS (fourcc));
6452           /* Let's jump that one and go back to initial state */
6453         }
6454         gst_adapter_unmap (demux->adapter);
6455         data = NULL;
6456
6457         if (demux->mdatbuffer && demux->n_streams) {
6458           gsize remaining_data_size = 0;
6459
6460           /* the mdat was before the header */
6461           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6462               demux->n_streams, demux->mdatbuffer);
6463           /* restore our adapter/offset view of things with upstream;
6464            * put preceding buffered data ahead of current moov data.
6465            * This should also handle evil mdat, moov, mdat cases and alike */
6466           gst_adapter_flush (demux->adapter, demux->neededbytes);
6467
6468           /* Store any remaining data after the mdat for later usage */
6469           remaining_data_size = gst_adapter_available (demux->adapter);
6470           if (remaining_data_size > 0) {
6471             g_assert (demux->restoredata_buffer == NULL);
6472             demux->restoredata_buffer =
6473                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6474             demux->restoredata_offset = demux->offset + demux->neededbytes;
6475             GST_DEBUG_OBJECT (demux,
6476                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6477                 G_GUINT64_FORMAT, remaining_data_size,
6478                 demux->restoredata_offset);
6479           }
6480
6481           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6482           demux->mdatbuffer = NULL;
6483           demux->offset = demux->mdatoffset;
6484           demux->neededbytes = next_entry_size (demux);
6485           demux->state = QTDEMUX_STATE_MOVIE;
6486           demux->mdatleft = gst_adapter_available (demux->adapter);
6487         } else {
6488           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6489           gst_adapter_flush (demux->adapter, demux->neededbytes);
6490
6491           /* only go back to the mdat if there are samples to play */
6492           if (demux->got_moov && demux->first_mdat != -1
6493               && has_next_entry (demux)) {
6494             gboolean res;
6495
6496             /* we need to seek back */
6497             res = qtdemux_seek_offset (demux, demux->first_mdat);
6498             if (res) {
6499               demux->offset = demux->first_mdat;
6500             } else {
6501               GST_DEBUG_OBJECT (demux, "Seek back failed");
6502             }
6503           } else {
6504             demux->offset += demux->neededbytes;
6505           }
6506           demux->neededbytes = 16;
6507           demux->state = QTDEMUX_STATE_INITIAL;
6508         }
6509
6510         break;
6511       }
6512       case QTDEMUX_STATE_BUFFER_MDAT:{
6513         GstBuffer *buf;
6514         guint8 fourcc[4];
6515
6516         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6517             demux->offset);
6518         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6519         gst_buffer_extract (buf, 0, fourcc, 4);
6520         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6521             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6522         if (demux->mdatbuffer)
6523           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6524         else
6525           demux->mdatbuffer = buf;
6526         demux->offset += demux->neededbytes;
6527         demux->neededbytes = 16;
6528         demux->state = QTDEMUX_STATE_INITIAL;
6529         gst_qtdemux_post_progress (demux, 1, 1);
6530
6531         break;
6532       }
6533       case QTDEMUX_STATE_MOVIE:{
6534         QtDemuxStream *stream = NULL;
6535         QtDemuxSample *sample;
6536         int i = -1;
6537         GstClockTime dts, pts, duration;
6538         gboolean keyframe;
6539
6540         GST_DEBUG_OBJECT (demux,
6541             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6542
6543         if (demux->fragmented) {
6544           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6545               demux->mdatleft);
6546           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6547             /* if needed data starts within this atom,
6548              * then it should not exceed this atom */
6549             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6550               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6551                   (_("This file is invalid and cannot be played.")),
6552                   ("sample data crosses atom boundary"));
6553               ret = GST_FLOW_ERROR;
6554               break;
6555             }
6556             demux->mdatleft -= demux->neededbytes;
6557           } else {
6558             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6559             /* so we are dropping more than left in this atom */
6560             gst_qtdemux_drop_data (demux, demux->mdatleft);
6561             demux->mdatleft = 0;
6562
6563             /* need to resume atom parsing so we do not miss any other pieces */
6564             demux->state = QTDEMUX_STATE_INITIAL;
6565             demux->neededbytes = 16;
6566
6567             /* check if there was any stored post mdat data from previous buffers */
6568             if (demux->restoredata_buffer) {
6569               g_assert (gst_adapter_available (demux->adapter) == 0);
6570
6571               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6572               demux->restoredata_buffer = NULL;
6573               demux->offset = demux->restoredata_offset;
6574             }
6575
6576             break;
6577           }
6578         }
6579
6580         if (demux->todrop) {
6581           if (demux->cenc_aux_info_offset > 0) {
6582             GstByteReader br;
6583             const guint8 *data;
6584
6585             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6586             data = gst_adapter_map (demux->adapter, demux->todrop);
6587             gst_byte_reader_init (&br, data + 8, demux->todrop);
6588             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6589                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6590               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6591               ret = GST_FLOW_ERROR;
6592               gst_adapter_unmap (demux->adapter);
6593               g_free (demux->cenc_aux_info_sizes);
6594               demux->cenc_aux_info_sizes = NULL;
6595               goto done;
6596             }
6597             demux->cenc_aux_info_offset = 0;
6598             g_free (demux->cenc_aux_info_sizes);
6599             demux->cenc_aux_info_sizes = NULL;
6600             gst_adapter_unmap (demux->adapter);
6601           }
6602           gst_qtdemux_drop_data (demux, demux->todrop);
6603         }
6604
6605         /* first buffer? */
6606         /* initial newsegment sent here after having added pads,
6607          * possible others in sink_event */
6608         gst_qtdemux_check_send_pending_segment (demux);
6609
6610         /* Figure out which stream this packet belongs to */
6611         for (i = 0; i < demux->n_streams; i++) {
6612           stream = demux->streams[i];
6613           if (stream->sample_index >= stream->n_samples)
6614             continue;
6615           GST_LOG_OBJECT (demux,
6616               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6617               " / size:%d)", i, stream->sample_index,
6618               stream->samples[stream->sample_index].offset,
6619               stream->samples[stream->sample_index].size);
6620
6621           if (stream->samples[stream->sample_index].offset == demux->offset)
6622             break;
6623         }
6624
6625         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6626           goto unknown_stream;
6627
6628         if (stream->new_caps) {
6629           gst_qtdemux_configure_stream (demux, stream);
6630         }
6631
6632         /* Put data in a buffer, set timestamps, caps, ... */
6633         sample = &stream->samples[stream->sample_index];
6634
6635         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6636           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6637               GST_FOURCC_ARGS (stream->fourcc));
6638
6639           dts = QTSAMPLE_DTS (stream, sample);
6640           pts = QTSAMPLE_PTS (stream, sample);
6641           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6642           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6643
6644           /* check for segment end */
6645           if (G_UNLIKELY (demux->segment.stop != -1
6646                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6647             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6648             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6649
6650             /* skip this data, stream is EOS */
6651             gst_adapter_flush (demux->adapter, demux->neededbytes);
6652
6653             /* check if all streams are eos */
6654             ret = GST_FLOW_EOS;
6655             for (i = 0; i < demux->n_streams; i++) {
6656               if (!STREAM_IS_EOS (demux->streams[i])) {
6657                 ret = GST_FLOW_OK;
6658                 break;
6659               }
6660             }
6661
6662             if (ret == GST_FLOW_EOS) {
6663               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6664               goto eos;
6665             }
6666           } else {
6667             GstBuffer *outbuf;
6668
6669             outbuf =
6670                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6671
6672             /* FIXME: should either be an assert or a plain check */
6673             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6674
6675             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6676                 dts, pts, duration, keyframe, dts, demux->offset);
6677           }
6678
6679           /* combine flows */
6680           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6681           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6682             goto non_ok_unlinked_flow;
6683         } else {
6684           /* skip this data, stream is EOS */
6685           gst_adapter_flush (demux->adapter, demux->neededbytes);
6686         }
6687
6688         stream->sample_index++;
6689         stream->offset_in_sample = 0;
6690
6691         /* update current offset and figure out size of next buffer */
6692         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6693             demux->offset, demux->neededbytes);
6694         demux->offset += demux->neededbytes;
6695         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6696             demux->offset);
6697
6698         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6699           if (demux->fragmented) {
6700             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6701             /* there may be more to follow, only finish this atom */
6702             demux->todrop = demux->mdatleft;
6703             demux->neededbytes = demux->todrop;
6704             break;
6705           }
6706           goto eos;
6707         }
6708         break;
6709       }
6710       default:
6711         goto invalid_state;
6712     }
6713   }
6714
6715   /* when buffering movie data, at least show user something is happening */
6716   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6717       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6718     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6719         demux->neededbytes);
6720   }
6721 done:
6722
6723   return ret;
6724
6725   /* ERRORS */
6726 non_ok_unlinked_flow:
6727   {
6728     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6729         gst_flow_get_name (ret));
6730     return ret;
6731   }
6732 unknown_stream:
6733   {
6734     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6735     ret = GST_FLOW_ERROR;
6736     goto done;
6737   }
6738 eos:
6739   {
6740     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6741     ret = GST_FLOW_EOS;
6742     goto done;
6743   }
6744 invalid_state:
6745   {
6746     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6747         (NULL), ("qtdemuxer invalid state %d", demux->state));
6748     ret = GST_FLOW_ERROR;
6749     goto done;
6750   }
6751 no_moov:
6752   {
6753     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6754         (NULL), ("no 'moov' atom within the first 10 MB"));
6755     ret = GST_FLOW_ERROR;
6756     goto done;
6757   }
6758 }
6759
6760 static gboolean
6761 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6762 {
6763   GstQuery *query;
6764   gboolean pull_mode;
6765
6766   query = gst_query_new_scheduling ();
6767
6768   if (!gst_pad_peer_query (sinkpad, query)) {
6769     gst_query_unref (query);
6770     goto activate_push;
6771   }
6772
6773   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6774       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6775   gst_query_unref (query);
6776
6777   if (!pull_mode)
6778     goto activate_push;
6779
6780   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6781   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6782
6783 activate_push:
6784   {
6785     GST_DEBUG_OBJECT (sinkpad, "activating push");
6786     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6787   }
6788 }
6789
6790 static gboolean
6791 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6792     GstPadMode mode, gboolean active)
6793 {
6794   gboolean res;
6795   GstQTDemux *demux = GST_QTDEMUX (parent);
6796
6797   switch (mode) {
6798     case GST_PAD_MODE_PUSH:
6799       demux->pullbased = FALSE;
6800       res = TRUE;
6801       break;
6802     case GST_PAD_MODE_PULL:
6803       if (active) {
6804         demux->pullbased = TRUE;
6805         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6806             sinkpad, NULL);
6807       } else {
6808         res = gst_pad_stop_task (sinkpad);
6809       }
6810       break;
6811     default:
6812       res = FALSE;
6813       break;
6814   }
6815   return res;
6816 }
6817
6818 #ifdef HAVE_ZLIB
6819 static void *
6820 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6821 {
6822   return g_malloc (items * size);
6823 }
6824
6825 static void
6826 qtdemux_zfree (void *opaque, void *addr)
6827 {
6828   g_free (addr);
6829 }
6830
6831 static void *
6832 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6833 {
6834   guint8 *buffer;
6835   z_stream *z;
6836   int ret;
6837
6838   z = g_new0 (z_stream, 1);
6839   z->zalloc = qtdemux_zalloc;
6840   z->zfree = qtdemux_zfree;
6841   z->opaque = NULL;
6842
6843   z->next_in = z_buffer;
6844   z->avail_in = z_length;
6845
6846   buffer = (guint8 *) g_malloc (length);
6847   ret = inflateInit (z);
6848   while (z->avail_in > 0) {
6849     if (z->avail_out == 0) {
6850       length += 1024;
6851       buffer = (guint8 *) g_realloc (buffer, length);
6852       z->next_out = buffer + z->total_out;
6853       z->avail_out = 1024;
6854     }
6855     ret = inflate (z, Z_SYNC_FLUSH);
6856     if (ret != Z_OK)
6857       break;
6858   }
6859   if (ret != Z_STREAM_END) {
6860     g_warning ("inflate() returned %d", ret);
6861   }
6862
6863   g_free (z);
6864   return buffer;
6865 }
6866 #endif /* HAVE_ZLIB */
6867
6868 static gboolean
6869 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6870 {
6871   GNode *cmov;
6872
6873   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6874
6875   /* counts as header data */
6876   qtdemux->header_size += length;
6877
6878   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6879   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6880
6881   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6882   if (cmov) {
6883     guint32 method;
6884     GNode *dcom;
6885     GNode *cmvd;
6886
6887     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6888     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6889     if (dcom == NULL || cmvd == NULL)
6890       goto invalid_compression;
6891
6892     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6893     switch (method) {
6894 #ifdef HAVE_ZLIB
6895       case FOURCC_zlib:{
6896         guint uncompressed_length;
6897         guint compressed_length;
6898         guint8 *buf;
6899
6900         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6901         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6902         GST_LOG ("length = %u", uncompressed_length);
6903
6904         buf =
6905             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6906             compressed_length, uncompressed_length);
6907
6908         qtdemux->moov_node_compressed = qtdemux->moov_node;
6909         qtdemux->moov_node = g_node_new (buf);
6910
6911         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6912             uncompressed_length);
6913         break;
6914       }
6915 #endif /* HAVE_ZLIB */
6916       default:
6917         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6918             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6919         break;
6920     }
6921   }
6922   return TRUE;
6923
6924   /* ERRORS */
6925 invalid_compression:
6926   {
6927     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6928     return FALSE;
6929   }
6930 }
6931
6932 static gboolean
6933 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6934     const guint8 * end)
6935 {
6936   while (G_UNLIKELY (buf < end)) {
6937     GNode *child;
6938     guint32 len;
6939
6940     if (G_UNLIKELY (buf + 4 > end)) {
6941       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6942       break;
6943     }
6944     len = QT_UINT32 (buf);
6945     if (G_UNLIKELY (len == 0)) {
6946       GST_LOG_OBJECT (qtdemux, "empty container");
6947       break;
6948     }
6949     if (G_UNLIKELY (len < 8)) {
6950       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6951       break;
6952     }
6953     if (G_UNLIKELY (len > (end - buf))) {
6954       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6955           (gint) (end - buf));
6956       break;
6957     }
6958
6959     child = g_node_new ((guint8 *) buf);
6960     g_node_append (node, child);
6961     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6962     qtdemux_parse_node (qtdemux, child, buf, len);
6963
6964     buf += len;
6965   }
6966   return TRUE;
6967 }
6968
6969 static gboolean
6970 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6971     GNode * xdxt)
6972 {
6973   int len = QT_UINT32 (xdxt->data);
6974   guint8 *buf = xdxt->data;
6975   guint8 *end = buf + len;
6976   GstBuffer *buffer;
6977
6978   /* skip size and type */
6979   buf += 8;
6980   end -= 8;
6981
6982   while (buf < end) {
6983     gint size;
6984     guint32 type;
6985
6986     size = QT_UINT32 (buf);
6987     type = QT_FOURCC (buf + 4);
6988
6989     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6990
6991     if (buf + size > end || size <= 0)
6992       break;
6993
6994     buf += 8;
6995     size -= 8;
6996
6997     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6998         GST_FOURCC_ARGS (type));
6999
7000     switch (type) {
7001       case FOURCC_tCtH:
7002         buffer = gst_buffer_new_and_alloc (size);
7003         gst_buffer_fill (buffer, 0, buf, size);
7004         stream->buffers = g_slist_append (stream->buffers, buffer);
7005         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7006         break;
7007       case FOURCC_tCt_:
7008         buffer = gst_buffer_new_and_alloc (size);
7009         gst_buffer_fill (buffer, 0, buf, size);
7010         stream->buffers = g_slist_append (stream->buffers, buffer);
7011         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7012         break;
7013       case FOURCC_tCtC:
7014         buffer = gst_buffer_new_and_alloc (size);
7015         gst_buffer_fill (buffer, 0, buf, size);
7016         stream->buffers = g_slist_append (stream->buffers, buffer);
7017         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7018         break;
7019       default:
7020         GST_WARNING_OBJECT (qtdemux,
7021             "unknown theora cookie %" GST_FOURCC_FORMAT,
7022             GST_FOURCC_ARGS (type));
7023         break;
7024     }
7025     buf += size;
7026   }
7027   return TRUE;
7028 }
7029
7030 static gboolean
7031 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7032     guint length)
7033 {
7034   guint32 fourcc = 0;
7035   guint32 node_length = 0;
7036   const QtNodeType *type;
7037   const guint8 *end;
7038
7039   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7040
7041   if (G_UNLIKELY (length < 8))
7042     goto not_enough_data;
7043
7044   node_length = QT_UINT32 (buffer);
7045   fourcc = QT_FOURCC (buffer + 4);
7046
7047   /* ignore empty nodes */
7048   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7049     return TRUE;
7050
7051   type = qtdemux_type_get (fourcc);
7052
7053   end = buffer + length;
7054
7055   GST_LOG_OBJECT (qtdemux,
7056       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7057       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7058
7059   if (node_length > length)
7060     goto broken_atom_size;
7061
7062   if (type->flags & QT_FLAG_CONTAINER) {
7063     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7064   } else {
7065     switch (fourcc) {
7066       case FOURCC_stsd:
7067       {
7068         if (node_length < 20) {
7069           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7070           break;
7071         }
7072         GST_DEBUG_OBJECT (qtdemux,
7073             "parsing stsd (sample table, sample description) atom");
7074         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7075         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7076         break;
7077       }
7078       case FOURCC_mp4a:
7079       case FOURCC_alac:
7080       case FOURCC_fLaC:
7081       {
7082         guint32 version;
7083         guint32 offset;
7084         guint min_size;
7085
7086         /* also read alac (or whatever) in stead of mp4a in the following,
7087          * since a similar layout is used in other cases as well */
7088         if (fourcc == FOURCC_mp4a)
7089           min_size = 20;
7090         else if (fourcc == FOURCC_fLaC)
7091           min_size = 86;
7092         else
7093           min_size = 40;
7094
7095         /* There are two things we might encounter here: a true mp4a atom, and
7096            an mp4a entry in an stsd atom. The latter is what we're interested
7097            in, and it looks like an atom, but isn't really one. The true mp4a
7098            atom is short, so we detect it based on length here. */
7099         if (length < min_size) {
7100           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7101               GST_FOURCC_ARGS (fourcc));
7102           break;
7103         }
7104
7105         /* 'version' here is the sound sample description version. Types 0 and
7106            1 are documented in the QTFF reference, but type 2 is not: it's
7107            described in Apple header files instead (struct SoundDescriptionV2
7108            in Movies.h) */
7109         version = QT_UINT16 (buffer + 16);
7110
7111         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7112             GST_FOURCC_ARGS (fourcc), version);
7113
7114         /* parse any esds descriptors */
7115         switch (version) {
7116           case 0:
7117             offset = 0x24;
7118             break;
7119           case 1:
7120             offset = 0x34;
7121             break;
7122           case 2:
7123             offset = 0x48;
7124             break;
7125           default:
7126             GST_WARNING_OBJECT (qtdemux,
7127                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7128                 GST_FOURCC_ARGS (fourcc), version);
7129             offset = 0;
7130             break;
7131         }
7132         if (offset)
7133           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7134         break;
7135       }
7136       case FOURCC_mp4v:
7137       case FOURCC_MP4V:
7138       case FOURCC_fmp4:
7139       case FOURCC_FMP4:
7140       case FOURCC_apcs:
7141       case FOURCC_apch:
7142       case FOURCC_apcn:
7143       case FOURCC_apco:
7144       case FOURCC_ap4h:
7145       {
7146         const guint8 *buf;
7147         guint32 version;
7148         int tlen;
7149
7150         /* codec_data is contained inside these atoms, which all have
7151          * the same format. */
7152
7153         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7154             GST_FOURCC_ARGS (fourcc));
7155         version = QT_UINT32 (buffer + 16);
7156         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7157         if (1 || version == 0x00000000) {
7158           buf = buffer + 0x32;
7159
7160           /* FIXME Quicktime uses PASCAL string while
7161            * the iso format uses C strings. Check the file
7162            * type before attempting to parse the string here. */
7163           tlen = QT_UINT8 (buf);
7164           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
7165           buf++;
7166           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
7167           /* the string has a reserved space of 32 bytes so skip
7168            * the remaining 31 */
7169           buf += 31;
7170           buf += 4;             /* and 4 bytes reserved */
7171
7172           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
7173
7174           qtdemux_parse_container (qtdemux, node, buf, end);
7175         }
7176         break;
7177       }
7178       case FOURCC_H264:
7179       {
7180         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
7181         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7182         break;
7183       }
7184       case FOURCC_avc1:
7185       {
7186         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
7187         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7188         break;
7189       }
7190       case FOURCC_avc3:
7191       {
7192         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
7193         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7194         break;
7195       }
7196       case FOURCC_H265:
7197       {
7198         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
7199         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7200         break;
7201       }
7202       case FOURCC_hvc1:
7203       {
7204         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
7205         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7206         break;
7207       }
7208       case FOURCC_hev1:
7209       {
7210         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
7211         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
7212         break;
7213       }
7214       case FOURCC_mjp2:
7215       {
7216         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7217         break;
7218       }
7219       case FOURCC_meta:
7220       {
7221         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7222         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7223         break;
7224       }
7225       case FOURCC_mp4s:
7226       {
7227         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7228         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7229         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7230         break;
7231       }
7232       case FOURCC_XiTh:
7233       {
7234         guint32 version;
7235         guint32 offset;
7236
7237         version = QT_UINT32 (buffer + 12);
7238         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7239
7240         switch (version) {
7241           case 0x00000001:
7242             offset = 0x62;
7243             break;
7244           default:
7245             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7246             offset = 0;
7247             break;
7248         }
7249         if (offset)
7250           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7251         break;
7252       }
7253       case FOURCC_in24:
7254       {
7255         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7256         break;
7257       }
7258       case FOURCC_uuid:
7259       {
7260         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7261         break;
7262       }
7263       case FOURCC_encv:
7264       {
7265         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7266         break;
7267       }
7268       case FOURCC_enca:
7269       {
7270         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7271         break;
7272       }
7273       default:
7274         if (!strcmp (type->name, "unknown"))
7275           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7276         break;
7277     }
7278   }
7279   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7280       GST_FOURCC_ARGS (fourcc));
7281   return TRUE;
7282
7283 /* ERRORS */
7284 not_enough_data:
7285   {
7286     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7287         (_("This file is corrupt and cannot be played.")),
7288         ("Not enough data for an atom header, got only %u bytes", length));
7289     return FALSE;
7290   }
7291 broken_atom_size:
7292   {
7293     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7294         (_("This file is corrupt and cannot be played.")),
7295         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7296             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7297             length));
7298     return FALSE;
7299   }
7300 }
7301
7302 static GNode *
7303 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7304 {
7305   GNode *child;
7306   guint8 *buffer;
7307   guint32 child_fourcc;
7308
7309   for (child = g_node_first_child (node); child;
7310       child = g_node_next_sibling (child)) {
7311     buffer = (guint8 *) child->data;
7312
7313     child_fourcc = QT_FOURCC (buffer + 4);
7314
7315     if (G_UNLIKELY (child_fourcc == fourcc)) {
7316       return child;
7317     }
7318   }
7319   return NULL;
7320 }
7321
7322 static GNode *
7323 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7324     GstByteReader * parser)
7325 {
7326   GNode *child;
7327   guint8 *buffer;
7328   guint32 child_fourcc, child_len;
7329
7330   for (child = g_node_first_child (node); child;
7331       child = g_node_next_sibling (child)) {
7332     buffer = (guint8 *) child->data;
7333
7334     child_len = QT_UINT32 (buffer);
7335     child_fourcc = QT_FOURCC (buffer + 4);
7336
7337     if (G_UNLIKELY (child_fourcc == fourcc)) {
7338       if (G_UNLIKELY (child_len < (4 + 4)))
7339         return NULL;
7340       /* FIXME: must verify if atom length < parent atom length */
7341       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7342       return child;
7343     }
7344   }
7345   return NULL;
7346 }
7347
7348 static GNode *
7349 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7350     GstByteReader * parser)
7351 {
7352   GNode *child;
7353   guint8 *buffer;
7354   guint32 child_fourcc, child_len;
7355
7356   for (child = g_node_next_sibling (node); child;
7357       child = g_node_next_sibling (child)) {
7358     buffer = (guint8 *) child->data;
7359
7360     child_fourcc = QT_FOURCC (buffer + 4);
7361
7362     if (child_fourcc == fourcc) {
7363       if (parser) {
7364         child_len = QT_UINT32 (buffer);
7365         if (G_UNLIKELY (child_len < (4 + 4)))
7366           return NULL;
7367         /* FIXME: must verify if atom length < parent atom length */
7368         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7369       }
7370       return child;
7371     }
7372   }
7373   return NULL;
7374 }
7375
7376 static GNode *
7377 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7378 {
7379   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7380 }
7381
7382 static void
7383 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7384 {
7385 /* FIXME: This can only reliably work if demuxers have a
7386  * separate streaming thread per srcpad. This should be
7387  * done in a demuxer base class, which integrates parts
7388  * of multiqueue
7389  *
7390  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7391  */
7392 #if 0
7393   GstQuery *query;
7394
7395   query = gst_query_new_allocation (stream->caps, FALSE);
7396
7397   if (!gst_pad_peer_query (stream->pad, query)) {
7398     /* not a problem, just debug a little */
7399     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7400   }
7401
7402   if (stream->allocator)
7403     gst_object_unref (stream->allocator);
7404
7405   if (gst_query_get_n_allocation_params (query) > 0) {
7406     /* try the allocator */
7407     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7408         &stream->params);
7409     stream->use_allocator = TRUE;
7410   } else {
7411     stream->allocator = NULL;
7412     gst_allocation_params_init (&stream->params);
7413     stream->use_allocator = FALSE;
7414   }
7415   gst_query_unref (query);
7416 #endif
7417 }
7418
7419 static gboolean
7420 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7421     QtDemuxStream * stream)
7422 {
7423   GstStructure *s;
7424   const gchar *selected_system;
7425
7426   g_return_val_if_fail (qtdemux != NULL, FALSE);
7427   g_return_val_if_fail (stream != NULL, FALSE);
7428   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7429
7430   if (stream->protection_scheme_type != FOURCC_cenc) {
7431     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7432     return FALSE;
7433   }
7434   if (qtdemux->protection_system_ids == NULL) {
7435     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7436         "cenc protection system information has been found");
7437     return FALSE;
7438   }
7439   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7440   selected_system = gst_protection_select_system ((const gchar **)
7441       qtdemux->protection_system_ids->pdata);
7442   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7443       qtdemux->protection_system_ids->len - 1);
7444   if (!selected_system) {
7445     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7446         "suitable decryptor element has been found");
7447     return FALSE;
7448   }
7449
7450   s = gst_caps_get_structure (stream->caps, 0);
7451   if (!gst_structure_has_name (s, "application/x-cenc")) {
7452     gst_structure_set (s,
7453         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7454         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7455         NULL);
7456     gst_structure_set_name (s, "application/x-cenc");
7457   }
7458   return TRUE;
7459 }
7460
7461 static gboolean
7462 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7463 {
7464   if (stream->subtype == FOURCC_vide) {
7465     /* fps is calculated base on the duration of the average framerate since
7466      * qt does not have a fixed framerate. */
7467     gboolean fps_available = TRUE;
7468
7469     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7470       /* still frame */
7471       stream->fps_n = 0;
7472       stream->fps_d = 1;
7473     } else {
7474       if (stream->duration == 0 || stream->n_samples < 2) {
7475         stream->fps_n = stream->timescale;
7476         stream->fps_d = 1;
7477         fps_available = FALSE;
7478       } else {
7479         GstClockTime avg_duration;
7480         guint64 duration;
7481         guint32 n_samples;
7482
7483         /* duration and n_samples can be updated for fragmented format
7484          * so, framerate of fragmented format is calculated using data in a moof */
7485         if (qtdemux->fragmented && stream->n_samples_moof > 0
7486             && stream->duration_moof > 0) {
7487           n_samples = stream->n_samples_moof;
7488           duration = stream->duration_moof;
7489         } else {
7490           n_samples = stream->n_samples;
7491           duration = stream->duration;
7492         }
7493
7494         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7495         /* stream->duration is guint64, timescale, n_samples are guint32 */
7496         avg_duration =
7497             gst_util_uint64_scale_round (duration -
7498             stream->first_duration, GST_SECOND,
7499             (guint64) (stream->timescale) * (n_samples - 1));
7500
7501         GST_LOG_OBJECT (qtdemux,
7502             "Calculating avg sample duration based on stream (or moof) duration %"
7503             G_GUINT64_FORMAT
7504             " minus first sample %u, leaving %d samples gives %"
7505             GST_TIME_FORMAT, duration, stream->first_duration,
7506             n_samples - 1, GST_TIME_ARGS (avg_duration));
7507
7508         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7509             &stream->fps_d);
7510
7511         GST_DEBUG_OBJECT (qtdemux,
7512             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7513             stream->timescale, stream->fps_n, stream->fps_d);
7514       }
7515     }
7516
7517     if (stream->caps) {
7518       stream->caps = gst_caps_make_writable (stream->caps);
7519
7520       gst_caps_set_simple (stream->caps,
7521           "width", G_TYPE_INT, stream->width,
7522           "height", G_TYPE_INT, stream->height, NULL);
7523
7524       /* set framerate if calculated framerate is reliable */
7525       if (fps_available) {
7526         gst_caps_set_simple (stream->caps,
7527             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7528       }
7529
7530       /* calculate pixel-aspect-ratio using display width and height */
7531       GST_DEBUG_OBJECT (qtdemux,
7532           "video size %dx%d, target display size %dx%d", stream->width,
7533           stream->height, stream->display_width, stream->display_height);
7534       /* qt file might have pasp atom */
7535       if (stream->par_w > 0 && stream->par_h > 0) {
7536         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7537         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7538             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7539       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7540           stream->width > 0 && stream->height > 0) {
7541         gint n, d;
7542
7543         /* calculate the pixel aspect ratio using the display and pixel w/h */
7544         n = stream->display_width * stream->height;
7545         d = stream->display_height * stream->width;
7546         if (n == d)
7547           n = d = 1;
7548         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7549         stream->par_w = n;
7550         stream->par_h = d;
7551         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7552             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7553       }
7554
7555       /* Create incomplete colorimetry here if needed */
7556       if (stream->colorimetry.range ||
7557           stream->colorimetry.matrix ||
7558           stream->colorimetry.transfer || stream->colorimetry.primaries) {
7559         gchar *colorimetry =
7560             gst_video_colorimetry_to_string (&stream->colorimetry);
7561         gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
7562             colorimetry, NULL);
7563         g_free (colorimetry);
7564       }
7565
7566       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7567         guint par_w = 1, par_h = 1;
7568
7569         if (stream->par_w > 0 && stream->par_h > 0) {
7570           par_w = stream->par_w;
7571           par_h = stream->par_h;
7572         }
7573
7574         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7575                 stream->width, stream->height, par_w, par_h)) {
7576           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7577         }
7578
7579         gst_caps_set_simple (stream->caps,
7580             "multiview-mode", G_TYPE_STRING,
7581             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7582             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7583             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7584       }
7585     }
7586   }
7587
7588   else if (stream->subtype == FOURCC_soun) {
7589     if (stream->caps) {
7590       stream->caps = gst_caps_make_writable (stream->caps);
7591       if (stream->rate > 0)
7592         gst_caps_set_simple (stream->caps,
7593             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7594       if (stream->n_channels > 0)
7595         gst_caps_set_simple (stream->caps,
7596             "channels", G_TYPE_INT, stream->n_channels, NULL);
7597       if (stream->n_channels > 2) {
7598         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7599          * correctly; this is just the minimum we can do - assume
7600          * we don't actually have any channel positions. */
7601         gst_caps_set_simple (stream->caps,
7602             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7603       }
7604     }
7605   }
7606
7607   if (stream->pad) {
7608     GstCaps *prev_caps = NULL;
7609
7610     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7611     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7612     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7613     gst_pad_set_active (stream->pad, TRUE);
7614
7615     gst_pad_use_fixed_caps (stream->pad);
7616
7617     if (stream->protected) {
7618       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7619         GST_ERROR_OBJECT (qtdemux,
7620             "Failed to configure protected stream caps.");
7621         return FALSE;
7622       }
7623     }
7624
7625     if (stream->new_stream) {
7626       gchar *stream_id;
7627       GstEvent *event;
7628       GstStreamFlags stream_flags;
7629
7630       event =
7631           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7632           0);
7633       if (event) {
7634         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7635           qtdemux->have_group_id = TRUE;
7636         else
7637           qtdemux->have_group_id = FALSE;
7638         gst_event_unref (event);
7639       } else if (!qtdemux->have_group_id) {
7640         qtdemux->have_group_id = TRUE;
7641         qtdemux->group_id = gst_util_group_id_next ();
7642       }
7643
7644       stream->new_stream = FALSE;
7645       stream_id =
7646           gst_pad_create_stream_id_printf (stream->pad,
7647           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7648       event = gst_event_new_stream_start (stream_id);
7649       if (qtdemux->have_group_id)
7650         gst_event_set_group_id (event, qtdemux->group_id);
7651       stream_flags = GST_STREAM_FLAG_NONE;
7652       if (stream->disabled)
7653         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7654       if (stream->sparse)
7655         stream_flags |= GST_STREAM_FLAG_SPARSE;
7656       gst_event_set_stream_flags (event, stream_flags);
7657       gst_pad_push_event (stream->pad, event);
7658       g_free (stream_id);
7659     }
7660
7661     prev_caps = gst_pad_get_current_caps (stream->pad);
7662
7663     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7664       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7665       gst_pad_set_caps (stream->pad, stream->caps);
7666     } else {
7667       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7668     }
7669
7670     if (prev_caps)
7671       gst_caps_unref (prev_caps);
7672     stream->new_caps = FALSE;
7673   }
7674   return TRUE;
7675 }
7676
7677 static gboolean
7678 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7679     QtDemuxStream * stream, GstTagList * list)
7680 {
7681   gboolean ret = TRUE;
7682   /* consistent default for push based mode */
7683   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7684
7685   if (stream->subtype == FOURCC_vide) {
7686     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7687
7688     stream->pad =
7689         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7690     g_free (name);
7691
7692     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7693       gst_object_unref (stream->pad);
7694       stream->pad = NULL;
7695       ret = FALSE;
7696       goto done;
7697     }
7698
7699     qtdemux->n_video_streams++;
7700   } else if (stream->subtype == FOURCC_soun) {
7701     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7702
7703     stream->pad =
7704         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7705     g_free (name);
7706     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7707       gst_object_unref (stream->pad);
7708       stream->pad = NULL;
7709       ret = FALSE;
7710       goto done;
7711     }
7712     qtdemux->n_audio_streams++;
7713   } else if (stream->subtype == FOURCC_strm) {
7714     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7715   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7716       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7717     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7718
7719     stream->pad =
7720         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7721     g_free (name);
7722     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7723       gst_object_unref (stream->pad);
7724       stream->pad = NULL;
7725       ret = FALSE;
7726       goto done;
7727     }
7728     qtdemux->n_sub_streams++;
7729   } else if (stream->caps) {
7730     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7731
7732     stream->pad =
7733         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7734     g_free (name);
7735     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7736       gst_object_unref (stream->pad);
7737       stream->pad = NULL;
7738       ret = FALSE;
7739       goto done;
7740     }
7741     qtdemux->n_video_streams++;
7742   } else {
7743     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7744     goto done;
7745   }
7746
7747   if (stream->pad) {
7748     GList *l;
7749
7750     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7751         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7752     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7753     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7754
7755     if (stream->pending_tags)
7756       gst_tag_list_unref (stream->pending_tags);
7757     stream->pending_tags = list;
7758     list = NULL;
7759     /* global tags go on each pad anyway */
7760     stream->send_global_tags = TRUE;
7761     /* send upstream GST_EVENT_PROTECTION events that were received before
7762        this source pad was created */
7763     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7764       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7765   }
7766 done:
7767   if (list)
7768     gst_tag_list_unref (list);
7769   return ret;
7770 }
7771
7772 /* find next atom with @fourcc starting at @offset */
7773 static GstFlowReturn
7774 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7775     guint64 * length, guint32 fourcc)
7776 {
7777   GstFlowReturn ret;
7778   guint32 lfourcc;
7779   GstBuffer *buf;
7780
7781   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7782       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7783
7784   while (TRUE) {
7785     GstMapInfo map;
7786
7787     buf = NULL;
7788     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7789     if (G_UNLIKELY (ret != GST_FLOW_OK))
7790       goto locate_failed;
7791     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7792       /* likely EOF */
7793       ret = GST_FLOW_EOS;
7794       gst_buffer_unref (buf);
7795       goto locate_failed;
7796     }
7797     gst_buffer_map (buf, &map, GST_MAP_READ);
7798     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7799     gst_buffer_unmap (buf, &map);
7800     gst_buffer_unref (buf);
7801
7802     if (G_UNLIKELY (*length == 0)) {
7803       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7804       ret = GST_FLOW_ERROR;
7805       goto locate_failed;
7806     }
7807
7808     if (lfourcc == fourcc) {
7809       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7810           *offset);
7811       break;
7812     } else {
7813       GST_LOG_OBJECT (qtdemux,
7814           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7815           GST_FOURCC_ARGS (fourcc), *offset);
7816       *offset += *length;
7817     }
7818   }
7819
7820   return GST_FLOW_OK;
7821
7822 locate_failed:
7823   {
7824     /* might simply have had last one */
7825     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7826     return ret;
7827   }
7828 }
7829
7830 /* should only do something in pull mode */
7831 /* call with OBJECT lock */
7832 static GstFlowReturn
7833 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7834 {
7835   guint64 length, offset;
7836   GstBuffer *buf = NULL;
7837   GstFlowReturn ret = GST_FLOW_OK;
7838   GstFlowReturn res = GST_FLOW_OK;
7839   GstMapInfo map;
7840
7841   offset = qtdemux->moof_offset;
7842   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7843
7844   if (!offset) {
7845     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7846     return GST_FLOW_EOS;
7847   }
7848
7849   /* best not do pull etc with lock held */
7850   GST_OBJECT_UNLOCK (qtdemux);
7851
7852   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7853   if (ret != GST_FLOW_OK)
7854     goto flow_failed;
7855
7856   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7857   if (G_UNLIKELY (ret != GST_FLOW_OK))
7858     goto flow_failed;
7859   gst_buffer_map (buf, &map, GST_MAP_READ);
7860   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7861     gst_buffer_unmap (buf, &map);
7862     gst_buffer_unref (buf);
7863     buf = NULL;
7864     goto parse_failed;
7865   }
7866
7867   gst_buffer_unmap (buf, &map);
7868   gst_buffer_unref (buf);
7869   buf = NULL;
7870
7871   offset += length;
7872   /* look for next moof */
7873   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7874   if (G_UNLIKELY (ret != GST_FLOW_OK))
7875     goto flow_failed;
7876
7877 exit:
7878   GST_OBJECT_LOCK (qtdemux);
7879
7880   qtdemux->moof_offset = offset;
7881
7882   return res;
7883
7884 parse_failed:
7885   {
7886     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7887     offset = 0;
7888     res = GST_FLOW_ERROR;
7889     goto exit;
7890   }
7891 flow_failed:
7892   {
7893     /* maybe upstream temporarily flushing */
7894     if (ret != GST_FLOW_FLUSHING) {
7895       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7896       offset = 0;
7897     } else {
7898       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7899       /* resume at current position next time */
7900     }
7901     res = ret;
7902     goto exit;
7903   }
7904 }
7905
7906 /* initialise bytereaders for stbl sub-atoms */
7907 static gboolean
7908 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7909 {
7910   stream->stbl_index = -1;      /* no samples have yet been parsed */
7911   stream->sample_index = -1;
7912
7913   /* time-to-sample atom */
7914   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7915     goto corrupt_file;
7916
7917   /* copy atom data into a new buffer for later use */
7918   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7919
7920   /* skip version + flags */
7921   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7922       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7923     goto corrupt_file;
7924   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7925
7926   /* make sure there's enough data */
7927   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7928     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7929     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7930         stream->n_sample_times);
7931     if (!stream->n_sample_times)
7932       goto corrupt_file;
7933   }
7934
7935   /* sync sample atom */
7936   stream->stps_present = FALSE;
7937   if ((stream->stss_present =
7938           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7939               &stream->stss) ? TRUE : FALSE) == TRUE) {
7940     /* copy atom data into a new buffer for later use */
7941     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7942
7943     /* skip version + flags */
7944     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7945         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7946       goto corrupt_file;
7947
7948     if (stream->n_sample_syncs) {
7949       /* make sure there's enough data */
7950       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7951         goto corrupt_file;
7952     }
7953
7954     /* partial sync sample atom */
7955     if ((stream->stps_present =
7956             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7957                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7958       /* copy atom data into a new buffer for later use */
7959       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7960
7961       /* skip version + flags */
7962       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7963           !gst_byte_reader_get_uint32_be (&stream->stps,
7964               &stream->n_sample_partial_syncs))
7965         goto corrupt_file;
7966
7967       /* if there are no entries, the stss table contains the real
7968        * sync samples */
7969       if (stream->n_sample_partial_syncs) {
7970         /* make sure there's enough data */
7971         if (!qt_atom_parser_has_chunks (&stream->stps,
7972                 stream->n_sample_partial_syncs, 4))
7973           goto corrupt_file;
7974       }
7975     }
7976   }
7977
7978   /* sample size */
7979   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7980     goto no_samples;
7981
7982   /* copy atom data into a new buffer for later use */
7983   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7984
7985   /* skip version + flags */
7986   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7987       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7988     goto corrupt_file;
7989
7990   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7991     goto corrupt_file;
7992
7993   if (!stream->n_samples)
7994     goto no_samples;
7995
7996   /* sample-to-chunk atom */
7997   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7998     goto corrupt_file;
7999
8000   /* copy atom data into a new buffer for later use */
8001   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8002
8003   /* skip version + flags */
8004   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8005       !gst_byte_reader_get_uint32_be (&stream->stsc,
8006           &stream->n_samples_per_chunk))
8007     goto corrupt_file;
8008
8009   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8010       stream->n_samples_per_chunk);
8011
8012   /* make sure there's enough data */
8013   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8014           12))
8015     goto corrupt_file;
8016
8017
8018   /* chunk offset */
8019   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8020     stream->co_size = sizeof (guint32);
8021   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8022           &stream->stco))
8023     stream->co_size = sizeof (guint64);
8024   else
8025     goto corrupt_file;
8026
8027   /* copy atom data into a new buffer for later use */
8028   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8029
8030   /* skip version + flags */
8031   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8032     goto corrupt_file;
8033
8034   /* chunks_are_samples == TRUE means treat chunks as samples */
8035   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
8036   if (stream->chunks_are_samples) {
8037     /* treat chunks as samples */
8038     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8039       goto corrupt_file;
8040   } else {
8041     /* skip number of entries */
8042     if (!gst_byte_reader_skip (&stream->stco, 4))
8043       goto corrupt_file;
8044
8045     /* make sure there are enough data in the stsz atom */
8046     if (!stream->sample_size) {
8047       /* different sizes for each sample */
8048       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8049         goto corrupt_file;
8050     }
8051   }
8052
8053   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8054       stream->n_samples, (guint) sizeof (QtDemuxSample),
8055       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8056
8057   if (stream->n_samples >=
8058       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8059     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8060         "be larger than %uMB (broken file?)", stream->n_samples,
8061         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8062     return FALSE;
8063   }
8064
8065   g_assert (stream->samples == NULL);
8066   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8067   if (!stream->samples) {
8068     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8069         stream->n_samples);
8070     return FALSE;
8071   }
8072
8073   /* composition time-to-sample */
8074   if ((stream->ctts_present =
8075           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8076               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8077     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8078
8079     /* copy atom data into a new buffer for later use */
8080     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8081
8082     /* skip version + flags */
8083     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8084         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8085             &stream->n_composition_times))
8086       goto corrupt_file;
8087
8088     /* make sure there's enough data */
8089     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8090             4 + 4))
8091       goto corrupt_file;
8092
8093     /* This is optional, if missing we iterate the ctts */
8094     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8095       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8096           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8097         g_free ((gpointer) cslg.data);
8098         goto corrupt_file;
8099       }
8100     } else {
8101       gint32 cslg_least = 0;
8102       guint num_entries, pos;
8103       gint i;
8104
8105       pos = gst_byte_reader_get_pos (&stream->ctts);
8106       num_entries = stream->n_composition_times;
8107
8108       stream->cslg_shift = 0;
8109
8110       for (i = 0; i < num_entries; i++) {
8111         gint32 offset;
8112
8113         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8114         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8115
8116         if (offset < cslg_least)
8117           cslg_least = offset;
8118       }
8119
8120       if (cslg_least < 0)
8121         stream->cslg_shift = ABS (cslg_least);
8122       else
8123         stream->cslg_shift = 0;
8124
8125       /* reset the reader so we can generate sample table */
8126       gst_byte_reader_set_pos (&stream->ctts, pos);
8127     }
8128   } else {
8129     /* Ensure the cslg_shift value is consistent so we can use it
8130      * unconditionnally to produce TS and Segment */
8131     stream->cslg_shift = 0;
8132   }
8133
8134   return TRUE;
8135
8136 corrupt_file:
8137   {
8138     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8139         (_("This file is corrupt and cannot be played.")), (NULL));
8140     return FALSE;
8141   }
8142 no_samples:
8143   {
8144     gst_qtdemux_stbl_free (stream);
8145     if (!qtdemux->fragmented) {
8146       /* not quite good */
8147       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8148       return FALSE;
8149     } else {
8150       /* may pick up samples elsewhere */
8151       return TRUE;
8152     }
8153   }
8154 }
8155
8156 /* collect samples from the next sample to be parsed up to sample @n for @stream
8157  * by reading the info from @stbl
8158  *
8159  * This code can be executed from both the streaming thread and the seeking
8160  * thread so it takes the object lock to protect itself
8161  */
8162 static gboolean
8163 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8164 {
8165   gint i, j, k;
8166   QtDemuxSample *samples, *first, *cur, *last;
8167   guint32 n_samples_per_chunk;
8168   guint32 n_samples;
8169
8170   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8171       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8172       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8173
8174   n_samples = stream->n_samples;
8175
8176   if (n >= n_samples)
8177     goto out_of_samples;
8178
8179   GST_OBJECT_LOCK (qtdemux);
8180   if (n <= stream->stbl_index)
8181     goto already_parsed;
8182
8183   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8184
8185   if (!stream->stsz.data) {
8186     /* so we already parsed and passed all the moov samples;
8187      * onto fragmented ones */
8188     g_assert (qtdemux->fragmented);
8189     goto done;
8190   }
8191
8192   /* pointer to the sample table */
8193   samples = stream->samples;
8194
8195   /* starts from -1, moves to the next sample index to parse */
8196   stream->stbl_index++;
8197
8198   /* keep track of the first and last sample to fill */
8199   first = &samples[stream->stbl_index];
8200   last = &samples[n];
8201
8202   if (!stream->chunks_are_samples) {
8203     /* set the sample sizes */
8204     if (stream->sample_size == 0) {
8205       /* different sizes for each sample */
8206       for (cur = first; cur <= last; cur++) {
8207         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8208         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8209             (guint) (cur - samples), cur->size);
8210       }
8211     } else {
8212       /* samples have the same size */
8213       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8214       for (cur = first; cur <= last; cur++)
8215         cur->size = stream->sample_size;
8216     }
8217   }
8218
8219   n_samples_per_chunk = stream->n_samples_per_chunk;
8220   cur = first;
8221
8222   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8223     guint32 last_chunk;
8224
8225     if (stream->stsc_chunk_index >= stream->last_chunk
8226         || stream->stsc_chunk_index < stream->first_chunk) {
8227       stream->first_chunk =
8228           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8229       stream->samples_per_chunk =
8230           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8231       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8232
8233       /* chunk numbers are counted from 1 it seems */
8234       if (G_UNLIKELY (stream->first_chunk == 0))
8235         goto corrupt_file;
8236
8237       --stream->first_chunk;
8238
8239       /* the last chunk of each entry is calculated by taking the first chunk
8240        * of the next entry; except if there is no next, where we fake it with
8241        * INT_MAX */
8242       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8243         stream->last_chunk = G_MAXUINT32;
8244       } else {
8245         stream->last_chunk =
8246             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8247         if (G_UNLIKELY (stream->last_chunk == 0))
8248           goto corrupt_file;
8249
8250         --stream->last_chunk;
8251       }
8252
8253       GST_LOG_OBJECT (qtdemux,
8254           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8255           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8256
8257       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8258         goto corrupt_file;
8259
8260       if (stream->last_chunk != G_MAXUINT32) {
8261         if (!qt_atom_parser_peek_sub (&stream->stco,
8262                 stream->first_chunk * stream->co_size,
8263                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8264                 &stream->co_chunk))
8265           goto corrupt_file;
8266
8267       } else {
8268         stream->co_chunk = stream->stco;
8269         if (!gst_byte_reader_skip (&stream->co_chunk,
8270                 stream->first_chunk * stream->co_size))
8271           goto corrupt_file;
8272       }
8273
8274       stream->stsc_chunk_index = stream->first_chunk;
8275     }
8276
8277     last_chunk = stream->last_chunk;
8278
8279     if (stream->chunks_are_samples) {
8280       cur = &samples[stream->stsc_chunk_index];
8281
8282       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8283         if (j > n) {
8284           /* save state */
8285           stream->stsc_chunk_index = j;
8286           goto done;
8287         }
8288
8289         cur->offset =
8290             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8291             stream->co_size);
8292
8293         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8294             "%" G_GUINT64_FORMAT, j, cur->offset);
8295
8296         if (stream->samples_per_frame * stream->bytes_per_frame) {
8297           cur->size =
8298               (stream->samples_per_chunk * stream->n_channels) /
8299               stream->samples_per_frame * stream->bytes_per_frame;
8300         } else {
8301           cur->size = stream->samples_per_chunk;
8302         }
8303
8304         GST_DEBUG_OBJECT (qtdemux,
8305             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8306             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8307                     stream->stco_sample_index)), cur->size);
8308
8309         cur->timestamp = stream->stco_sample_index;
8310         cur->duration = stream->samples_per_chunk;
8311         cur->keyframe = TRUE;
8312         cur++;
8313
8314         stream->stco_sample_index += stream->samples_per_chunk;
8315       }
8316       stream->stsc_chunk_index = j;
8317     } else {
8318       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8319         guint32 samples_per_chunk;
8320         guint64 chunk_offset;
8321
8322         if (!stream->stsc_sample_index
8323             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8324                 &stream->chunk_offset))
8325           goto corrupt_file;
8326
8327         samples_per_chunk = stream->samples_per_chunk;
8328         chunk_offset = stream->chunk_offset;
8329
8330         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8331           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8332               G_GUINT64_FORMAT " and size %d",
8333               (guint) (cur - samples), chunk_offset, cur->size);
8334
8335           cur->offset = chunk_offset;
8336           chunk_offset += cur->size;
8337           cur++;
8338
8339           if (G_UNLIKELY (cur > last)) {
8340             /* save state */
8341             stream->stsc_sample_index = k + 1;
8342             stream->chunk_offset = chunk_offset;
8343             stream->stsc_chunk_index = j;
8344             goto done2;
8345           }
8346         }
8347         stream->stsc_sample_index = 0;
8348       }
8349       stream->stsc_chunk_index = j;
8350     }
8351     stream->stsc_index++;
8352   }
8353
8354   if (stream->chunks_are_samples)
8355     goto ctts;
8356 done2:
8357   {
8358     guint32 n_sample_times;
8359
8360     n_sample_times = stream->n_sample_times;
8361     cur = first;
8362
8363     for (i = stream->stts_index; i < n_sample_times; i++) {
8364       guint32 stts_samples;
8365       gint32 stts_duration;
8366       gint64 stts_time;
8367
8368       if (stream->stts_sample_index >= stream->stts_samples
8369           || !stream->stts_sample_index) {
8370
8371         stream->stts_samples =
8372             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8373         stream->stts_duration =
8374             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8375
8376         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8377             i, stream->stts_samples, stream->stts_duration);
8378
8379         stream->stts_sample_index = 0;
8380       }
8381
8382       stts_samples = stream->stts_samples;
8383       stts_duration = stream->stts_duration;
8384       stts_time = stream->stts_time;
8385
8386       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8387         GST_DEBUG_OBJECT (qtdemux,
8388             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8389             (guint) (cur - samples), j,
8390             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8391
8392         cur->timestamp = stts_time;
8393         cur->duration = stts_duration;
8394
8395         /* avoid 32-bit wrap-around,
8396          * but still mind possible 'negative' duration */
8397         stts_time += (gint64) stts_duration;
8398         cur++;
8399
8400         if (G_UNLIKELY (cur > last)) {
8401           /* save values */
8402           stream->stts_time = stts_time;
8403           stream->stts_sample_index = j + 1;
8404           goto done3;
8405         }
8406       }
8407       stream->stts_sample_index = 0;
8408       stream->stts_time = stts_time;
8409       stream->stts_index++;
8410     }
8411     /* fill up empty timestamps with the last timestamp, this can happen when
8412      * the last samples do not decode and so we don't have timestamps for them.
8413      * We however look at the last timestamp to estimate the track length so we
8414      * need something in here. */
8415     for (; cur < last; cur++) {
8416       GST_DEBUG_OBJECT (qtdemux,
8417           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8418           (guint) (cur - samples),
8419           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8420       cur->timestamp = stream->stts_time;
8421       cur->duration = -1;
8422     }
8423   }
8424 done3:
8425   {
8426     /* sample sync, can be NULL */
8427     if (stream->stss_present == TRUE) {
8428       guint32 n_sample_syncs;
8429
8430       n_sample_syncs = stream->n_sample_syncs;
8431
8432       if (!n_sample_syncs) {
8433         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8434         stream->all_keyframe = TRUE;
8435       } else {
8436         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8437           /* note that the first sample is index 1, not 0 */
8438           guint32 index;
8439
8440           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8441
8442           if (G_LIKELY (index > 0 && index <= n_samples)) {
8443             index -= 1;
8444             samples[index].keyframe = TRUE;
8445             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8446             /* and exit if we have enough samples */
8447             if (G_UNLIKELY (index >= n)) {
8448               i++;
8449               break;
8450             }
8451           }
8452         }
8453         /* save state */
8454         stream->stss_index = i;
8455       }
8456
8457       /* stps marks partial sync frames like open GOP I-Frames */
8458       if (stream->stps_present == TRUE) {
8459         guint32 n_sample_partial_syncs;
8460
8461         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8462
8463         /* if there are no entries, the stss table contains the real
8464          * sync samples */
8465         if (n_sample_partial_syncs) {
8466           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8467             /* note that the first sample is index 1, not 0 */
8468             guint32 index;
8469
8470             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8471
8472             if (G_LIKELY (index > 0 && index <= n_samples)) {
8473               index -= 1;
8474               samples[index].keyframe = TRUE;
8475               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8476               /* and exit if we have enough samples */
8477               if (G_UNLIKELY (index >= n)) {
8478                 i++;
8479                 break;
8480               }
8481             }
8482           }
8483           /* save state */
8484           stream->stps_index = i;
8485         }
8486       }
8487     } else {
8488       /* no stss, all samples are keyframes */
8489       stream->all_keyframe = TRUE;
8490       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8491     }
8492   }
8493
8494 ctts:
8495   /* composition time to sample */
8496   if (stream->ctts_present == TRUE) {
8497     guint32 n_composition_times;
8498     guint32 ctts_count;
8499     gint32 ctts_soffset;
8500
8501     /* Fill in the pts_offsets */
8502     cur = first;
8503     n_composition_times = stream->n_composition_times;
8504
8505     for (i = stream->ctts_index; i < n_composition_times; i++) {
8506       if (stream->ctts_sample_index >= stream->ctts_count
8507           || !stream->ctts_sample_index) {
8508         stream->ctts_count =
8509             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8510         stream->ctts_soffset =
8511             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8512         stream->ctts_sample_index = 0;
8513       }
8514
8515       ctts_count = stream->ctts_count;
8516       ctts_soffset = stream->ctts_soffset;
8517
8518       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8519         cur->pts_offset = ctts_soffset;
8520         cur++;
8521
8522         if (G_UNLIKELY (cur > last)) {
8523           /* save state */
8524           stream->ctts_sample_index = j + 1;
8525           goto done;
8526         }
8527       }
8528       stream->ctts_sample_index = 0;
8529       stream->ctts_index++;
8530     }
8531   }
8532 done:
8533   stream->stbl_index = n;
8534   /* if index has been completely parsed, free data that is no-longer needed */
8535   if (n + 1 == stream->n_samples) {
8536     gst_qtdemux_stbl_free (stream);
8537     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8538     if (qtdemux->pullbased) {
8539       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8540       while (n + 1 == stream->n_samples)
8541         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8542           break;
8543     }
8544   }
8545   GST_OBJECT_UNLOCK (qtdemux);
8546
8547   return TRUE;
8548
8549   /* SUCCESS */
8550 already_parsed:
8551   {
8552     GST_LOG_OBJECT (qtdemux,
8553         "Tried to parse up to sample %u but this sample has already been parsed",
8554         n);
8555     /* if fragmented, there may be more */
8556     if (qtdemux->fragmented && n == stream->stbl_index)
8557       goto done;
8558     GST_OBJECT_UNLOCK (qtdemux);
8559     return TRUE;
8560   }
8561   /* ERRORS */
8562 out_of_samples:
8563   {
8564     GST_LOG_OBJECT (qtdemux,
8565         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8566         stream->n_samples);
8567     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8568         (_("This file is corrupt and cannot be played.")), (NULL));
8569     return FALSE;
8570   }
8571 corrupt_file:
8572   {
8573     GST_OBJECT_UNLOCK (qtdemux);
8574     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8575         (_("This file is corrupt and cannot be played.")), (NULL));
8576     return FALSE;
8577   }
8578 }
8579
8580 /* collect all segment info for @stream.
8581  */
8582 static gboolean
8583 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8584     GNode * trak)
8585 {
8586   GNode *edts;
8587   /* accept edts if they contain gaps at start and there is only
8588    * one media segment */
8589   gboolean allow_pushbased_edts = TRUE;
8590   gint media_segments_count = 0;
8591
8592   /* parse and prepare segment info from the edit list */
8593   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8594   stream->n_segments = 0;
8595   stream->segments = NULL;
8596   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8597     GNode *elst;
8598     gint n_segments;
8599     gint i, count, entry_size;
8600     guint64 time;
8601     GstClockTime stime;
8602     guint8 *buffer;
8603     guint8 version;
8604
8605     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8606     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8607       goto done;
8608
8609     buffer = elst->data;
8610
8611     version = QT_UINT8 (buffer + 8);
8612     entry_size = (version == 1) ? 20 : 12;
8613
8614     n_segments = QT_UINT32 (buffer + 12);
8615
8616     /* we might allocate a bit too much, at least allocate 1 segment */
8617     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8618
8619     /* segments always start from 0 */
8620     time = 0;
8621     stime = 0;
8622     count = 0;
8623     for (i = 0; i < n_segments; i++) {
8624       guint64 duration;
8625       guint64 media_time;
8626       gboolean time_valid = TRUE;
8627       QtDemuxSegment *segment;
8628       guint32 rate_int;
8629       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8630
8631       if (version == 1) {
8632         media_time = QT_UINT64 (buffer + 24 + i * entry_size);
8633         duration = QT_UINT64 (buffer + 16 + i * entry_size);
8634         if (media_time == G_MAXUINT64)
8635           time_valid = FALSE;
8636       } else {
8637         media_time = QT_UINT32 (buffer + 20 + i * entry_size);
8638         duration = QT_UINT32 (buffer + 16 + i * entry_size);
8639         if (media_time == G_MAXUINT32)
8640           time_valid = FALSE;
8641       }
8642
8643       if (time_valid)
8644         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8645
8646       segment = &stream->segments[count++];
8647
8648       /* time and duration expressed in global timescale */
8649       segment->time = stime;
8650       /* add non scaled values so we don't cause roundoff errors */
8651       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8652         time += duration;
8653         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8654         segment->duration = stime - segment->time;
8655       } else {
8656         /* zero duration does not imply media_start == media_stop
8657          * but, only specify media_start.*/
8658         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8659         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8660             && stime >= media_start) {
8661           segment->duration = stime - media_start;
8662         } else {
8663           segment->duration = GST_CLOCK_TIME_NONE;
8664         }
8665       }
8666       segment->stop_time = stime;
8667
8668       segment->trak_media_start = media_time;
8669       /* media_time expressed in stream timescale */
8670       if (time_valid) {
8671         segment->media_start = media_start;
8672         segment->media_stop = segment->media_start + segment->duration;
8673         media_segments_count++;
8674       } else {
8675         segment->media_start = GST_CLOCK_TIME_NONE;
8676         segment->media_stop = GST_CLOCK_TIME_NONE;
8677       }
8678       rate_int =
8679           QT_UINT32 (buffer + ((version == 1) ? 32 : 24) + i * entry_size);
8680
8681       if (rate_int <= 1) {
8682         /* 0 is not allowed, some programs write 1 instead of the floating point
8683          * value */
8684         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8685             rate_int);
8686         segment->rate = 1;
8687       } else {
8688         segment->rate = rate_int / 65536.0;
8689       }
8690
8691       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8692           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8693           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8694           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8695           i, GST_TIME_ARGS (segment->time),
8696           GST_TIME_ARGS (segment->duration),
8697           GST_TIME_ARGS (segment->media_start), media_time,
8698           GST_TIME_ARGS (segment->media_stop),
8699           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8700           stream->timescale);
8701       if (segment->stop_time > qtdemux->segment.stop) {
8702         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8703             " extends to %" GST_TIME_FORMAT
8704             " past the end of the file duration %" GST_TIME_FORMAT
8705             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8706             GST_TIME_ARGS (qtdemux->segment.stop));
8707         qtdemux->segment.stop = segment->stop_time;
8708       }
8709     }
8710     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8711     stream->n_segments = count;
8712     if (media_segments_count != 1)
8713       allow_pushbased_edts = FALSE;
8714   }
8715 done:
8716
8717   /* push based does not handle segments, so act accordingly here,
8718    * and warn if applicable */
8719   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8720     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8721     /* remove and use default one below, we stream like it anyway */
8722     g_free (stream->segments);
8723     stream->segments = NULL;
8724     stream->n_segments = 0;
8725   }
8726
8727   /* no segments, create one to play the complete trak */
8728   if (stream->n_segments == 0) {
8729     GstClockTime stream_duration =
8730         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8731
8732     if (stream->segments == NULL)
8733       stream->segments = g_new (QtDemuxSegment, 1);
8734
8735     /* represent unknown our way */
8736     if (stream_duration == 0)
8737       stream_duration = GST_CLOCK_TIME_NONE;
8738
8739     stream->segments[0].time = 0;
8740     stream->segments[0].stop_time = stream_duration;
8741     stream->segments[0].duration = stream_duration;
8742     stream->segments[0].media_start = 0;
8743     stream->segments[0].media_stop = stream_duration;
8744     stream->segments[0].rate = 1.0;
8745     stream->segments[0].trak_media_start = 0;
8746
8747     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8748         GST_TIME_ARGS (stream_duration));
8749     stream->n_segments = 1;
8750     stream->dummy_segment = TRUE;
8751   }
8752   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8753
8754   return TRUE;
8755 }
8756
8757 /*
8758  * Parses the stsd atom of a svq3 trak looking for
8759  * the SMI and gama atoms.
8760  */
8761 static void
8762 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8763     guint8 ** gamma, GstBuffer ** seqh)
8764 {
8765   guint8 *_gamma = NULL;
8766   GstBuffer *_seqh = NULL;
8767   guint8 *stsd_data = stsd->data;
8768   guint32 length = QT_UINT32 (stsd_data);
8769   guint16 version;
8770
8771   if (length < 32) {
8772     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8773     goto end;
8774   }
8775
8776   stsd_data += 32;
8777   length -= 32;
8778   version = QT_UINT16 (stsd_data);
8779   if (version == 3) {
8780     if (length >= 70) {
8781       length -= 70;
8782       stsd_data += 70;
8783       while (length > 8) {
8784         guint32 fourcc, size;
8785         guint8 *data;
8786         size = QT_UINT32 (stsd_data);
8787         fourcc = QT_FOURCC (stsd_data + 4);
8788         data = stsd_data + 8;
8789
8790         if (size == 0) {
8791           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8792               "svq3 atom parsing");
8793           goto end;
8794         }
8795
8796         switch (fourcc) {
8797           case FOURCC_gama:{
8798             if (size == 12) {
8799               _gamma = data;
8800             } else {
8801               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8802                   " for gama atom, expected 12", size);
8803             }
8804             break;
8805           }
8806           case FOURCC_SMI_:{
8807             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8808               guint32 seqh_size;
8809               if (_seqh != NULL) {
8810                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8811                     " found, ignoring");
8812               } else {
8813                 seqh_size = QT_UINT32 (data + 4);
8814                 if (seqh_size > 0) {
8815                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8816                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8817                 }
8818               }
8819             }
8820             break;
8821           }
8822           default:{
8823             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8824                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8825           }
8826         }
8827
8828         if (size <= length) {
8829           length -= size;
8830           stsd_data += size;
8831         }
8832       }
8833     } else {
8834       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8835     }
8836   } else {
8837     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8838         G_GUINT16_FORMAT, version);
8839     goto end;
8840   }
8841
8842 end:
8843   if (gamma) {
8844     *gamma = _gamma;
8845   }
8846   if (seqh) {
8847     *seqh = _seqh;
8848   } else if (_seqh) {
8849     gst_buffer_unref (_seqh);
8850   }
8851 }
8852
8853 static gchar *
8854 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8855 {
8856   GNode *dinf;
8857   GstByteReader dref;
8858   gchar *uri = NULL;
8859
8860   /*
8861    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8862    * atom that might contain a 'data' atom with the rtsp uri.
8863    * This case was reported in bug #597497, some info about
8864    * the hndl atom can be found in TN1195
8865    */
8866   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8867   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8868
8869   if (dinf) {
8870     guint32 dref_num_entries = 0;
8871     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8872         gst_byte_reader_skip (&dref, 4) &&
8873         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8874       gint i;
8875
8876       /* search dref entries for hndl atom */
8877       for (i = 0; i < dref_num_entries; i++) {
8878         guint32 size = 0, type;
8879         guint8 string_len = 0;
8880         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8881             qt_atom_parser_get_fourcc (&dref, &type)) {
8882           if (type == FOURCC_hndl) {
8883             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8884
8885             /* skip data reference handle bytes and the
8886              * following pascal string and some extra 4
8887              * bytes I have no idea what are */
8888             if (!gst_byte_reader_skip (&dref, 4) ||
8889                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8890                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8891               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8892               break;
8893             }
8894
8895             /* iterate over the atoms to find the data atom */
8896             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8897               guint32 atom_size;
8898               guint32 atom_type;
8899
8900               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8901                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8902                 if (atom_type == FOURCC_data) {
8903                   const guint8 *uri_aux = NULL;
8904
8905                   /* found the data atom that might contain the rtsp uri */
8906                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8907                       "hndl atom, interpreting it as an URI");
8908                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8909                           &uri_aux)) {
8910                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8911                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8912                     else
8913                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8914                           "didn't contain a rtsp address");
8915                   } else {
8916                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8917                         "atom contents");
8918                   }
8919                   break;
8920                 }
8921                 /* skipping to the next entry */
8922                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8923                   break;
8924               } else {
8925                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8926                     "atom header");
8927                 break;
8928               }
8929             }
8930             break;
8931           }
8932           /* skip to the next entry */
8933           if (!gst_byte_reader_skip (&dref, size - 8))
8934             break;
8935         } else {
8936           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8937         }
8938       }
8939       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8940     }
8941   }
8942   return uri;
8943 }
8944
8945 #define AMR_NB_ALL_MODES        0x81ff
8946 #define AMR_WB_ALL_MODES        0x83ff
8947 static guint
8948 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8949 {
8950   /* The 'damr' atom is of the form:
8951    *
8952    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8953    *    32 b       8 b          16 b           8 b                 8 b
8954    *
8955    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8956    * represents the highest mode used in the stream (and thus the maximum
8957    * bitrate), with a couple of special cases as seen below.
8958    */
8959
8960   /* Map of frame type ID -> bitrate */
8961   static const guint nb_bitrates[] = {
8962     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8963   };
8964   static const guint wb_bitrates[] = {
8965     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8966   };
8967   GstMapInfo map;
8968   gsize max_mode;
8969   guint16 mode_set;
8970
8971   gst_buffer_map (buf, &map, GST_MAP_READ);
8972
8973   if (map.size != 0x11) {
8974     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8975     goto bad_data;
8976   }
8977
8978   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8979     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8980         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8981     goto bad_data;
8982   }
8983
8984   mode_set = QT_UINT16 (map.data + 13);
8985
8986   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8987     max_mode = 7 + (wb ? 1 : 0);
8988   else
8989     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8990     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8991
8992   if (max_mode == -1) {
8993     GST_DEBUG ("No mode indication was found (mode set) = %x",
8994         (guint) mode_set);
8995     goto bad_data;
8996   }
8997
8998   gst_buffer_unmap (buf, &map);
8999   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9000
9001 bad_data:
9002   gst_buffer_unmap (buf, &map);
9003   return 0;
9004 }
9005
9006 static gboolean
9007 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9008     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9009 {
9010   /*
9011    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9012    * [0 1 2]
9013    * [3 4 5]
9014    * [6 7 8]
9015    */
9016
9017   if (gst_byte_reader_get_remaining (reader) < 36)
9018     return FALSE;
9019
9020   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9021   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9022   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9023   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9024   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9025   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9026   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9027   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9028   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9029
9030   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9031   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9032       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9033       matrix[2] & 0xFF);
9034   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9035       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9036       matrix[5] & 0xFF);
9037   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9038       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9039       matrix[8] & 0xFF);
9040
9041   return TRUE;
9042 }
9043
9044 static void
9045 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9046     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9047 {
9048
9049 /* [a b c]
9050  * [d e f]
9051  * [g h i]
9052  *
9053  * This macro will only compare value abdegh, it expects cfi to have already
9054  * been checked
9055  */
9056 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9057                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9058
9059   /* only handle the cases where the last column has standard values */
9060   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9061     const gchar *rotation_tag = NULL;
9062
9063     /* no rotation needed */
9064     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9065       /* NOP */
9066     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9067       rotation_tag = "rotate-90";
9068     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9069       rotation_tag = "rotate-180";
9070     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9071       rotation_tag = "rotate-270";
9072     } else {
9073       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9074     }
9075
9076     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9077         rotation_tag);
9078     if (rotation_tag != NULL) {
9079       if (*taglist == NULL)
9080         *taglist = gst_tag_list_new_empty ();
9081       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9082           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9083     }
9084   } else {
9085     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9086   }
9087 }
9088
9089 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9090  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9091  * Common Encryption (cenc), the function will also parse the tenc box (defined
9092  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9093  * (typically an enc[v|a|t|s] sample entry); the function will set
9094  * @original_fmt to the fourcc of the original unencrypted stream format.
9095  * Returns TRUE if successful; FALSE otherwise. */
9096 static gboolean
9097 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9098     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9099 {
9100   GNode *sinf;
9101   GNode *frma;
9102   GNode *schm;
9103   GNode *schi;
9104
9105   g_return_val_if_fail (qtdemux != NULL, FALSE);
9106   g_return_val_if_fail (stream != NULL, FALSE);
9107   g_return_val_if_fail (container != NULL, FALSE);
9108   g_return_val_if_fail (original_fmt != NULL, FALSE);
9109
9110   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9111   if (G_UNLIKELY (!sinf)) {
9112     if (stream->protection_scheme_type == FOURCC_cenc) {
9113       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9114           "mandatory for Common Encryption");
9115       return FALSE;
9116     }
9117     return TRUE;
9118   }
9119
9120   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9121   if (G_UNLIKELY (!frma)) {
9122     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9123     return FALSE;
9124   }
9125
9126   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9127   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9128       GST_FOURCC_ARGS (*original_fmt));
9129
9130   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9131   if (!schm) {
9132     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9133     return FALSE;
9134   }
9135   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9136   stream->protection_scheme_version =
9137       QT_UINT32 ((const guint8 *) schm->data + 16);
9138
9139   GST_DEBUG_OBJECT (qtdemux,
9140       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9141       "protection_scheme_version: %#010x",
9142       GST_FOURCC_ARGS (stream->protection_scheme_type),
9143       stream->protection_scheme_version);
9144
9145   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9146   if (!schi) {
9147     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9148     return FALSE;
9149   }
9150   if (stream->protection_scheme_type == FOURCC_cenc) {
9151     QtDemuxCencSampleSetInfo *info;
9152     GNode *tenc;
9153     const guint8 *tenc_data;
9154     guint32 isEncrypted;
9155     guint8 iv_size;
9156     const guint8 *default_kid;
9157     GstBuffer *kid_buf;
9158
9159     if (G_UNLIKELY (!stream->protection_scheme_info))
9160       stream->protection_scheme_info =
9161           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9162
9163     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9164
9165     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9166     if (!tenc) {
9167       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9168           "which is mandatory for Common Encryption");
9169       return FALSE;
9170     }
9171     tenc_data = (const guint8 *) tenc->data + 12;
9172     isEncrypted = QT_UINT24 (tenc_data);
9173     iv_size = QT_UINT8 (tenc_data + 3);
9174     default_kid = (tenc_data + 4);
9175     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9176     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9177     if (info->default_properties)
9178       gst_structure_free (info->default_properties);
9179     info->default_properties =
9180         gst_structure_new ("application/x-cenc",
9181         "iv_size", G_TYPE_UINT, iv_size,
9182         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9183         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9184     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9185         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9186     gst_buffer_unref (kid_buf);
9187   }
9188   return TRUE;
9189 }
9190
9191 /* parse the traks.
9192  * With each track we associate a new QtDemuxStream that contains all the info
9193  * about the trak.
9194  * traks that do not decode to something (like strm traks) will not have a pad.
9195  */
9196 static gboolean
9197 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9198 {
9199   GstByteReader tkhd;
9200   int offset;
9201   GNode *mdia;
9202   GNode *mdhd;
9203   GNode *hdlr;
9204   GNode *minf;
9205   GNode *stbl;
9206   GNode *stsd;
9207   GNode *mp4a;
9208   GNode *mp4v;
9209   GNode *wave;
9210   GNode *esds;
9211   GNode *pasp;
9212   GNode *colr;
9213   GNode *tref;
9214   GNode *udta;
9215   GNode *svmi;
9216
9217   QtDemuxStream *stream = NULL;
9218   gboolean new_stream = FALSE;
9219   gchar *codec = NULL;
9220   const guint8 *stsd_data;
9221   guint16 lang_code;            /* quicktime lang code or packed iso code */
9222   guint32 version;
9223   guint32 tkhd_flags = 0;
9224   guint8 tkhd_version = 0;
9225   guint32 fourcc;
9226   guint value_size, stsd_len, len;
9227   guint32 track_id;
9228   guint32 dummy;
9229
9230   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9231
9232   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9233       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9234       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9235     goto corrupt_file;
9236
9237   /* pick between 64 or 32 bits */
9238   value_size = tkhd_version == 1 ? 8 : 4;
9239   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9240       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9241     goto corrupt_file;
9242
9243   if (!qtdemux->got_moov) {
9244     if (qtdemux_find_stream (qtdemux, track_id))
9245       goto existing_stream;
9246     stream = _create_stream ();
9247     stream->track_id = track_id;
9248     new_stream = TRUE;
9249   } else {
9250     stream = qtdemux_find_stream (qtdemux, track_id);
9251     if (!stream) {
9252       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9253       goto skip_track;
9254     }
9255
9256     /* flush samples data from this track from previous moov */
9257     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9258     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9259   }
9260   /* need defaults for fragments */
9261   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9262
9263   if (stream->pending_tags == NULL)
9264     stream->pending_tags = gst_tag_list_new_empty ();
9265
9266   if ((tkhd_flags & 1) == 0)
9267     stream->disabled = TRUE;
9268
9269   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9270       tkhd_version, tkhd_flags, stream->track_id);
9271
9272   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9273     goto corrupt_file;
9274
9275   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9276     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9277     if (qtdemux->major_brand != FOURCC_mjp2 ||
9278         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9279       goto corrupt_file;
9280   }
9281
9282   len = QT_UINT32 ((guint8 *) mdhd->data);
9283   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9284   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9285   if (version == 0x01000000) {
9286     if (len < 38)
9287       goto corrupt_file;
9288     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9289     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9290     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9291   } else {
9292     if (len < 30)
9293       goto corrupt_file;
9294     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9295     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9296     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9297   }
9298
9299   if (lang_code < 0x400) {
9300     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9301   } else if (lang_code == 0x7fff) {
9302     stream->lang_id[0] = 0;     /* unspecified */
9303   } else {
9304     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9305     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9306     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9307     stream->lang_id[3] = 0;
9308   }
9309
9310   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9311       stream->timescale);
9312   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9313       stream->duration);
9314   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9315       lang_code, stream->lang_id);
9316
9317   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9318     goto corrupt_file;
9319
9320   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9321     /* chapters track reference */
9322     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9323     if (chap) {
9324       gsize length = GST_READ_UINT32_BE (chap->data);
9325       if (qtdemux->chapters_track_id)
9326         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9327
9328       if (length >= 12) {
9329         qtdemux->chapters_track_id =
9330             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9331       }
9332     }
9333   }
9334
9335   /* fragmented files may have bogus duration in moov */
9336   if (!qtdemux->fragmented &&
9337       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9338     guint64 tdur1, tdur2;
9339
9340     /* don't overflow */
9341     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9342     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9343
9344     /* HACK:
9345      * some of those trailers, nowadays, have prologue images that are
9346      * themselves video tracks as well. I haven't really found a way to
9347      * identify those yet, except for just looking at their duration. */
9348     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9349       GST_WARNING_OBJECT (qtdemux,
9350           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9351           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9352           "found, assuming preview image or something; skipping track",
9353           stream->duration, stream->timescale, qtdemux->duration,
9354           qtdemux->timescale);
9355       if (new_stream)
9356         gst_qtdemux_stream_free (qtdemux, stream);
9357       return TRUE;
9358     }
9359   }
9360
9361   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9362     goto corrupt_file;
9363
9364   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9365       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9366
9367   len = QT_UINT32 ((guint8 *) hdlr->data);
9368   if (len >= 20)
9369     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9370   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9371       GST_FOURCC_ARGS (stream->subtype));
9372
9373   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9374     goto corrupt_file;
9375
9376   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9377     goto corrupt_file;
9378
9379   /*parse svmi header if existing */
9380   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9381   if (svmi) {
9382     len = QT_UINT32 ((guint8 *) svmi->data);
9383     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9384     if (!version) {
9385       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9386       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9387       guint8 frame_type, frame_layout;
9388
9389       /* MPEG-A stereo video */
9390       if (qtdemux->major_brand == FOURCC_ss02)
9391         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9392
9393       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9394       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9395       switch (frame_type) {
9396         case 0:
9397           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9398           break;
9399         case 1:
9400           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9401           break;
9402         case 2:
9403           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9404           break;
9405         case 3:
9406           /* mode 3 is primary/secondary view sequence, ie
9407            * left/right views in separate tracks. See section 7.2
9408            * of ISO/IEC 23000-11:2009 */
9409           GST_FIXME_OBJECT (qtdemux,
9410               "Implement stereo video in separate streams");
9411       }
9412
9413       if ((frame_layout & 0x1) == 0)
9414         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9415
9416       GST_LOG_OBJECT (qtdemux,
9417           "StereoVideo: composition type: %u, is_left_first: %u",
9418           frame_type, frame_layout);
9419       stream->multiview_mode = mode;
9420       stream->multiview_flags = flags;
9421     }
9422   }
9423
9424   /* parse stsd */
9425   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9426     goto corrupt_file;
9427   stsd_data = (const guint8 *) stsd->data;
9428
9429   /* stsd should at least have one entry */
9430   stsd_len = QT_UINT32 (stsd_data);
9431   if (stsd_len < 24) {
9432     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9433     if (stream->subtype == FOURCC_vivo) {
9434       if (new_stream)
9435         gst_qtdemux_stream_free (qtdemux, stream);
9436       return TRUE;
9437     } else {
9438       goto corrupt_file;
9439     }
9440   }
9441
9442   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9443
9444   /* and that entry should fit within stsd */
9445   len = QT_UINT32 (stsd_data + 16);
9446   if (len > stsd_len + 16)
9447     goto corrupt_file;
9448
9449   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9450   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9451       GST_FOURCC_ARGS (stream->fourcc));
9452   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9453
9454   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9455     goto error_encrypted;
9456
9457   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9458     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9459     stream->protected = TRUE;
9460     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9461       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9462   }
9463
9464   if (stream->subtype == FOURCC_vide) {
9465     guint32 w = 0, h = 0;
9466     gboolean gray;
9467     gint depth, palette_size, palette_count;
9468     guint32 matrix[9];
9469     guint32 *palette_data = NULL;
9470
9471     stream->sampled = TRUE;
9472
9473     /* version 1 uses some 64-bit ints */
9474     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9475       goto corrupt_file;
9476
9477     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9478       goto corrupt_file;
9479
9480     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9481         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9482       goto corrupt_file;
9483
9484     stream->display_width = w >> 16;
9485     stream->display_height = h >> 16;
9486
9487     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9488         &stream->pending_tags);
9489
9490     offset = 16;
9491     if (len < 86)
9492       goto corrupt_file;
9493
9494     stream->width = QT_UINT16 (stsd_data + offset + 32);
9495     stream->height = QT_UINT16 (stsd_data + offset + 34);
9496     stream->fps_n = 0;          /* this is filled in later */
9497     stream->fps_d = 0;          /* this is filled in later */
9498     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9499     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9500
9501     /* if color_table_id is 0, ctab atom must follow; however some files
9502      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9503      * if color table is not present we'll correct the value */
9504     if (stream->color_table_id == 0 &&
9505         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9506       stream->color_table_id = -1;
9507     }
9508
9509     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9510         stream->width, stream->height, stream->bits_per_sample,
9511         stream->color_table_id);
9512
9513     depth = stream->bits_per_sample;
9514
9515     /* more than 32 bits means grayscale */
9516     gray = (depth > 32);
9517     /* low 32 bits specify the depth  */
9518     depth &= 0x1F;
9519
9520     /* different number of palette entries is determined by depth. */
9521     palette_count = 0;
9522     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9523       palette_count = (1 << depth);
9524     palette_size = palette_count * 4;
9525
9526     if (stream->color_table_id) {
9527       switch (palette_count) {
9528         case 0:
9529           break;
9530         case 2:
9531           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9532           break;
9533         case 4:
9534           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9535           break;
9536         case 16:
9537           if (gray)
9538             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9539           else
9540             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9541           break;
9542         case 256:
9543           if (gray)
9544             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9545           else
9546             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9547           break;
9548         default:
9549           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9550               (_("The video in this file might not play correctly.")),
9551               ("unsupported palette depth %d", depth));
9552           break;
9553       }
9554     } else {
9555       gint i, j, start, end;
9556
9557       if (len < 94)
9558         goto corrupt_file;
9559
9560       /* read table */
9561       start = QT_UINT32 (stsd_data + offset + 86);
9562       palette_count = QT_UINT16 (stsd_data + offset + 90);
9563       end = QT_UINT16 (stsd_data + offset + 92);
9564
9565       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9566           start, end, palette_count);
9567
9568       if (end > 255)
9569         end = 255;
9570       if (start > end)
9571         start = end;
9572
9573       if (len < 94 + (end - start) * 8)
9574         goto corrupt_file;
9575
9576       /* palette is always the same size */
9577       palette_data = g_malloc0 (256 * 4);
9578       palette_size = 256 * 4;
9579
9580       for (j = 0, i = start; i <= end; j++, i++) {
9581         guint32 a, r, g, b;
9582
9583         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9584         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9585         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9586         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9587
9588         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9589             (g & 0xff00) | (b >> 8);
9590       }
9591     }
9592
9593     if (stream->caps)
9594       gst_caps_unref (stream->caps);
9595
9596     stream->caps =
9597         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9598     if (G_UNLIKELY (!stream->caps)) {
9599       g_free (palette_data);
9600       goto unknown_stream;
9601     }
9602
9603     if (codec) {
9604       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9605           GST_TAG_VIDEO_CODEC, codec, NULL);
9606       g_free (codec);
9607       codec = NULL;
9608     }
9609
9610
9611     if (palette_data) {
9612       GstStructure *s;
9613
9614       if (stream->rgb8_palette)
9615         gst_memory_unref (stream->rgb8_palette);
9616       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9617           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9618
9619       s = gst_caps_get_structure (stream->caps, 0);
9620
9621       /* non-raw video has a palette_data property. raw video has the palette as
9622        * an extra plane that we append to the output buffers before we push
9623        * them*/
9624       if (!gst_structure_has_name (s, "video/x-raw")) {
9625         GstBuffer *palette;
9626
9627         palette = gst_buffer_new ();
9628         gst_buffer_append_memory (palette, stream->rgb8_palette);
9629         stream->rgb8_palette = NULL;
9630
9631         gst_caps_set_simple (stream->caps, "palette_data",
9632             GST_TYPE_BUFFER, palette, NULL);
9633         gst_buffer_unref (palette);
9634       }
9635     } else if (palette_count != 0) {
9636       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9637           (NULL), ("Unsupported palette depth %d", depth));
9638     }
9639
9640     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9641         QT_UINT16 (stsd_data + offset + 48));
9642
9643     esds = NULL;
9644     pasp = NULL;
9645     colr = NULL;
9646     /* pick 'the' stsd child */
9647     if (!stream->protected)
9648       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9649     else
9650       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9651
9652     if (mp4v) {
9653       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9654       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9655       colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
9656     }
9657
9658     if (pasp) {
9659       const guint8 *pasp_data = (const guint8 *) pasp->data;
9660
9661       stream->par_w = QT_UINT32 (pasp_data + 8);
9662       stream->par_h = QT_UINT32 (pasp_data + 12);
9663     } else {
9664       stream->par_w = 0;
9665       stream->par_h = 0;
9666     }
9667
9668     if (colr) {
9669       const guint8 *colr_data = (const guint8 *) colr->data;
9670       gint len = QT_UINT32 (colr_data);
9671
9672       if (len == 19 || len == 18) {
9673         guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
9674
9675         if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
9676           guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
9677           guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
9678           guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
9679           gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
9680
9681           switch (primaries) {
9682             case 1:
9683               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
9684               break;
9685             case 5:
9686               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
9687               break;
9688             case 6:
9689               stream->colorimetry.primaries =
9690                   GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
9691               break;
9692             case 9:
9693               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
9694               break;
9695             default:
9696               break;
9697           }
9698
9699           switch (transfer_function) {
9700             case 1:
9701               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
9702               break;
9703             case 7:
9704               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
9705               break;
9706             default:
9707               break;
9708           }
9709
9710           switch (matrix) {
9711             case 1:
9712               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
9713               break;
9714             case 6:
9715               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
9716               break;
9717             case 7:
9718               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
9719               break;
9720             case 9:
9721               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
9722               break;
9723             default:
9724               break;
9725           }
9726
9727           stream->colorimetry.range =
9728               full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
9729               GST_VIDEO_COLOR_RANGE_16_235;
9730         } else {
9731           GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
9732         }
9733       } else {
9734         GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
9735       }
9736     }
9737
9738     if (esds) {
9739       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9740     } else {
9741       switch (fourcc) {
9742         case FOURCC_H264:
9743         case FOURCC_avc1:
9744         case FOURCC_avc3:
9745         {
9746           gint len = QT_UINT32 (stsd_data) - 0x66;
9747           const guint8 *avc_data = stsd_data + 0x66;
9748
9749           /* find avcC */
9750           while (len >= 0x8) {
9751             gint size;
9752
9753             if (QT_UINT32 (avc_data) <= len)
9754               size = QT_UINT32 (avc_data) - 0x8;
9755             else
9756               size = len - 0x8;
9757
9758             if (size < 1)
9759               /* No real data, so break out */
9760               break;
9761
9762             switch (QT_FOURCC (avc_data + 0x4)) {
9763               case FOURCC_avcC:
9764               {
9765                 /* parse, if found */
9766                 GstBuffer *buf;
9767
9768                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9769
9770                 /* First 4 bytes are the length of the atom, the next 4 bytes
9771                  * are the fourcc, the next 1 byte is the version, and the
9772                  * subsequent bytes are profile_tier_level structure like data. */
9773                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9774                     avc_data + 8 + 1, size - 1);
9775                 buf = gst_buffer_new_and_alloc (size);
9776                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9777                 gst_caps_set_simple (stream->caps,
9778                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9779                 gst_buffer_unref (buf);
9780
9781                 break;
9782               }
9783               case FOURCC_strf:
9784               {
9785                 GstBuffer *buf;
9786
9787                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9788
9789                 /* First 4 bytes are the length of the atom, the next 4 bytes
9790                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9791                  * next 1 byte is the version, and the
9792                  * subsequent bytes are sequence parameter set like data. */
9793
9794                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9795                 if (size > 1) {
9796                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9797                       avc_data + 8 + 40 + 1, size - 1);
9798
9799                   buf = gst_buffer_new_and_alloc (size);
9800                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9801                   gst_caps_set_simple (stream->caps,
9802                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9803                   gst_buffer_unref (buf);
9804                 }
9805                 break;
9806               }
9807               case FOURCC_btrt:
9808               {
9809                 guint avg_bitrate, max_bitrate;
9810
9811                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9812                 if (size < 12)
9813                   break;
9814
9815                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9816                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9817
9818                 if (!max_bitrate && !avg_bitrate)
9819                   break;
9820
9821                 /* Some muxers seem to swap the average and maximum bitrates
9822                  * (I'm looking at you, YouTube), so we swap for sanity. */
9823                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9824                   guint temp = avg_bitrate;
9825
9826                   avg_bitrate = max_bitrate;
9827                   max_bitrate = temp;
9828                 }
9829
9830                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9831                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9832                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9833                 }
9834                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9835                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9836                       GST_TAG_BITRATE, avg_bitrate, NULL);
9837                 }
9838
9839                 break;
9840               }
9841
9842               default:
9843                 break;
9844             }
9845
9846             len -= size + 8;
9847             avc_data += size + 8;
9848           }
9849
9850           break;
9851         }
9852         case FOURCC_H265:
9853         case FOURCC_hvc1:
9854         case FOURCC_hev1:
9855         {
9856           gint len = QT_UINT32 (stsd_data) - 0x66;
9857           const guint8 *hevc_data = stsd_data + 0x66;
9858
9859           /* find hevc */
9860           while (len >= 0x8) {
9861             gint size;
9862
9863             if (QT_UINT32 (hevc_data) <= len)
9864               size = QT_UINT32 (hevc_data) - 0x8;
9865             else
9866               size = len - 0x8;
9867
9868             if (size < 1)
9869               /* No real data, so break out */
9870               break;
9871
9872             switch (QT_FOURCC (hevc_data + 0x4)) {
9873               case FOURCC_hvcC:
9874               {
9875                 /* parse, if found */
9876                 GstBuffer *buf;
9877
9878                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9879
9880                 /* First 4 bytes are the length of the atom, the next 4 bytes
9881                  * are the fourcc, the next 1 byte is the version, and the
9882                  * subsequent bytes are sequence parameter set like data. */
9883                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9884                     (stream->caps, hevc_data + 8 + 1, size - 1);
9885
9886                 buf = gst_buffer_new_and_alloc (size);
9887                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9888                 gst_caps_set_simple (stream->caps,
9889                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9890                 gst_buffer_unref (buf);
9891                 break;
9892               }
9893               default:
9894                 break;
9895             }
9896             len -= size + 8;
9897             hevc_data += size + 8;
9898           }
9899           break;
9900         }
9901         case FOURCC_mp4v:
9902         case FOURCC_MP4V:
9903         case FOURCC_fmp4:
9904         case FOURCC_FMP4:
9905         {
9906           GNode *glbl;
9907
9908           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9909               GST_FOURCC_ARGS (fourcc));
9910
9911           /* codec data might be in glbl extension atom */
9912           glbl = mp4v ?
9913               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9914           if (glbl) {
9915             guint8 *data;
9916             GstBuffer *buf;
9917             gint len;
9918
9919             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9920             data = glbl->data;
9921             len = QT_UINT32 (data);
9922             if (len > 0x8) {
9923               len -= 0x8;
9924               buf = gst_buffer_new_and_alloc (len);
9925               gst_buffer_fill (buf, 0, data + 8, len);
9926               gst_caps_set_simple (stream->caps,
9927                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9928               gst_buffer_unref (buf);
9929             }
9930           }
9931           break;
9932         }
9933         case FOURCC_mjp2:
9934         {
9935           /* see annex I of the jpeg2000 spec */
9936           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9937           const guint8 *data;
9938           const gchar *colorspace = NULL;
9939           gint ncomp = 0;
9940           guint32 ncomp_map = 0;
9941           gint32 *comp_map = NULL;
9942           guint32 nchan_def = 0;
9943           gint32 *chan_def = NULL;
9944
9945           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9946           /* some required atoms */
9947           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9948           if (!mjp2)
9949             break;
9950           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9951           if (!jp2h)
9952             break;
9953
9954           /* number of components; redundant with info in codestream, but useful
9955              to a muxer */
9956           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9957           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9958             break;
9959           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9960
9961           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9962           if (!colr)
9963             break;
9964           GST_DEBUG_OBJECT (qtdemux, "found colr");
9965           /* extract colour space info */
9966           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9967             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9968               case 16:
9969                 colorspace = "sRGB";
9970                 break;
9971               case 17:
9972                 colorspace = "GRAY";
9973                 break;
9974               case 18:
9975                 colorspace = "sYUV";
9976                 break;
9977               default:
9978                 colorspace = NULL;
9979                 break;
9980             }
9981           }
9982           if (!colorspace)
9983             /* colr is required, and only values 16, 17, and 18 are specified,
9984                so error if we have no colorspace */
9985             break;
9986
9987           /* extract component mapping */
9988           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9989           if (cmap) {
9990             guint32 cmap_len = 0;
9991             int i;
9992             cmap_len = QT_UINT32 (cmap->data);
9993             if (cmap_len >= 8) {
9994               /* normal box, subtract off header */
9995               cmap_len -= 8;
9996               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9997               if (cmap_len % 4 == 0) {
9998                 ncomp_map = (cmap_len / 4);
9999                 comp_map = g_new0 (gint32, ncomp_map);
10000                 for (i = 0; i < ncomp_map; i++) {
10001                   guint16 cmp;
10002                   guint8 mtyp, pcol;
10003                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10004                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10005                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10006                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10007                 }
10008               }
10009             }
10010           }
10011           /* extract channel definitions */
10012           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10013           if (cdef) {
10014             guint32 cdef_len = 0;
10015             int i;
10016             cdef_len = QT_UINT32 (cdef->data);
10017             if (cdef_len >= 10) {
10018               /* normal box, subtract off header and len */
10019               cdef_len -= 10;
10020               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10021               if (cdef_len % 6 == 0) {
10022                 nchan_def = (cdef_len / 6);
10023                 chan_def = g_new0 (gint32, nchan_def);
10024                 for (i = 0; i < nchan_def; i++)
10025                   chan_def[i] = -1;
10026                 for (i = 0; i < nchan_def; i++) {
10027                   guint16 cn, typ, asoc;
10028                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10029                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10030                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10031                   if (cn < nchan_def) {
10032                     switch (typ) {
10033                       case 0:
10034                         chan_def[cn] = asoc;
10035                         break;
10036                       case 1:
10037                         chan_def[cn] = 0;       /* alpha */
10038                         break;
10039                       default:
10040                         chan_def[cn] = -typ;
10041                     }
10042                   }
10043                 }
10044               }
10045             }
10046           }
10047
10048           gst_caps_set_simple (stream->caps,
10049               "num-components", G_TYPE_INT, ncomp, NULL);
10050           gst_caps_set_simple (stream->caps,
10051               "colorspace", G_TYPE_STRING, colorspace, NULL);
10052
10053           if (comp_map) {
10054             GValue arr = { 0, };
10055             GValue elt = { 0, };
10056             int i;
10057             g_value_init (&arr, GST_TYPE_ARRAY);
10058             g_value_init (&elt, G_TYPE_INT);
10059             for (i = 0; i < ncomp_map; i++) {
10060               g_value_set_int (&elt, comp_map[i]);
10061               gst_value_array_append_value (&arr, &elt);
10062             }
10063             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10064                 "component-map", &arr);
10065             g_value_unset (&elt);
10066             g_value_unset (&arr);
10067             g_free (comp_map);
10068           }
10069
10070           if (chan_def) {
10071             GValue arr = { 0, };
10072             GValue elt = { 0, };
10073             int i;
10074             g_value_init (&arr, GST_TYPE_ARRAY);
10075             g_value_init (&elt, G_TYPE_INT);
10076             for (i = 0; i < nchan_def; i++) {
10077               g_value_set_int (&elt, chan_def[i]);
10078               gst_value_array_append_value (&arr, &elt);
10079             }
10080             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10081                 "channel-definitions", &arr);
10082             g_value_unset (&elt);
10083             g_value_unset (&arr);
10084             g_free (chan_def);
10085           }
10086
10087           /* some optional atoms */
10088           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10089           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10090
10091           /* indicate possible fields in caps */
10092           if (field) {
10093             data = (guint8 *) field->data + 8;
10094             if (*data != 1)
10095               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
10096                   (gint) * data, NULL);
10097           }
10098           /* add codec_data if provided */
10099           if (prefix) {
10100             GstBuffer *buf;
10101             gint len;
10102
10103             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10104             data = prefix->data;
10105             len = QT_UINT32 (data);
10106             if (len > 0x8) {
10107               len -= 0x8;
10108               buf = gst_buffer_new_and_alloc (len);
10109               gst_buffer_fill (buf, 0, data + 8, len);
10110               gst_caps_set_simple (stream->caps,
10111                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10112               gst_buffer_unref (buf);
10113             }
10114           }
10115           break;
10116         }
10117         case FOURCC_jpeg:
10118         {
10119           /* https://developer.apple.com/standards/qtff-2001.pdf,
10120            * page 92, "Video Sample Description", under table 3.1 */
10121           GstByteReader br;
10122
10123           const off_t compressor_offset =
10124               16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10125           const off_t min_size = compressor_offset + 32 + 2 + 2;
10126           GNode *jpeg;
10127           guint32 len;
10128           guint16 color_table_id = 0;
10129           gboolean ok;
10130
10131           GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10132
10133           /* recover information on interlaced/progressive */
10134           jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10135           if (!jpeg)
10136             break;
10137
10138           len = QT_UINT32 (jpeg->data);
10139           GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %lu", len,
10140               min_size);
10141           if (len >= min_size) {
10142             gst_byte_reader_init (&br, jpeg->data, len);
10143
10144             gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10145             gst_byte_reader_get_uint16_le (&br, &color_table_id);
10146             if (color_table_id != 0) {
10147               /* the spec says there can be concatenated chunks in the data, and we want
10148                * to find one called field. Walk through them. */
10149               off_t offset = min_size;
10150               while (offset + 8 < len) {
10151                 guint32 size, tag;
10152                 ok = gst_byte_reader_get_uint32_le (&br, &size);
10153                 ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10154                 if (!ok || size < 8) {
10155                   GST_WARNING_OBJECT (qtdemux,
10156                       "Failed to walk optional chunk list");
10157                   break;
10158                 }
10159                 GST_DEBUG_OBJECT (qtdemux,
10160                     "Found optional %4.4s chunk, size %u", (const char *) &tag,
10161                     size);
10162                 if (tag == FOURCC_fiel) {
10163                   guint8 n_fields, ordering;
10164                   gst_byte_reader_get_uint8 (&br, &n_fields);
10165                   gst_byte_reader_get_uint8 (&br, &ordering);
10166                   if (n_fields == 1 || n_fields == 2) {
10167                     GST_DEBUG_OBJECT (qtdemux,
10168                         "Found fiel tag with %u fields, ordering %u", n_fields,
10169                         ordering);
10170                     if (n_fields == 2)
10171                       gst_caps_set_simple (stream->caps, "interlace-mode",
10172                           G_TYPE_STRING, "interleaved", NULL);
10173                   } else {
10174                     GST_WARNING_OBJECT (qtdemux,
10175                         "Found fiel tag with invalid fields (%u)", n_fields);
10176                   }
10177                 }
10178                 offset += size;
10179               }
10180             } else {
10181               GST_DEBUG_OBJECT (qtdemux,
10182                   "Color table ID is 0, not trying to get interlacedness");
10183             }
10184           } else {
10185             GST_WARNING_OBJECT (qtdemux,
10186                 "Length of jpeg chunk is too small, not trying to get interlacedness");
10187           }
10188
10189           break;
10190         }
10191         case FOURCC_SVQ3:
10192         case FOURCC_VP31:
10193         {
10194           GstBuffer *buf;
10195           GstBuffer *seqh = NULL;
10196           guint8 *gamma_data = NULL;
10197           gint len = QT_UINT32 (stsd_data);
10198
10199           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10200           if (gamma_data) {
10201             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10202                 QT_FP32 (gamma_data), NULL);
10203           }
10204           if (seqh) {
10205             /* sorry for the bad name, but we don't know what this is, other
10206              * than its own fourcc */
10207             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10208                 NULL);
10209           }
10210
10211           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10212           buf = gst_buffer_new_and_alloc (len);
10213           gst_buffer_fill (buf, 0, stsd_data, len);
10214           gst_caps_set_simple (stream->caps,
10215               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10216           gst_buffer_unref (buf);
10217           break;
10218         }
10219         case FOURCC_rle_:
10220         case FOURCC_WRLE:
10221         {
10222           gst_caps_set_simple (stream->caps,
10223               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10224           break;
10225         }
10226         case FOURCC_XiTh:
10227         {
10228           GNode *xith, *xdxt;
10229
10230           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10231           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
10232           if (!xith)
10233             break;
10234
10235           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10236           if (!xdxt)
10237             break;
10238
10239           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10240           /* collect the headers and store them in a stream list so that we can
10241            * send them out first */
10242           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10243           break;
10244         }
10245         case FOURCC_ovc1:
10246         {
10247           GNode *ovc1;
10248           guint8 *ovc1_data;
10249           guint ovc1_len;
10250           GstBuffer *buf;
10251
10252           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10253           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
10254           if (!ovc1)
10255             break;
10256           ovc1_data = ovc1->data;
10257           ovc1_len = QT_UINT32 (ovc1_data);
10258           if (ovc1_len <= 198) {
10259             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10260             break;
10261           }
10262           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10263           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10264           gst_caps_set_simple (stream->caps,
10265               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10266           gst_buffer_unref (buf);
10267           break;
10268         }
10269         case FOURCC_vc_1:
10270         {
10271           gint len = QT_UINT32 (stsd_data) - 0x66;
10272           const guint8 *vc1_data = stsd_data + 0x66;
10273
10274           /* find dvc1 */
10275           while (len >= 8) {
10276             gint size;
10277
10278             if (QT_UINT32 (vc1_data) <= len)
10279               size = QT_UINT32 (vc1_data) - 8;
10280             else
10281               size = len - 8;
10282
10283             if (size < 1)
10284               /* No real data, so break out */
10285               break;
10286
10287             switch (QT_FOURCC (vc1_data + 0x4)) {
10288               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10289               {
10290                 GstBuffer *buf;
10291
10292                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10293                 buf = gst_buffer_new_and_alloc (size);
10294                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10295                 gst_caps_set_simple (stream->caps,
10296                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10297                 gst_buffer_unref (buf);
10298                 break;
10299               }
10300               default:
10301                 break;
10302             }
10303             len -= size + 8;
10304             vc1_data += size + 8;
10305           }
10306           break;
10307         }
10308         default:
10309           break;
10310       }
10311     }
10312
10313     GST_INFO_OBJECT (qtdemux,
10314         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10315         GST_FOURCC_ARGS (fourcc), stream->caps);
10316
10317   } else if (stream->subtype == FOURCC_soun) {
10318     int version, samplesize;
10319     guint16 compression_id;
10320     gboolean amrwb = FALSE;
10321
10322     offset = 32;
10323     /* sample description entry (16) + sound sample description v0 (20) */
10324     if (len < 36)
10325       goto corrupt_file;
10326
10327     version = QT_UINT32 (stsd_data + offset);
10328     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10329     samplesize = QT_UINT16 (stsd_data + offset + 10);
10330     compression_id = QT_UINT16 (stsd_data + offset + 12);
10331     stream->rate = QT_FP32 (stsd_data + offset + 16);
10332
10333     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10334     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10335         QT_UINT32 (stsd_data + offset + 4));
10336     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10337     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10338     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10339     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10340         QT_UINT16 (stsd_data + offset + 14));
10341     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10342
10343     if (compression_id == 0xfffe)
10344       stream->sampled = TRUE;
10345
10346     /* first assume uncompressed audio */
10347     stream->bytes_per_sample = samplesize / 8;
10348     stream->samples_per_frame = stream->n_channels;
10349     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10350     stream->samples_per_packet = stream->samples_per_frame;
10351     stream->bytes_per_packet = stream->bytes_per_sample;
10352
10353     offset = 52;
10354     switch (fourcc) {
10355         /* Yes, these have to be hard-coded */
10356       case FOURCC_MAC6:
10357       {
10358         stream->samples_per_packet = 6;
10359         stream->bytes_per_packet = 1;
10360         stream->bytes_per_frame = 1 * stream->n_channels;
10361         stream->bytes_per_sample = 1;
10362         stream->samples_per_frame = 6 * stream->n_channels;
10363         break;
10364       }
10365       case FOURCC_MAC3:
10366       {
10367         stream->samples_per_packet = 3;
10368         stream->bytes_per_packet = 1;
10369         stream->bytes_per_frame = 1 * stream->n_channels;
10370         stream->bytes_per_sample = 1;
10371         stream->samples_per_frame = 3 * stream->n_channels;
10372         break;
10373       }
10374       case FOURCC_ima4:
10375       {
10376         stream->samples_per_packet = 64;
10377         stream->bytes_per_packet = 34;
10378         stream->bytes_per_frame = 34 * stream->n_channels;
10379         stream->bytes_per_sample = 2;
10380         stream->samples_per_frame = 64 * stream->n_channels;
10381         break;
10382       }
10383       case FOURCC_ulaw:
10384       case FOURCC_alaw:
10385       {
10386         stream->samples_per_packet = 1;
10387         stream->bytes_per_packet = 1;
10388         stream->bytes_per_frame = 1 * stream->n_channels;
10389         stream->bytes_per_sample = 1;
10390         stream->samples_per_frame = 1 * stream->n_channels;
10391         break;
10392       }
10393       case FOURCC_agsm:
10394       {
10395         stream->samples_per_packet = 160;
10396         stream->bytes_per_packet = 33;
10397         stream->bytes_per_frame = 33 * stream->n_channels;
10398         stream->bytes_per_sample = 2;
10399         stream->samples_per_frame = 160 * stream->n_channels;
10400         break;
10401       }
10402       default:
10403         break;
10404     }
10405
10406     if (version == 0x00010000) {
10407       /* sample description entry (16) + sound sample description v1 (20+16) */
10408       if (len < 52)
10409         goto corrupt_file;
10410
10411       switch (fourcc) {
10412         case FOURCC_twos:
10413         case FOURCC_sowt:
10414         case FOURCC_raw_:
10415           break;
10416         default:
10417         {
10418           /* only parse extra decoding config for non-pcm audio */
10419           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10420           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10421           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10422           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10423
10424           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10425               stream->samples_per_packet);
10426           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10427               stream->bytes_per_packet);
10428           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10429               stream->bytes_per_frame);
10430           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10431               stream->bytes_per_sample);
10432
10433           if (!stream->sampled && stream->bytes_per_packet) {
10434             stream->samples_per_frame = (stream->bytes_per_frame /
10435                 stream->bytes_per_packet) * stream->samples_per_packet;
10436             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10437                 stream->samples_per_frame);
10438           }
10439           break;
10440         }
10441       }
10442     } else if (version == 0x00020000) {
10443       union
10444       {
10445         gdouble fp;
10446         guint64 val;
10447       } qtfp;
10448
10449       /* sample description entry (16) + sound sample description v2 (56) */
10450       if (len < 72)
10451         goto corrupt_file;
10452
10453       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10454       stream->rate = qtfp.fp;
10455       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10456
10457       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10458       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10459       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10460       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10461           QT_UINT32 (stsd_data + offset + 20));
10462       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10463           QT_UINT32 (stsd_data + offset + 24));
10464       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10465           QT_UINT32 (stsd_data + offset + 28));
10466       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10467           QT_UINT32 (stsd_data + offset + 32));
10468     } else if (version != 0x00000) {
10469       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10470     }
10471
10472     if (stream->caps)
10473       gst_caps_unref (stream->caps);
10474
10475     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10476         stsd_data + 32, len - 16, &codec);
10477
10478     switch (fourcc) {
10479       case FOURCC_in24:
10480       {
10481         GNode *enda;
10482         GNode *in24;
10483
10484         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10485
10486         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10487         if (!enda) {
10488           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10489           if (wave)
10490             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10491         }
10492         if (enda) {
10493           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10494           gst_caps_set_simple (stream->caps,
10495               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10496         }
10497         break;
10498       }
10499       case FOURCC_owma:
10500       {
10501         GNode *owma;
10502         const guint8 *owma_data;
10503         const gchar *codec_name = NULL;
10504         guint owma_len;
10505         GstBuffer *buf;
10506         gint version = 1;
10507         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10508         /* FIXME this should also be gst_riff_strf_auds,
10509          * but the latter one is actually missing bits-per-sample :( */
10510         typedef struct
10511         {
10512           gint16 wFormatTag;
10513           gint16 nChannels;
10514           gint32 nSamplesPerSec;
10515           gint32 nAvgBytesPerSec;
10516           gint16 nBlockAlign;
10517           gint16 wBitsPerSample;
10518           gint16 cbSize;
10519         } WAVEFORMATEX;
10520         WAVEFORMATEX *wfex;
10521
10522         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10523         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10524         if (!owma)
10525           break;
10526         owma_data = owma->data;
10527         owma_len = QT_UINT32 (owma_data);
10528         if (owma_len <= 54) {
10529           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10530           break;
10531         }
10532         wfex = (WAVEFORMATEX *) (owma_data + 36);
10533         buf = gst_buffer_new_and_alloc (owma_len - 54);
10534         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10535         if (wfex->wFormatTag == 0x0161) {
10536           codec_name = "Windows Media Audio";
10537           version = 2;
10538         } else if (wfex->wFormatTag == 0x0162) {
10539           codec_name = "Windows Media Audio 9 Pro";
10540           version = 3;
10541         } else if (wfex->wFormatTag == 0x0163) {
10542           codec_name = "Windows Media Audio 9 Lossless";
10543           /* is that correct? gstffmpegcodecmap.c is missing it, but
10544            * fluendo codec seems to support it */
10545           version = 4;
10546         }
10547
10548         gst_caps_set_simple (stream->caps,
10549             "codec_data", GST_TYPE_BUFFER, buf,
10550             "wmaversion", G_TYPE_INT, version,
10551             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10552             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10553             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10554             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10555             NULL);
10556         gst_buffer_unref (buf);
10557
10558         if (codec_name) {
10559           g_free (codec);
10560           codec = g_strdup (codec_name);
10561         }
10562         break;
10563       }
10564       case FOURCC_wma_:
10565       {
10566         gint len = QT_UINT32 (stsd_data) - offset;
10567         const guint8 *wfex_data = stsd_data + offset;
10568         const gchar *codec_name = NULL;
10569         gint version = 1;
10570         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10571         /* FIXME this should also be gst_riff_strf_auds,
10572          * but the latter one is actually missing bits-per-sample :( */
10573         typedef struct
10574         {
10575           gint16 wFormatTag;
10576           gint16 nChannels;
10577           gint32 nSamplesPerSec;
10578           gint32 nAvgBytesPerSec;
10579           gint16 nBlockAlign;
10580           gint16 wBitsPerSample;
10581           gint16 cbSize;
10582         } WAVEFORMATEX;
10583         WAVEFORMATEX wfex;
10584
10585         /* FIXME: unify with similar wavformatex parsing code above */
10586         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10587
10588         /* find wfex */
10589         while (len >= 8) {
10590           gint size;
10591
10592           if (QT_UINT32 (wfex_data) <= len)
10593             size = QT_UINT32 (wfex_data) - 8;
10594           else
10595             size = len - 8;
10596
10597           if (size < 1)
10598             /* No real data, so break out */
10599             break;
10600
10601           switch (QT_FOURCC (wfex_data + 4)) {
10602             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10603             {
10604               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10605
10606               if (size < 8 + 18)
10607                 break;
10608
10609               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10610               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10611               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10612               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10613               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10614               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10615               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10616
10617               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10618               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10619                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10620                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10621                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10622                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10623
10624               if (wfex.wFormatTag == 0x0161) {
10625                 codec_name = "Windows Media Audio";
10626                 version = 2;
10627               } else if (wfex.wFormatTag == 0x0162) {
10628                 codec_name = "Windows Media Audio 9 Pro";
10629                 version = 3;
10630               } else if (wfex.wFormatTag == 0x0163) {
10631                 codec_name = "Windows Media Audio 9 Lossless";
10632                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10633                  * fluendo codec seems to support it */
10634                 version = 4;
10635               }
10636
10637               gst_caps_set_simple (stream->caps,
10638                   "wmaversion", G_TYPE_INT, version,
10639                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10640                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10641                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10642                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10643
10644               if (size > wfex.cbSize) {
10645                 GstBuffer *buf;
10646
10647                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10648                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10649                     size - wfex.cbSize);
10650                 gst_caps_set_simple (stream->caps,
10651                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10652                 gst_buffer_unref (buf);
10653               } else {
10654                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10655               }
10656
10657               if (codec_name) {
10658                 g_free (codec);
10659                 codec = g_strdup (codec_name);
10660               }
10661               break;
10662             }
10663             default:
10664               break;
10665           }
10666           len -= size + 8;
10667           wfex_data += size + 8;
10668         }
10669         break;
10670       }
10671       case FOURCC_opus:
10672       {
10673         GNode *opus;
10674         const guint8 *opus_data;
10675         guint8 *channel_mapping = NULL;
10676         guint32 rate;
10677         guint8 channels;
10678         guint8 channel_mapping_family;
10679         guint8 stream_count;
10680         guint8 coupled_count;
10681         guint8 i;
10682
10683         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10684         opus_data = opus->data;
10685
10686         channels = GST_READ_UINT8 (opus_data + 45);
10687         rate = GST_READ_UINT32_LE (opus_data + 48);
10688         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10689         stream_count = GST_READ_UINT8 (opus_data + 55);
10690         coupled_count = GST_READ_UINT8 (opus_data + 56);
10691
10692         if (channels > 0) {
10693           channel_mapping = g_malloc (channels * sizeof (guint8));
10694           for (i = 0; i < channels; i++)
10695             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10696         }
10697
10698         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10699             channel_mapping_family, stream_count, coupled_count,
10700             channel_mapping);
10701         break;
10702       }
10703       default:
10704         break;
10705     }
10706
10707     if (codec) {
10708       GstStructure *s;
10709       gint bitrate = 0;
10710
10711       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10712           GST_TAG_AUDIO_CODEC, codec, NULL);
10713       g_free (codec);
10714       codec = NULL;
10715
10716       /* some bitrate info may have ended up in caps */
10717       s = gst_caps_get_structure (stream->caps, 0);
10718       gst_structure_get_int (s, "bitrate", &bitrate);
10719       if (bitrate > 0)
10720         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10721             GST_TAG_BITRATE, bitrate, NULL);
10722     }
10723
10724     if (stream->protected && fourcc == FOURCC_mp4a)
10725       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10726     else
10727       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10728
10729     wave = NULL;
10730     esds = NULL;
10731     if (mp4a) {
10732       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10733       if (wave)
10734         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10735       if (!esds)
10736         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10737     }
10738
10739
10740     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10741        16 bits is a byte-swapped wave-style codec identifier,
10742        and we can find a WAVE header internally to a 'wave' atom here.
10743        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10744        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10745        is big-endian).
10746      */
10747     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10748       if (len < offset + 20) {
10749         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10750       } else {
10751         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10752         const guint8 *data = stsd_data + offset + 16;
10753         GNode *wavenode;
10754         GNode *waveheadernode;
10755
10756         wavenode = g_node_new ((guint8 *) data);
10757         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10758           const guint8 *waveheader;
10759           guint32 headerlen;
10760
10761           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10762           if (waveheadernode) {
10763             waveheader = (const guint8 *) waveheadernode->data;
10764             headerlen = QT_UINT32 (waveheader);
10765
10766             if (headerlen > 8) {
10767               gst_riff_strf_auds *header = NULL;
10768               GstBuffer *headerbuf;
10769               GstBuffer *extra;
10770
10771               waveheader += 8;
10772               headerlen -= 8;
10773
10774               headerbuf = gst_buffer_new_and_alloc (headerlen);
10775               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10776
10777               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10778                       headerbuf, &header, &extra)) {
10779                 gst_caps_unref (stream->caps);
10780                 /* FIXME: Need to do something with the channel reorder map */
10781                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10782                     header, extra, NULL, NULL, NULL);
10783
10784                 if (extra)
10785                   gst_buffer_unref (extra);
10786                 g_free (header);
10787               }
10788             }
10789           } else
10790             GST_DEBUG ("Didn't find waveheadernode for this codec");
10791         }
10792         g_node_destroy (wavenode);
10793       }
10794     } else if (esds) {
10795       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10796     } else {
10797       switch (fourcc) {
10798 #if 0
10799           /* FIXME: what is in the chunk? */
10800         case FOURCC_QDMC:
10801         {
10802           gint len = QT_UINT32 (stsd_data);
10803
10804           /* seems to be always = 116 = 0x74 */
10805           break;
10806         }
10807 #endif
10808         case FOURCC_QDM2:
10809         {
10810           gint len = QT_UINT32 (stsd_data);
10811
10812           if (len > 0x4C) {
10813             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10814
10815             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10816             gst_caps_set_simple (stream->caps,
10817                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10818             gst_buffer_unref (buf);
10819           }
10820           gst_caps_set_simple (stream->caps,
10821               "samplesize", G_TYPE_INT, samplesize, NULL);
10822           break;
10823         }
10824         case FOURCC_alac:
10825         {
10826           GNode *alac, *wave = NULL;
10827
10828           /* apparently, m4a has this atom appended directly in the stsd entry,
10829            * while mov has it in a wave atom */
10830           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10831           if (alac) {
10832             /* alac now refers to stsd entry atom */
10833             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10834             if (wave)
10835               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10836             else
10837               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10838           }
10839           if (alac) {
10840             const guint8 *alac_data = alac->data;
10841             gint len = QT_UINT32 (alac->data);
10842             GstBuffer *buf;
10843
10844             if (len < 36) {
10845               GST_DEBUG_OBJECT (qtdemux,
10846                   "discarding alac atom with unexpected len %d", len);
10847             } else {
10848               /* codec-data contains alac atom size and prefix,
10849                * ffmpeg likes it that way, not quite gst-ish though ...*/
10850               buf = gst_buffer_new_and_alloc (len);
10851               gst_buffer_fill (buf, 0, alac->data, len);
10852               gst_caps_set_simple (stream->caps,
10853                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10854               gst_buffer_unref (buf);
10855
10856               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10857               stream->n_channels = QT_UINT8 (alac_data + 21);
10858               stream->rate = QT_UINT32 (alac_data + 32);
10859             }
10860           }
10861           gst_caps_set_simple (stream->caps,
10862               "samplesize", G_TYPE_INT, samplesize, NULL);
10863           break;
10864         }
10865         case FOURCC_fLaC:
10866         {
10867           /* The codingname of the sample entry is 'fLaC' */
10868           GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
10869
10870           if (flac) {
10871             /* The 'dfLa' box is added to the sample entry to convey
10872                initializing information for the decoder. */
10873             const GNode *dfla =
10874                 qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
10875
10876             if (dfla) {
10877               const guint32 len = QT_UINT32 (dfla->data);
10878
10879               /* Must contain at least dfLa box header (12),
10880                * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
10881               if (len < 50) {
10882                 GST_DEBUG_OBJECT (qtdemux,
10883                     "discarding dfla atom with unexpected len %d", len);
10884               } else {
10885                 /* skip dfLa header to get the METADATA_BLOCKs */
10886                 const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
10887                 const guint32 metadata_blocks_len = len - 12;
10888
10889                 gchar *stream_marker = g_strdup ("fLaC");
10890                 GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
10891                     strlen (stream_marker));
10892
10893                 guint index = 0;
10894                 gboolean is_last = FALSE;
10895
10896                 GValue array = G_VALUE_INIT;
10897                 GValue value = G_VALUE_INIT;
10898
10899                 g_value_init (&array, GST_TYPE_ARRAY);
10900                 g_value_init (&value, GST_TYPE_BUFFER);
10901
10902                 gst_value_set_buffer (&value, block);
10903                 gst_value_array_append_value (&array, &value);
10904                 g_value_reset (&value);
10905
10906                 gst_buffer_unref (block);
10907
10908                 while (is_last == FALSE && index < metadata_blocks_len) {
10909                   /* add the METADATA_BLOCK_HEADER size to the signalled size */
10910                   const guint block_size = 4 +
10911                       (metadata_blocks[index + 1] << 16) +
10912                       (metadata_blocks[index + 2] << 8) +
10913                       metadata_blocks[index + 3];
10914
10915                   is_last = metadata_blocks[index] >> 7;
10916
10917                   block = gst_buffer_new_and_alloc (block_size);
10918
10919                   gst_buffer_fill (block, 0, &metadata_blocks[index],
10920                       block_size);
10921
10922                   gst_value_set_buffer (&value, block);
10923                   gst_value_array_append_value (&array, &value);
10924                   g_value_reset (&value);
10925
10926                   gst_buffer_unref (block);
10927
10928                   index += block_size;
10929                 }
10930
10931                 gst_structure_set_value (gst_caps_get_structure (stream->caps,
10932                         0), "streamheader", &array);
10933
10934                 g_value_unset (&value);
10935                 g_value_unset (&array);
10936
10937                 /* The sample rate obtained from the stsd may not be accurate
10938                  * since it cannot represent rates greater than 65535Hz, so
10939                  * override that value with the sample rate from the
10940                  * METADATA_BLOCK_STREAMINFO block */
10941                 stream->rate =
10942                     (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
10943               }
10944             }
10945           }
10946           break;
10947         }
10948         case FOURCC_sawb:
10949           /* Fallthrough! */
10950           amrwb = TRUE;
10951         case FOURCC_samr:
10952         {
10953           gint len = QT_UINT32 (stsd_data);
10954
10955           if (len > 0x34) {
10956             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10957             guint bitrate;
10958
10959             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10960
10961             /* If we have enough data, let's try to get the 'damr' atom. See
10962              * the 3GPP container spec (26.244) for more details. */
10963             if ((len - 0x34) > 8 &&
10964                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10965               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10966                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10967             }
10968
10969             gst_caps_set_simple (stream->caps,
10970                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10971             gst_buffer_unref (buf);
10972           }
10973           break;
10974         }
10975         case FOURCC_mp4a:
10976         {
10977           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10978           gint len = QT_UINT32 (stsd_data);
10979
10980           if (len >= 50) {
10981             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10982
10983             if (sound_version == 1) {
10984               guint16 channels = QT_UINT16 (stsd_data + 40);
10985               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10986               guint8 codec_data[2];
10987               GstBuffer *buf;
10988               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10989
10990               gint sample_rate_index =
10991                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10992
10993               /* build AAC codec data */
10994               codec_data[0] = profile << 3;
10995               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10996               codec_data[1] = (sample_rate_index & 0x01) << 7;
10997               codec_data[1] |= (channels & 0xF) << 3;
10998
10999               buf = gst_buffer_new_and_alloc (2);
11000               gst_buffer_fill (buf, 0, codec_data, 2);
11001               gst_caps_set_simple (stream->caps,
11002                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11003               gst_buffer_unref (buf);
11004             }
11005           }
11006           break;
11007         }
11008         default:
11009           GST_INFO_OBJECT (qtdemux,
11010               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11011           break;
11012       }
11013     }
11014     GST_INFO_OBJECT (qtdemux,
11015         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11016         GST_FOURCC_ARGS (fourcc), stream->caps);
11017
11018   } else if (stream->subtype == FOURCC_strm) {
11019     if (fourcc == FOURCC_rtsp) {
11020       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11021     } else {
11022       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11023           GST_FOURCC_ARGS (fourcc));
11024       goto unknown_stream;
11025     }
11026     stream->sampled = TRUE;
11027   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11028       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11029
11030     stream->sampled = TRUE;
11031     stream->sparse = TRUE;
11032
11033     stream->caps =
11034         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11035     if (codec) {
11036       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11037           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11038       g_free (codec);
11039       codec = NULL;
11040     }
11041
11042     /* hunt for sort-of codec data */
11043     switch (fourcc) {
11044       case FOURCC_mp4s:
11045       {
11046         GNode *mp4s = NULL;
11047         GNode *esds = NULL;
11048
11049         /* look for palette in a stsd->mp4s->esds sub-atom */
11050         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11051         if (mp4s)
11052           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11053         if (esds == NULL) {
11054           /* Invalid STSD */
11055           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11056           break;
11057         }
11058
11059         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
11060         break;
11061       }
11062       default:
11063         GST_INFO_OBJECT (qtdemux,
11064             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11065         break;
11066     }
11067     GST_INFO_OBJECT (qtdemux,
11068         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11069         GST_FOURCC_ARGS (fourcc), stream->caps);
11070   } else {
11071     /* everything in 1 sample */
11072     stream->sampled = TRUE;
11073
11074     stream->caps =
11075         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11076
11077     if (stream->caps == NULL)
11078       goto unknown_stream;
11079
11080     if (codec) {
11081       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11082           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11083       g_free (codec);
11084       codec = NULL;
11085     }
11086   }
11087
11088   /* promote to sampled format */
11089   if (stream->fourcc == FOURCC_samr) {
11090     /* force mono 8000 Hz for AMR */
11091     stream->sampled = TRUE;
11092     stream->n_channels = 1;
11093     stream->rate = 8000;
11094   } else if (stream->fourcc == FOURCC_sawb) {
11095     /* force mono 16000 Hz for AMR-WB */
11096     stream->sampled = TRUE;
11097     stream->n_channels = 1;
11098     stream->rate = 16000;
11099   } else if (stream->fourcc == FOURCC_mp4a) {
11100     stream->sampled = TRUE;
11101   }
11102
11103   /* collect sample information */
11104   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11105     goto samples_failed;
11106
11107   if (qtdemux->fragmented) {
11108     guint64 offset;
11109
11110     /* need all moov samples as basis; probably not many if any at all */
11111     /* prevent moof parsing taking of at this time */
11112     offset = qtdemux->moof_offset;
11113     qtdemux->moof_offset = 0;
11114     if (stream->n_samples &&
11115         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11116       qtdemux->moof_offset = offset;
11117       goto samples_failed;
11118     }
11119     qtdemux->moof_offset = 0;
11120     /* movie duration more reliable in this case (e.g. mehd) */
11121     if (qtdemux->segment.duration &&
11122         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11123       stream->duration =
11124           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11125   }
11126
11127   /* configure segments */
11128   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11129     goto segments_failed;
11130
11131   /* add some language tag, if useful */
11132   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11133       strcmp (stream->lang_id, "und")) {
11134     const gchar *lang_code;
11135
11136     /* convert ISO 639-2 code to ISO 639-1 */
11137     lang_code = gst_tag_get_language_code (stream->lang_id);
11138     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11139         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11140   }
11141
11142   /* Check for UDTA tags */
11143   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11144     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
11145   }
11146
11147   /* now we are ready to add the stream */
11148   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11149     goto too_many_streams;
11150
11151   if (!qtdemux->got_moov) {
11152     qtdemux->streams[qtdemux->n_streams] = stream;
11153     qtdemux->n_streams++;
11154     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11155   }
11156
11157   return TRUE;
11158
11159 /* ERRORS */
11160 skip_track:
11161   {
11162     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11163     if (new_stream)
11164       gst_qtdemux_stream_free (qtdemux, stream);
11165     return TRUE;
11166   }
11167 corrupt_file:
11168   {
11169     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11170         (_("This file is corrupt and cannot be played.")), (NULL));
11171     if (new_stream)
11172       gst_qtdemux_stream_free (qtdemux, stream);
11173     return FALSE;
11174   }
11175 error_encrypted:
11176   {
11177     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11178     if (new_stream)
11179       gst_qtdemux_stream_free (qtdemux, stream);
11180     return FALSE;
11181   }
11182 samples_failed:
11183 segments_failed:
11184   {
11185     /* we posted an error already */
11186     /* free stbl sub-atoms */
11187     gst_qtdemux_stbl_free (stream);
11188     if (new_stream)
11189       gst_qtdemux_stream_free (qtdemux, stream);
11190     return FALSE;
11191   }
11192 existing_stream:
11193   {
11194     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11195         track_id);
11196     if (new_stream)
11197       gst_qtdemux_stream_free (qtdemux, stream);
11198     return TRUE;
11199   }
11200 unknown_stream:
11201   {
11202     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11203         GST_FOURCC_ARGS (stream->subtype));
11204     if (new_stream)
11205       gst_qtdemux_stream_free (qtdemux, stream);
11206     return TRUE;
11207   }
11208 too_many_streams:
11209   {
11210     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11211         (_("This file contains too many streams. Only playing first %d"),
11212             GST_QTDEMUX_MAX_STREAMS), (NULL));
11213     return TRUE;
11214   }
11215 }
11216
11217 /* If we can estimate the overall bitrate, and don't have information about the
11218  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11219  * the overall bitrate minus the sum of the bitrates of all other streams. This
11220  * should be useful for the common case where we have one audio and one video
11221  * stream and can estimate the bitrate of one, but not the other. */
11222 static void
11223 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11224 {
11225   QtDemuxStream *stream = NULL;
11226   gint64 size, sys_bitrate, sum_bitrate = 0;
11227   GstClockTime duration;
11228   gint i;
11229   guint bitrate;
11230
11231   if (qtdemux->fragmented)
11232     return;
11233
11234   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11235
11236   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11237       || size <= 0) {
11238     GST_DEBUG_OBJECT (qtdemux,
11239         "Size in bytes of the stream not known - bailing");
11240     return;
11241   }
11242
11243   /* Subtract the header size */
11244   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11245       size, qtdemux->header_size);
11246
11247   if (size < qtdemux->header_size)
11248     return;
11249
11250   size = size - qtdemux->header_size;
11251
11252   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11253     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11254     return;
11255   }
11256
11257   for (i = 0; i < qtdemux->n_streams; i++) {
11258     switch (qtdemux->streams[i]->subtype) {
11259       case FOURCC_soun:
11260       case FOURCC_vide:
11261         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11262             qtdemux->streams[i]->caps);
11263         /* retrieve bitrate, prefer avg then max */
11264         bitrate = 0;
11265         if (qtdemux->streams[i]->pending_tags) {
11266           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11267               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11268           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11269           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11270               GST_TAG_NOMINAL_BITRATE, &bitrate);
11271           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11272           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11273               GST_TAG_BITRATE, &bitrate);
11274           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11275         }
11276         if (bitrate)
11277           sum_bitrate += bitrate;
11278         else {
11279           if (stream) {
11280             GST_DEBUG_OBJECT (qtdemux,
11281                 ">1 stream with unknown bitrate - bailing");
11282             return;
11283           } else
11284             stream = qtdemux->streams[i];
11285         }
11286
11287       default:
11288         /* For other subtypes, we assume no significant impact on bitrate */
11289         break;
11290     }
11291   }
11292
11293   if (!stream) {
11294     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11295     return;
11296   }
11297
11298   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11299
11300   if (sys_bitrate < sum_bitrate) {
11301     /* This can happen, since sum_bitrate might be derived from maximum
11302      * bitrates and not average bitrates */
11303     GST_DEBUG_OBJECT (qtdemux,
11304         "System bitrate less than sum bitrate - bailing");
11305     return;
11306   }
11307
11308   bitrate = sys_bitrate - sum_bitrate;
11309   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11310       ", Stream bitrate = %u", sys_bitrate, bitrate);
11311
11312   if (!stream->pending_tags)
11313     stream->pending_tags = gst_tag_list_new_empty ();
11314
11315   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11316       GST_TAG_BITRATE, bitrate, NULL);
11317 }
11318
11319 static GstFlowReturn
11320 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11321 {
11322   gint i;
11323   GstFlowReturn ret = GST_FLOW_OK;
11324
11325   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11326
11327   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11328     QtDemuxStream *stream = qtdemux->streams[i];
11329     guint32 sample_num = 0;
11330
11331     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11332         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11333
11334     if (qtdemux->fragmented) {
11335       /* need all moov samples first */
11336       GST_OBJECT_LOCK (qtdemux);
11337       while (stream->n_samples == 0)
11338         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11339           break;
11340       GST_OBJECT_UNLOCK (qtdemux);
11341     } else {
11342       /* discard any stray moof */
11343       qtdemux->moof_offset = 0;
11344     }
11345
11346     /* prepare braking */
11347     if (ret != GST_FLOW_ERROR)
11348       ret = GST_FLOW_OK;
11349
11350     /* in pull mode, we should have parsed some sample info by now;
11351      * and quite some code will not handle no samples.
11352      * in push mode, we'll just have to deal with it */
11353     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11354       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11355       gst_qtdemux_remove_stream (qtdemux, i);
11356       i--;
11357       continue;
11358     }
11359
11360     /* parse the initial sample for use in setting the frame rate cap */
11361     while (sample_num == 0 && sample_num < stream->n_samples) {
11362       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11363         break;
11364       ++sample_num;
11365     }
11366     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11367       stream->first_duration = stream->samples[0].duration;
11368       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11369           stream->track_id, stream->first_duration);
11370     }
11371   }
11372
11373   return ret;
11374 }
11375
11376 static GstFlowReturn
11377 qtdemux_expose_streams (GstQTDemux * qtdemux)
11378 {
11379   gint i;
11380   GstFlowReturn ret = GST_FLOW_OK;
11381   GSList *oldpads = NULL;
11382   GSList *iter;
11383
11384   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11385
11386   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11387     QtDemuxStream *stream = qtdemux->streams[i];
11388     GstPad *oldpad = stream->pad;
11389     GstTagList *list;
11390
11391     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11392         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11393
11394     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11395         stream->track_id == qtdemux->chapters_track_id) {
11396       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11397          so that it doesn't look like a subtitle track */
11398       gst_qtdemux_remove_stream (qtdemux, i);
11399       i--;
11400       continue;
11401     }
11402
11403     /* now we have all info and can expose */
11404     list = stream->pending_tags;
11405     stream->pending_tags = NULL;
11406     if (oldpad)
11407       oldpads = g_slist_prepend (oldpads, oldpad);
11408     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11409       return GST_FLOW_ERROR;
11410   }
11411
11412   gst_qtdemux_guess_bitrate (qtdemux);
11413
11414   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11415
11416   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11417     GstPad *oldpad = iter->data;
11418     GstEvent *event;
11419
11420     event = gst_event_new_eos ();
11421     if (qtdemux->segment_seqnum)
11422       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11423
11424     gst_pad_push_event (oldpad, event);
11425     gst_pad_set_active (oldpad, FALSE);
11426     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11427     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11428     gst_object_unref (oldpad);
11429   }
11430
11431   /* check if we should post a redirect in case there is a single trak
11432    * and it is a redirecting trak */
11433   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11434     GstMessage *m;
11435
11436     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11437         "an external content");
11438     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11439         gst_structure_new ("redirect",
11440             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11441             NULL));
11442     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11443     qtdemux->posted_redirect = TRUE;
11444   }
11445
11446   for (i = 0; i < qtdemux->n_streams; i++) {
11447     QtDemuxStream *stream = qtdemux->streams[i];
11448
11449     qtdemux_do_allocation (qtdemux, stream);
11450   }
11451
11452   qtdemux->exposed = TRUE;
11453   return ret;
11454 }
11455
11456 /* check if major or compatible brand is 3GP */
11457 static inline gboolean
11458 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11459 {
11460   if (major) {
11461     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11462         FOURCC_3g__);
11463   } else if (qtdemux->comp_brands != NULL) {
11464     GstMapInfo map;
11465     guint8 *data;
11466     gsize size;
11467     gboolean res = FALSE;
11468
11469     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11470     data = map.data;
11471     size = map.size;
11472     while (size >= 4) {
11473       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11474           FOURCC_3g__);
11475       data += 4;
11476       size -= 4;
11477     }
11478     gst_buffer_unmap (qtdemux->comp_brands, &map);
11479     return res;
11480   } else {
11481     return FALSE;
11482   }
11483 }
11484
11485 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11486 static inline gboolean
11487 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11488 {
11489   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11490       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11491       || fourcc == FOURCC_albm;
11492 }
11493
11494 static void
11495 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11496     const char *tag, const char *dummy, GNode * node)
11497 {
11498   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11499   int offset;
11500   char *name;
11501   gchar *data;
11502   gdouble longitude, latitude, altitude;
11503   gint len;
11504
11505   len = QT_UINT32 (node->data);
11506   if (len <= 14)
11507     goto short_read;
11508
11509   data = node->data;
11510   offset = 14;
11511
11512   /* TODO: language code skipped */
11513
11514   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11515
11516   if (!name) {
11517     /* do not alarm in trivial case, but bail out otherwise */
11518     if (*(data + offset) != 0) {
11519       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11520           "giving up", tag);
11521     }
11522   } else {
11523     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11524         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11525     offset += strlen (name);
11526     g_free (name);
11527   }
11528
11529   if (len < offset + 2 + 4 + 4 + 4)
11530     goto short_read;
11531
11532   /* +1 +1 = skip null-terminator and location role byte */
11533   offset += 1 + 1;
11534   /* table in spec says unsigned, semantics say negative has meaning ... */
11535   longitude = QT_SFP32 (data + offset);
11536
11537   offset += 4;
11538   latitude = QT_SFP32 (data + offset);
11539
11540   offset += 4;
11541   altitude = QT_SFP32 (data + offset);
11542
11543   /* one invalid means all are invalid */
11544   if (longitude >= -180.0 && longitude <= 180.0 &&
11545       latitude >= -90.0 && latitude <= 90.0) {
11546     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11547         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11548         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11549         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11550   }
11551
11552   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11553
11554   return;
11555
11556   /* ERRORS */
11557 short_read:
11558   {
11559     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11560     return;
11561   }
11562 }
11563
11564
11565 static void
11566 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11567     const char *tag, const char *dummy, GNode * node)
11568 {
11569   guint16 y;
11570   GDate *date;
11571   gint len;
11572
11573   len = QT_UINT32 (node->data);
11574   if (len < 14)
11575     return;
11576
11577   y = QT_UINT16 ((guint8 *) node->data + 12);
11578   if (y == 0) {
11579     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11580     return;
11581   }
11582   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11583
11584   date = g_date_new_dmy (1, 1, y);
11585   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11586   g_date_free (date);
11587 }
11588
11589 static void
11590 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11591     const char *tag, const char *dummy, GNode * node)
11592 {
11593   int offset;
11594   char *tag_str = NULL;
11595   guint8 *entity;
11596   guint16 table;
11597   gint len;
11598
11599   len = QT_UINT32 (node->data);
11600   if (len <= 20)
11601     goto short_read;
11602
11603   offset = 12;
11604   entity = (guint8 *) node->data + offset;
11605   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11606     GST_DEBUG_OBJECT (qtdemux,
11607         "classification info: %c%c%c%c invalid classification entity",
11608         entity[0], entity[1], entity[2], entity[3]);
11609     return;
11610   }
11611
11612   offset += 4;
11613   table = QT_UINT16 ((guint8 *) node->data + offset);
11614
11615   /* Language code skipped */
11616
11617   offset += 4;
11618
11619   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11620    * XXXX: classification entity, fixed length 4 chars.
11621    * Y[YYYY]: classification table, max 5 chars.
11622    */
11623   tag_str = g_strdup_printf ("----://%u/%s",
11624       table, (char *) node->data + offset);
11625
11626   /* memcpy To be sure we're preserving byte order */
11627   memcpy (tag_str, entity, 4);
11628   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11629
11630   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11631
11632   g_free (tag_str);
11633
11634   return;
11635
11636   /* ERRORS */
11637 short_read:
11638   {
11639     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11640     return;
11641   }
11642 }
11643
11644 static gboolean
11645 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11646     const char *tag, const char *dummy, GNode * node)
11647 {
11648   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11649   GNode *data;
11650   char *s;
11651   int len;
11652   guint32 type;
11653   int offset;
11654   gboolean ret = TRUE;
11655   const gchar *charset = NULL;
11656
11657   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11658   if (data) {
11659     len = QT_UINT32 (data->data);
11660     type = QT_UINT32 ((guint8 *) data->data + 8);
11661     if (type == 0x00000001 && len > 16) {
11662       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11663           env_vars);
11664       if (s) {
11665         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11666         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11667         g_free (s);
11668       } else {
11669         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11670       }
11671     }
11672   } else {
11673     len = QT_UINT32 (node->data);
11674     type = QT_UINT32 ((guint8 *) node->data + 4);
11675     if ((type >> 24) == 0xa9) {
11676       gint str_len;
11677       gint lang_code;
11678
11679       /* Type starts with the (C) symbol, so the next data is a list
11680        * of (string size(16), language code(16), string) */
11681
11682       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11683       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11684
11685       /* the string + fourcc + size + 2 16bit fields,
11686        * means that there are more tags in this atom */
11687       if (len > str_len + 8 + 4) {
11688         /* TODO how to represent the same tag in different languages? */
11689         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11690             "text alternatives, reading only first one");
11691       }
11692
11693       offset = 12;
11694       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
11695       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11696
11697       if (lang_code < 0x800) {  /* MAC encoded string */
11698         charset = "mac";
11699       }
11700     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11701             QT_FOURCC ((guint8 *) node->data + 4))) {
11702       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11703
11704       /* we go for 3GP style encoding if major brands claims so,
11705        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11706       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11707           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11708               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11709         offset = 14;
11710         /* 16-bit Language code is ignored here as well */
11711         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11712       } else {
11713         goto normal;
11714       }
11715     } else {
11716     normal:
11717       offset = 8;
11718       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11719       ret = FALSE;              /* may have to fallback */
11720     }
11721     if (charset) {
11722       GError *err = NULL;
11723
11724       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11725           charset, NULL, NULL, &err);
11726       if (err) {
11727         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11728             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11729             err->message);
11730         g_error_free (err);
11731       }
11732     } else {
11733       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11734           len - offset, env_vars);
11735     }
11736     if (s) {
11737       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11738       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11739       g_free (s);
11740       ret = TRUE;
11741     } else {
11742       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11743     }
11744   }
11745   return ret;
11746 }
11747
11748 static void
11749 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11750     const char *tag, const char *dummy, GNode * node)
11751 {
11752   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11753 }
11754
11755 static void
11756 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11757     const char *tag, const char *dummy, GNode * node)
11758 {
11759   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11760   guint8 *data;
11761   char *s, *t, *k = NULL;
11762   int len;
11763   int offset;
11764   int count;
11765
11766   /* first try normal string tag if major brand not 3GP */
11767   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11768     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11769       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11770        * let's try it 3gpp way after minor safety check */
11771       data = node->data;
11772       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11773         return;
11774     } else
11775       return;
11776   }
11777
11778   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11779
11780   data = node->data;
11781
11782   len = QT_UINT32 (data);
11783   if (len < 15)
11784     goto short_read;
11785
11786   count = QT_UINT8 (data + 14);
11787   offset = 15;
11788   for (; count; count--) {
11789     gint slen;
11790
11791     if (offset + 1 > len)
11792       goto short_read;
11793     slen = QT_UINT8 (data + offset);
11794     offset += 1;
11795     if (offset + slen > len)
11796       goto short_read;
11797     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11798         slen, env_vars);
11799     if (s) {
11800       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11801       if (k) {
11802         t = g_strjoin (",", k, s, NULL);
11803         g_free (s);
11804         g_free (k);
11805         k = t;
11806       } else {
11807         k = s;
11808       }
11809     } else {
11810       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11811     }
11812     offset += slen;
11813   }
11814
11815 done:
11816   if (k) {
11817     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
11818     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
11819   }
11820   g_free (k);
11821
11822   return;
11823
11824   /* ERRORS */
11825 short_read:
11826   {
11827     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11828     goto done;
11829   }
11830 }
11831
11832 static void
11833 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11834     const char *tag1, const char *tag2, GNode * node)
11835 {
11836   GNode *data;
11837   int len;
11838   int type;
11839   int n1, n2;
11840
11841   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11842   if (data) {
11843     len = QT_UINT32 (data->data);
11844     type = QT_UINT32 ((guint8 *) data->data + 8);
11845     if (type == 0x00000000 && len >= 22) {
11846       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11847       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11848       if (n1 > 0) {
11849         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11850         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11851       }
11852       if (n2 > 0) {
11853         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11854         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11855       }
11856     }
11857   }
11858 }
11859
11860 static void
11861 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11862     const char *tag1, const char *dummy, GNode * node)
11863 {
11864   GNode *data;
11865   int len;
11866   int type;
11867   int n1;
11868
11869   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11870   if (data) {
11871     len = QT_UINT32 (data->data);
11872     type = QT_UINT32 ((guint8 *) data->data + 8);
11873     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11874     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11875     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11876       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11877       if (n1) {
11878         /* do not add bpm=0 */
11879         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11880         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11881             NULL);
11882       }
11883     }
11884   }
11885 }
11886
11887 static void
11888 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11889     const char *tag1, const char *dummy, GNode * node)
11890 {
11891   GNode *data;
11892   int len;
11893   int type;
11894   guint32 num;
11895
11896   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11897   if (data) {
11898     len = QT_UINT32 (data->data);
11899     type = QT_UINT32 ((guint8 *) data->data + 8);
11900     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11901     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11902     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11903       num = QT_UINT32 ((guint8 *) data->data + 16);
11904       if (num) {
11905         /* do not add num=0 */
11906         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11907         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11908       }
11909     }
11910   }
11911 }
11912
11913 static void
11914 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11915     const char *tag1, const char *dummy, GNode * node)
11916 {
11917   GNode *data;
11918   int len;
11919   int type;
11920   GstSample *sample;
11921
11922   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11923   if (data) {
11924     len = QT_UINT32 (data->data);
11925     type = QT_UINT32 ((guint8 *) data->data + 8);
11926     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11927     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11928       if ((sample =
11929               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11930                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11931         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11932         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11933         gst_sample_unref (sample);
11934       }
11935     }
11936   }
11937 }
11938
11939 static void
11940 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11941     const char *tag, const char *dummy, GNode * node)
11942 {
11943   GNode *data;
11944   char *s;
11945   int len;
11946   int type;
11947
11948   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11949   if (data) {
11950     len = QT_UINT32 (data->data);
11951     type = QT_UINT32 ((guint8 *) data->data + 8);
11952     if (type == 0x00000001 && len > 16) {
11953       guint y, m = 1, d = 1;
11954       gint ret;
11955
11956       s = g_strndup ((char *) data->data + 16, len - 16);
11957       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11958       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11959       if (ret >= 1 && y > 1500 && y < 3000) {
11960         GDate *date;
11961
11962         date = g_date_new_dmy (d, m, y);
11963         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11964         g_date_free (date);
11965       } else {
11966         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11967       }
11968       g_free (s);
11969     }
11970   }
11971 }
11972
11973 static void
11974 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11975     const char *tag, const char *dummy, GNode * node)
11976 {
11977   GNode *data;
11978
11979   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11980
11981   /* re-route to normal string tag if major brand says so
11982    * or no data atom and compatible brand suggests so */
11983   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11984       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11985     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11986     return;
11987   }
11988
11989   if (data) {
11990     guint len, type, n;
11991
11992     len = QT_UINT32 (data->data);
11993     type = QT_UINT32 ((guint8 *) data->data + 8);
11994     if (type == 0x00000000 && len >= 18) {
11995       n = QT_UINT16 ((guint8 *) data->data + 16);
11996       if (n > 0) {
11997         const gchar *genre;
11998
11999         genre = gst_tag_id3_genre_get (n - 1);
12000         if (genre != NULL) {
12001           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12002           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12003         }
12004       }
12005     }
12006   }
12007 }
12008
12009 static void
12010 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12011     const gchar * tag, guint8 * data, guint32 datasize)
12012 {
12013   gdouble value;
12014   gchar *datacopy;
12015
12016   /* make a copy to have \0 at the end */
12017   datacopy = g_strndup ((gchar *) data, datasize);
12018
12019   /* convert the str to double */
12020   if (sscanf (datacopy, "%lf", &value) == 1) {
12021     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12022     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12023   } else {
12024     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12025         datacopy);
12026   }
12027   g_free (datacopy);
12028 }
12029
12030
12031 static void
12032 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12033     const char *tag, const char *tag_bis, GNode * node)
12034 {
12035   GNode *mean;
12036   GNode *name;
12037   GNode *data;
12038   guint32 meansize;
12039   guint32 namesize;
12040   guint32 datatype;
12041   guint32 datasize;
12042   const gchar *meanstr;
12043   const gchar *namestr;
12044
12045   /* checking the whole ---- atom size for consistency */
12046   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12047     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12048     return;
12049   }
12050
12051   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12052   if (!mean) {
12053     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12054     return;
12055   }
12056
12057   meansize = QT_UINT32 (mean->data);
12058   if (meansize <= 12) {
12059     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12060     return;
12061   }
12062   meanstr = ((gchar *) mean->data) + 12;
12063   meansize -= 12;
12064
12065   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12066   if (!name) {
12067     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12068     return;
12069   }
12070
12071   namesize = QT_UINT32 (name->data);
12072   if (namesize <= 12) {
12073     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12074     return;
12075   }
12076   namestr = ((gchar *) name->data) + 12;
12077   namesize -= 12;
12078
12079   /*
12080    * Data atom is:
12081    * uint32 - size
12082    * uint32 - name
12083    * uint8  - version
12084    * uint24 - data type
12085    * uint32 - all 0
12086    * rest   - the data
12087    */
12088   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12089   if (!data) {
12090     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12091     return;
12092   }
12093   datasize = QT_UINT32 (data->data);
12094   if (datasize <= 16) {
12095     GST_WARNING_OBJECT (demux, "Data atom too small");
12096     return;
12097   }
12098   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12099
12100   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12101       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12102     static const struct
12103     {
12104       const gchar name[28];
12105       const gchar tag[28];
12106     } tags[] = {
12107       {
12108       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12109       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12110       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12111       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12112       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12113       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12114       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12115       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12116     };
12117     int i;
12118
12119     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12120       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12121         switch (gst_tag_get_type (tags[i].tag)) {
12122           case G_TYPE_DOUBLE:
12123             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12124                 ((guint8 *) data->data) + 16, datasize - 16);
12125             break;
12126           case G_TYPE_STRING:
12127             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12128             break;
12129           default:
12130             /* not reached */
12131             break;
12132         }
12133         break;
12134       }
12135     }
12136     if (i == G_N_ELEMENTS (tags))
12137       goto unknown_tag;
12138   } else {
12139     goto unknown_tag;
12140   }
12141
12142   return;
12143
12144 /* errors */
12145 unknown_tag:
12146 #ifndef GST_DISABLE_GST_DEBUG
12147   {
12148     gchar *namestr_dbg;
12149     gchar *meanstr_dbg;
12150
12151     meanstr_dbg = g_strndup (meanstr, meansize);
12152     namestr_dbg = g_strndup (namestr, namesize);
12153
12154     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12155         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12156
12157     g_free (namestr_dbg);
12158     g_free (meanstr_dbg);
12159   }
12160 #endif
12161   return;
12162 }
12163
12164 static void
12165 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12166     const char *tag_bis, GNode * node)
12167 {
12168   guint8 *data;
12169   GstBuffer *buf;
12170   guint len;
12171   GstTagList *id32_taglist = NULL;
12172
12173   GST_LOG_OBJECT (demux, "parsing ID32");
12174
12175   data = node->data;
12176   len = GST_READ_UINT32_BE (data);
12177
12178   /* need at least full box and language tag */
12179   if (len < 12 + 2)
12180     return;
12181
12182   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12183   gst_buffer_fill (buf, 0, data + 14, len - 14);
12184
12185   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12186   if (id32_taglist) {
12187     GST_LOG_OBJECT (demux, "parsing ok");
12188     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12189     gst_tag_list_unref (id32_taglist);
12190   } else {
12191     GST_LOG_OBJECT (demux, "parsing failed");
12192   }
12193
12194   gst_buffer_unref (buf);
12195 }
12196
12197 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12198     const char *tag, const char *tag_bis, GNode * node);
12199
12200 /* unmapped tags
12201 FOURCC_pcst -> if media is a podcast -> bool
12202 FOURCC_cpil -> if media is part of a compilation -> bool
12203 FOURCC_pgap -> if media is part of a gapless context -> bool
12204 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12205 */
12206
12207 static const struct
12208 {
12209   guint32 fourcc;
12210   const gchar *gst_tag;
12211   const gchar *gst_tag_bis;
12212   const GstQTDemuxAddTagFunc func;
12213 } add_funcs[] = {
12214   {
12215   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12216   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12217   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12218   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12219   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12220   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12221   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12222   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12223   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12224   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12225   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12226   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12227   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12228   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12229   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12230   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12231   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12232   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12233   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12234   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12235   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12236   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12237   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12238         qtdemux_tag_add_num}, {
12239   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12240         qtdemux_tag_add_num}, {
12241   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12242   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12243   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12244   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
12245   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12246   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12247   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12248   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12249   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12250   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12251   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12252   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12253   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12254   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12255   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12256   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12257   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12258   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12259         qtdemux_tag_add_classification}, {
12260   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12261   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12262   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12263
12264     /* This is a special case, some tags are stored in this
12265      * 'reverse dns naming', according to:
12266      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12267      * bug #614471
12268      */
12269   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12270     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12271   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12272 };
12273
12274 struct _GstQtDemuxTagList
12275 {
12276   GstQTDemux *demux;
12277   GstTagList *taglist;
12278 };
12279 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12280
12281 static void
12282 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12283 {
12284   gint len;
12285   guint8 *data;
12286   GstBuffer *buf;
12287   gchar *media_type;
12288   const gchar *style;
12289   GstSample *sample;
12290   GstStructure *s;
12291   guint i;
12292   guint8 ndata[4];
12293   GstQTDemux *demux = qtdemuxtaglist->demux;
12294   GstTagList *taglist = qtdemuxtaglist->taglist;
12295
12296   data = node->data;
12297   len = QT_UINT32 (data);
12298   buf = gst_buffer_new_and_alloc (len);
12299   gst_buffer_fill (buf, 0, data, len);
12300
12301   /* heuristic to determine style of tag */
12302   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12303       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12304     style = "itunes";
12305   else if (demux->major_brand == FOURCC_qt__)
12306     style = "quicktime";
12307   /* fall back to assuming iso/3gp tag style */
12308   else
12309     style = "iso";
12310
12311   /* santize the name for the caps. */
12312   for (i = 0; i < 4; i++) {
12313     guint8 d = data[4 + i];
12314     if (g_ascii_isalnum (d))
12315       ndata[i] = g_ascii_tolower (d);
12316     else
12317       ndata[i] = '_';
12318   }
12319
12320   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12321       ndata[0], ndata[1], ndata[2], ndata[3]);
12322   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12323
12324   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12325   sample = gst_sample_new (buf, NULL, NULL, s);
12326   gst_buffer_unref (buf);
12327   g_free (media_type);
12328
12329   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12330       len, s);
12331
12332   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12333       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12334
12335   gst_sample_unref (sample);
12336 }
12337
12338 static void
12339 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12340 {
12341   GNode *meta;
12342   GNode *ilst;
12343   GNode *xmp_;
12344   GNode *node;
12345   gint i;
12346   GstQtDemuxTagList demuxtaglist;
12347
12348   demuxtaglist.demux = qtdemux;
12349   demuxtaglist.taglist = taglist;
12350
12351   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12352   if (meta != NULL) {
12353     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12354     if (ilst == NULL) {
12355       GST_LOG_OBJECT (qtdemux, "no ilst");
12356       return;
12357     }
12358   } else {
12359     ilst = udta;
12360     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12361   }
12362
12363   i = 0;
12364   while (i < G_N_ELEMENTS (add_funcs)) {
12365     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12366     if (node) {
12367       gint len;
12368
12369       len = QT_UINT32 (node->data);
12370       if (len < 12) {
12371         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12372             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12373       } else {
12374         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12375             add_funcs[i].gst_tag_bis, node);
12376       }
12377       g_node_destroy (node);
12378     } else {
12379       i++;
12380     }
12381   }
12382
12383   /* parsed nodes have been removed, pass along remainder as blob */
12384   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12385       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12386
12387   /* parse up XMP_ node if existing */
12388   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12389   if (xmp_ != NULL) {
12390     GstBuffer *buf;
12391     GstTagList *xmptaglist;
12392
12393     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12394         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12395     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12396     gst_buffer_unref (buf);
12397
12398     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12399   } else {
12400     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12401   }
12402 }
12403
12404 typedef struct
12405 {
12406   GstStructure *structure;      /* helper for sort function */
12407   gchar *location;
12408   guint min_req_bitrate;
12409   guint min_req_qt_version;
12410 } GstQtReference;
12411
12412 static gint
12413 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12414 {
12415   GstQtReference *ref_a = (GstQtReference *) a;
12416   GstQtReference *ref_b = (GstQtReference *) b;
12417
12418   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12419     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12420
12421   /* known bitrates go before unknown; higher bitrates go first */
12422   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12423 }
12424
12425 /* sort the redirects and post a message for the application.
12426  */
12427 static void
12428 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12429 {
12430   GstQtReference *best;
12431   GstStructure *s;
12432   GstMessage *msg;
12433   GValue list_val = { 0, };
12434   GList *l;
12435
12436   g_assert (references != NULL);
12437
12438   references = g_list_sort (references, qtdemux_redirects_sort_func);
12439
12440   best = (GstQtReference *) references->data;
12441
12442   g_value_init (&list_val, GST_TYPE_LIST);
12443
12444   for (l = references; l != NULL; l = l->next) {
12445     GstQtReference *ref = (GstQtReference *) l->data;
12446     GValue struct_val = { 0, };
12447
12448     ref->structure = gst_structure_new ("redirect",
12449         "new-location", G_TYPE_STRING, ref->location, NULL);
12450
12451     if (ref->min_req_bitrate > 0) {
12452       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12453           ref->min_req_bitrate, NULL);
12454     }
12455
12456     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12457     g_value_set_boxed (&struct_val, ref->structure);
12458     gst_value_list_append_value (&list_val, &struct_val);
12459     g_value_unset (&struct_val);
12460     /* don't free anything here yet, since we need best->structure below */
12461   }
12462
12463   g_assert (best != NULL);
12464   s = gst_structure_copy (best->structure);
12465
12466   if (g_list_length (references) > 1) {
12467     gst_structure_set_value (s, "locations", &list_val);
12468   }
12469
12470   g_value_unset (&list_val);
12471
12472   for (l = references; l != NULL; l = l->next) {
12473     GstQtReference *ref = (GstQtReference *) l->data;
12474
12475     gst_structure_free (ref->structure);
12476     g_free (ref->location);
12477     g_free (ref);
12478   }
12479   g_list_free (references);
12480
12481   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12482   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12483   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12484   qtdemux->posted_redirect = TRUE;
12485 }
12486
12487 /* look for redirect nodes, collect all redirect information and
12488  * process it.
12489  */
12490 static gboolean
12491 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12492 {
12493   GNode *rmra, *rmda, *rdrf;
12494
12495   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12496   if (rmra) {
12497     GList *redirects = NULL;
12498
12499     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12500     while (rmda) {
12501       GstQtReference ref = { NULL, NULL, 0, 0 };
12502       GNode *rmdr, *rmvc;
12503
12504       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12505         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12506         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12507             ref.min_req_bitrate);
12508       }
12509
12510       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12511         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12512         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12513
12514 #ifndef GST_DISABLE_GST_DEBUG
12515         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12516 #endif
12517         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12518
12519         GST_LOG_OBJECT (qtdemux,
12520             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12521             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12522             bitmask, check_type);
12523         if (package == FOURCC_qtim && check_type == 0) {
12524           ref.min_req_qt_version = version;
12525         }
12526       }
12527
12528       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12529       if (rdrf) {
12530         guint32 ref_type;
12531         guint8 *ref_data;
12532         guint ref_len;
12533
12534         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12535         if (ref_len > 20) {
12536           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12537           ref_data = (guint8 *) rdrf->data + 20;
12538           if (ref_type == FOURCC_alis) {
12539             guint record_len, record_version, fn_len;
12540
12541             if (ref_len > 70) {
12542               /* MacOSX alias record, google for alias-layout.txt */
12543               record_len = QT_UINT16 (ref_data + 4);
12544               record_version = QT_UINT16 (ref_data + 4 + 2);
12545               fn_len = QT_UINT8 (ref_data + 50);
12546               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12547                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12548               }
12549             } else {
12550               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12551                   ref_len);
12552             }
12553           } else if (ref_type == FOURCC_url_) {
12554             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12555           } else {
12556             GST_DEBUG_OBJECT (qtdemux,
12557                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12558                 GST_FOURCC_ARGS (ref_type));
12559           }
12560           if (ref.location != NULL) {
12561             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12562             redirects =
12563                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12564           } else {
12565             GST_WARNING_OBJECT (qtdemux,
12566                 "Failed to extract redirect location from rdrf atom");
12567           }
12568         } else {
12569           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12570         }
12571       }
12572
12573       /* look for others */
12574       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12575     }
12576
12577     if (redirects != NULL) {
12578       qtdemux_process_redirects (qtdemux, redirects);
12579     }
12580   }
12581   return TRUE;
12582 }
12583
12584 static GstTagList *
12585 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12586 {
12587   const gchar *fmt;
12588
12589   if (tags == NULL) {
12590     tags = gst_tag_list_new_empty ();
12591     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12592   }
12593
12594   if (qtdemux->major_brand == FOURCC_mjp2)
12595     fmt = "Motion JPEG 2000";
12596   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12597     fmt = "3GP";
12598   else if (qtdemux->major_brand == FOURCC_qt__)
12599     fmt = "Quicktime";
12600   else if (qtdemux->fragmented)
12601     fmt = "ISO fMP4";
12602   else
12603     fmt = "ISO MP4/M4A";
12604
12605   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12606       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12607
12608   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12609       fmt, NULL);
12610
12611   return tags;
12612 }
12613
12614 /* we have read the complete moov node now.
12615  * This function parses all of the relevant info, creates the traks and
12616  * prepares all data structures for playback
12617  */
12618 static gboolean
12619 qtdemux_parse_tree (GstQTDemux * qtdemux)
12620 {
12621   GNode *mvhd;
12622   GNode *trak;
12623   GNode *udta;
12624   GNode *mvex;
12625   GstClockTime duration;
12626   GNode *pssh;
12627   guint64 creation_time;
12628   GstDateTime *datetime = NULL;
12629   gint version;
12630
12631   /* make sure we have a usable taglist */
12632   if (!qtdemux->tag_list) {
12633     qtdemux->tag_list = gst_tag_list_new_empty ();
12634     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12635   } else {
12636     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12637   }
12638
12639   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12640   if (mvhd == NULL) {
12641     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12642     return qtdemux_parse_redirects (qtdemux);
12643   }
12644
12645   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12646   if (version == 1) {
12647     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12648     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12649     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12650   } else if (version == 0) {
12651     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12652     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12653     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12654   } else {
12655     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12656     return FALSE;
12657   }
12658
12659   /* Moving qt creation time (secs since 1904) to unix time */
12660   if (creation_time != 0) {
12661     /* Try to use epoch first as it should be faster and more commonly found */
12662     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12663       GTimeVal now;
12664
12665       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12666       /* some data cleansing sanity */
12667       g_get_current_time (&now);
12668       if (now.tv_sec + 24 * 3600 < creation_time) {
12669         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12670       } else {
12671         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12672       }
12673     } else {
12674       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12675       GDateTime *dt, *dt_local;
12676
12677       dt = g_date_time_add_seconds (base_dt, creation_time);
12678       dt_local = g_date_time_to_local (dt);
12679       datetime = gst_date_time_new_from_g_date_time (dt_local);
12680
12681       g_date_time_unref (base_dt);
12682       g_date_time_unref (dt);
12683     }
12684   }
12685   if (datetime) {
12686     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12687     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12688         datetime, NULL);
12689     gst_date_time_unref (datetime);
12690   }
12691
12692   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12693   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12694
12695   /* check for fragmented file and get some (default) data */
12696   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12697   if (mvex) {
12698     GNode *mehd;
12699     GstByteReader mehd_data;
12700
12701     /* let track parsing or anyone know weird stuff might happen ... */
12702     qtdemux->fragmented = TRUE;
12703
12704     /* compensate for total duration */
12705     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12706     if (mehd)
12707       qtdemux_parse_mehd (qtdemux, &mehd_data);
12708   }
12709
12710   /* set duration in the segment info */
12711   gst_qtdemux_get_duration (qtdemux, &duration);
12712   if (duration) {
12713     qtdemux->segment.duration = duration;
12714     /* also do not exceed duration; stop is set that way post seek anyway,
12715      * and segment activation falls back to duration,
12716      * whereas loop only checks stop, so let's align this here as well */
12717     qtdemux->segment.stop = duration;
12718   }
12719
12720   /* parse all traks */
12721   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12722   while (trak) {
12723     qtdemux_parse_trak (qtdemux, trak);
12724     /* iterate all siblings */
12725     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12726   }
12727
12728   if (!qtdemux->tag_list) {
12729     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12730     qtdemux->tag_list = gst_tag_list_new_empty ();
12731     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12732   } else {
12733     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12734   }
12735
12736   /* find tags */
12737   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12738   if (udta) {
12739     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12740   } else {
12741     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12742   }
12743
12744   /* maybe also some tags in meta box */
12745   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12746   if (udta) {
12747     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12748     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12749   } else {
12750     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12751   }
12752
12753   /* parse any protection system info */
12754   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12755   while (pssh) {
12756     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12757     qtdemux_parse_pssh (qtdemux, pssh);
12758     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12759   }
12760
12761   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12762
12763   return TRUE;
12764 }
12765
12766 /* taken from ffmpeg */
12767 static int
12768 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12769 {
12770   int count = 4;
12771   int len = 0;
12772
12773   while (count--) {
12774     int c;
12775
12776     if (ptr >= end)
12777       return -1;
12778
12779     c = *ptr++;
12780     len = (len << 7) | (c & 0x7f);
12781     if (!(c & 0x80))
12782       break;
12783   }
12784   *end_out = ptr;
12785   return len;
12786 }
12787
12788 /* this can change the codec originally present in @list */
12789 static void
12790 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12791     GNode * esds, GstTagList * list)
12792 {
12793   int len = QT_UINT32 (esds->data);
12794   guint8 *ptr = esds->data;
12795   guint8 *end = ptr + len;
12796   int tag;
12797   guint8 *data_ptr = NULL;
12798   int data_len = 0;
12799   guint8 object_type_id = 0;
12800   const char *codec_name = NULL;
12801   GstCaps *caps = NULL;
12802
12803   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12804   ptr += 8;
12805   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
12806   ptr += 4;
12807   while (ptr + 1 < end) {
12808     tag = QT_UINT8 (ptr);
12809     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
12810     ptr++;
12811     len = read_descr_size (ptr, end, &ptr);
12812     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
12813
12814     /* Check the stated amount of data is available for reading */
12815     if (len < 0 || ptr + len > end)
12816       break;
12817
12818     switch (tag) {
12819       case ES_DESCRIPTOR_TAG:
12820         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
12821         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
12822         ptr += 3;
12823         break;
12824       case DECODER_CONFIG_DESC_TAG:{
12825         guint max_bitrate, avg_bitrate;
12826
12827         object_type_id = QT_UINT8 (ptr);
12828         max_bitrate = QT_UINT32 (ptr + 5);
12829         avg_bitrate = QT_UINT32 (ptr + 9);
12830         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12831         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12832         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12833         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12834         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12835         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12836           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12837               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12838         }
12839         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12840           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12841               avg_bitrate, NULL);
12842         }
12843         ptr += 13;
12844         break;
12845       }
12846       case DECODER_SPECIFIC_INFO_TAG:
12847         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12848         if (object_type_id == 0xe0 && len == 0x40) {
12849           guint8 *data;
12850           GstStructure *s;
12851           guint32 clut[16];
12852           gint i;
12853
12854           GST_DEBUG_OBJECT (qtdemux,
12855               "Have VOBSUB palette. Creating palette event");
12856           /* move to decConfigDescr data and read palette */
12857           data = ptr;
12858           for (i = 0; i < 16; i++) {
12859             clut[i] = QT_UINT32 (data);
12860             data += 4;
12861           }
12862
12863           s = gst_structure_new ("application/x-gst-dvd", "event",
12864               G_TYPE_STRING, "dvd-spu-clut-change",
12865               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12866               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12867               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12868               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12869               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12870               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12871               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12872               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12873               NULL);
12874
12875           /* store event and trigger custom processing */
12876           stream->pending_event =
12877               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12878         } else {
12879           /* Generic codec_data handler puts it on the caps */
12880           data_ptr = ptr;
12881           data_len = len;
12882         }
12883
12884         ptr += len;
12885         break;
12886       case SL_CONFIG_DESC_TAG:
12887         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12888         ptr += 1;
12889         break;
12890       default:
12891         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12892             tag);
12893         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12894         ptr += len;
12895         break;
12896     }
12897   }
12898
12899   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12900    * in use, and should also be used to override some other parameters for some
12901    * codecs. */
12902   switch (object_type_id) {
12903     case 0x20:                 /* MPEG-4 */
12904       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12905        * profile_and_level_indication */
12906       if (data_ptr != NULL && data_len >= 5 &&
12907           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12908         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12909             data_ptr + 4, data_len - 4);
12910       }
12911       break;                    /* Nothing special needed here */
12912     case 0x21:                 /* H.264 */
12913       codec_name = "H.264 / AVC";
12914       caps = gst_caps_new_simple ("video/x-h264",
12915           "stream-format", G_TYPE_STRING, "avc",
12916           "alignment", G_TYPE_STRING, "au", NULL);
12917       break;
12918     case 0x40:                 /* AAC (any) */
12919     case 0x66:                 /* AAC Main */
12920     case 0x67:                 /* AAC LC */
12921     case 0x68:                 /* AAC SSR */
12922       /* Override channels and rate based on the codec_data, as it's often
12923        * wrong. */
12924       /* Only do so for basic setup without HE-AAC extension */
12925       if (data_ptr && data_len == 2) {
12926         guint channels, rate;
12927
12928         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
12929         if (channels > 0)
12930           stream->n_channels = channels;
12931
12932         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
12933         if (rate > 0)
12934           stream->rate = rate;
12935       }
12936
12937       /* Set level and profile if possible */
12938       if (data_ptr != NULL && data_len >= 2) {
12939         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12940             data_ptr, data_len);
12941       } else {
12942         const gchar *profile_str = NULL;
12943         GstBuffer *buffer;
12944         GstMapInfo map;
12945         guint8 *codec_data;
12946         gint rate_idx, profile;
12947
12948         /* No codec_data, let's invent something.
12949          * FIXME: This is wrong for SBR! */
12950
12951         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
12952
12953         buffer = gst_buffer_new_and_alloc (2);
12954         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
12955         codec_data = map.data;
12956
12957         rate_idx =
12958             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
12959
12960         switch (object_type_id) {
12961           case 0x66:
12962             profile_str = "main";
12963             profile = 0;
12964             break;
12965           case 0x67:
12966             profile_str = "lc";
12967             profile = 1;
12968             break;
12969           case 0x68:
12970             profile_str = "ssr";
12971             profile = 2;
12972             break;
12973           default:
12974             profile = 3;
12975             break;
12976         }
12977
12978         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
12979         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
12980
12981         gst_buffer_unmap (buffer, &map);
12982         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12983             buffer, NULL);
12984         gst_buffer_unref (buffer);
12985
12986         if (profile_str) {
12987           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
12988               profile_str, NULL);
12989         }
12990       }
12991       break;
12992     case 0x60:                 /* MPEG-2, various profiles */
12993     case 0x61:
12994     case 0x62:
12995     case 0x63:
12996     case 0x64:
12997     case 0x65:
12998       codec_name = "MPEG-2 video";
12999       caps = gst_caps_new_simple ("video/mpeg",
13000           "mpegversion", G_TYPE_INT, 2,
13001           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13002       break;
13003     case 0x69:                 /* MPEG-2 BC audio */
13004     case 0x6B:                 /* MPEG-1 audio */
13005       caps = gst_caps_new_simple ("audio/mpeg",
13006           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13007       codec_name = "MPEG-1 audio";
13008       break;
13009     case 0x6A:                 /* MPEG-1 */
13010       codec_name = "MPEG-1 video";
13011       caps = gst_caps_new_simple ("video/mpeg",
13012           "mpegversion", G_TYPE_INT, 1,
13013           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13014       break;
13015     case 0x6C:                 /* MJPEG */
13016       caps =
13017           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13018           NULL);
13019       codec_name = "Motion-JPEG";
13020       break;
13021     case 0x6D:                 /* PNG */
13022       caps =
13023           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13024           NULL);
13025       codec_name = "PNG still images";
13026       break;
13027     case 0x6E:                 /* JPEG2000 */
13028       codec_name = "JPEG-2000";
13029       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13030       break;
13031     case 0xA4:                 /* Dirac */
13032       codec_name = "Dirac";
13033       caps = gst_caps_new_empty_simple ("video/x-dirac");
13034       break;
13035     case 0xA5:                 /* AC3 */
13036       codec_name = "AC-3 audio";
13037       caps = gst_caps_new_simple ("audio/x-ac3",
13038           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13039       break;
13040     case 0xA9:                 /* AC3 */
13041       codec_name = "DTS audio";
13042       caps = gst_caps_new_simple ("audio/x-dts",
13043           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13044       break;
13045     case 0xE1:                 /* QCELP */
13046       /* QCELP, the codec_data is a riff tag (little endian) with
13047        * 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). */
13048       caps = gst_caps_new_empty_simple ("audio/qcelp");
13049       codec_name = "QCELP";
13050       break;
13051     default:
13052       break;
13053   }
13054
13055   /* If we have a replacement caps, then change our caps for this stream */
13056   if (caps) {
13057     gst_caps_unref (stream->caps);
13058     stream->caps = caps;
13059   }
13060
13061   if (codec_name && list)
13062     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13063         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13064
13065   /* Add the codec_data attribute to caps, if we have it */
13066   if (data_ptr) {
13067     GstBuffer *buffer;
13068
13069     buffer = gst_buffer_new_and_alloc (data_len);
13070     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13071
13072     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13073     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13074
13075     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13076         buffer, NULL);
13077     gst_buffer_unref (buffer);
13078   }
13079
13080 }
13081
13082 #define _codec(name) \
13083   do { \
13084     if (codec_name) { \
13085       *codec_name = g_strdup (name); \
13086     } \
13087   } while (0)
13088
13089 static GstCaps *
13090 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13091     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13092 {
13093   GstCaps *caps = NULL;
13094   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13095
13096   switch (fourcc) {
13097     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13098       _codec ("PNG still images");
13099       caps = gst_caps_new_empty_simple ("image/png");
13100       break;
13101     case FOURCC_jpeg:
13102       _codec ("JPEG still images");
13103       caps =
13104           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13105           NULL);
13106       break;
13107     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13108     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13109     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13110     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13111       _codec ("Motion-JPEG");
13112       caps =
13113           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13114           NULL);
13115       break;
13116     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13117       _codec ("Motion-JPEG format B");
13118       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13119       break;
13120     case FOURCC_mjp2:
13121       _codec ("JPEG-2000");
13122       /* override to what it should be according to spec, avoid palette_data */
13123       stream->bits_per_sample = 24;
13124       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13125       break;
13126     case FOURCC_SVQ3:
13127       _codec ("Sorensen video v.3");
13128       caps = gst_caps_new_simple ("video/x-svq",
13129           "svqversion", G_TYPE_INT, 3, NULL);
13130       break;
13131     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13132     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13133       _codec ("Sorensen video v.1");
13134       caps = gst_caps_new_simple ("video/x-svq",
13135           "svqversion", G_TYPE_INT, 1, NULL);
13136       break;
13137     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13138       caps = gst_caps_new_empty_simple ("video/x-raw");
13139       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13140       _codec ("Windows Raw RGB");
13141       break;
13142     case FOURCC_raw_:
13143     {
13144       guint16 bps;
13145
13146       bps = QT_UINT16 (stsd_data + 98);
13147       switch (bps) {
13148         case 15:
13149           format = GST_VIDEO_FORMAT_RGB15;
13150           break;
13151         case 16:
13152           format = GST_VIDEO_FORMAT_RGB16;
13153           break;
13154         case 24:
13155           format = GST_VIDEO_FORMAT_RGB;
13156           break;
13157         case 32:
13158           format = GST_VIDEO_FORMAT_ARGB;
13159           break;
13160         default:
13161           /* unknown */
13162           break;
13163       }
13164       break;
13165     }
13166     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13167       format = GST_VIDEO_FORMAT_I420;
13168       break;
13169     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13170     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13171       format = GST_VIDEO_FORMAT_I420;
13172       break;
13173     case FOURCC_2vuy:
13174     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13175       format = GST_VIDEO_FORMAT_UYVY;
13176       break;
13177     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13178       format = GST_VIDEO_FORMAT_v308;
13179       break;
13180     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13181       format = GST_VIDEO_FORMAT_v216;
13182       break;
13183     case FOURCC_v210:
13184       format = GST_VIDEO_FORMAT_v210;
13185       break;
13186     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13187       format = GST_VIDEO_FORMAT_r210;
13188       break;
13189       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13190          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13191          format = GST_VIDEO_FORMAT_v410;
13192          break;
13193        */
13194       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13195        * but different order than AYUV
13196        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13197        format = GST_VIDEO_FORMAT_v408;
13198        break;
13199        */
13200     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13201     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13202       _codec ("MPEG-1 video");
13203       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13204           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13205       break;
13206     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13207     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13208     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13209     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13210     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13211     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13212     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13213     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13214     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13215     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13216     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13217     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13218     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13219     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13220     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13221     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13222     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13223     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13224     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13225     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13226     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13227     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13228     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13229     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13230     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13231     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13232     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13233     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13234     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13235     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13236     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13237     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13238     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13239     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13240     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13241     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13242     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13243     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13244     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13245     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13246     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13247     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13248     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13249     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13250     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13251     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13252       _codec ("MPEG-2 video");
13253       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13254           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13255       break;
13256     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13257       _codec ("GIF still images");
13258       caps = gst_caps_new_empty_simple ("image/gif");
13259       break;
13260     case FOURCC_h263:
13261     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13262     case FOURCC_s263:
13263     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13264       _codec ("H.263");
13265       /* ffmpeg uses the height/width props, don't know why */
13266       caps = gst_caps_new_simple ("video/x-h263",
13267           "variant", G_TYPE_STRING, "itu", NULL);
13268       break;
13269     case FOURCC_mp4v:
13270     case FOURCC_MP4V:
13271       _codec ("MPEG-4 video");
13272       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13273           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13274       break;
13275     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13276     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13277       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13278       caps = gst_caps_new_simple ("video/x-msmpeg",
13279           "msmpegversion", G_TYPE_INT, 43, NULL);
13280       break;
13281     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13282       _codec ("DivX 3");
13283       caps = gst_caps_new_simple ("video/x-divx",
13284           "divxversion", G_TYPE_INT, 3, NULL);
13285       break;
13286     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13287     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13288       _codec ("DivX 4");
13289       caps = gst_caps_new_simple ("video/x-divx",
13290           "divxversion", G_TYPE_INT, 4, NULL);
13291       break;
13292     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13293       _codec ("DivX 5");
13294       caps = gst_caps_new_simple ("video/x-divx",
13295           "divxversion", G_TYPE_INT, 5, NULL);
13296       break;
13297
13298     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13299       _codec ("FFV1");
13300       caps = gst_caps_new_simple ("video/x-ffv",
13301           "ffvversion", G_TYPE_INT, 1, NULL);
13302       break;
13303
13304     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13305     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13306     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
13307     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
13308     case FOURCC_FMP4:
13309     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13310       caps = gst_caps_new_simple ("video/mpeg",
13311           "mpegversion", G_TYPE_INT, 4, NULL);
13312       _codec ("MPEG-4");
13313       break;
13314
13315     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13316       _codec ("Cinepak");
13317       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13318       break;
13319     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13320       _codec ("Apple QuickDraw");
13321       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13322       break;
13323     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13324       _codec ("Apple video");
13325       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13326       break;
13327     case FOURCC_H264:
13328     case FOURCC_avc1:
13329       _codec ("H.264 / AVC");
13330       caps = gst_caps_new_simple ("video/x-h264",
13331           "stream-format", G_TYPE_STRING, "avc",
13332           "alignment", G_TYPE_STRING, "au", NULL);
13333       break;
13334     case FOURCC_avc3:
13335       _codec ("H.264 / AVC");
13336       caps = gst_caps_new_simple ("video/x-h264",
13337           "stream-format", G_TYPE_STRING, "avc3",
13338           "alignment", G_TYPE_STRING, "au", NULL);
13339       break;
13340     case FOURCC_H265:
13341     case FOURCC_hvc1:
13342       _codec ("H.265 / HEVC");
13343       caps = gst_caps_new_simple ("video/x-h265",
13344           "stream-format", G_TYPE_STRING, "hvc1",
13345           "alignment", G_TYPE_STRING, "au", NULL);
13346       break;
13347     case FOURCC_hev1:
13348       _codec ("H.265 / HEVC");
13349       caps = gst_caps_new_simple ("video/x-h265",
13350           "stream-format", G_TYPE_STRING, "hev1",
13351           "alignment", G_TYPE_STRING, "au", NULL);
13352       break;
13353     case FOURCC_rle_:
13354       _codec ("Run-length encoding");
13355       caps = gst_caps_new_simple ("video/x-rle",
13356           "layout", G_TYPE_STRING, "quicktime", NULL);
13357       break;
13358     case FOURCC_WRLE:
13359       _codec ("Run-length encoding");
13360       caps = gst_caps_new_simple ("video/x-rle",
13361           "layout", G_TYPE_STRING, "microsoft", NULL);
13362       break;
13363     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13364     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13365       _codec ("Indeo Video 3");
13366       caps = gst_caps_new_simple ("video/x-indeo",
13367           "indeoversion", G_TYPE_INT, 3, NULL);
13368       break;
13369     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13370     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13371       _codec ("Intel Video 4");
13372       caps = gst_caps_new_simple ("video/x-indeo",
13373           "indeoversion", G_TYPE_INT, 4, NULL);
13374       break;
13375     case FOURCC_dvcp:
13376     case FOURCC_dvc_:
13377     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13378     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13379     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13380     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13381     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13382     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13383       _codec ("DV Video");
13384       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13385           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13386       break;
13387     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13388     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13389       _codec ("DVCPro50 Video");
13390       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13391           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13392       break;
13393     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13394     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13395       _codec ("DVCProHD Video");
13396       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13397           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13398       break;
13399     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13400       _codec ("Apple Graphics (SMC)");
13401       caps = gst_caps_new_empty_simple ("video/x-smc");
13402       break;
13403     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13404       _codec ("VP3");
13405       caps = gst_caps_new_empty_simple ("video/x-vp3");
13406       break;
13407     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13408       _codec ("VP6 Flash");
13409       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13410       break;
13411     case FOURCC_XiTh:
13412       _codec ("Theora");
13413       caps = gst_caps_new_empty_simple ("video/x-theora");
13414       /* theora uses one byte of padding in the data stream because it does not
13415        * allow 0 sized packets while theora does */
13416       stream->padding = 1;
13417       break;
13418     case FOURCC_drac:
13419       _codec ("Dirac");
13420       caps = gst_caps_new_empty_simple ("video/x-dirac");
13421       break;
13422     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13423       _codec ("TIFF still images");
13424       caps = gst_caps_new_empty_simple ("image/tiff");
13425       break;
13426     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13427       _codec ("Apple Intermediate Codec");
13428       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13429       break;
13430     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13431       _codec ("AVID DNxHD");
13432       caps = gst_caps_from_string ("video/x-dnxhd");
13433       break;
13434     case FOURCC_VP80:
13435       _codec ("On2 VP8");
13436       caps = gst_caps_from_string ("video/x-vp8");
13437       break;
13438     case FOURCC_apcs:
13439       _codec ("Apple ProRes LT");
13440       caps =
13441           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13442           NULL);
13443       break;
13444     case FOURCC_apch:
13445       _codec ("Apple ProRes HQ");
13446       caps =
13447           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13448           NULL);
13449       break;
13450     case FOURCC_apcn:
13451       _codec ("Apple ProRes");
13452       caps =
13453           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13454           "standard", NULL);
13455       break;
13456     case FOURCC_apco:
13457       _codec ("Apple ProRes Proxy");
13458       caps =
13459           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13460           "proxy", NULL);
13461       break;
13462     case FOURCC_ap4h:
13463       _codec ("Apple ProRes 4444");
13464       caps =
13465           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13466           "4444", NULL);
13467       break;
13468     case FOURCC_ap4x:
13469       _codec ("Apple ProRes 4444 XQ");
13470       caps =
13471           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13472           "4444xq", NULL);
13473       break;
13474     case FOURCC_vc_1:
13475     case FOURCC_ovc1:
13476       _codec ("VC-1");
13477       caps = gst_caps_new_simple ("video/x-wmv",
13478           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13479       break;
13480     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13481     default:
13482     {
13483       char *s, fourstr[5];
13484
13485       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13486       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
13487       caps = gst_caps_new_empty_simple (s);
13488       g_free (s);
13489       break;
13490     }
13491   }
13492
13493   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13494     GstVideoInfo info;
13495
13496     gst_video_info_init (&info);
13497     gst_video_info_set_format (&info, format, stream->width, stream->height);
13498
13499     caps = gst_video_info_to_caps (&info);
13500     *codec_name = gst_pb_utils_get_codec_description (caps);
13501
13502     /* enable clipping for raw video streams */
13503     stream->need_clip = TRUE;
13504   }
13505
13506   return caps;
13507 }
13508
13509 static GstCaps *
13510 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13511     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13512 {
13513   GstCaps *caps;
13514   const GstStructure *s;
13515   const gchar *name;
13516   gint endian = 0;
13517   GstAudioFormat format = 0;
13518   gint depth;
13519
13520   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13521
13522   depth = stream->bytes_per_packet * 8;
13523
13524   switch (fourcc) {
13525     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13526     case FOURCC_raw_:
13527       /* 8-bit audio is unsigned */
13528       if (depth == 8)
13529         format = GST_AUDIO_FORMAT_U8;
13530       /* otherwise it's signed and big-endian just like 'twos' */
13531     case FOURCC_twos:
13532       endian = G_BIG_ENDIAN;
13533       /* fall-through */
13534     case FOURCC_sowt:
13535     {
13536       gchar *str;
13537
13538       if (!endian)
13539         endian = G_LITTLE_ENDIAN;
13540
13541       if (!format)
13542         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13543
13544       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13545       _codec (str);
13546       g_free (str);
13547
13548       caps = gst_caps_new_simple ("audio/x-raw",
13549           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13550           "layout", G_TYPE_STRING, "interleaved", NULL);
13551       break;
13552     }
13553     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13554       _codec ("Raw 64-bit floating-point audio");
13555       caps = gst_caps_new_simple ("audio/x-raw",
13556           "format", G_TYPE_STRING, "F64BE",
13557           "layout", G_TYPE_STRING, "interleaved", NULL);
13558       break;
13559     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13560       _codec ("Raw 32-bit floating-point audio");
13561       caps = gst_caps_new_simple ("audio/x-raw",
13562           "format", G_TYPE_STRING, "F32BE",
13563           "layout", G_TYPE_STRING, "interleaved", NULL);
13564       break;
13565     case FOURCC_in24:
13566       _codec ("Raw 24-bit PCM audio");
13567       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13568        * endian later */
13569       caps = gst_caps_new_simple ("audio/x-raw",
13570           "format", G_TYPE_STRING, "S24BE",
13571           "layout", G_TYPE_STRING, "interleaved", NULL);
13572       break;
13573     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13574       _codec ("Raw 32-bit PCM audio");
13575       caps = gst_caps_new_simple ("audio/x-raw",
13576           "format", G_TYPE_STRING, "S32BE",
13577           "layout", G_TYPE_STRING, "interleaved", NULL);
13578       break;
13579     case FOURCC_ulaw:
13580       _codec ("Mu-law audio");
13581       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13582       break;
13583     case FOURCC_alaw:
13584       _codec ("A-law audio");
13585       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13586       break;
13587     case 0x0200736d:
13588     case 0x6d730002:
13589       _codec ("Microsoft ADPCM");
13590       /* Microsoft ADPCM-ACM code 2 */
13591       caps = gst_caps_new_simple ("audio/x-adpcm",
13592           "layout", G_TYPE_STRING, "microsoft", NULL);
13593       break;
13594     case 0x1100736d:
13595     case 0x6d730011:
13596       _codec ("DVI/IMA ADPCM");
13597       caps = gst_caps_new_simple ("audio/x-adpcm",
13598           "layout", G_TYPE_STRING, "dvi", NULL);
13599       break;
13600     case 0x1700736d:
13601     case 0x6d730017:
13602       _codec ("DVI/Intel IMA ADPCM");
13603       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13604       caps = gst_caps_new_simple ("audio/x-adpcm",
13605           "layout", G_TYPE_STRING, "quicktime", NULL);
13606       break;
13607     case 0x5500736d:
13608     case 0x6d730055:
13609       /* MPEG layer 3, CBR only (pre QT4.1) */
13610     case FOURCC__mp3:
13611       _codec ("MPEG-1 layer 3");
13612       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13613       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13614           "mpegversion", G_TYPE_INT, 1, NULL);
13615       break;
13616     case 0x20736d:
13617     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13618       _codec ("EAC-3 audio");
13619       caps = gst_caps_new_simple ("audio/x-eac3",
13620           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13621       stream->sampled = TRUE;
13622       break;
13623     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13624     case FOURCC_ac_3:
13625       _codec ("AC-3 audio");
13626       caps = gst_caps_new_simple ("audio/x-ac3",
13627           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13628       stream->sampled = TRUE;
13629       break;
13630     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13631     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13632       _codec ("DTS audio");
13633       caps = gst_caps_new_simple ("audio/x-dts",
13634           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13635       stream->sampled = TRUE;
13636       break;
13637     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13638     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13639       _codec ("DTS-HD audio");
13640       caps = gst_caps_new_simple ("audio/x-dts",
13641           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13642       stream->sampled = TRUE;
13643       break;
13644     case FOURCC_MAC3:
13645       _codec ("MACE-3");
13646       caps = gst_caps_new_simple ("audio/x-mace",
13647           "maceversion", G_TYPE_INT, 3, NULL);
13648       break;
13649     case FOURCC_MAC6:
13650       _codec ("MACE-6");
13651       caps = gst_caps_new_simple ("audio/x-mace",
13652           "maceversion", G_TYPE_INT, 6, NULL);
13653       break;
13654     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13655       /* ogg/vorbis */
13656       caps = gst_caps_new_empty_simple ("application/ogg");
13657       break;
13658     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13659       _codec ("DV audio");
13660       caps = gst_caps_new_empty_simple ("audio/x-dv");
13661       break;
13662     case FOURCC_mp4a:
13663       _codec ("MPEG-4 AAC audio");
13664       caps = gst_caps_new_simple ("audio/mpeg",
13665           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13666           "stream-format", G_TYPE_STRING, "raw", NULL);
13667       break;
13668     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13669       _codec ("QDesign Music");
13670       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13671       break;
13672     case FOURCC_QDM2:
13673       _codec ("QDesign Music v.2");
13674       /* FIXME: QDesign music version 2 (no constant) */
13675       if (FALSE && data) {
13676         caps = gst_caps_new_simple ("audio/x-qdm2",
13677             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13678             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13679             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13680       } else {
13681         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13682       }
13683       break;
13684     case FOURCC_agsm:
13685       _codec ("GSM audio");
13686       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13687       break;
13688     case FOURCC_samr:
13689       _codec ("AMR audio");
13690       caps = gst_caps_new_empty_simple ("audio/AMR");
13691       break;
13692     case FOURCC_sawb:
13693       _codec ("AMR-WB audio");
13694       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13695       break;
13696     case FOURCC_ima4:
13697       _codec ("Quicktime IMA ADPCM");
13698       caps = gst_caps_new_simple ("audio/x-adpcm",
13699           "layout", G_TYPE_STRING, "quicktime", NULL);
13700       break;
13701     case FOURCC_alac:
13702       _codec ("Apple lossless audio");
13703       caps = gst_caps_new_empty_simple ("audio/x-alac");
13704       break;
13705     case FOURCC_fLaC:
13706       _codec ("Free Lossless Audio Codec");
13707       caps = gst_caps_new_simple ("audio/x-flac",
13708           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13709       break;
13710     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13711       _codec ("QualComm PureVoice");
13712       caps = gst_caps_from_string ("audio/qcelp");
13713       break;
13714     case FOURCC_wma_:
13715     case FOURCC_owma:
13716       _codec ("WMA");
13717       caps = gst_caps_new_empty_simple ("audio/x-wma");
13718       break;
13719     case FOURCC_opus:
13720       _codec ("Opus");
13721       caps = gst_caps_new_empty_simple ("audio/x-opus");
13722       break;
13723     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13724     {
13725       guint32 flags = 0;
13726       guint32 depth = 0;
13727       guint32 width = 0;
13728       GstAudioFormat format;
13729       enum
13730       {
13731         FLAG_IS_FLOAT = 0x1,
13732         FLAG_IS_BIG_ENDIAN = 0x2,
13733         FLAG_IS_SIGNED = 0x4,
13734         FLAG_IS_PACKED = 0x8,
13735         FLAG_IS_ALIGNED_HIGH = 0x10,
13736         FLAG_IS_NON_INTERLEAVED = 0x20
13737       };
13738       _codec ("Raw LPCM audio");
13739
13740       if (data && len >= 56) {
13741         depth = QT_UINT32 (data + 40);
13742         flags = QT_UINT32 (data + 44);
13743         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13744       }
13745       if ((flags & FLAG_IS_FLOAT) == 0) {
13746         if (depth == 0)
13747           depth = 16;
13748         if (width == 0)
13749           width = 16;
13750         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13751             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13752             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13753         caps = gst_caps_new_simple ("audio/x-raw",
13754             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13755             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13756             "non-interleaved" : "interleaved", NULL);
13757       } else {
13758         if (width == 0)
13759           width = 32;
13760         if (width == 64) {
13761           if (flags & FLAG_IS_BIG_ENDIAN)
13762             format = GST_AUDIO_FORMAT_F64BE;
13763           else
13764             format = GST_AUDIO_FORMAT_F64LE;
13765         } else {
13766           if (flags & FLAG_IS_BIG_ENDIAN)
13767             format = GST_AUDIO_FORMAT_F32BE;
13768           else
13769             format = GST_AUDIO_FORMAT_F32LE;
13770         }
13771         caps = gst_caps_new_simple ("audio/x-raw",
13772             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13773             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13774             "non-interleaved" : "interleaved", NULL);
13775       }
13776       break;
13777     }
13778     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
13779       /* ? */
13780     default:
13781     {
13782       char *s, fourstr[5];
13783
13784       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13785       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
13786       caps = gst_caps_new_empty_simple (s);
13787       g_free (s);
13788       break;
13789     }
13790   }
13791
13792   if (caps) {
13793     GstCaps *templ_caps =
13794         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
13795     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
13796     gst_caps_unref (caps);
13797     gst_caps_unref (templ_caps);
13798     caps = intersection;
13799   }
13800
13801   /* enable clipping for raw audio streams */
13802   s = gst_caps_get_structure (caps, 0);
13803   name = gst_structure_get_name (s);
13804   if (g_str_has_prefix (name, "audio/x-raw")) {
13805     stream->need_clip = TRUE;
13806     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
13807     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
13808   }
13809   return caps;
13810 }
13811
13812 static GstCaps *
13813 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13814     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13815 {
13816   GstCaps *caps;
13817
13818   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13819
13820   switch (fourcc) {
13821     case FOURCC_mp4s:
13822       _codec ("DVD subtitle");
13823       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
13824       stream->need_process = TRUE;
13825       break;
13826     case FOURCC_text:
13827       _codec ("Quicktime timed text");
13828       goto text;
13829     case FOURCC_tx3g:
13830       _codec ("3GPP timed text");
13831     text:
13832       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
13833           "utf8", NULL);
13834       /* actual text piece needs to be extracted */
13835       stream->need_process = TRUE;
13836       break;
13837     case FOURCC_stpp:
13838       _codec ("XML subtitles");
13839       caps = gst_caps_new_empty_simple ("application/ttml+xml");
13840       break;
13841     default:
13842     {
13843       char *s, fourstr[5];
13844
13845       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13846       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
13847       caps = gst_caps_new_empty_simple (s);
13848       g_free (s);
13849       break;
13850     }
13851   }
13852   return caps;
13853 }
13854
13855 static GstCaps *
13856 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13857     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13858 {
13859   GstCaps *caps;
13860
13861   switch (fourcc) {
13862     case FOURCC_m1v:
13863       _codec ("MPEG 1 video");
13864       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13865           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13866       break;
13867     default:
13868       caps = NULL;
13869       break;
13870   }
13871   return caps;
13872 }
13873
13874 static void
13875 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
13876     const gchar * system_id)
13877 {
13878   gint i;
13879
13880   if (!qtdemux->protection_system_ids)
13881     qtdemux->protection_system_ids =
13882         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13883   /* Check whether we already have an entry for this system ID. */
13884   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13885     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13886     if (g_ascii_strcasecmp (system_id, id) == 0) {
13887       return;
13888     }
13889   }
13890   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13891   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13892           -1));
13893 }