qtdemux: Don't set pared=True on underspecified audio/mpeg
[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 (200*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 QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104
105 typedef struct _QtDemuxSegment QtDemuxSegment;
106 typedef struct _QtDemuxSample QtDemuxSample;
107
108 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
109
110 struct _QtDemuxSample
111 {
112   guint32 size;
113   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
114   guint64 offset;
115   guint64 timestamp;            /* DTS In mov time */
116   guint32 duration;             /* In mov time */
117   gboolean keyframe;            /* TRUE when this packet is a keyframe */
118 };
119
120 /* Macros for converting to/from timescale */
121 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
122 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
123
124 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
125 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
126
127 /* timestamp is the DTS */
128 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
129 /* timestamp + offset + cslg_shift is the outgoing PTS */
130 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
131 /* timestamp + offset is the PTS used for internal seek calcuations */
132 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
133 /* timestamp + duration - dts is the duration */
134 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
135
136 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
137
138 /*
139  * Quicktime has tracks and segments. A track is a continuous piece of
140  * multimedia content. The track is not always played from start to finish but
141  * instead, pieces of the track are 'cut out' and played in sequence. This is
142  * what the segments do.
143  *
144  * Inside the track we have keyframes (K) and delta frames. The track has its
145  * own timing, which starts from 0 and extends to end. The position in the track
146  * is called the media_time.
147  *
148  * The segments now describe the pieces that should be played from this track
149  * and are basically tuples of media_time/duration/rate entries. We can have
150  * multiple segments and they are all played after one another. An example:
151  *
152  * segment 1: media_time: 1 second, duration: 1 second, rate 1
153  * segment 2: media_time: 3 second, duration: 2 second, rate 2
154  *
155  * To correctly play back this track, one must play: 1 second of media starting
156  * from media_time 1 followed by 2 seconds of media starting from media_time 3
157  * at a rate of 2.
158  *
159  * Each of the segments will be played at a specific time, the first segment at
160  * time 0, the second one after the duration of the first one, etc.. Note that
161  * the time in resulting playback is not identical to the media_time of the
162  * track anymore.
163  *
164  * Visually, assuming the track has 4 second of media_time:
165  *
166  *                (a)                   (b)          (c)              (d)
167  *         .-----------------------------------------------------------.
168  * track:  | K.....K.........K........K.......K.......K...........K... |
169  *         '-----------------------------------------------------------'
170  *         0              1              2              3              4
171  *           .------------^              ^   .----------^              ^
172  *          /              .-------------'  /       .------------------'
173  *         /              /          .-----'       /
174  *         .--------------.         .--------------.
175  *         | segment 1    |         | segment 2    |
176  *         '--------------'         '--------------'
177  *
178  * The challenge here is to cut out the right pieces of the track for each of
179  * the playback segments. This fortunately can easily be done with the SEGMENT
180  * events of GStreamer.
181  *
182  * For playback of segment 1, we need to provide the decoder with the keyframe
183  * (a), in the above figure, but we must instruct it only to output the decoded
184  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
185  * position set to the time of the segment: 0.
186  *
187  * We then proceed to push data from keyframe (a) to frame (b). The decoder
188  * decodes but clips all before media_time 1.
189  *
190  * After finishing a segment, we push out a new SEGMENT event with the clipping
191  * boundaries of the new data.
192  *
193  * This is a good usecase for the GStreamer accumulated SEGMENT events.
194  */
195
196 struct _QtDemuxSegment
197 {
198   /* global time and duration, all gst time */
199   GstClockTime time;
200   GstClockTime stop_time;
201   GstClockTime duration;
202   /* media time of trak, all gst time */
203   GstClockTime media_start;
204   GstClockTime media_stop;
205   gdouble rate;
206   /* Media start time in trak timescale units */
207   guint32 trak_media_start;
208 };
209
210 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
211
212 /* Used with fragmented MP4 files (mfra atom) */
213 typedef struct
214 {
215   GstClockTime ts;
216   guint64 moof_offset;
217 } QtDemuxRandomAccessEntry;
218
219 typedef struct _QtDemuxStreamStsdEntry
220 {
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   /* video info */
226   gint width;
227   gint height;
228   gint par_w;
229   gint par_h;
230   /* Numerator/denominator framerate */
231   gint fps_n;
232   gint fps_d;
233   GstVideoColorimetry colorimetry;
234   guint16 bits_per_sample;
235   guint16 color_table_id;
236   GstMemory *rgb8_palette;
237   guint interlace_mode;
238   guint field_order;
239
240   /* audio info */
241   gdouble rate;
242   gint n_channels;
243   guint samples_per_packet;
244   guint samples_per_frame;
245   guint bytes_per_packet;
246   guint bytes_per_sample;
247   guint bytes_per_frame;
248   guint compression;
249
250   /* if we use chunks or samples */
251   gboolean sampled;
252   guint padding;
253
254 } QtDemuxStreamStsdEntry;
255
256 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
257
258 struct _QtDemuxStream
259 {
260   GstPad *pad;
261
262   QtDemuxStreamStsdEntry *stsd_entries;
263   guint stsd_entries_length;
264   guint cur_stsd_entry_index;
265
266   /* stream type */
267   guint32 subtype;
268
269   gboolean new_caps;            /* If TRUE, caps need to be generated (by
270                                  * calling _configure_stream()) This happens
271                                  * for MSS and fragmented streams */
272
273   gboolean new_stream;          /* signals that a stream_start is required */
274   gboolean on_keyframe;         /* if this stream last pushed buffer was a
275                                  * keyframe. This is important to identify
276                                  * where to stop pushing buffers after a
277                                  * segment stop time */
278
279   /* if the stream has a redirect URI in its headers, we store it here */
280   gchar *redirect_uri;
281
282   /* track id */
283   guint track_id;
284
285   /* duration/scale */
286   guint64 duration;             /* in timescale units */
287   guint32 timescale;
288
289   /* language */
290   gchar lang_id[4];             /* ISO 639-2T language code */
291
292   /* our samples */
293   guint32 n_samples;
294   QtDemuxSample *samples;
295   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
296   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
297                                    the framerate */
298   guint32 n_samples_moof;       /* sample count in a moof */
299   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
300                                  * the framerate of fragmented format stream */
301   guint64 duration_last_moof;
302
303   guint32 offset_in_sample;     /* Offset in the current sample, used for
304                                  * streams which have got exceedingly big
305                                  * sample size (such as 24s of raw audio).
306                                  * Only used when max_buffer_size is non-NULL */
307   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
308                                  * Currently only set for raw audio streams*/
309
310   /* video info */
311   /* aspect ratio */
312   gint display_width;
313   gint display_height;
314
315   /* allocation */
316   gboolean use_allocator;
317   GstAllocator *allocator;
318   GstAllocationParams params;
319
320   gsize alignment;
321
322   /* when a discontinuity is pending */
323   gboolean discont;
324
325   /* list of buffers to push first */
326   GSList *buffers;
327
328   /* if we need to clip this buffer. This is only needed for uncompressed
329    * data */
330   gboolean need_clip;
331
332   /* buffer needs some custom processing, e.g. subtitles */
333   gboolean need_process;
334
335   /* current position */
336   guint32 segment_index;
337   guint32 sample_index;
338   GstClockTime time_position;   /* in gst time */
339   guint64 accumulated_base;
340
341   /* the Gst segment we are processing out, used for clipping */
342   GstSegment segment;
343
344   /* quicktime segments */
345   guint32 n_segments;
346   QtDemuxSegment *segments;
347   gboolean dummy_segment;
348   guint32 from_sample;
349   guint32 to_sample;
350
351   gboolean sent_eos;
352   GstTagList *stream_tags;
353   gboolean send_global_tags;
354
355   GstEvent *pending_event;
356
357   GstByteReader stco;
358   GstByteReader stsz;
359   GstByteReader stsc;
360   GstByteReader stts;
361   GstByteReader stss;
362   GstByteReader stps;
363   GstByteReader ctts;
364
365   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
366   gint64 stbl_index;
367   /* stco */
368   guint co_size;
369   GstByteReader co_chunk;
370   guint32 first_chunk;
371   guint32 current_chunk;
372   guint32 last_chunk;
373   guint32 samples_per_chunk;
374   guint32 stsd_sample_description_id;
375   guint32 stco_sample_index;
376   /* stsz */
377   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
378   /* stsc */
379   guint32 stsc_index;
380   guint32 n_samples_per_chunk;
381   guint32 stsc_chunk_index;
382   guint32 stsc_sample_index;
383   guint64 chunk_offset;
384   /* stts */
385   guint32 stts_index;
386   guint32 stts_samples;
387   guint32 n_sample_times;
388   guint32 stts_sample_index;
389   guint64 stts_time;
390   guint32 stts_duration;
391   /* stss */
392   gboolean stss_present;
393   guint32 n_sample_syncs;
394   guint32 stss_index;
395   /* stps */
396   gboolean stps_present;
397   guint32 n_sample_partial_syncs;
398   guint32 stps_index;
399   QtDemuxRandomAccessEntry *ra_entries;
400   guint n_ra_entries;
401
402   const QtDemuxRandomAccessEntry *pending_seek;
403
404   /* ctts */
405   gboolean ctts_present;
406   guint32 n_composition_times;
407   guint32 ctts_index;
408   guint32 ctts_sample_index;
409   guint32 ctts_count;
410   gint32 ctts_soffset;
411
412   /* cslg */
413   guint32 cslg_shift;
414
415   /* fragmented */
416   gboolean parsed_trex;
417   guint32 def_sample_description_index; /* index is 1-based */
418   guint32 def_sample_duration;
419   guint32 def_sample_size;
420   guint32 def_sample_flags;
421
422   gboolean disabled;
423
424   /* stereoscopic video streams */
425   GstVideoMultiviewMode multiview_mode;
426   GstVideoMultiviewFlags multiview_flags;
427
428   /* protected streams */
429   gboolean protected;
430   guint32 protection_scheme_type;
431   guint32 protection_scheme_version;
432   gpointer protection_scheme_info;      /* specific to the protection scheme */
433   GQueue protection_scheme_event_queue;
434 };
435
436 /* Contains properties and cryptographic info for a set of samples from a
437  * track protected using Common Encryption (cenc) */
438 struct _QtDemuxCencSampleSetInfo
439 {
440   GstStructure *default_properties;
441
442   /* @crypto_info holds one GstStructure per sample */
443   GPtrArray *crypto_info;
444 };
445
446 static const gchar *
447 qt_demux_state_string (enum QtDemuxState state)
448 {
449   switch (state) {
450     case QTDEMUX_STATE_INITIAL:
451       return "<INITIAL>";
452     case QTDEMUX_STATE_HEADER:
453       return "<HEADER>";
454     case QTDEMUX_STATE_MOVIE:
455       return "<MOVIE>";
456     case QTDEMUX_STATE_BUFFER_MDAT:
457       return "<BUFFER_MDAT>";
458     default:
459       return "<UNKNOWN>";
460   }
461 }
462
463 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
464 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
465     guint32 fourcc, GstByteReader * parser);
466 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
467 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
468     guint32 fourcc, GstByteReader * parser);
469
470 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
471
472 static GstStaticPadTemplate gst_qtdemux_sink_template =
473     GST_STATIC_PAD_TEMPLATE ("sink",
474     GST_PAD_SINK,
475     GST_PAD_ALWAYS,
476     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
477         "application/x-3gp")
478     );
479
480 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
481 GST_STATIC_PAD_TEMPLATE ("video_%u",
482     GST_PAD_SRC,
483     GST_PAD_SOMETIMES,
484     GST_STATIC_CAPS_ANY);
485
486 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
487 GST_STATIC_PAD_TEMPLATE ("audio_%u",
488     GST_PAD_SRC,
489     GST_PAD_SOMETIMES,
490     GST_STATIC_CAPS_ANY);
491
492 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
493 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
494     GST_PAD_SRC,
495     GST_PAD_SOMETIMES,
496     GST_STATIC_CAPS_ANY);
497
498 #define gst_qtdemux_parent_class parent_class
499 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
500
501 static void gst_qtdemux_dispose (GObject * object);
502
503 static guint32
504 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
505     GstClockTime media_time);
506 static guint32
507 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
508     QtDemuxStream * str, gint64 media_offset);
509
510 #if 0
511 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
512 static GstIndex *gst_qtdemux_get_index (GstElement * element);
513 #endif
514 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
515     GstStateChange transition);
516 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
517 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
518     GstObject * parent, GstPadMode mode, gboolean active);
519
520 static void gst_qtdemux_loop (GstPad * pad);
521 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
522     GstBuffer * inbuf);
523 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
524     GstEvent * event);
525 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
526 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
527     QtDemuxStream * stream);
528 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
529     QtDemuxStream * stream);
530 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
531     gboolean force);
532
533 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
534     const guint8 * buffer, guint length);
535 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
536     const guint8 * buffer, guint length);
537 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
538 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
539     GNode * udta);
540
541 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
542     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
543     GstTagList * list);
544 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
545     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
546     const guint8 * stsd_entry_data, gchar ** codec_name);
547 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
548     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
549     const guint8 * data, int len, gchar ** codec_name);
550 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
551     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
552     gchar ** codec_name);
553 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
554     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
555     const guint8 * stsd_entry_data, gchar ** codec_name);
556
557 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
558     QtDemuxStream * stream, guint32 n);
559 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
560 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
561     QtDemuxStream * stream);
562 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
563     QtDemuxStream * stream);
564 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
565 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
566 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
567     QtDemuxStream * stream);
568 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
569     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
570 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
571     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
572     GstClockTime * _start, GstClockTime * _stop);
573 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
574     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
575
576 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
577 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
578
579 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
580
581 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
582     QtDemuxStream * stream, guint sample_index);
583 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
584     const gchar * id);
585 static void qtdemux_gst_structure_free (GstStructure * gststructure);
586
587 static void
588 gst_qtdemux_class_init (GstQTDemuxClass * klass)
589 {
590   GObjectClass *gobject_class;
591   GstElementClass *gstelement_class;
592
593   gobject_class = (GObjectClass *) klass;
594   gstelement_class = (GstElementClass *) klass;
595
596   parent_class = g_type_class_peek_parent (klass);
597
598   gobject_class->dispose = gst_qtdemux_dispose;
599
600   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
601 #if 0
602   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
603   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
604 #endif
605
606   gst_tag_register_musicbrainz_tags ();
607
608   gst_element_class_add_static_pad_template (gstelement_class,
609       &gst_qtdemux_sink_template);
610   gst_element_class_add_static_pad_template (gstelement_class,
611       &gst_qtdemux_videosrc_template);
612   gst_element_class_add_static_pad_template (gstelement_class,
613       &gst_qtdemux_audiosrc_template);
614   gst_element_class_add_static_pad_template (gstelement_class,
615       &gst_qtdemux_subsrc_template);
616   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
617       "Codec/Demuxer",
618       "Demultiplex a QuickTime file into audio and video streams",
619       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
620
621   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
622
623 }
624
625 static void
626 gst_qtdemux_init (GstQTDemux * qtdemux)
627 {
628   qtdemux->sinkpad =
629       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
630   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
631   gst_pad_set_activatemode_function (qtdemux->sinkpad,
632       qtdemux_sink_activate_mode);
633   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
634   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
635   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
636
637   qtdemux->state = QTDEMUX_STATE_INITIAL;
638   qtdemux->pullbased = FALSE;
639   qtdemux->posted_redirect = FALSE;
640   qtdemux->neededbytes = 16;
641   qtdemux->todrop = 0;
642   qtdemux->adapter = gst_adapter_new ();
643   qtdemux->offset = 0;
644   qtdemux->first_mdat = -1;
645   qtdemux->got_moov = FALSE;
646   qtdemux->mdatoffset = -1;
647   qtdemux->mdatbuffer = NULL;
648   qtdemux->restoredata_buffer = NULL;
649   qtdemux->restoredata_offset = -1;
650   qtdemux->fragment_start = -1;
651   qtdemux->fragment_start_offset = -1;
652   qtdemux->media_caps = NULL;
653   qtdemux->exposed = FALSE;
654   qtdemux->mss_mode = FALSE;
655   qtdemux->pending_newsegment = NULL;
656   qtdemux->upstream_format_is_time = FALSE;
657   qtdemux->have_group_id = FALSE;
658   qtdemux->group_id = G_MAXUINT;
659   qtdemux->cenc_aux_info_offset = 0;
660   qtdemux->cenc_aux_info_sizes = NULL;
661   qtdemux->cenc_aux_sample_count = 0;
662   qtdemux->protection_system_ids = NULL;
663   g_queue_init (&qtdemux->protection_event_queue);
664   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
665   qtdemux->tag_list = gst_tag_list_new_empty ();
666   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
667   qtdemux->flowcombiner = gst_flow_combiner_new ();
668
669   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
670 }
671
672 static void
673 gst_qtdemux_dispose (GObject * object)
674 {
675   GstQTDemux *qtdemux = GST_QTDEMUX (object);
676
677   if (qtdemux->adapter) {
678     g_object_unref (G_OBJECT (qtdemux->adapter));
679     qtdemux->adapter = NULL;
680   }
681   gst_tag_list_unref (qtdemux->tag_list);
682   gst_flow_combiner_free (qtdemux->flowcombiner);
683   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
684       NULL);
685   g_queue_clear (&qtdemux->protection_event_queue);
686
687   g_free (qtdemux->cenc_aux_info_sizes);
688   qtdemux->cenc_aux_info_sizes = NULL;
689
690   G_OBJECT_CLASS (parent_class)->dispose (object);
691 }
692
693 static void
694 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
695 {
696   if (qtdemux->posted_redirect) {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found, a redirect message has been posted"));
700   } else {
701     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
702         (_("This file contains no playable streams.")),
703         ("no known streams found"));
704   }
705 }
706
707 static GstBuffer *
708 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
709 {
710   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
711       mem, size, 0, size, mem, free_func);
712 }
713
714 static GstFlowReturn
715 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
716     GstBuffer ** buf)
717 {
718   GstFlowReturn flow;
719   GstMapInfo map;
720   gsize bsize;
721
722   if (G_UNLIKELY (size == 0)) {
723     GstFlowReturn ret;
724     GstBuffer *tmp = NULL;
725
726     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
727     if (ret != GST_FLOW_OK)
728       return ret;
729
730     gst_buffer_map (tmp, &map, GST_MAP_READ);
731     size = QT_UINT32 (map.data);
732     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
733
734     gst_buffer_unmap (tmp, &map);
735     gst_buffer_unref (tmp);
736   }
737
738   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
739   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
740     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
741       /* we're pulling header but already got most interesting bits,
742        * so never mind the rest (e.g. tags) (that much) */
743       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
744           size);
745       return GST_FLOW_EOS;
746     } else {
747       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
748           (_("This file is invalid and cannot be played.")),
749           ("atom has bogus size %" G_GUINT64_FORMAT, size));
750       return GST_FLOW_ERROR;
751     }
752   }
753
754   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
755
756   if (G_UNLIKELY (flow != GST_FLOW_OK))
757     return flow;
758
759   bsize = gst_buffer_get_size (*buf);
760   /* Catch short reads - we don't want any partial atoms */
761   if (G_UNLIKELY (bsize < size)) {
762     GST_WARNING_OBJECT (qtdemux,
763         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
764     gst_buffer_unref (*buf);
765     *buf = NULL;
766     return GST_FLOW_EOS;
767   }
768
769   return flow;
770 }
771
772 #if 1
773 static gboolean
774 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
775     GstFormat src_format, gint64 src_value, GstFormat dest_format,
776     gint64 * dest_value)
777 {
778   gboolean res = TRUE;
779   QtDemuxStream *stream = gst_pad_get_element_private (pad);
780   gint32 index;
781
782   if (stream->subtype != FOURCC_vide) {
783     res = FALSE;
784     goto done;
785   }
786
787   switch (src_format) {
788     case GST_FORMAT_TIME:
789       switch (dest_format) {
790         case GST_FORMAT_BYTES:{
791           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
792           if (-1 == index) {
793             res = FALSE;
794             goto done;
795           }
796
797           *dest_value = stream->samples[index].offset;
798
799           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
800               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
801               GST_TIME_ARGS (src_value), *dest_value);
802           break;
803         }
804         default:
805           res = FALSE;
806           break;
807       }
808       break;
809     case GST_FORMAT_BYTES:
810       switch (dest_format) {
811         case GST_FORMAT_TIME:{
812           index =
813               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
814               stream, src_value);
815
816           if (-1 == index) {
817             res = FALSE;
818             goto done;
819           }
820
821           *dest_value =
822               QTSTREAMTIME_TO_GSTTIME (stream,
823               stream->samples[index].timestamp);
824           GST_DEBUG_OBJECT (qtdemux,
825               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
826               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
827           break;
828         }
829         default:
830           res = FALSE;
831           break;
832       }
833       break;
834     default:
835       res = FALSE;
836       break;
837   }
838
839 done:
840   return res;
841 }
842 #endif
843
844 static gboolean
845 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
846 {
847   gboolean res = FALSE;
848
849   *duration = GST_CLOCK_TIME_NONE;
850
851   if (qtdemux->duration != 0 &&
852       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
853     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
854     res = TRUE;
855   } else {
856     *duration = GST_CLOCK_TIME_NONE;
857   }
858
859   return res;
860 }
861
862 static gboolean
863 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
864     GstQuery * query)
865 {
866   gboolean res = FALSE;
867   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
868
869   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
870
871   switch (GST_QUERY_TYPE (query)) {
872     case GST_QUERY_POSITION:{
873       GstFormat fmt;
874
875       gst_query_parse_position (query, &fmt, NULL);
876       if (fmt == GST_FORMAT_TIME
877           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
878         gst_query_set_position (query, GST_FORMAT_TIME,
879             qtdemux->segment.position);
880         res = TRUE;
881       }
882     }
883       break;
884     case GST_QUERY_DURATION:{
885       GstFormat fmt;
886
887       gst_query_parse_duration (query, &fmt, NULL);
888       if (fmt == GST_FORMAT_TIME) {
889         /* First try to query upstream */
890         res = gst_pad_query_default (pad, parent, query);
891         if (!res) {
892           GstClockTime duration;
893           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
894             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
895             res = TRUE;
896           }
897         }
898       }
899       break;
900     }
901     case GST_QUERY_CONVERT:{
902       GstFormat src_fmt, dest_fmt;
903       gint64 src_value, dest_value = 0;
904
905       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
906
907       res = gst_qtdemux_src_convert (qtdemux, pad,
908           src_fmt, src_value, dest_fmt, &dest_value);
909       if (res)
910         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
911
912       break;
913     }
914     case GST_QUERY_FORMATS:
915       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
916       res = TRUE;
917       break;
918     case GST_QUERY_SEEKING:{
919       GstFormat fmt;
920       gboolean seekable;
921
922       /* try upstream first */
923       res = gst_pad_query_default (pad, parent, query);
924
925       if (!res) {
926         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
927         if (fmt == GST_FORMAT_TIME) {
928           GstClockTime duration;
929
930           gst_qtdemux_get_duration (qtdemux, &duration);
931           seekable = TRUE;
932           if (!qtdemux->pullbased) {
933             GstQuery *q;
934
935             /* we might be able with help from upstream */
936             seekable = FALSE;
937             q = gst_query_new_seeking (GST_FORMAT_BYTES);
938             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
939               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
940               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
941             }
942             gst_query_unref (q);
943           }
944           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
945           res = TRUE;
946         }
947       }
948       break;
949     }
950     case GST_QUERY_SEGMENT:
951     {
952       GstFormat format;
953       gint64 start, stop;
954
955       format = qtdemux->segment.format;
956
957       start =
958           gst_segment_to_stream_time (&qtdemux->segment, format,
959           qtdemux->segment.start);
960       if ((stop = qtdemux->segment.stop) == -1)
961         stop = qtdemux->segment.duration;
962       else
963         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
964
965       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
966       res = TRUE;
967       break;
968     }
969     default:
970       res = gst_pad_query_default (pad, parent, query);
971       break;
972   }
973
974   return res;
975 }
976
977 static void
978 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
979 {
980   if (G_LIKELY (stream->pad)) {
981     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
982         GST_DEBUG_PAD_NAME (stream->pad));
983
984     if (!gst_tag_list_is_empty (stream->stream_tags)) {
985       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
986           stream->stream_tags);
987       gst_pad_push_event (stream->pad,
988           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
989     }
990
991     if (G_UNLIKELY (stream->send_global_tags)) {
992       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
993           qtdemux->tag_list);
994       gst_pad_push_event (stream->pad,
995           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
996       stream->send_global_tags = FALSE;
997     }
998   }
999 }
1000
1001 /* push event on all source pads; takes ownership of the event */
1002 static void
1003 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1004 {
1005   guint n;
1006   gboolean has_valid_stream = FALSE;
1007   GstEventType etype = GST_EVENT_TYPE (event);
1008
1009   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1010       GST_EVENT_TYPE_NAME (event));
1011
1012   for (n = 0; n < qtdemux->n_streams; n++) {
1013     GstPad *pad;
1014     QtDemuxStream *stream = qtdemux->streams[n];
1015     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1016
1017     if ((pad = stream->pad)) {
1018       has_valid_stream = TRUE;
1019
1020       if (etype == GST_EVENT_EOS) {
1021         /* let's not send twice */
1022         if (stream->sent_eos)
1023           continue;
1024         stream->sent_eos = TRUE;
1025       }
1026
1027       gst_pad_push_event (pad, gst_event_ref (event));
1028     }
1029   }
1030
1031   gst_event_unref (event);
1032
1033   /* if it is EOS and there are no pads, post an error */
1034   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1035     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1036   }
1037 }
1038
1039 /* push a pending newsegment event, if any from the streaming thread */
1040 static void
1041 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1042 {
1043   if (qtdemux->pending_newsegment) {
1044     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1045     qtdemux->pending_newsegment = NULL;
1046   }
1047 }
1048
1049 typedef struct
1050 {
1051   guint64 media_time;
1052 } FindData;
1053
1054 static gint
1055 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1056 {
1057   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1058     return 1;
1059   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1060     return 0;
1061
1062   return -1;
1063 }
1064
1065 /* find the index of the sample that includes the data for @media_time using a
1066  * binary search.  Only to be called in optimized cases of linear search below.
1067  *
1068  * Returns the index of the sample.
1069  */
1070 static guint32
1071 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1072     guint64 media_time)
1073 {
1074   QtDemuxSample *result;
1075   guint32 index;
1076
1077   /* convert media_time to mov format */
1078   media_time =
1079       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1080
1081   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1082       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1083       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1084
1085   if (G_LIKELY (result))
1086     index = result - str->samples;
1087   else
1088     index = 0;
1089
1090   return index;
1091 }
1092
1093
1094
1095 /* find the index of the sample that includes the data for @media_offset using a
1096  * linear search
1097  *
1098  * Returns the index of the sample.
1099  */
1100 static guint32
1101 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1102     QtDemuxStream * str, gint64 media_offset)
1103 {
1104   QtDemuxSample *result = str->samples;
1105   guint32 index = 0;
1106
1107   if (result == NULL || str->n_samples == 0)
1108     return -1;
1109
1110   if (media_offset == result->offset)
1111     return index;
1112
1113   result++;
1114   while (index < str->n_samples - 1) {
1115     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1116       goto parse_failed;
1117
1118     if (media_offset < result->offset)
1119       break;
1120
1121     index++;
1122     result++;
1123   }
1124   return index;
1125
1126   /* ERRORS */
1127 parse_failed:
1128   {
1129     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1130     return -1;
1131   }
1132 }
1133
1134 /* find the index of the sample that includes the data for @media_time using a
1135  * linear search, and keeping in mind that not all samples may have been parsed
1136  * yet.  If possible, it will delegate to binary search.
1137  *
1138  * Returns the index of the sample.
1139  */
1140 static guint32
1141 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1142     GstClockTime media_time)
1143 {
1144   guint32 index = 0;
1145   guint64 mov_time;
1146   QtDemuxSample *sample;
1147
1148   /* convert media_time to mov format */
1149   mov_time =
1150       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1151
1152   sample = str->samples;
1153   if (mov_time == sample->timestamp + sample->pts_offset)
1154     return index;
1155
1156   /* use faster search if requested time in already parsed range */
1157   sample = str->samples + str->stbl_index;
1158   if (str->stbl_index >= 0 &&
1159       mov_time <= (sample->timestamp + sample->pts_offset))
1160     return gst_qtdemux_find_index (qtdemux, str, media_time);
1161
1162   while (index < str->n_samples - 1) {
1163     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1164       goto parse_failed;
1165
1166     sample = str->samples + index + 1;
1167     if (mov_time < (sample->timestamp + sample->pts_offset))
1168       break;
1169
1170     index++;
1171   }
1172   return index;
1173
1174   /* ERRORS */
1175 parse_failed:
1176   {
1177     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1178     return -1;
1179   }
1180 }
1181
1182 /* find the index of the keyframe needed to decode the sample at @index
1183  * of stream @str, or of a subsequent keyframe (depending on @next)
1184  *
1185  * Returns the index of the keyframe.
1186  */
1187 static guint32
1188 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1189     guint32 index, gboolean next)
1190 {
1191   guint32 new_index = index;
1192
1193   if (index >= str->n_samples) {
1194     new_index = str->n_samples;
1195     goto beach;
1196   }
1197
1198   /* all keyframes, return index */
1199   if (str->all_keyframe) {
1200     new_index = index;
1201     goto beach;
1202   }
1203
1204   /* else search until we have a keyframe */
1205   while (new_index < str->n_samples) {
1206     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1207       goto parse_failed;
1208
1209     if (str->samples[new_index].keyframe)
1210       break;
1211
1212     if (new_index == 0)
1213       break;
1214
1215     if (next)
1216       new_index++;
1217     else
1218       new_index--;
1219   }
1220
1221   if (new_index == str->n_samples) {
1222     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1223     new_index = -1;
1224   }
1225
1226 beach:
1227   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1228       "gave %u", next ? "after" : "before", index, new_index);
1229
1230   return new_index;
1231
1232   /* ERRORS */
1233 parse_failed:
1234   {
1235     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1236     return -1;
1237   }
1238 }
1239
1240 /* find the segment for @time_position for @stream
1241  *
1242  * Returns the index of the segment containing @time_position.
1243  * Returns the last segment and sets the @eos variable to TRUE
1244  * if the time is beyond the end. @eos may be NULL
1245  */
1246 static guint32
1247 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1248     GstClockTime time_position)
1249 {
1250   gint i;
1251   guint32 seg_idx;
1252
1253   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1254       GST_TIME_ARGS (time_position));
1255
1256   seg_idx = -1;
1257   for (i = 0; i < stream->n_segments; i++) {
1258     QtDemuxSegment *segment = &stream->segments[i];
1259
1260     GST_LOG_OBJECT (stream->pad,
1261         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1262         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1263
1264     /* For the last segment we include stop_time in the last segment */
1265     if (i < stream->n_segments - 1) {
1266       if (segment->time <= time_position && time_position < segment->stop_time) {
1267         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1268         seg_idx = i;
1269         break;
1270       }
1271     } else {
1272       /* Last segment always matches */
1273       seg_idx = i;
1274       break;
1275     }
1276   }
1277   return seg_idx;
1278 }
1279
1280 /* move the stream @str to the sample position @index.
1281  *
1282  * Updates @str->sample_index and marks discontinuity if needed.
1283  */
1284 static void
1285 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1286     guint32 index)
1287 {
1288   /* no change needed */
1289   if (index == str->sample_index)
1290     return;
1291
1292   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1293       str->n_samples);
1294
1295   /* position changed, we have a discont */
1296   str->sample_index = index;
1297   str->offset_in_sample = 0;
1298   /* Each time we move in the stream we store the position where we are
1299    * starting from */
1300   str->from_sample = index;
1301   str->discont = TRUE;
1302 }
1303
1304 static void
1305 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1306     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1307 {
1308   guint64 min_offset;
1309   gint64 min_byte_offset = -1;
1310   gint n;
1311
1312   min_offset = desired_time;
1313
1314   /* for each stream, find the index of the sample in the segment
1315    * and move back to the previous keyframe. */
1316   for (n = 0; n < qtdemux->n_streams; n++) {
1317     QtDemuxStream *str;
1318     guint32 index, kindex;
1319     guint32 seg_idx;
1320     GstClockTime media_start;
1321     GstClockTime media_time;
1322     GstClockTime seg_time;
1323     QtDemuxSegment *seg;
1324     gboolean empty_segment = FALSE;
1325
1326     str = qtdemux->streams[n];
1327
1328     if (CUR_STREAM (str)->sparse && !use_sparse)
1329       continue;
1330
1331     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1332     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1333
1334     /* get segment and time in the segment */
1335     seg = &str->segments[seg_idx];
1336     seg_time = (desired_time - seg->time) * seg->rate;
1337
1338     while (QTSEGMENT_IS_EMPTY (seg)) {
1339       seg_time = 0;
1340       empty_segment = TRUE;
1341       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1342           seg_idx);
1343       seg_idx++;
1344       if (seg_idx == str->n_segments)
1345         break;
1346       seg = &str->segments[seg_idx];
1347     }
1348
1349     if (seg_idx == str->n_segments) {
1350       /* FIXME track shouldn't have the last segment as empty, but if it
1351        * happens we better handle it */
1352       continue;
1353     }
1354
1355     /* get the media time in the segment */
1356     media_start = seg->media_start + seg_time;
1357
1358     /* get the index of the sample with media time */
1359     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1360     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1361         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1362         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1363         empty_segment);
1364
1365     /* shift to next frame if we are looking for next keyframe */
1366     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1367         && index < str->stbl_index)
1368       index++;
1369
1370     if (!empty_segment) {
1371       /* find previous keyframe */
1372       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1373
1374       /* we will settle for one before if none found after */
1375       if (next && kindex == -1)
1376         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1377
1378       /* if the keyframe is at a different position, we need to update the
1379        * requested seek time */
1380       if (index != kindex) {
1381         index = kindex;
1382
1383         /* get timestamp of keyframe */
1384         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1385         GST_DEBUG_OBJECT (qtdemux,
1386             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1387             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1388             str->samples[kindex].offset);
1389
1390         /* keyframes in the segment get a chance to change the
1391          * desired_offset. keyframes out of the segment are
1392          * ignored. */
1393         if (media_time >= seg->media_start) {
1394           GstClockTime seg_time;
1395
1396           /* this keyframe is inside the segment, convert back to
1397            * segment time */
1398           seg_time = (media_time - seg->media_start) + seg->time;
1399           if ((!next && (seg_time < min_offset)) ||
1400               (next && (seg_time > min_offset)))
1401             min_offset = seg_time;
1402         }
1403       }
1404     }
1405
1406     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1407       min_byte_offset = str->samples[index].offset;
1408   }
1409
1410   if (key_time)
1411     *key_time = min_offset;
1412   if (key_offset)
1413     *key_offset = min_byte_offset;
1414 }
1415
1416 static gboolean
1417 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1418     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1419 {
1420   gboolean res;
1421
1422   g_return_val_if_fail (format != NULL, FALSE);
1423   g_return_val_if_fail (cur != NULL, FALSE);
1424   g_return_val_if_fail (stop != NULL, FALSE);
1425
1426   if (*format == GST_FORMAT_TIME)
1427     return TRUE;
1428
1429   res = TRUE;
1430   if (cur_type != GST_SEEK_TYPE_NONE)
1431     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1432   if (res && stop_type != GST_SEEK_TYPE_NONE)
1433     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1434
1435   if (res)
1436     *format = GST_FORMAT_TIME;
1437
1438   return res;
1439 }
1440
1441 /* perform seek in push based mode:
1442    find BYTE position to move to based on time and delegate to upstream
1443 */
1444 static gboolean
1445 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1446 {
1447   gdouble rate;
1448   GstFormat format;
1449   GstSeekFlags flags;
1450   GstSeekType cur_type, stop_type;
1451   gint64 cur, stop, key_cur;
1452   gboolean res;
1453   gint64 byte_cur;
1454   gint64 original_stop;
1455   guint32 seqnum;
1456
1457   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1458
1459   gst_event_parse_seek (event, &rate, &format, &flags,
1460       &cur_type, &cur, &stop_type, &stop);
1461   seqnum = gst_event_get_seqnum (event);
1462
1463   /* only forward streaming and seeking is possible */
1464   if (rate <= 0)
1465     goto unsupported_seek;
1466
1467   /* convert to TIME if needed and possible */
1468   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1469           stop_type, &stop))
1470     goto no_format;
1471
1472   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1473    * the original stop position to use when upstream pushes the new segment
1474    * for this seek */
1475   original_stop = stop;
1476   stop = -1;
1477
1478   /* find reasonable corresponding BYTE position,
1479    * also try to mind about keyframes, since we can not go back a bit for them
1480    * later on */
1481   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1482    * mostly just work, but let's not yet boldly go there  ... */
1483   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1484
1485   if (byte_cur == -1)
1486     goto abort_seek;
1487
1488   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1489       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1490       stop);
1491
1492   GST_OBJECT_LOCK (qtdemux);
1493   qtdemux->seek_offset = byte_cur;
1494   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1495     qtdemux->push_seek_start = cur;
1496   } else {
1497     qtdemux->push_seek_start = key_cur;
1498   }
1499
1500   if (stop_type == GST_SEEK_TYPE_NONE) {
1501     qtdemux->push_seek_stop = qtdemux->segment.stop;
1502   } else {
1503     qtdemux->push_seek_stop = original_stop;
1504   }
1505   GST_OBJECT_UNLOCK (qtdemux);
1506
1507   /* BYTE seek event */
1508   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1509       stop_type, stop);
1510   gst_event_set_seqnum (event, seqnum);
1511   res = gst_pad_push_event (qtdemux->sinkpad, event);
1512
1513   return res;
1514
1515   /* ERRORS */
1516 abort_seek:
1517   {
1518     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1519         "seek aborted.");
1520     return FALSE;
1521   }
1522 unsupported_seek:
1523   {
1524     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1525     return FALSE;
1526   }
1527 no_format:
1528   {
1529     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1530     return FALSE;
1531   }
1532 }
1533
1534 /* perform the seek.
1535  *
1536  * We set all segment_indexes in the streams to unknown and
1537  * adjust the time_position to the desired position. this is enough
1538  * to trigger a segment switch in the streaming thread to start
1539  * streaming from the desired position.
1540  *
1541  * Keyframe seeking is a little more complicated when dealing with
1542  * segments. Ideally we want to move to the previous keyframe in
1543  * the segment but there might not be a keyframe in the segment. In
1544  * fact, none of the segments could contain a keyframe. We take a
1545  * practical approach: seek to the previous keyframe in the segment,
1546  * if there is none, seek to the beginning of the segment.
1547  *
1548  * Called with STREAM_LOCK
1549  */
1550 static gboolean
1551 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1552     guint32 seqnum, GstSeekFlags flags)
1553 {
1554   gint64 desired_offset;
1555   gint n;
1556
1557   desired_offset = segment->position;
1558
1559   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1560       GST_TIME_ARGS (desired_offset));
1561
1562   /* may not have enough fragmented info to do this adjustment,
1563    * and we can't scan (and probably should not) at this time with
1564    * possibly flushing upstream */
1565   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1566     gint64 min_offset;
1567     gboolean next, before, after;
1568
1569     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1570     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1571     next = after && !before;
1572     if (segment->rate < 0)
1573       next = !next;
1574
1575     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1576         NULL);
1577     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1578         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1579     desired_offset = min_offset;
1580   }
1581
1582   /* and set all streams to the final position */
1583   gst_flow_combiner_reset (qtdemux->flowcombiner);
1584   qtdemux->segment_seqnum = seqnum;
1585   for (n = 0; n < qtdemux->n_streams; n++) {
1586     QtDemuxStream *stream = qtdemux->streams[n];
1587
1588     stream->time_position = desired_offset;
1589     stream->accumulated_base = 0;
1590     stream->sample_index = -1;
1591     stream->offset_in_sample = 0;
1592     stream->segment_index = -1;
1593     stream->sent_eos = FALSE;
1594
1595     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1596       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1597   }
1598   segment->position = desired_offset;
1599   segment->time = desired_offset;
1600   if (segment->rate >= 0) {
1601     segment->start = desired_offset;
1602
1603     /* we stop at the end */
1604     if (segment->stop == -1)
1605       segment->stop = segment->duration;
1606   } else {
1607     segment->stop = desired_offset;
1608   }
1609
1610   if (qtdemux->fragmented)
1611     qtdemux->fragmented_seek_pending = TRUE;
1612
1613   return TRUE;
1614 }
1615
1616 /* do a seek in pull based mode */
1617 static gboolean
1618 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1619 {
1620   gdouble rate;
1621   GstFormat format;
1622   GstSeekFlags flags;
1623   GstSeekType cur_type, stop_type;
1624   gint64 cur, stop;
1625   gboolean flush;
1626   gboolean update;
1627   GstSegment seeksegment;
1628   guint32 seqnum = GST_SEQNUM_INVALID;
1629   GstEvent *flush_event;
1630   gboolean ret;
1631
1632   if (event) {
1633     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1634
1635     gst_event_parse_seek (event, &rate, &format, &flags,
1636         &cur_type, &cur, &stop_type, &stop);
1637     seqnum = gst_event_get_seqnum (event);
1638
1639     /* we have to have a format as the segment format. Try to convert
1640      * if not. */
1641     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1642             stop_type, &stop))
1643       goto no_format;
1644
1645     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1646   } else {
1647     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1648     flags = 0;
1649   }
1650
1651   flush = flags & GST_SEEK_FLAG_FLUSH;
1652
1653   /* stop streaming, either by flushing or by pausing the task */
1654   if (flush) {
1655     flush_event = gst_event_new_flush_start ();
1656     if (seqnum != GST_SEQNUM_INVALID)
1657       gst_event_set_seqnum (flush_event, seqnum);
1658     /* unlock upstream pull_range */
1659     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1660     /* make sure out loop function exits */
1661     gst_qtdemux_push_event (qtdemux, flush_event);
1662   } else {
1663     /* non flushing seek, pause the task */
1664     gst_pad_pause_task (qtdemux->sinkpad);
1665   }
1666
1667   /* wait for streaming to finish */
1668   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1669
1670   /* copy segment, we need this because we still need the old
1671    * segment when we close the current segment. */
1672   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1673
1674   if (event) {
1675     /* configure the segment with the seek variables */
1676     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1677     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1678             cur_type, cur, stop_type, stop, &update)) {
1679       ret = FALSE;
1680       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1681     } else {
1682       /* now do the seek */
1683       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1684     }
1685   } else {
1686     /* now do the seek */
1687     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1688   }
1689
1690   /* prepare for streaming again */
1691   if (flush) {
1692     flush_event = gst_event_new_flush_stop (TRUE);
1693     if (seqnum != GST_SEQNUM_INVALID)
1694       gst_event_set_seqnum (flush_event, seqnum);
1695
1696     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1697     gst_qtdemux_push_event (qtdemux, flush_event);
1698   }
1699
1700   /* commit the new segment */
1701   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1702
1703   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1704     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1705         qtdemux->segment.format, qtdemux->segment.position);
1706     if (seqnum != GST_SEQNUM_INVALID)
1707       gst_message_set_seqnum (msg, seqnum);
1708     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1709   }
1710
1711   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1712   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1713       qtdemux->sinkpad, NULL);
1714
1715   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1716
1717   return ret;
1718
1719   /* ERRORS */
1720 no_format:
1721   {
1722     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1723     return FALSE;
1724   }
1725 }
1726
1727 static gboolean
1728 qtdemux_ensure_index (GstQTDemux * qtdemux)
1729 {
1730   guint i;
1731
1732   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1733
1734   /* Build complete index */
1735   for (i = 0; i < qtdemux->n_streams; i++) {
1736     QtDemuxStream *stream = qtdemux->streams[i];
1737
1738     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1739       goto parse_error;
1740   }
1741   return TRUE;
1742
1743   /* ERRORS */
1744 parse_error:
1745   {
1746     GST_LOG_OBJECT (qtdemux,
1747         "Building complete index of stream %u for seeking failed!", i);
1748     return FALSE;
1749   }
1750 }
1751
1752 static gboolean
1753 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1754     GstEvent * event)
1755 {
1756   gboolean res = TRUE;
1757   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1758
1759   switch (GST_EVENT_TYPE (event)) {
1760     case GST_EVENT_SEEK:
1761     {
1762 #ifndef GST_DISABLE_GST_DEBUG
1763       GstClockTime ts = gst_util_get_timestamp ();
1764 #endif
1765       guint32 seqnum = gst_event_get_seqnum (event);
1766
1767       if (seqnum == qtdemux->segment_seqnum) {
1768         GST_LOG_OBJECT (pad,
1769             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1770         gst_event_unref (event);
1771         return TRUE;
1772       }
1773
1774       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1775         /* seek should be handled by upstream, we might need to re-download fragments */
1776         GST_DEBUG_OBJECT (qtdemux,
1777             "let upstream handle seek for fragmented playback");
1778         goto upstream;
1779       }
1780
1781       /* Build complete index for seeking;
1782        * if not a fragmented file at least */
1783       if (!qtdemux->fragmented)
1784         if (!qtdemux_ensure_index (qtdemux))
1785           goto index_failed;
1786 #ifndef GST_DISABLE_GST_DEBUG
1787       ts = gst_util_get_timestamp () - ts;
1788       GST_INFO_OBJECT (qtdemux,
1789           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1790 #endif
1791     }
1792       if (qtdemux->pullbased) {
1793         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1794       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1795         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1796         res = TRUE;
1797       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1798           && !qtdemux->fragmented) {
1799         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1800       } else {
1801         GST_DEBUG_OBJECT (qtdemux,
1802             "ignoring seek in push mode in current state");
1803         res = FALSE;
1804       }
1805       gst_event_unref (event);
1806       break;
1807     default:
1808     upstream:
1809       res = gst_pad_event_default (pad, parent, event);
1810       break;
1811   }
1812
1813 done:
1814   return res;
1815
1816   /* ERRORS */
1817 index_failed:
1818   {
1819     GST_ERROR_OBJECT (qtdemux, "Index failed");
1820     gst_event_unref (event);
1821     res = FALSE;
1822     goto done;
1823   }
1824 }
1825
1826 /* stream/index return sample that is min/max w.r.t. byte position,
1827  * time is min/max w.r.t. time of samples,
1828  * the latter need not be time of the former sample */
1829 static void
1830 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1831     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1832 {
1833   gint i, n, index;
1834   gint64 time, min_time;
1835   QtDemuxStream *stream;
1836
1837   min_time = -1;
1838   stream = NULL;
1839   index = -1;
1840
1841   for (n = 0; n < qtdemux->n_streams; ++n) {
1842     QtDemuxStream *str;
1843     gint inc;
1844     gboolean set_sample;
1845
1846     str = qtdemux->streams[n];
1847     set_sample = !set;
1848
1849     if (fw) {
1850       i = 0;
1851       inc = 1;
1852     } else {
1853       i = str->n_samples - 1;
1854       inc = -1;
1855     }
1856
1857     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1858       if (str->samples[i].size == 0)
1859         continue;
1860
1861       if (fw && (str->samples[i].offset < byte_pos))
1862         continue;
1863
1864       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1865         continue;
1866
1867       /* move stream to first available sample */
1868       if (set) {
1869         gst_qtdemux_move_stream (qtdemux, str, i);
1870         set_sample = TRUE;
1871       }
1872
1873       /* avoid index from sparse streams since they might be far away */
1874       if (!CUR_STREAM (str)->sparse) {
1875         /* determine min/max time */
1876         time = QTSAMPLE_PTS (str, &str->samples[i]);
1877         if (min_time == -1 || (!fw && time > min_time) ||
1878             (fw && time < min_time)) {
1879           min_time = time;
1880         }
1881
1882         /* determine stream with leading sample, to get its position */
1883         if (!stream ||
1884             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1885             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1886           stream = str;
1887           index = i;
1888         }
1889       }
1890       break;
1891     }
1892
1893     /* no sample for this stream, mark eos */
1894     if (!set_sample)
1895       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1896   }
1897
1898   if (_time)
1899     *_time = min_time;
1900   if (_stream)
1901     *_stream = stream;
1902   if (_index)
1903     *_index = index;
1904 }
1905
1906 static QtDemuxStream *
1907 _create_stream (void)
1908 {
1909   QtDemuxStream *stream;
1910
1911   stream = g_new0 (QtDemuxStream, 1);
1912   /* new streams always need a discont */
1913   stream->discont = TRUE;
1914   /* we enable clipping for raw audio/video streams */
1915   stream->need_clip = FALSE;
1916   stream->need_process = FALSE;
1917   stream->segment_index = -1;
1918   stream->time_position = 0;
1919   stream->sample_index = -1;
1920   stream->offset_in_sample = 0;
1921   stream->new_stream = TRUE;
1922   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1923   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1924   stream->protected = FALSE;
1925   stream->protection_scheme_type = 0;
1926   stream->protection_scheme_version = 0;
1927   stream->protection_scheme_info = NULL;
1928   stream->n_samples_moof = 0;
1929   stream->duration_moof = 0;
1930   stream->duration_last_moof = 0;
1931   stream->alignment = 1;
1932   stream->stream_tags = gst_tag_list_new_empty ();
1933   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1934   g_queue_init (&stream->protection_scheme_event_queue);
1935   return stream;
1936 }
1937
1938 static gboolean
1939 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1940 {
1941   GstStructure *structure;
1942   const gchar *variant;
1943   const GstCaps *mediacaps = NULL;
1944
1945   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1946
1947   structure = gst_caps_get_structure (caps, 0);
1948   variant = gst_structure_get_string (structure, "variant");
1949
1950   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1951     QtDemuxStream *stream;
1952     const GValue *value;
1953
1954     demux->fragmented = TRUE;
1955     demux->mss_mode = TRUE;
1956
1957     if (demux->n_streams > 1) {
1958       /* can't do this, we can only renegotiate for another mss format */
1959       return FALSE;
1960     }
1961
1962     value = gst_structure_get_value (structure, "media-caps");
1963     /* create stream */
1964     if (value) {
1965       const GValue *timescale_v;
1966
1967       /* TODO update when stream changes during playback */
1968
1969       if (demux->n_streams == 0) {
1970         stream = _create_stream ();
1971         demux->streams[demux->n_streams] = stream;
1972         demux->n_streams = 1;
1973         /* mss has no stsd/stsd entry, use id 0 as default */
1974         stream->stsd_entries_length = 1;
1975         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1976         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1977       } else {
1978         stream = demux->streams[0];
1979       }
1980
1981       timescale_v = gst_structure_get_value (structure, "timescale");
1982       if (timescale_v) {
1983         stream->timescale = g_value_get_uint64 (timescale_v);
1984       } else {
1985         /* default mss timescale */
1986         stream->timescale = 10000000;
1987       }
1988       demux->timescale = stream->timescale;
1989
1990       mediacaps = gst_value_get_caps (value);
1991       if (!CUR_STREAM (stream)->caps
1992           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1993         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1994             mediacaps);
1995         stream->new_caps = TRUE;
1996       }
1997       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1998       structure = gst_caps_get_structure (mediacaps, 0);
1999       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2000         stream->subtype = FOURCC_vide;
2001
2002         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2003         gst_structure_get_int (structure, "height",
2004             &CUR_STREAM (stream)->height);
2005         gst_structure_get_fraction (structure, "framerate",
2006             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2007       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2008         gint rate = 0;
2009         stream->subtype = FOURCC_soun;
2010         gst_structure_get_int (structure, "channels",
2011             &CUR_STREAM (stream)->n_channels);
2012         gst_structure_get_int (structure, "rate", &rate);
2013         CUR_STREAM (stream)->rate = rate;
2014       }
2015     }
2016     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2017   } else {
2018     demux->mss_mode = FALSE;
2019   }
2020
2021   return TRUE;
2022 }
2023
2024 static void
2025 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2026 {
2027   gint n;
2028
2029   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2030   gst_pad_stop_task (qtdemux->sinkpad);
2031
2032   if (hard || qtdemux->upstream_format_is_time) {
2033     qtdemux->state = QTDEMUX_STATE_INITIAL;
2034     qtdemux->neededbytes = 16;
2035     qtdemux->todrop = 0;
2036     qtdemux->pullbased = FALSE;
2037     qtdemux->posted_redirect = FALSE;
2038     qtdemux->first_mdat = -1;
2039     qtdemux->header_size = 0;
2040     qtdemux->mdatoffset = -1;
2041     qtdemux->restoredata_offset = -1;
2042     if (qtdemux->mdatbuffer)
2043       gst_buffer_unref (qtdemux->mdatbuffer);
2044     if (qtdemux->restoredata_buffer)
2045       gst_buffer_unref (qtdemux->restoredata_buffer);
2046     qtdemux->mdatbuffer = NULL;
2047     qtdemux->restoredata_buffer = NULL;
2048     qtdemux->mdatleft = 0;
2049     qtdemux->mdatsize = 0;
2050     if (qtdemux->comp_brands)
2051       gst_buffer_unref (qtdemux->comp_brands);
2052     qtdemux->comp_brands = NULL;
2053     qtdemux->last_moov_offset = -1;
2054     if (qtdemux->moov_node_compressed) {
2055       g_node_destroy (qtdemux->moov_node_compressed);
2056       if (qtdemux->moov_node)
2057         g_free (qtdemux->moov_node->data);
2058     }
2059     qtdemux->moov_node_compressed = NULL;
2060     if (qtdemux->moov_node)
2061       g_node_destroy (qtdemux->moov_node);
2062     qtdemux->moov_node = NULL;
2063     if (qtdemux->tag_list)
2064       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2065     qtdemux->tag_list = gst_tag_list_new_empty ();
2066     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2067 #if 0
2068     if (qtdemux->element_index)
2069       gst_object_unref (qtdemux->element_index);
2070     qtdemux->element_index = NULL;
2071 #endif
2072     qtdemux->major_brand = 0;
2073     if (qtdemux->pending_newsegment)
2074       gst_event_unref (qtdemux->pending_newsegment);
2075     qtdemux->pending_newsegment = NULL;
2076     qtdemux->upstream_format_is_time = FALSE;
2077     qtdemux->upstream_seekable = FALSE;
2078     qtdemux->upstream_size = 0;
2079
2080     qtdemux->fragment_start = -1;
2081     qtdemux->fragment_start_offset = -1;
2082     qtdemux->duration = 0;
2083     qtdemux->moof_offset = 0;
2084     qtdemux->chapters_track_id = 0;
2085     qtdemux->have_group_id = FALSE;
2086     qtdemux->group_id = G_MAXUINT;
2087
2088     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2089         NULL);
2090     g_queue_clear (&qtdemux->protection_event_queue);
2091   }
2092   qtdemux->offset = 0;
2093   gst_adapter_clear (qtdemux->adapter);
2094   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2095   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2096
2097   if (hard) {
2098     for (n = 0; n < qtdemux->n_streams; n++) {
2099       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2100       qtdemux->streams[n] = NULL;
2101     }
2102     qtdemux->n_streams = 0;
2103     qtdemux->n_video_streams = 0;
2104     qtdemux->n_audio_streams = 0;
2105     qtdemux->n_sub_streams = 0;
2106     qtdemux->exposed = FALSE;
2107     qtdemux->fragmented = FALSE;
2108     qtdemux->mss_mode = FALSE;
2109     gst_caps_replace (&qtdemux->media_caps, NULL);
2110     qtdemux->timescale = 0;
2111     qtdemux->got_moov = FALSE;
2112     if (qtdemux->protection_system_ids) {
2113       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2114       qtdemux->protection_system_ids = NULL;
2115     }
2116   } else if (qtdemux->mss_mode) {
2117     gst_flow_combiner_reset (qtdemux->flowcombiner);
2118     for (n = 0; n < qtdemux->n_streams; n++)
2119       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2120   } else {
2121     gst_flow_combiner_reset (qtdemux->flowcombiner);
2122     for (n = 0; n < qtdemux->n_streams; n++) {
2123       qtdemux->streams[n]->sent_eos = FALSE;
2124       qtdemux->streams[n]->time_position = 0;
2125       qtdemux->streams[n]->accumulated_base = 0;
2126     }
2127     if (!qtdemux->pending_newsegment) {
2128       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2129       if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
2130         gst_event_set_seqnum (qtdemux->pending_newsegment,
2131             qtdemux->segment_seqnum);
2132     }
2133   }
2134 }
2135
2136
2137 /* Maps the @segment to the qt edts internal segments and pushes
2138  * the correspnding segment event.
2139  *
2140  * If it ends up being at a empty segment, a gap will be pushed and the next
2141  * edts segment will be activated in sequence.
2142  *
2143  * To be used in push-mode only */
2144 static void
2145 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2146 {
2147   gint n, i;
2148
2149   for (n = 0; n < qtdemux->n_streams; n++) {
2150     QtDemuxStream *stream = qtdemux->streams[n];
2151
2152     stream->time_position = segment->start;
2153
2154     /* in push mode we should be guaranteed that we will have empty segments
2155      * at the beginning and then one segment after, other scenarios are not
2156      * supported and are discarded when parsing the edts */
2157     for (i = 0; i < stream->n_segments; i++) {
2158       if (stream->segments[i].stop_time > segment->start) {
2159         gst_qtdemux_activate_segment (qtdemux, stream, i,
2160             stream->time_position);
2161         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2162           /* push the empty segment and move to the next one */
2163           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2164               stream->time_position);
2165           continue;
2166         }
2167
2168         g_assert (i == stream->n_segments - 1);
2169       }
2170     }
2171   }
2172 }
2173
2174 static gboolean
2175 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2176     GstEvent * event)
2177 {
2178   GstQTDemux *demux = GST_QTDEMUX (parent);
2179   gboolean res = TRUE;
2180
2181   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2182
2183   switch (GST_EVENT_TYPE (event)) {
2184     case GST_EVENT_SEGMENT:
2185     {
2186       gint64 offset = 0;
2187       QtDemuxStream *stream;
2188       gint idx;
2189       GstSegment segment;
2190
2191       /* some debug output */
2192       gst_event_copy_segment (event, &segment);
2193       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2194           &segment);
2195
2196       /* erase any previously set segment */
2197       gst_event_replace (&demux->pending_newsegment, NULL);
2198
2199       if (segment.format == GST_FORMAT_TIME) {
2200         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2201         gst_event_replace (&demux->pending_newsegment, event);
2202         demux->upstream_format_is_time = TRUE;
2203       } else {
2204         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2205             "not in time format");
2206
2207         /* chain will send initial newsegment after pads have been added */
2208         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2209           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2210           goto exit;
2211         }
2212       }
2213
2214       /* check if this matches a time seek we received previously
2215        * FIXME for backwards compatibility reasons we use the
2216        * seek_offset here to compare. In the future we might want to
2217        * change this to use the seqnum as it uniquely should identify
2218        * the segment that corresponds to the seek. */
2219       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2220           ", received segment offset %" G_GINT64_FORMAT,
2221           demux->seek_offset, segment.start);
2222       if (segment.format == GST_FORMAT_BYTES
2223           && demux->seek_offset == segment.start) {
2224         GST_OBJECT_LOCK (demux);
2225         offset = segment.start;
2226
2227         segment.format = GST_FORMAT_TIME;
2228         segment.start = demux->push_seek_start;
2229         segment.stop = demux->push_seek_stop;
2230         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2231             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2232             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2233         GST_OBJECT_UNLOCK (demux);
2234       }
2235
2236       /* we only expect a BYTE segment, e.g. following a seek */
2237       if (segment.format == GST_FORMAT_BYTES) {
2238         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2239           offset = segment.start;
2240
2241           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2242               NULL, (gint64 *) & segment.start);
2243           if ((gint64) segment.start < 0)
2244             segment.start = 0;
2245         }
2246         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2247           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2248               NULL, (gint64 *) & segment.stop);
2249           /* keyframe seeking should already arrange for start >= stop,
2250            * but make sure in other rare cases */
2251           segment.stop = MAX (segment.stop, segment.start);
2252         }
2253       } else if (segment.format == GST_FORMAT_TIME) {
2254         /* push all data on the adapter before starting this
2255          * new segment */
2256         gst_qtdemux_process_adapter (demux, TRUE);
2257       } else {
2258         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2259         goto exit;
2260       }
2261
2262       /* We shouldn't modify upstream driven TIME FORMAT segment */
2263       if (!demux->upstream_format_is_time) {
2264         /* accept upstream's notion of segment and distribute along */
2265         segment.format = GST_FORMAT_TIME;
2266         segment.position = segment.time = segment.start;
2267         segment.duration = demux->segment.duration;
2268         segment.base = gst_segment_to_running_time (&demux->segment,
2269             GST_FORMAT_TIME, demux->segment.position);
2270       }
2271
2272       gst_segment_copy_into (&segment, &demux->segment);
2273       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2274
2275       /* map segment to internal qt segments and push on each stream */
2276       if (demux->n_streams) {
2277         if (demux->fragmented) {
2278           GstEvent *segment_event = gst_event_new_segment (&segment);
2279
2280           gst_event_replace (&demux->pending_newsegment, NULL);
2281           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2282           gst_qtdemux_push_event (demux, segment_event);
2283         } else {
2284           gst_event_replace (&demux->pending_newsegment, NULL);
2285           gst_qtdemux_map_and_push_segments (demux, &segment);
2286         }
2287       }
2288
2289       /* clear leftover in current segment, if any */
2290       gst_adapter_clear (demux->adapter);
2291
2292       /* set up streaming thread */
2293       demux->offset = offset;
2294       if (demux->upstream_format_is_time) {
2295         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2296             "set values to restart reading from a new atom");
2297         demux->neededbytes = 16;
2298         demux->todrop = 0;
2299       } else {
2300         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2301             NULL);
2302         if (stream) {
2303           demux->todrop = stream->samples[idx].offset - offset;
2304           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2305         } else {
2306           /* set up for EOS */
2307           demux->neededbytes = -1;
2308           demux->todrop = 0;
2309         }
2310       }
2311     exit:
2312       gst_event_unref (event);
2313       res = TRUE;
2314       goto drop;
2315     }
2316     case GST_EVENT_FLUSH_START:
2317     {
2318       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2319         gst_event_unref (event);
2320         goto drop;
2321       }
2322       break;
2323     }
2324     case GST_EVENT_FLUSH_STOP:
2325     {
2326       guint64 dur;
2327
2328       dur = demux->segment.duration;
2329       gst_qtdemux_reset (demux, FALSE);
2330       demux->segment.duration = dur;
2331
2332       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2333         gst_event_unref (event);
2334         goto drop;
2335       }
2336       break;
2337     }
2338     case GST_EVENT_EOS:
2339       /* If we are in push mode, and get an EOS before we've seen any streams,
2340        * then error out - we have nowhere to send the EOS */
2341       if (!demux->pullbased) {
2342         gint i;
2343         gboolean has_valid_stream = FALSE;
2344         for (i = 0; i < demux->n_streams; i++) {
2345           if (demux->streams[i]->pad != NULL) {
2346             has_valid_stream = TRUE;
2347             break;
2348           }
2349         }
2350         if (!has_valid_stream)
2351           gst_qtdemux_post_no_playable_stream_error (demux);
2352         else {
2353           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2354               (guint) gst_adapter_available (demux->adapter));
2355           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2356             res = FALSE;
2357           }
2358         }
2359       }
2360       break;
2361     case GST_EVENT_CAPS:{
2362       GstCaps *caps = NULL;
2363
2364       gst_event_parse_caps (event, &caps);
2365       gst_qtdemux_setcaps (demux, caps);
2366       res = TRUE;
2367       gst_event_unref (event);
2368       goto drop;
2369     }
2370     case GST_EVENT_PROTECTION:
2371     {
2372       const gchar *system_id = NULL;
2373
2374       gst_event_parse_protection (event, &system_id, NULL, NULL);
2375       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2376           system_id);
2377       gst_qtdemux_append_protection_system_id (demux, system_id);
2378       /* save the event for later, for source pads that have not been created */
2379       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2380       /* send it to all pads that already exist */
2381       gst_qtdemux_push_event (demux, event);
2382       res = TRUE;
2383       goto drop;
2384     }
2385     default:
2386       break;
2387   }
2388
2389   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2390
2391 drop:
2392   return res;
2393 }
2394
2395 #if 0
2396 static void
2397 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2398 {
2399   GstQTDemux *demux = GST_QTDEMUX (element);
2400
2401   GST_OBJECT_LOCK (demux);
2402   if (demux->element_index)
2403     gst_object_unref (demux->element_index);
2404   if (index) {
2405     demux->element_index = gst_object_ref (index);
2406   } else {
2407     demux->element_index = NULL;
2408   }
2409   GST_OBJECT_UNLOCK (demux);
2410   /* object lock might be taken again */
2411   if (index)
2412     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2413   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2414       demux->element_index, demux->index_id);
2415 }
2416
2417 static GstIndex *
2418 gst_qtdemux_get_index (GstElement * element)
2419 {
2420   GstIndex *result = NULL;
2421   GstQTDemux *demux = GST_QTDEMUX (element);
2422
2423   GST_OBJECT_LOCK (demux);
2424   if (demux->element_index)
2425     result = gst_object_ref (demux->element_index);
2426   GST_OBJECT_UNLOCK (demux);
2427
2428   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2429
2430   return result;
2431 }
2432 #endif
2433
2434 static void
2435 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2436 {
2437   g_free ((gpointer) stream->stco.data);
2438   stream->stco.data = NULL;
2439   g_free ((gpointer) stream->stsz.data);
2440   stream->stsz.data = NULL;
2441   g_free ((gpointer) stream->stsc.data);
2442   stream->stsc.data = NULL;
2443   g_free ((gpointer) stream->stts.data);
2444   stream->stts.data = NULL;
2445   g_free ((gpointer) stream->stss.data);
2446   stream->stss.data = NULL;
2447   g_free ((gpointer) stream->stps.data);
2448   stream->stps.data = NULL;
2449   g_free ((gpointer) stream->ctts.data);
2450   stream->ctts.data = NULL;
2451 }
2452
2453 static void
2454 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2455     QtDemuxStream * stream)
2456 {
2457   g_free (stream->segments);
2458   stream->segments = NULL;
2459   stream->segment_index = -1;
2460   stream->accumulated_base = 0;
2461 }
2462
2463 static void
2464 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2465     QtDemuxStream * stream)
2466 {
2467   g_free (stream->samples);
2468   stream->samples = NULL;
2469   gst_qtdemux_stbl_free (stream);
2470
2471   /* fragments */
2472   g_free (stream->ra_entries);
2473   stream->ra_entries = NULL;
2474   stream->n_ra_entries = 0;
2475
2476   stream->sample_index = -1;
2477   stream->stbl_index = -1;
2478   stream->n_samples = 0;
2479   stream->time_position = 0;
2480
2481   stream->n_samples_moof = 0;
2482   stream->duration_moof = 0;
2483   stream->duration_last_moof = 0;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2488 {
2489   gint i;
2490   if (stream->allocator)
2491     gst_object_unref (stream->allocator);
2492   while (stream->buffers) {
2493     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2494     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2495   }
2496   for (i = 0; i < stream->stsd_entries_length; i++) {
2497     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2498     if (entry->rgb8_palette) {
2499       gst_memory_unref (entry->rgb8_palette);
2500       entry->rgb8_palette = NULL;
2501     }
2502     entry->sparse = FALSE;
2503   }
2504
2505   gst_tag_list_unref (stream->stream_tags);
2506   stream->stream_tags = gst_tag_list_new_empty ();
2507   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2508   g_free (stream->redirect_uri);
2509   stream->redirect_uri = NULL;
2510   stream->sent_eos = FALSE;
2511   stream->protected = FALSE;
2512   if (stream->protection_scheme_info) {
2513     if (stream->protection_scheme_type == FOURCC_cenc) {
2514       QtDemuxCencSampleSetInfo *info =
2515           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2516       if (info->default_properties)
2517         gst_structure_free (info->default_properties);
2518       if (info->crypto_info)
2519         g_ptr_array_free (info->crypto_info, TRUE);
2520     }
2521     g_free (stream->protection_scheme_info);
2522     stream->protection_scheme_info = NULL;
2523   }
2524   stream->protection_scheme_type = 0;
2525   stream->protection_scheme_version = 0;
2526   g_queue_foreach (&stream->protection_scheme_event_queue,
2527       (GFunc) gst_event_unref, NULL);
2528   g_queue_clear (&stream->protection_scheme_event_queue);
2529   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2530   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2531 }
2532
2533 static void
2534 gst_qtdemux_stream_reset (GstQTDemux * qtdemux, QtDemuxStream * stream)
2535 {
2536   gint i;
2537   gst_qtdemux_stream_clear (qtdemux, stream);
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->caps) {
2541       gst_caps_unref (entry->caps);
2542       entry->caps = NULL;
2543     }
2544   }
2545   g_free (stream->stsd_entries);
2546   stream->stsd_entries = NULL;
2547   stream->stsd_entries_length = 0;
2548 }
2549
2550
2551 static void
2552 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2553 {
2554   gst_qtdemux_stream_reset (qtdemux, stream);
2555   gst_tag_list_unref (stream->stream_tags);
2556   if (stream->pad) {
2557     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2558     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2559   }
2560   g_free (stream);
2561 }
2562
2563 static void
2564 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2565 {
2566   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2567
2568   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2569   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2570   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2571   qtdemux->n_streams--;
2572 }
2573
2574 static GstStateChangeReturn
2575 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2576 {
2577   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2578   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2579
2580   switch (transition) {
2581     case GST_STATE_CHANGE_PAUSED_TO_READY:
2582       break;
2583     default:
2584       break;
2585   }
2586
2587   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2588
2589   switch (transition) {
2590     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2591       gst_qtdemux_reset (qtdemux, TRUE);
2592       break;
2593     }
2594     default:
2595       break;
2596   }
2597
2598   return result;
2599 }
2600
2601 static void
2602 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2603 {
2604   /* counts as header data */
2605   qtdemux->header_size += length;
2606
2607   /* only consider at least a sufficiently complete ftyp atom */
2608   if (length >= 20) {
2609     GstBuffer *buf;
2610
2611     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2612     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2613         GST_FOURCC_ARGS (qtdemux->major_brand));
2614     if (qtdemux->comp_brands)
2615       gst_buffer_unref (qtdemux->comp_brands);
2616     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2617     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2618   }
2619 }
2620
2621 static void
2622 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2623     GstTagList * xmptaglist)
2624 {
2625   /* Strip out bogus fields */
2626   if (xmptaglist) {
2627     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2628       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2629       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2630     } else {
2631       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2632     }
2633
2634     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2635
2636     /* prioritize native tags using _KEEP mode */
2637     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2638     gst_tag_list_unref (xmptaglist);
2639   }
2640 }
2641
2642 static void
2643 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2644     guint offset)
2645 {
2646   GstByteReader br;
2647   guint8 version;
2648   guint32 flags = 0;
2649   guint i;
2650   guint8 iv_size = 8;
2651   QtDemuxStream *stream;
2652   GstStructure *structure;
2653   QtDemuxCencSampleSetInfo *ss_info = NULL;
2654   const gchar *system_id;
2655   gboolean uses_sub_sample_encryption = FALSE;
2656
2657   if (qtdemux->n_streams == 0)
2658     return;
2659
2660   stream = qtdemux->streams[0];
2661
2662   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2663   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2664     GST_WARNING_OBJECT (qtdemux,
2665         "Attempting PIFF box parsing on an unencrypted stream.");
2666     return;
2667   }
2668
2669   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2670       G_TYPE_STRING, &system_id, NULL);
2671   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2672
2673   stream->protected = TRUE;
2674   stream->protection_scheme_type = FOURCC_cenc;
2675
2676   if (!stream->protection_scheme_info)
2677     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2678
2679   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2680
2681   if (ss_info->default_properties)
2682     gst_structure_free (ss_info->default_properties);
2683
2684   ss_info->default_properties =
2685       gst_structure_new ("application/x-cenc",
2686       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2687
2688   if (ss_info->crypto_info) {
2689     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2690     g_ptr_array_free (ss_info->crypto_info, TRUE);
2691     ss_info->crypto_info = NULL;
2692   }
2693
2694   /* skip UUID */
2695   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2696
2697   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2698     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2699     return;
2700   }
2701
2702   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2703     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2704     return;
2705   }
2706
2707   if ((flags & 0x000001)) {
2708     guint32 algorithm_id = 0;
2709     const guint8 *kid;
2710     GstBuffer *kid_buf;
2711     gboolean is_encrypted = TRUE;
2712
2713     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2714       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2715       return;
2716     }
2717
2718     algorithm_id >>= 8;
2719     if (algorithm_id == 0) {
2720       is_encrypted = FALSE;
2721     } else if (algorithm_id == 1) {
2722       /* FIXME: maybe store this in properties? */
2723       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2724     } else if (algorithm_id == 2) {
2725       /* FIXME: maybe store this in properties? */
2726       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2727     }
2728
2729     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2730       return;
2731
2732     if (!gst_byte_reader_get_data (&br, 16, &kid))
2733       return;
2734
2735     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2736     gst_buffer_fill (kid_buf, 0, kid, 16);
2737     if (ss_info->default_properties)
2738       gst_structure_free (ss_info->default_properties);
2739     ss_info->default_properties =
2740         gst_structure_new ("application/x-cenc",
2741         "iv_size", G_TYPE_UINT, iv_size,
2742         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2743         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2744     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2745         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2746     gst_buffer_unref (kid_buf);
2747   } else if ((flags & 0x000002)) {
2748     uses_sub_sample_encryption = TRUE;
2749   }
2750
2751   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2752     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2753     return;
2754   }
2755
2756   ss_info->crypto_info =
2757       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2758       (GDestroyNotify) qtdemux_gst_structure_free);
2759
2760   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2761     GstStructure *properties;
2762     guint8 *data;
2763     GstBuffer *buf;
2764
2765     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2766     if (properties == NULL) {
2767       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2768       return;
2769     }
2770
2771     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2772       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2773       gst_structure_free (properties);
2774       return;
2775     }
2776     buf = gst_buffer_new_wrapped (data, iv_size);
2777     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2778     gst_buffer_unref (buf);
2779
2780     if (uses_sub_sample_encryption) {
2781       guint16 n_subsamples;
2782
2783       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2784           || n_subsamples == 0) {
2785         GST_ERROR_OBJECT (qtdemux,
2786             "failed to get subsample count for sample %u", i);
2787         gst_structure_free (properties);
2788         return;
2789       }
2790       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2791       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2792         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2793             i);
2794         gst_structure_free (properties);
2795         return;
2796       }
2797       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2798       gst_structure_set (properties,
2799           "subsample_count", G_TYPE_UINT, n_subsamples,
2800           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2801       gst_buffer_unref (buf);
2802     } else {
2803       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2804     }
2805
2806     g_ptr_array_add (ss_info->crypto_info, properties);
2807   }
2808 }
2809
2810 static void
2811 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2812 {
2813   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2814     0x97, 0xA9, 0x42, 0xE8,
2815     0x9C, 0x71, 0x99, 0x94,
2816     0x91, 0xE3, 0xAF, 0xAC
2817   };
2818   static const guint8 playready_uuid[] = {
2819     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2820     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2821   };
2822
2823   static const guint8 piff_sample_encryption_uuid[] = {
2824     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2825     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2826   };
2827
2828   guint offset;
2829
2830   /* counts as header data */
2831   qtdemux->header_size += length;
2832
2833   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2834
2835   if (length <= offset + 16) {
2836     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2837     return;
2838   }
2839
2840   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2841     GstBuffer *buf;
2842     GstTagList *taglist;
2843
2844     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2845         length - offset - 16, NULL);
2846     taglist = gst_tag_list_from_xmp_buffer (buf);
2847     gst_buffer_unref (buf);
2848
2849     /* make sure we have a usable taglist */
2850     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2851
2852     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2853
2854   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2855     int len;
2856     const gunichar2 *s_utf16;
2857     char *contents;
2858
2859     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2860     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2861     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2862     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2863
2864     g_free (contents);
2865
2866     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2867         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2868         (NULL));
2869   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2870     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2871   } else {
2872     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2873         GST_READ_UINT32_LE (buffer + offset),
2874         GST_READ_UINT32_LE (buffer + offset + 4),
2875         GST_READ_UINT32_LE (buffer + offset + 8),
2876         GST_READ_UINT32_LE (buffer + offset + 12));
2877   }
2878 }
2879
2880 static void
2881 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2882 {
2883   GstSidxParser sidx_parser;
2884   GstIsoffParserResult res;
2885   guint consumed;
2886
2887   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2888
2889   res =
2890       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2891       &consumed);
2892   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2893   if (res == GST_ISOFF_QT_PARSER_DONE) {
2894     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2895   }
2896   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2897 }
2898
2899 /* caller verifies at least 8 bytes in buf */
2900 static void
2901 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2902     guint64 * plength, guint32 * pfourcc)
2903 {
2904   guint64 length;
2905   guint32 fourcc;
2906
2907   length = QT_UINT32 (data);
2908   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2909   fourcc = QT_FOURCC (data + 4);
2910   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2911
2912   if (length == 0) {
2913     length = G_MAXUINT64;
2914   } else if (length == 1 && size >= 16) {
2915     /* this means we have an extended size, which is the 64 bit value of
2916      * the next 8 bytes */
2917     length = QT_UINT64 (data + 8);
2918     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2919   }
2920
2921   if (plength)
2922     *plength = length;
2923   if (pfourcc)
2924     *pfourcc = fourcc;
2925 }
2926
2927 static gboolean
2928 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2929 {
2930   guint32 version = 0;
2931   GstClockTime duration = 0;
2932
2933   if (!gst_byte_reader_get_uint32_be (br, &version))
2934     goto failed;
2935
2936   version >>= 24;
2937   if (version == 1) {
2938     if (!gst_byte_reader_get_uint64_be (br, &duration))
2939       goto failed;
2940   } else {
2941     guint32 dur = 0;
2942
2943     if (!gst_byte_reader_get_uint32_be (br, &dur))
2944       goto failed;
2945     duration = dur;
2946   }
2947
2948   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2949   qtdemux->duration = duration;
2950
2951   return TRUE;
2952
2953 failed:
2954   {
2955     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2956     return FALSE;
2957   }
2958 }
2959
2960 static gboolean
2961 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2962     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2963 {
2964   if (!stream->parsed_trex && qtdemux->moov_node) {
2965     GNode *mvex, *trex;
2966     GstByteReader trex_data;
2967
2968     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2969     if (mvex) {
2970       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2971           &trex_data);
2972       while (trex) {
2973         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2974
2975         /* skip version/flags */
2976         if (!gst_byte_reader_skip (&trex_data, 4))
2977           goto next;
2978         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2979           goto next;
2980         if (id != stream->track_id)
2981           goto next;
2982         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2983           goto next;
2984         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2985           goto next;
2986         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2987           goto next;
2988         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2989           goto next;
2990
2991         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2992             "duration %d,  size %d, flags 0x%x", stream->track_id,
2993             dur, size, flags);
2994
2995         stream->parsed_trex = TRUE;
2996         stream->def_sample_description_index = sdi;
2997         stream->def_sample_duration = dur;
2998         stream->def_sample_size = size;
2999         stream->def_sample_flags = flags;
3000
3001       next:
3002         /* iterate all siblings */
3003         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3004             &trex_data);
3005       }
3006     }
3007   }
3008
3009   *ds_duration = stream->def_sample_duration;
3010   *ds_size = stream->def_sample_size;
3011   *ds_flags = stream->def_sample_flags;
3012
3013   /* even then, above values are better than random ... */
3014   if (G_UNLIKELY (!stream->parsed_trex)) {
3015     GST_WARNING_OBJECT (qtdemux,
3016         "failed to find fragment defaults for stream %d", stream->track_id);
3017     return FALSE;
3018   }
3019
3020   return TRUE;
3021 }
3022
3023 /* This method should be called whenever a more accurate duration might
3024  * have been found. It will update all relevant variables if/where needed
3025  */
3026 static void
3027 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3028 {
3029   guint i;
3030   guint64 movdur;
3031   GstClockTime prevdur;
3032
3033   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3034
3035   if (movdur > qtdemux->duration) {
3036     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3037     GST_DEBUG_OBJECT (qtdemux,
3038         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3039         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3040     qtdemux->duration = movdur;
3041     GST_DEBUG_OBJECT (qtdemux,
3042         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3043         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3044         GST_TIME_ARGS (qtdemux->segment.stop));
3045     if (qtdemux->segment.duration == prevdur) {
3046       /* If the current segment has duration/stop identical to previous duration
3047        * update them also (because they were set at that point in time with
3048        * the wrong duration */
3049       /* We convert the value *from* the timescale version to avoid rounding errors */
3050       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3051       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3052       qtdemux->segment.duration = fixeddur;
3053       qtdemux->segment.stop = fixeddur;
3054     }
3055   }
3056   for (i = 0; i < qtdemux->n_streams; i++) {
3057     QtDemuxStream *stream = qtdemux->streams[i];
3058     if (stream) {
3059       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3060       if (movdur > stream->duration) {
3061         GST_DEBUG_OBJECT (qtdemux,
3062             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3063             GST_TIME_ARGS (duration));
3064         stream->duration = movdur;
3065         /* internal duration tracking state has been updated above, so */
3066         /* preserve an open-ended dummy segment rather than repeatedly updating
3067          * it and spamming downstream accordingly with segment events */
3068         if (stream->dummy_segment &&
3069             GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3070           /* Update all dummy values to new duration */
3071           stream->segments[0].stop_time = duration;
3072           stream->segments[0].duration = duration;
3073           stream->segments[0].media_stop = duration;
3074
3075           /* let downstream know we possibly have a new stop time */
3076           if (stream->segment_index != -1) {
3077             GstClockTime pos;
3078
3079             if (qtdemux->segment.rate >= 0) {
3080               pos = stream->segment.start;
3081             } else {
3082               pos = stream->segment.stop;
3083             }
3084
3085             gst_qtdemux_stream_update_segment (qtdemux, stream,
3086                 stream->segment_index, pos, NULL, NULL);
3087           }
3088         }
3089       }
3090     }
3091   }
3092 }
3093
3094 static gboolean
3095 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3096     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3097     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3098     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3099     gboolean has_tfdt)
3100 {
3101   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3102   guint64 timestamp;
3103   gint32 data_offset = 0;
3104   guint32 flags = 0, first_flags = 0, samples_count = 0;
3105   gint i;
3106   guint8 *data;
3107   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3108   QtDemuxSample *sample;
3109   gboolean ismv = FALSE;
3110   gint64 initial_offset;
3111
3112   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3113       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3114       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3115       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3116
3117   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3118     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3119     return TRUE;
3120   }
3121
3122   /* presence of stss or not can't really tell us much,
3123    * and flags and so on tend to be marginally reliable in these files */
3124   if (stream->subtype == FOURCC_soun) {
3125     GST_DEBUG_OBJECT (qtdemux,
3126         "sound track in fragmented file; marking all keyframes");
3127     stream->all_keyframe = TRUE;
3128   }
3129
3130   if (!gst_byte_reader_skip (trun, 1) ||
3131       !gst_byte_reader_get_uint24_be (trun, &flags))
3132     goto fail;
3133
3134   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3135     goto fail;
3136
3137   if (flags & TR_DATA_OFFSET) {
3138     /* note this is really signed */
3139     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3140       goto fail;
3141     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3142     /* default base offset = first byte of moof */
3143     if (*base_offset == -1) {
3144       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3145       *base_offset = moof_offset;
3146     }
3147     *running_offset = *base_offset + data_offset;
3148   } else {
3149     /* if no offset at all, that would mean data starts at moof start,
3150      * which is a bit wrong and is ismv crappy way, so compensate
3151      * assuming data is in mdat following moof */
3152     if (*base_offset == -1) {
3153       *base_offset = moof_offset + moof_length + 8;
3154       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3155       ismv = TRUE;
3156     }
3157     if (*running_offset == -1)
3158       *running_offset = *base_offset;
3159   }
3160
3161   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3162       *running_offset);
3163   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3164       data_offset, flags, samples_count);
3165
3166   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3167     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3168       GST_DEBUG_OBJECT (qtdemux,
3169           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3170       flags ^= TR_FIRST_SAMPLE_FLAGS;
3171     } else {
3172       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3173         goto fail;
3174       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3175     }
3176   }
3177
3178   /* FIXME ? spec says other bits should also be checked to determine
3179    * entry size (and prefix size for that matter) */
3180   entry_size = 0;
3181   dur_offset = size_offset = 0;
3182   if (flags & TR_SAMPLE_DURATION) {
3183     GST_LOG_OBJECT (qtdemux, "entry duration present");
3184     dur_offset = entry_size;
3185     entry_size += 4;
3186   }
3187   if (flags & TR_SAMPLE_SIZE) {
3188     GST_LOG_OBJECT (qtdemux, "entry size present");
3189     size_offset = entry_size;
3190     entry_size += 4;
3191   }
3192   if (flags & TR_SAMPLE_FLAGS) {
3193     GST_LOG_OBJECT (qtdemux, "entry flags present");
3194     flags_offset = entry_size;
3195     entry_size += 4;
3196   }
3197   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3198     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3199     ct_offset = entry_size;
3200     entry_size += 4;
3201   }
3202
3203   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3204     goto fail;
3205   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3206
3207   if (stream->n_samples + samples_count >=
3208       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3209     goto index_too_big;
3210
3211   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3212       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3213       (stream->n_samples + samples_count) *
3214       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3215
3216   /* create a new array of samples if it's the first sample parsed */
3217   if (stream->n_samples == 0) {
3218     g_assert (stream->samples == NULL);
3219     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3220     /* or try to reallocate it with space enough to insert the new samples */
3221   } else
3222     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3223         stream->n_samples + samples_count);
3224   if (stream->samples == NULL)
3225     goto out_of_memory;
3226
3227   if (qtdemux->fragment_start != -1) {
3228     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3229     qtdemux->fragment_start = -1;
3230   } else {
3231     if (stream->n_samples == 0) {
3232       if (decode_ts > 0) {
3233         timestamp = decode_ts;
3234       } else if (stream->pending_seek != NULL) {
3235         /* if we don't have a timestamp from a tfdt box, we'll use the one
3236          * from the mfra seek table */
3237         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3238             GST_TIME_ARGS (stream->pending_seek->ts));
3239
3240         /* FIXME: this is not fully correct, the timestamp refers to the random
3241          * access sample refered to in the tfra entry, which may not necessarily
3242          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3243         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3244       } else {
3245         timestamp = 0;
3246       }
3247
3248       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3249       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3250           GST_TIME_ARGS (gst_ts));
3251     } else {
3252       /* subsequent fragments extend stream */
3253       timestamp =
3254           stream->samples[stream->n_samples - 1].timestamp +
3255           stream->samples[stream->n_samples - 1].duration;
3256
3257       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3258        * difference (1 sec.) between decode_ts and timestamp, prefer the
3259        * former */
3260       if (has_tfdt && !qtdemux->upstream_format_is_time
3261           && ABSDIFF (decode_ts, timestamp) >
3262           MAX (stream->duration_last_moof / 2,
3263               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3264         GST_INFO_OBJECT (qtdemux,
3265             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3266             ") are significantly different (more than %" GST_TIME_FORMAT
3267             "), using decode_ts",
3268             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3269             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3270             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3271                     MAX (stream->duration_last_moof / 2,
3272                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3273         timestamp = decode_ts;
3274       }
3275
3276       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3277       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3278           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3279     }
3280   }
3281
3282   initial_offset = *running_offset;
3283
3284   sample = stream->samples + stream->n_samples;
3285   for (i = 0; i < samples_count; i++) {
3286     guint32 dur, size, sflags, ct;
3287
3288     /* first read sample data */
3289     if (flags & TR_SAMPLE_DURATION) {
3290       dur = QT_UINT32 (data + dur_offset);
3291     } else {
3292       dur = d_sample_duration;
3293     }
3294     if (flags & TR_SAMPLE_SIZE) {
3295       size = QT_UINT32 (data + size_offset);
3296     } else {
3297       size = d_sample_size;
3298     }
3299     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3300       if (i == 0) {
3301         sflags = first_flags;
3302       } else {
3303         sflags = d_sample_flags;
3304       }
3305     } else if (flags & TR_SAMPLE_FLAGS) {
3306       sflags = QT_UINT32 (data + flags_offset);
3307     } else {
3308       sflags = d_sample_flags;
3309     }
3310     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3311       ct = QT_UINT32 (data + ct_offset);
3312     } else {
3313       ct = 0;
3314     }
3315     data += entry_size;
3316
3317     /* fill the sample information */
3318     sample->offset = *running_offset;
3319     sample->pts_offset = ct;
3320     sample->size = size;
3321     sample->timestamp = timestamp;
3322     sample->duration = dur;
3323     /* sample-is-difference-sample */
3324     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3325      * now idea how it relates to bitfield other than massive LE/BE confusion */
3326     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3327     *running_offset += size;
3328     timestamp += dur;
3329     stream->duration_moof += dur;
3330     sample++;
3331   }
3332
3333   /* Update total duration if needed */
3334   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3335
3336   /* Pre-emptively figure out size of mdat based on trun information.
3337    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3338    * size, else we will still be able to use this when dealing with gap'ed
3339    * input */
3340   qtdemux->mdatleft = *running_offset - initial_offset;
3341   qtdemux->mdatoffset = initial_offset;
3342   qtdemux->mdatsize = qtdemux->mdatleft;
3343
3344   stream->n_samples += samples_count;
3345   stream->n_samples_moof += samples_count;
3346
3347   if (stream->pending_seek != NULL)
3348     stream->pending_seek = NULL;
3349
3350   return TRUE;
3351
3352 fail:
3353   {
3354     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3355     return FALSE;
3356   }
3357 out_of_memory:
3358   {
3359     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3360         stream->n_samples);
3361     return FALSE;
3362   }
3363 index_too_big:
3364   {
3365     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3366         "be larger than %uMB (broken file?)", stream->n_samples,
3367         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3368     return FALSE;
3369   }
3370 }
3371
3372 /* find stream with @id */
3373 static inline QtDemuxStream *
3374 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3375 {
3376   QtDemuxStream *stream;
3377   gint i;
3378
3379   /* check */
3380   if (G_UNLIKELY (!id)) {
3381     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3382     return NULL;
3383   }
3384
3385   /* try to get it fast and simple */
3386   if (G_LIKELY (id <= qtdemux->n_streams)) {
3387     stream = qtdemux->streams[id - 1];
3388     if (G_LIKELY (stream->track_id == id))
3389       return stream;
3390   }
3391
3392   /* linear search otherwise */
3393   for (i = 0; i < qtdemux->n_streams; i++) {
3394     stream = qtdemux->streams[i];
3395     if (stream->track_id == id)
3396       return stream;
3397   }
3398   if (qtdemux->mss_mode) {
3399     /* mss should have only 1 stream anyway */
3400     return qtdemux->streams[0];
3401   }
3402
3403   return NULL;
3404 }
3405
3406 static gboolean
3407 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3408     guint32 * fragment_number)
3409 {
3410   if (!gst_byte_reader_skip (mfhd, 4))
3411     goto fail;
3412   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3413     goto fail;
3414   return TRUE;
3415 fail:
3416   {
3417     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3418     return FALSE;
3419   }
3420 }
3421
3422 static gboolean
3423 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3424     QtDemuxStream ** stream, guint32 * default_sample_duration,
3425     guint32 * default_sample_size, guint32 * default_sample_flags,
3426     gint64 * base_offset)
3427 {
3428   guint32 flags = 0;
3429   guint32 track_id = 0;
3430
3431   if (!gst_byte_reader_skip (tfhd, 1) ||
3432       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3433     goto invalid_track;
3434
3435   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3436     goto invalid_track;
3437
3438   *stream = qtdemux_find_stream (qtdemux, track_id);
3439   if (G_UNLIKELY (!*stream))
3440     goto unknown_stream;
3441
3442   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3443     *base_offset = qtdemux->moof_offset;
3444
3445   if (flags & TF_BASE_DATA_OFFSET)
3446     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3447       goto invalid_track;
3448
3449   /* obtain stream defaults */
3450   qtdemux_parse_trex (qtdemux, *stream,
3451       default_sample_duration, default_sample_size, default_sample_flags);
3452
3453   (*stream)->stsd_sample_description_id =
3454       (*stream)->def_sample_description_index - 1;
3455
3456   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3457     guint32 sample_description_index;
3458     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3459       goto invalid_track;
3460     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3461   }
3462
3463   if (qtdemux->mss_mode) {
3464     /* mss has no stsd entry */
3465     (*stream)->stsd_sample_description_id = 0;
3466   }
3467
3468   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3469     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3470       goto invalid_track;
3471
3472   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3473     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3474       goto invalid_track;
3475
3476   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3477     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3478       goto invalid_track;
3479
3480   return TRUE;
3481
3482 invalid_track:
3483   {
3484     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3485     return FALSE;
3486   }
3487 unknown_stream:
3488   {
3489     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3490     return TRUE;
3491   }
3492 }
3493
3494 static gboolean
3495 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3496     guint64 * decode_time)
3497 {
3498   guint32 version = 0;
3499
3500   if (!gst_byte_reader_get_uint32_be (br, &version))
3501     return FALSE;
3502
3503   version >>= 24;
3504   if (version == 1) {
3505     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3506       goto failed;
3507   } else {
3508     guint32 dec_time = 0;
3509     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3510       goto failed;
3511     *decode_time = dec_time;
3512   }
3513
3514   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3515       *decode_time);
3516
3517   return TRUE;
3518
3519 failed:
3520   {
3521     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3522     return FALSE;
3523   }
3524 }
3525
3526 /* Returns a pointer to a GstStructure containing the properties of
3527  * the stream sample identified by @sample_index. The caller must unref
3528  * the returned object after use. Returns NULL if unsuccessful. */
3529 static GstStructure *
3530 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3531     QtDemuxStream * stream, guint sample_index)
3532 {
3533   QtDemuxCencSampleSetInfo *info = NULL;
3534
3535   g_return_val_if_fail (stream != NULL, NULL);
3536   g_return_val_if_fail (stream->protected, NULL);
3537   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3538
3539   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3540
3541   /* Currently, cenc properties for groups of samples are not supported, so
3542    * simply return a copy of the default sample properties */
3543   return gst_structure_copy (info->default_properties);
3544 }
3545
3546 /* Parses the sizes of sample auxiliary information contained within a stream,
3547  * as given in a saiz box. Returns array of sample_count guint8 size values,
3548  * or NULL on failure */
3549 static guint8 *
3550 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3551     GstByteReader * br, guint32 * sample_count)
3552 {
3553   guint32 flags = 0;
3554   guint8 *info_sizes;
3555   guint8 default_info_size;
3556
3557   g_return_val_if_fail (qtdemux != NULL, NULL);
3558   g_return_val_if_fail (stream != NULL, NULL);
3559   g_return_val_if_fail (br != NULL, NULL);
3560   g_return_val_if_fail (sample_count != NULL, NULL);
3561
3562   if (!gst_byte_reader_get_uint32_be (br, &flags))
3563     return NULL;
3564
3565   if (flags & 0x1) {
3566     /* aux_info_type and aux_info_type_parameter are ignored */
3567     if (!gst_byte_reader_skip (br, 8))
3568       return NULL;
3569   }
3570
3571   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3572     return NULL;
3573   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3574
3575   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3576     return NULL;
3577   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3578
3579
3580   if (default_info_size == 0) {
3581     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3582       return NULL;
3583     }
3584   } else {
3585     info_sizes = g_new (guint8, *sample_count);
3586     memset (info_sizes, default_info_size, *sample_count);
3587   }
3588
3589   return info_sizes;
3590 }
3591
3592 /* Parses the offset of sample auxiliary information contained within a stream,
3593  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3594 static gboolean
3595 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3596     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3597     guint64 * offset)
3598 {
3599   guint8 version = 0;
3600   guint32 flags = 0;
3601   guint32 aux_info_type = 0;
3602   guint32 aux_info_type_parameter = 0;
3603   guint32 entry_count;
3604   guint32 off_32;
3605   guint64 off_64;
3606   const guint8 *aux_info_type_data = NULL;
3607
3608   g_return_val_if_fail (qtdemux != NULL, FALSE);
3609   g_return_val_if_fail (stream != NULL, FALSE);
3610   g_return_val_if_fail (br != NULL, FALSE);
3611   g_return_val_if_fail (offset != NULL, FALSE);
3612
3613   if (!gst_byte_reader_get_uint8 (br, &version))
3614     return FALSE;
3615
3616   if (!gst_byte_reader_get_uint24_be (br, &flags))
3617     return FALSE;
3618
3619   if (flags & 0x1) {
3620
3621     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3622       return FALSE;
3623     aux_info_type = QT_FOURCC (aux_info_type_data);
3624
3625     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3626       return FALSE;
3627   } else if (stream->protected) {
3628     aux_info_type = stream->protection_scheme_type;
3629   } else {
3630     aux_info_type = CUR_STREAM (stream)->fourcc;
3631   }
3632
3633   if (info_type)
3634     *info_type = aux_info_type;
3635   if (info_type_parameter)
3636     *info_type_parameter = aux_info_type_parameter;
3637
3638   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3639       "aux_info_type_parameter:  %#06x",
3640       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3641
3642   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3643     return FALSE;
3644
3645   if (entry_count != 1) {
3646     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3647     return FALSE;
3648   }
3649
3650   if (version == 0) {
3651     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3652       return FALSE;
3653     *offset = (guint64) off_32;
3654   } else {
3655     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3656       return FALSE;
3657     *offset = off_64;
3658   }
3659
3660   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3661   return TRUE;
3662 }
3663
3664 static void
3665 qtdemux_gst_structure_free (GstStructure * gststructure)
3666 {
3667   if (gststructure) {
3668     gst_structure_free (gststructure);
3669   }
3670 }
3671
3672 /* Parses auxiliary information relating to samples protected using Common
3673  * Encryption (cenc); the format of this information is defined in
3674  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3675 static gboolean
3676 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3677     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3678 {
3679   QtDemuxCencSampleSetInfo *ss_info = NULL;
3680   guint8 size;
3681   gint i;
3682   GPtrArray *old_crypto_info = NULL;
3683   guint old_entries = 0;
3684
3685   g_return_val_if_fail (qtdemux != NULL, FALSE);
3686   g_return_val_if_fail (stream != NULL, FALSE);
3687   g_return_val_if_fail (br != NULL, FALSE);
3688   g_return_val_if_fail (stream->protected, FALSE);
3689   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3690
3691   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3692
3693   if (ss_info->crypto_info) {
3694     old_crypto_info = ss_info->crypto_info;
3695     /* Count number of non-null entries remaining at the tail end */
3696     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3697       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3698         break;
3699       old_entries++;
3700     }
3701   }
3702
3703   ss_info->crypto_info =
3704       g_ptr_array_new_full (sample_count + old_entries,
3705       (GDestroyNotify) qtdemux_gst_structure_free);
3706
3707   /* We preserve old entries because we parse the next moof in advance
3708    * of consuming all samples from the previous moof, and otherwise
3709    * we'd discard the corresponding crypto info for the samples
3710    * from the previous fragment. */
3711   if (old_entries) {
3712     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3713         old_entries);
3714     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3715       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3716               i));
3717       g_ptr_array_index (old_crypto_info, i) = NULL;
3718     }
3719   }
3720
3721   if (old_crypto_info) {
3722     /* Everything now belongs to the new array */
3723     g_ptr_array_free (old_crypto_info, TRUE);
3724   }
3725
3726   for (i = 0; i < sample_count; ++i) {
3727     GstStructure *properties;
3728     guint16 n_subsamples = 0;
3729     guint8 *data;
3730     guint iv_size;
3731     GstBuffer *buf;
3732
3733     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3734     if (properties == NULL) {
3735       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3736       return FALSE;
3737     }
3738     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3739       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3740       gst_structure_free (properties);
3741       return FALSE;
3742     }
3743     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3744       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3745       gst_structure_free (properties);
3746       return FALSE;
3747     }
3748     buf = gst_buffer_new_wrapped (data, iv_size);
3749     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3750     gst_buffer_unref (buf);
3751     size = info_sizes[i];
3752     if (size > iv_size) {
3753       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3754           || !(n_subsamples > 0)) {
3755         gst_structure_free (properties);
3756         GST_ERROR_OBJECT (qtdemux,
3757             "failed to get subsample count for sample %u", i);
3758         return FALSE;
3759       }
3760       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3761       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3762         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3763             i);
3764         gst_structure_free (properties);
3765         return FALSE;
3766       }
3767       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3768       if (!buf) {
3769         gst_structure_free (properties);
3770         return FALSE;
3771       }
3772       gst_structure_set (properties,
3773           "subsample_count", G_TYPE_UINT, n_subsamples,
3774           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3775       gst_buffer_unref (buf);
3776     } else {
3777       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3778     }
3779     g_ptr_array_add (ss_info->crypto_info, properties);
3780   }
3781   return TRUE;
3782 }
3783
3784 /* Converts a UUID in raw byte form to a string representation, as defined in
3785  * RFC 4122. The caller takes ownership of the returned string and is
3786  * responsible for freeing it after use. */
3787 static gchar *
3788 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3789 {
3790   const guint8 *uuid = (const guint8 *) uuid_bytes;
3791
3792   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3793       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3794       uuid[0], uuid[1], uuid[2], uuid[3],
3795       uuid[4], uuid[5], uuid[6], uuid[7],
3796       uuid[8], uuid[9], uuid[10], uuid[11],
3797       uuid[12], uuid[13], uuid[14], uuid[15]);
3798 }
3799
3800 /* Parses a Protection System Specific Header box (pssh), as defined in the
3801  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3802  * information needed by a specific content protection system in order to
3803  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3804  * otherwise. */
3805 static gboolean
3806 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3807 {
3808   gchar *sysid_string;
3809   guint32 pssh_size = QT_UINT32 (node->data);
3810   GstBuffer *pssh = NULL;
3811   GstEvent *event = NULL;
3812   guint32 parent_box_type;
3813   gint i;
3814
3815   if (G_UNLIKELY (pssh_size < 32U)) {
3816     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3817     return FALSE;
3818   }
3819
3820   sysid_string =
3821       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3822
3823   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3824
3825   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3826   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3827       gst_buffer_get_size (pssh));
3828
3829   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3830
3831   /* Push an event containing the pssh box onto the queues of all streams. */
3832   event = gst_event_new_protection (sysid_string, pssh,
3833       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3834   for (i = 0; i < qtdemux->n_streams; ++i) {
3835     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3836         gst_event_ref (event));
3837   }
3838   g_free (sysid_string);
3839   gst_event_unref (event);
3840   gst_buffer_unref (pssh);
3841   return TRUE;
3842 }
3843
3844 static gboolean
3845 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3846     guint64 moof_offset, QtDemuxStream * stream)
3847 {
3848   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3849   GNode *uuid_node;
3850   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3851   GNode *saiz_node, *saio_node, *pssh_node;
3852   GstByteReader saiz_data, saio_data;
3853   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3854   gint64 base_offset, running_offset;
3855   guint32 frag_num;
3856
3857   /* NOTE @stream ignored */
3858
3859   moof_node = g_node_new ((guint8 *) buffer);
3860   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3861   qtdemux_node_dump (qtdemux, moof_node);
3862
3863   /* Get fragment number from mfhd and check it's valid */
3864   mfhd_node =
3865       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3866   if (mfhd_node == NULL)
3867     goto missing_mfhd;
3868   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3869     goto fail;
3870   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3871
3872   /* unknown base_offset to start with */
3873   base_offset = running_offset = -1;
3874   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3875   while (traf_node) {
3876     guint64 decode_time = 0;
3877
3878     /* Fragment Header node */
3879     tfhd_node =
3880         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3881         &tfhd_data);
3882     if (!tfhd_node)
3883       goto missing_tfhd;
3884     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3885             &ds_size, &ds_flags, &base_offset))
3886       goto missing_tfhd;
3887
3888     /* The following code assumes at most a single set of sample auxiliary
3889      * data in the fragment (consisting of a saiz box and a corresponding saio
3890      * box); in theory, however, there could be multiple sets of sample
3891      * auxiliary data in a fragment. */
3892     saiz_node =
3893         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3894         &saiz_data);
3895     if (saiz_node) {
3896       guint32 info_type = 0;
3897       guint64 offset = 0;
3898       guint32 info_type_parameter = 0;
3899
3900       g_free (qtdemux->cenc_aux_info_sizes);
3901
3902       qtdemux->cenc_aux_info_sizes =
3903           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3904           &qtdemux->cenc_aux_sample_count);
3905       if (qtdemux->cenc_aux_info_sizes == NULL) {
3906         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3907         goto fail;
3908       }
3909       saio_node =
3910           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3911           &saio_data);
3912       if (!saio_node) {
3913         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3914         g_free (qtdemux->cenc_aux_info_sizes);
3915         qtdemux->cenc_aux_info_sizes = NULL;
3916         goto fail;
3917       }
3918
3919       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3920                   &info_type, &info_type_parameter, &offset))) {
3921         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3922         g_free (qtdemux->cenc_aux_info_sizes);
3923         qtdemux->cenc_aux_info_sizes = NULL;
3924         goto fail;
3925       }
3926       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3927         offset += (guint64) (base_offset - qtdemux->moof_offset);
3928       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3929         GstByteReader br;
3930         if (offset > length) {
3931           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3932           qtdemux->cenc_aux_info_offset = offset;
3933         } else {
3934           gst_byte_reader_init (&br, buffer + offset, length - offset);
3935           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3936                   qtdemux->cenc_aux_info_sizes,
3937                   qtdemux->cenc_aux_sample_count)) {
3938             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3939             g_free (qtdemux->cenc_aux_info_sizes);
3940             qtdemux->cenc_aux_info_sizes = NULL;
3941             goto fail;
3942           }
3943         }
3944       }
3945     }
3946
3947     tfdt_node =
3948         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3949         &tfdt_data);
3950     if (tfdt_node) {
3951       /* We'll use decode_time to interpolate timestamps
3952        * in case the input timestamps are missing */
3953       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3954
3955       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3956           " (%" GST_TIME_FORMAT ")", decode_time,
3957           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3958                   decode_time) : GST_CLOCK_TIME_NONE));
3959
3960       /* Discard the fragment buffer timestamp info to avoid using it.
3961        * Rely on tfdt instead as it is more accurate than the timestamp
3962        * that is fetched from a manifest/playlist and is usually
3963        * less accurate. */
3964       qtdemux->fragment_start = -1;
3965     }
3966
3967     if (G_UNLIKELY (!stream)) {
3968       /* we lost track of offset, we'll need to regain it,
3969        * but can delay complaining until later or avoid doing so altogether */
3970       base_offset = -2;
3971       goto next;
3972     }
3973     if (G_UNLIKELY (base_offset < -1))
3974       goto lost_offset;
3975
3976     if (qtdemux->upstream_format_is_time)
3977       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3978
3979     /* initialise moof sample data */
3980     stream->n_samples_moof = 0;
3981     stream->duration_last_moof = stream->duration_moof;
3982     stream->duration_moof = 0;
3983
3984     /* Track Run node */
3985     trun_node =
3986         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3987         &trun_data);
3988     while (trun_node) {
3989       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3990           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3991           &running_offset, decode_time, (tfdt_node != NULL));
3992       /* iterate all siblings */
3993       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3994           &trun_data);
3995     }
3996
3997     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3998     if (uuid_node) {
3999       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4000       guint32 box_length = QT_UINT32 (uuid_buffer);
4001
4002       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4003     }
4004
4005     /* if no new base_offset provided for next traf,
4006      * base is end of current traf */
4007     base_offset = running_offset;
4008     running_offset = -1;
4009
4010     if (stream->n_samples_moof && stream->duration_moof)
4011       stream->new_caps = TRUE;
4012
4013   next:
4014     /* iterate all siblings */
4015     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4016   }
4017
4018   /* parse any protection system info */
4019   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4020   while (pssh_node) {
4021     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4022     qtdemux_parse_pssh (qtdemux, pssh_node);
4023     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4024   }
4025
4026   g_node_destroy (moof_node);
4027   return TRUE;
4028
4029 missing_tfhd:
4030   {
4031     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4032     goto fail;
4033   }
4034 missing_mfhd:
4035   {
4036     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4037     goto fail;
4038   }
4039 lost_offset:
4040   {
4041     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4042     goto fail;
4043   }
4044 fail:
4045   {
4046     g_node_destroy (moof_node);
4047     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4048         (_("This file is corrupt and cannot be played.")), (NULL));
4049     return FALSE;
4050   }
4051 }
4052
4053 #if 0
4054 /* might be used if some day we actually use mfra & co
4055  * for random access to fragments,
4056  * but that will require quite some modifications and much less relying
4057  * on a sample array */
4058 #endif
4059
4060 static gboolean
4061 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4062 {
4063   QtDemuxStream *stream;
4064   guint32 ver_flags, track_id, len, num_entries, i;
4065   guint value_size, traf_size, trun_size, sample_size;
4066   guint64 time = 0, moof_offset = 0;
4067 #if 0
4068   GstBuffer *buf = NULL;
4069   GstFlowReturn ret;
4070 #endif
4071   GstByteReader tfra;
4072
4073   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4074
4075   if (!gst_byte_reader_skip (&tfra, 8))
4076     return FALSE;
4077
4078   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4079     return FALSE;
4080
4081   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4082       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4083       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4084     return FALSE;
4085
4086   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4087
4088   stream = qtdemux_find_stream (qtdemux, track_id);
4089   if (stream == NULL)
4090     goto unknown_trackid;
4091
4092   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4093   sample_size = (len & 3) + 1;
4094   trun_size = ((len & 12) >> 2) + 1;
4095   traf_size = ((len & 48) >> 4) + 1;
4096
4097   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4098       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4099
4100   if (num_entries == 0)
4101     goto no_samples;
4102
4103   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4104           value_size + value_size + traf_size + trun_size + sample_size))
4105     goto corrupt_file;
4106
4107   g_free (stream->ra_entries);
4108   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4109   stream->n_ra_entries = num_entries;
4110
4111   for (i = 0; i < num_entries; i++) {
4112     qt_atom_parser_get_offset (&tfra, value_size, &time);
4113     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4114     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4115     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4116     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4117
4118     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4119
4120     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4121         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4122
4123     stream->ra_entries[i].ts = time;
4124     stream->ra_entries[i].moof_offset = moof_offset;
4125
4126     /* don't want to go through the entire file and read all moofs at startup */
4127 #if 0
4128     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4129     if (ret != GST_FLOW_OK)
4130       goto corrupt_file;
4131     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4132         moof_offset, stream);
4133     gst_buffer_unref (buf);
4134 #endif
4135   }
4136
4137   check_update_duration (qtdemux, time);
4138
4139   return TRUE;
4140
4141 /* ERRORS */
4142 unknown_trackid:
4143   {
4144     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4145     return FALSE;
4146   }
4147 corrupt_file:
4148   {
4149     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4150     return FALSE;
4151   }
4152 no_samples:
4153   {
4154     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4155     return FALSE;
4156   }
4157 }
4158
4159 static gboolean
4160 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4161 {
4162   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4163   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4164   GstBuffer *mfro = NULL, *mfra = NULL;
4165   GstFlowReturn flow;
4166   gboolean ret = FALSE;
4167   GNode *mfra_node, *tfra_node;
4168   guint64 mfra_offset = 0;
4169   guint32 fourcc, mfra_size;
4170   gint64 len;
4171
4172   /* query upstream size in bytes */
4173   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4174     goto size_query_failed;
4175
4176   /* mfro box should be at the very end of the file */
4177   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4178   if (flow != GST_FLOW_OK)
4179     goto exit;
4180
4181   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4182
4183   fourcc = QT_FOURCC (mfro_map.data + 4);
4184   if (fourcc != FOURCC_mfro)
4185     goto exit;
4186
4187   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4188   if (mfro_map.size < 16)
4189     goto invalid_mfro_size;
4190
4191   mfra_size = QT_UINT32 (mfro_map.data + 12);
4192   if (mfra_size >= len)
4193     goto invalid_mfra_size;
4194
4195   mfra_offset = len - mfra_size;
4196
4197   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4198       mfra_offset, mfra_size);
4199
4200   /* now get and parse mfra box */
4201   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4202   if (flow != GST_FLOW_OK)
4203     goto broken_file;
4204
4205   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4206
4207   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4208   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4209
4210   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4211
4212   while (tfra_node) {
4213     qtdemux_parse_tfra (qtdemux, tfra_node);
4214     /* iterate all siblings */
4215     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4216   }
4217   g_node_destroy (mfra_node);
4218
4219   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4220   ret = TRUE;
4221
4222 exit:
4223
4224   if (mfro) {
4225     if (mfro_map.memory != NULL)
4226       gst_buffer_unmap (mfro, &mfro_map);
4227     gst_buffer_unref (mfro);
4228   }
4229   if (mfra) {
4230     if (mfra_map.memory != NULL)
4231       gst_buffer_unmap (mfra, &mfra_map);
4232     gst_buffer_unref (mfra);
4233   }
4234   return ret;
4235
4236 /* ERRORS */
4237 size_query_failed:
4238   {
4239     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4240     goto exit;
4241   }
4242 invalid_mfro_size:
4243   {
4244     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4245     goto exit;
4246   }
4247 invalid_mfra_size:
4248   {
4249     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4250     goto exit;
4251   }
4252 broken_file:
4253   {
4254     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4255     goto exit;
4256   }
4257 }
4258
4259 static guint64
4260 add_offset (guint64 offset, guint64 advance)
4261 {
4262   /* Avoid 64-bit overflow by clamping */
4263   if (offset > G_MAXUINT64 - advance)
4264     return G_MAXUINT64;
4265   return offset + advance;
4266 }
4267
4268 static GstFlowReturn
4269 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4270 {
4271   guint64 length = 0;
4272   guint32 fourcc = 0;
4273   GstBuffer *buf = NULL;
4274   GstFlowReturn ret = GST_FLOW_OK;
4275   guint64 cur_offset = qtdemux->offset;
4276   GstMapInfo map;
4277
4278   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4279   if (G_UNLIKELY (ret != GST_FLOW_OK))
4280     goto beach;
4281   gst_buffer_map (buf, &map, GST_MAP_READ);
4282   if (G_LIKELY (map.size >= 8))
4283     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4284   gst_buffer_unmap (buf, &map);
4285   gst_buffer_unref (buf);
4286
4287   /* maybe we already got most we needed, so only consider this eof */
4288   if (G_UNLIKELY (length == 0)) {
4289     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4290         (_("Invalid atom size.")),
4291         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4292             GST_FOURCC_ARGS (fourcc)));
4293     ret = GST_FLOW_EOS;
4294     goto beach;
4295   }
4296
4297   switch (fourcc) {
4298     case FOURCC_moof:
4299       /* record for later parsing when needed */
4300       if (!qtdemux->moof_offset) {
4301         qtdemux->moof_offset = qtdemux->offset;
4302       }
4303       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4304         /* FIXME */
4305       } else {
4306         qtdemux->offset += length;      /* skip moof and keep going */
4307       }
4308       if (qtdemux->got_moov) {
4309         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4310         ret = GST_FLOW_EOS;
4311         goto beach;
4312       }
4313       break;
4314     case FOURCC_mdat:
4315     case FOURCC_free:
4316     case FOURCC_skip:
4317     case FOURCC_wide:
4318     case FOURCC_PICT:
4319     case FOURCC_pnot:
4320     {
4321       GST_LOG_OBJECT (qtdemux,
4322           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4323           GST_FOURCC_ARGS (fourcc), cur_offset);
4324       qtdemux->offset = add_offset (qtdemux->offset, length);
4325       break;
4326     }
4327     case FOURCC_moov:
4328     {
4329       GstBuffer *moov = NULL;
4330
4331       if (qtdemux->got_moov) {
4332         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4333         qtdemux->offset = add_offset (qtdemux->offset, length);
4334         goto beach;
4335       }
4336
4337       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4338       if (ret != GST_FLOW_OK)
4339         goto beach;
4340       gst_buffer_map (moov, &map, GST_MAP_READ);
4341
4342       if (length != map.size) {
4343         /* Some files have a 'moov' atom at the end of the file which contains
4344          * a terminal 'free' atom where the body of the atom is missing.
4345          * Check for, and permit, this special case.
4346          */
4347         if (map.size >= 8) {
4348           guint8 *final_data = map.data + (map.size - 8);
4349           guint32 final_length = QT_UINT32 (final_data);
4350           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4351
4352           if (final_fourcc == FOURCC_free
4353               && map.size + final_length - 8 == length) {
4354             /* Ok, we've found that special case. Allocate a new buffer with
4355              * that free atom actually present. */
4356             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4357             gst_buffer_fill (newmoov, 0, map.data, map.size);
4358             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4359             gst_buffer_unmap (moov, &map);
4360             gst_buffer_unref (moov);
4361             moov = newmoov;
4362             gst_buffer_map (moov, &map, GST_MAP_READ);
4363           }
4364         }
4365       }
4366
4367       if (length != map.size) {
4368         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4369             (_("This file is incomplete and cannot be played.")),
4370             ("We got less than expected (received %" G_GSIZE_FORMAT
4371                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4372                 (guint) length, cur_offset));
4373         gst_buffer_unmap (moov, &map);
4374         gst_buffer_unref (moov);
4375         ret = GST_FLOW_ERROR;
4376         goto beach;
4377       }
4378       qtdemux->offset += length;
4379
4380       qtdemux_parse_moov (qtdemux, map.data, length);
4381       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4382
4383       qtdemux_parse_tree (qtdemux);
4384       if (qtdemux->moov_node_compressed) {
4385         g_node_destroy (qtdemux->moov_node_compressed);
4386         g_free (qtdemux->moov_node->data);
4387       }
4388       qtdemux->moov_node_compressed = NULL;
4389       g_node_destroy (qtdemux->moov_node);
4390       qtdemux->moov_node = NULL;
4391       gst_buffer_unmap (moov, &map);
4392       gst_buffer_unref (moov);
4393       qtdemux->got_moov = TRUE;
4394
4395       break;
4396     }
4397     case FOURCC_ftyp:
4398     {
4399       GstBuffer *ftyp = NULL;
4400
4401       /* extract major brand; might come in handy for ISO vs QT issues */
4402       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4403       if (ret != GST_FLOW_OK)
4404         goto beach;
4405       qtdemux->offset += length;
4406       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4407       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4408       gst_buffer_unmap (ftyp, &map);
4409       gst_buffer_unref (ftyp);
4410       break;
4411     }
4412     case FOURCC_uuid:
4413     {
4414       GstBuffer *uuid = NULL;
4415
4416       /* uuid are extension atoms */
4417       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4418       if (ret != GST_FLOW_OK)
4419         goto beach;
4420       qtdemux->offset += length;
4421       gst_buffer_map (uuid, &map, GST_MAP_READ);
4422       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4423       gst_buffer_unmap (uuid, &map);
4424       gst_buffer_unref (uuid);
4425       break;
4426     }
4427     case FOURCC_sidx:
4428     {
4429       GstBuffer *sidx = NULL;
4430       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4431       if (ret != GST_FLOW_OK)
4432         goto beach;
4433       qtdemux->offset += length;
4434       gst_buffer_map (sidx, &map, GST_MAP_READ);
4435       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4436       gst_buffer_unmap (sidx, &map);
4437       gst_buffer_unref (sidx);
4438       break;
4439     }
4440     default:
4441     {
4442       GstBuffer *unknown = NULL;
4443
4444       GST_LOG_OBJECT (qtdemux,
4445           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4446           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4447           cur_offset);
4448       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4449       if (ret != GST_FLOW_OK)
4450         goto beach;
4451       gst_buffer_map (unknown, &map, GST_MAP_READ);
4452       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4453       gst_buffer_unmap (unknown, &map);
4454       gst_buffer_unref (unknown);
4455       qtdemux->offset += length;
4456       break;
4457     }
4458   }
4459
4460 beach:
4461   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4462     /* digested all data, show what we have */
4463     qtdemux_prepare_streams (qtdemux);
4464     ret = qtdemux_expose_streams (qtdemux);
4465
4466     qtdemux->state = QTDEMUX_STATE_MOVIE;
4467     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4468         qtdemux->state);
4469     return ret;
4470   }
4471   return ret;
4472 }
4473
4474 /* Seeks to the previous keyframe of the indexed stream and
4475  * aligns other streams with respect to the keyframe timestamp
4476  * of indexed stream. Only called in case of Reverse Playback
4477  */
4478 static GstFlowReturn
4479 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4480 {
4481   guint8 n = 0;
4482   guint32 seg_idx = 0, k_index = 0;
4483   guint32 ref_seg_idx, ref_k_index;
4484   GstClockTime k_pos = 0, last_stop = 0;
4485   QtDemuxSegment *seg = NULL;
4486   QtDemuxStream *ref_str = NULL;
4487   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4488   guint64 target_ts;
4489
4490   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4491    * and finally align all the other streams on that timestamp with their
4492    * respective keyframes */
4493   for (n = 0; n < qtdemux->n_streams; n++) {
4494     QtDemuxStream *str = qtdemux->streams[n];
4495
4496     /* No candidate yet, take the first stream */
4497     if (!ref_str) {
4498       ref_str = str;
4499       continue;
4500     }
4501
4502     /* So that stream has a segment, we prefer video streams */
4503     if (str->subtype == FOURCC_vide) {
4504       ref_str = str;
4505       break;
4506     }
4507   }
4508
4509   if (G_UNLIKELY (!ref_str)) {
4510     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4511     goto eos;
4512   }
4513
4514   if (G_UNLIKELY (!ref_str->from_sample)) {
4515     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4516     goto eos;
4517   }
4518
4519   /* So that stream has been playing from from_sample to to_sample. We will
4520    * get the timestamp of the previous sample and search for a keyframe before
4521    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4522   if (ref_str->subtype == FOURCC_vide) {
4523     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4524         ref_str->from_sample - 1, FALSE);
4525   } else {
4526     if (ref_str->from_sample >= 10)
4527       k_index = ref_str->from_sample - 10;
4528     else
4529       k_index = 0;
4530   }
4531
4532   target_ts =
4533       ref_str->samples[k_index].timestamp +
4534       ref_str->samples[k_index].pts_offset;
4535
4536   /* get current segment for that stream */
4537   seg = &ref_str->segments[ref_str->segment_index];
4538   /* Use segment start in original timescale for comparisons */
4539   seg_media_start_mov = seg->trak_media_start;
4540
4541   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4542       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4543       k_index, target_ts, seg_media_start_mov,
4544       GST_TIME_ARGS (seg->media_start));
4545
4546   /* Crawl back through segments to find the one containing this I frame */
4547   while (target_ts < seg_media_start_mov) {
4548     GST_DEBUG_OBJECT (qtdemux,
4549         "keyframe position (sample %u) is out of segment %u " " target %"
4550         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4551         ref_str->segment_index, target_ts, seg_media_start_mov);
4552
4553     if (G_UNLIKELY (!ref_str->segment_index)) {
4554       /* Reached first segment, let's consider it's EOS */
4555       goto eos;
4556     }
4557     ref_str->segment_index--;
4558     seg = &ref_str->segments[ref_str->segment_index];
4559     /* Use segment start in original timescale for comparisons */
4560     seg_media_start_mov = seg->trak_media_start;
4561   }
4562   /* Calculate time position of the keyframe and where we should stop */
4563   k_pos =
4564       QTSTREAMTIME_TO_GSTTIME (ref_str,
4565       target_ts - seg->trak_media_start) + seg->time;
4566   last_stop =
4567       QTSTREAMTIME_TO_GSTTIME (ref_str,
4568       ref_str->samples[ref_str->from_sample].timestamp -
4569       seg->trak_media_start) + seg->time;
4570
4571   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4572       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4573       k_index, GST_TIME_ARGS (k_pos));
4574
4575   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4576   qtdemux->segment.position = last_stop;
4577   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4578       GST_TIME_ARGS (last_stop));
4579
4580   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4581     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4582     goto eos;
4583   }
4584
4585   ref_seg_idx = ref_str->segment_index;
4586   ref_k_index = k_index;
4587
4588   /* Align them all on this */
4589   for (n = 0; n < qtdemux->n_streams; n++) {
4590     guint32 index = 0;
4591     GstClockTime seg_time = 0;
4592     QtDemuxStream *str = qtdemux->streams[n];
4593
4594     /* aligning reference stream again might lead to backing up to yet another
4595      * keyframe (due to timestamp rounding issues),
4596      * potentially putting more load on downstream; so let's try to avoid */
4597     if (str == ref_str) {
4598       seg_idx = ref_seg_idx;
4599       seg = &str->segments[seg_idx];
4600       k_index = ref_k_index;
4601       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4602           "sample at index %d", n, ref_str->segment_index, k_index);
4603     } else {
4604       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4605       GST_DEBUG_OBJECT (qtdemux,
4606           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4607           seg_idx, GST_TIME_ARGS (k_pos));
4608
4609       /* get segment and time in the segment */
4610       seg = &str->segments[seg_idx];
4611       seg_time = k_pos - seg->time;
4612
4613       /* get the media time in the segment.
4614        * No adjustment for empty "filler" segments */
4615       if (seg->media_start != GST_CLOCK_TIME_NONE)
4616         seg_time += seg->media_start;
4617
4618       /* get the index of the sample with media time */
4619       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4620       GST_DEBUG_OBJECT (qtdemux,
4621           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4622           GST_TIME_ARGS (seg_time), index);
4623
4624       /* find previous keyframe */
4625       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4626     }
4627
4628     /* Remember until where we want to go */
4629     str->to_sample = str->from_sample - 1;
4630     /* Define our time position */
4631     target_ts =
4632         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4633     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4634     if (seg->media_start != GST_CLOCK_TIME_NONE)
4635       str->time_position -= seg->media_start;
4636
4637     /* Now seek back in time */
4638     gst_qtdemux_move_stream (qtdemux, str, k_index);
4639     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4640         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4641         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4642   }
4643
4644   return GST_FLOW_OK;
4645
4646 eos:
4647   return GST_FLOW_EOS;
4648 }
4649
4650 /*
4651  * Gets the current qt segment start, stop and position for the
4652  * given time offset. This is used in update_segment()
4653  */
4654 static void
4655 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4656     QtDemuxStream * stream, GstClockTime offset,
4657     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4658 {
4659   GstClockTime seg_time;
4660   GstClockTime start, stop, time;
4661   QtDemuxSegment *segment;
4662
4663   segment = &stream->segments[stream->segment_index];
4664
4665   /* get time in this segment */
4666   seg_time = (offset - segment->time) * segment->rate;
4667
4668   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4669       GST_TIME_ARGS (seg_time));
4670
4671   if (G_UNLIKELY (seg_time > segment->duration)) {
4672     GST_LOG_OBJECT (stream->pad,
4673         "seg_time > segment->duration %" GST_TIME_FORMAT,
4674         GST_TIME_ARGS (segment->duration));
4675     seg_time = segment->duration;
4676   }
4677
4678   /* qtdemux->segment.stop is in outside-time-realm, whereas
4679    * segment->media_stop is in track-time-realm.
4680    *
4681    * In order to compare the two, we need to bring segment.stop
4682    * into the track-time-realm
4683    *
4684    * FIXME - does this comment still hold? Don't see any conversion here */
4685
4686   stop = qtdemux->segment.stop;
4687   if (stop == GST_CLOCK_TIME_NONE)
4688     stop = qtdemux->segment.duration;
4689   if (stop == GST_CLOCK_TIME_NONE)
4690     stop = segment->media_stop;
4691   else
4692     stop =
4693         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4694
4695   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4696     start = segment->time + seg_time;
4697     time = offset;
4698     stop = start - seg_time + segment->duration;
4699   } else if (qtdemux->segment.rate >= 0) {
4700     start = MIN (segment->media_start + seg_time, stop);
4701     time = offset;
4702   } else {
4703     if (segment->media_start >= qtdemux->segment.start) {
4704       time = segment->time;
4705     } else {
4706       time = segment->time + (qtdemux->segment.start - segment->media_start);
4707     }
4708
4709     start = MAX (segment->media_start, qtdemux->segment.start);
4710     stop = MIN (segment->media_start + seg_time, stop);
4711   }
4712
4713   *_start = start;
4714   *_stop = stop;
4715   *_time = time;
4716 }
4717
4718 /*
4719  * Updates the qt segment used for the stream and pushes a new segment event
4720  * downstream on this stream's pad.
4721  */
4722 static gboolean
4723 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4724     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4725     GstClockTime * _stop)
4726 {
4727   QtDemuxSegment *segment;
4728   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4729   gdouble rate;
4730   GstEvent *event;
4731
4732   /* update the current segment */
4733   stream->segment_index = seg_idx;
4734
4735   /* get the segment */
4736   segment = &stream->segments[seg_idx];
4737
4738   if (G_UNLIKELY (offset < segment->time)) {
4739     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4740         GST_TIME_ARGS (segment->time));
4741     return FALSE;
4742   }
4743
4744   /* segment lies beyond total indicated duration */
4745   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4746           segment->time > qtdemux->segment.duration)) {
4747     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4748         " < segment->time %" GST_TIME_FORMAT,
4749         GST_TIME_ARGS (qtdemux->segment.duration),
4750         GST_TIME_ARGS (segment->time));
4751     return FALSE;
4752   }
4753
4754   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4755       &start, &stop, &time);
4756
4757   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4758       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4759       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4760
4761   /* combine global rate with that of the segment */
4762   rate = segment->rate * qtdemux->segment.rate;
4763
4764   /* Copy flags from main segment */
4765   stream->segment.flags = qtdemux->segment.flags;
4766
4767   /* update the segment values used for clipping */
4768   stream->segment.offset = qtdemux->segment.offset;
4769   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4770   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4771   stream->segment.rate = rate;
4772   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4773       stream->cslg_shift);
4774   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4775       stream->cslg_shift);
4776   stream->segment.time = time;
4777   stream->segment.position = stream->segment.start;
4778
4779   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4780       &stream->segment);
4781
4782   /* now prepare and send the segment */
4783   if (stream->pad) {
4784     event = gst_event_new_segment (&stream->segment);
4785     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4786       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4787     }
4788     gst_pad_push_event (stream->pad, event);
4789     /* assume we can send more data now */
4790     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4791     /* clear to send tags on this pad now */
4792     gst_qtdemux_push_tags (qtdemux, stream);
4793   }
4794
4795   if (_start)
4796     *_start = start;
4797   if (_stop)
4798     *_stop = stop;
4799
4800   return TRUE;
4801 }
4802
4803 /* activate the given segment number @seg_idx of @stream at time @offset.
4804  * @offset is an absolute global position over all the segments.
4805  *
4806  * This will push out a NEWSEGMENT event with the right values and
4807  * position the stream index to the first decodable sample before
4808  * @offset.
4809  */
4810 static gboolean
4811 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4812     guint32 seg_idx, GstClockTime offset)
4813 {
4814   QtDemuxSegment *segment;
4815   guint32 index, kf_index;
4816   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4817
4818   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4819       seg_idx, GST_TIME_ARGS (offset));
4820
4821   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4822           &start, &stop))
4823     return FALSE;
4824
4825   segment = &stream->segments[stream->segment_index];
4826
4827   /* in the fragmented case, we pick a fragment that starts before our
4828    * desired position and rely on downstream to wait for a keyframe
4829    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4830    * tfra entries tells us which trun/sample the key unit is in, but we don't
4831    * make use of this additional information at the moment) */
4832   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4833     stream->to_sample = G_MAXUINT32;
4834     return TRUE;
4835   } else {
4836     /* well, it will be taken care of below */
4837     qtdemux->fragmented_seek_pending = FALSE;
4838     /* FIXME ideally the do_fragmented_seek can be done right here,
4839      * rather than at loop level
4840      * (which might even allow handling edit lists in a fragmented file) */
4841   }
4842
4843   /* We don't need to look for a sample in push-based */
4844   if (!qtdemux->pullbased)
4845     return TRUE;
4846
4847   /* and move to the keyframe before the indicated media time of the
4848    * segment */
4849   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4850     if (qtdemux->segment.rate >= 0) {
4851       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4852       stream->to_sample = G_MAXUINT32;
4853       GST_DEBUG_OBJECT (stream->pad,
4854           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4855           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4856           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4857     } else {
4858       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4859       stream->to_sample = index;
4860       GST_DEBUG_OBJECT (stream->pad,
4861           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4862           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4863           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4864     }
4865   } else {
4866     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4867         "this is an empty segment");
4868     return TRUE;
4869   }
4870
4871   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4872    * encountered an error and printed a message so we return appropriately */
4873   if (index == -1)
4874     return FALSE;
4875
4876   /* we're at the right spot */
4877   if (index == stream->sample_index) {
4878     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4879     return TRUE;
4880   }
4881
4882   /* find keyframe of the target index */
4883   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4884
4885 /* *INDENT-OFF* */
4886 /* indent does stupid stuff with stream->samples[].timestamp */
4887
4888   /* if we move forwards, we don't have to go back to the previous
4889    * keyframe since we already sent that. We can also just jump to
4890    * the keyframe right before the target index if there is one. */
4891   if (index > stream->sample_index) {
4892     /* moving forwards check if we move past a keyframe */
4893     if (kf_index > stream->sample_index) {
4894       GST_DEBUG_OBJECT (stream->pad,
4895            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4896            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4897            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4898       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4899     } else {
4900       GST_DEBUG_OBJECT (stream->pad,
4901           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4902           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4903           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4904     }
4905   } else {
4906     GST_DEBUG_OBJECT (stream->pad,
4907         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4908         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4909         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4910     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4911   }
4912
4913 /* *INDENT-ON* */
4914
4915   return TRUE;
4916 }
4917
4918 /* prepare to get the current sample of @stream, getting essential values.
4919  *
4920  * This function will also prepare and send the segment when needed.
4921  *
4922  * Return FALSE if the stream is EOS.
4923  *
4924  * PULL-BASED
4925  */
4926 static gboolean
4927 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4928     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4929     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4930     gboolean * keyframe)
4931 {
4932   QtDemuxSample *sample;
4933   GstClockTime time_position;
4934   guint32 seg_idx;
4935
4936   g_return_val_if_fail (stream != NULL, FALSE);
4937
4938   time_position = stream->time_position;
4939   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4940     goto eos;
4941
4942   seg_idx = stream->segment_index;
4943   if (G_UNLIKELY (seg_idx == -1)) {
4944     /* find segment corresponding to time_position if we are looking
4945      * for a segment. */
4946     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4947   }
4948
4949   /* different segment, activate it, sample_index will be set. */
4950   if (G_UNLIKELY (stream->segment_index != seg_idx))
4951     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4952
4953   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4954                   segment_index]))) {
4955     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4956
4957     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4958         " prepare empty sample");
4959
4960     *empty = TRUE;
4961     *pts = *dts = time_position;
4962     *duration = seg->duration - (time_position - seg->time);
4963
4964     return TRUE;
4965   }
4966
4967   *empty = FALSE;
4968
4969   if (stream->sample_index == -1)
4970     stream->sample_index = 0;
4971
4972   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4973       stream->sample_index, stream->n_samples);
4974
4975   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4976     if (!qtdemux->fragmented)
4977       goto eos;
4978
4979     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4980     do {
4981       GstFlowReturn flow;
4982
4983       GST_OBJECT_LOCK (qtdemux);
4984       flow = qtdemux_add_fragmented_samples (qtdemux);
4985       GST_OBJECT_UNLOCK (qtdemux);
4986
4987       if (flow != GST_FLOW_OK)
4988         goto eos;
4989     }
4990     while (stream->sample_index >= stream->n_samples);
4991   }
4992
4993   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4994     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4995         stream->sample_index);
4996     return FALSE;
4997   }
4998
4999   /* now get the info for the sample we're at */
5000   sample = &stream->samples[stream->sample_index];
5001
5002   *dts = QTSAMPLE_DTS (stream, sample);
5003   *pts = QTSAMPLE_PTS (stream, sample);
5004   *offset = sample->offset;
5005   *size = sample->size;
5006   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5007   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5008
5009   return TRUE;
5010
5011   /* special cases */
5012 eos:
5013   {
5014     stream->time_position = GST_CLOCK_TIME_NONE;
5015     return FALSE;
5016   }
5017 }
5018
5019 /* move to the next sample in @stream.
5020  *
5021  * Moves to the next segment when needed.
5022  */
5023 static void
5024 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5025 {
5026   QtDemuxSample *sample;
5027   QtDemuxSegment *segment;
5028
5029   /* get current segment */
5030   segment = &stream->segments[stream->segment_index];
5031
5032   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5033     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5034     goto next_segment;
5035   }
5036
5037   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5038     /* Mark the stream as EOS */
5039     GST_DEBUG_OBJECT (qtdemux,
5040         "reached max allowed sample %u, mark EOS", stream->to_sample);
5041     stream->time_position = GST_CLOCK_TIME_NONE;
5042     return;
5043   }
5044
5045   /* move to next sample */
5046   stream->sample_index++;
5047   stream->offset_in_sample = 0;
5048
5049   /* reached the last sample, we need the next segment */
5050   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5051     goto next_segment;
5052
5053   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5054     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5055         stream->sample_index);
5056     return;
5057   }
5058
5059   /* get next sample */
5060   sample = &stream->samples[stream->sample_index];
5061
5062   /* see if we are past the segment */
5063   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5064     goto next_segment;
5065
5066   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5067     /* inside the segment, update time_position, looks very familiar to
5068      * GStreamer segments, doesn't it? */
5069     stream->time_position =
5070         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5071   } else {
5072     /* not yet in segment, time does not yet increment. This means
5073      * that we are still prerolling keyframes to the decoder so it can
5074      * decode the first sample of the segment. */
5075     stream->time_position = segment->time;
5076   }
5077   return;
5078
5079   /* move to the next segment */
5080 next_segment:
5081   {
5082     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5083
5084     if (stream->segment_index == stream->n_segments - 1) {
5085       /* are we at the end of the last segment, we're EOS */
5086       stream->time_position = GST_CLOCK_TIME_NONE;
5087     } else {
5088       /* else we're only at the end of the current segment */
5089       stream->time_position = segment->stop_time;
5090     }
5091     /* make sure we select a new segment */
5092
5093     /* accumulate previous segments */
5094     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5095       stream->accumulated_base +=
5096           (stream->segment.stop -
5097           stream->segment.start) / ABS (stream->segment.rate);
5098
5099     stream->segment_index = -1;
5100   }
5101 }
5102
5103 static void
5104 gst_qtdemux_sync_streams (GstQTDemux * demux)
5105 {
5106   gint i;
5107
5108   if (demux->n_streams <= 1)
5109     return;
5110
5111   for (i = 0; i < demux->n_streams; i++) {
5112     QtDemuxStream *stream;
5113     GstClockTime end_time;
5114
5115     stream = demux->streams[i];
5116
5117     if (!stream->pad)
5118       continue;
5119
5120     /* TODO advance time on subtitle streams here, if any some day */
5121
5122     /* some clips/trailers may have unbalanced streams at the end,
5123      * so send EOS on shorter stream to prevent stalling others */
5124
5125     /* do not mess with EOS if SEGMENT seeking */
5126     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5127       continue;
5128
5129     if (demux->pullbased) {
5130       /* loop mode is sample time based */
5131       if (!STREAM_IS_EOS (stream))
5132         continue;
5133     } else {
5134       /* push mode is byte position based */
5135       if (stream->n_samples &&
5136           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5137         continue;
5138     }
5139
5140     if (stream->sent_eos)
5141       continue;
5142
5143     /* only act if some gap */
5144     end_time = stream->segments[stream->n_segments - 1].stop_time;
5145     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5146         ", stream end: %" GST_TIME_FORMAT,
5147         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5148     if (GST_CLOCK_TIME_IS_VALID (end_time)
5149         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5150       GstEvent *event;
5151
5152       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5153           GST_PAD_NAME (stream->pad));
5154       stream->sent_eos = TRUE;
5155       event = gst_event_new_eos ();
5156       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5157         gst_event_set_seqnum (event, demux->segment_seqnum);
5158       gst_pad_push_event (stream->pad, event);
5159     }
5160   }
5161 }
5162
5163 /* EOS and NOT_LINKED need to be combined. This means that we return:
5164  *
5165  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5166  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5167  */
5168 static GstFlowReturn
5169 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5170     GstFlowReturn ret)
5171 {
5172   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5173
5174   if (stream->pad)
5175     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5176         ret);
5177   else
5178     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5179
5180   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5181   return ret;
5182 }
5183
5184 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5185  * completely clipped
5186  *
5187  * Should be used only with raw buffers */
5188 static GstBuffer *
5189 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5190     GstBuffer * buf)
5191 {
5192   guint64 start, stop, cstart, cstop, diff;
5193   GstClockTime pts, duration;
5194   gsize size, osize;
5195   gint num_rate, denom_rate;
5196   gint frame_size;
5197   gboolean clip_data;
5198   guint offset;
5199
5200   osize = size = gst_buffer_get_size (buf);
5201   offset = 0;
5202
5203   /* depending on the type, setup the clip parameters */
5204   if (stream->subtype == FOURCC_soun) {
5205     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5206     num_rate = GST_SECOND;
5207     denom_rate = (gint) CUR_STREAM (stream)->rate;
5208     clip_data = TRUE;
5209   } else if (stream->subtype == FOURCC_vide) {
5210     frame_size = size;
5211     num_rate = CUR_STREAM (stream)->fps_n;
5212     denom_rate = CUR_STREAM (stream)->fps_d;
5213     clip_data = FALSE;
5214   } else
5215     goto wrong_type;
5216
5217   if (frame_size <= 0)
5218     goto bad_frame_size;
5219
5220   /* we can only clip if we have a valid pts */
5221   pts = GST_BUFFER_PTS (buf);
5222   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5223     goto no_pts;
5224
5225   duration = GST_BUFFER_DURATION (buf);
5226
5227   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5228     duration =
5229         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5230   }
5231
5232   start = pts;
5233   stop = start + duration;
5234
5235   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5236               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5237     goto clipped;
5238
5239   /* see if some clipping happened */
5240   diff = cstart - start;
5241   if (diff > 0) {
5242     pts += diff;
5243     duration -= diff;
5244
5245     if (clip_data) {
5246       /* bring clipped time to samples and to bytes */
5247       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5248       diff *= frame_size;
5249
5250       GST_DEBUG_OBJECT (qtdemux,
5251           "clipping start to %" GST_TIME_FORMAT " %"
5252           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5253
5254       offset = diff;
5255       size -= diff;
5256     }
5257   }
5258   diff = stop - cstop;
5259   if (diff > 0) {
5260     duration -= diff;
5261
5262     if (clip_data) {
5263       /* bring clipped time to samples and then to bytes */
5264       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5265       diff *= frame_size;
5266       GST_DEBUG_OBJECT (qtdemux,
5267           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5268           " bytes", GST_TIME_ARGS (cstop), diff);
5269       size -= diff;
5270     }
5271   }
5272
5273   if (offset != 0 || size != osize)
5274     gst_buffer_resize (buf, offset, size);
5275
5276   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5277   GST_BUFFER_PTS (buf) = pts;
5278   GST_BUFFER_DURATION (buf) = duration;
5279
5280   return buf;
5281
5282   /* dropped buffer */
5283 wrong_type:
5284   {
5285     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5286     return buf;
5287   }
5288 bad_frame_size:
5289   {
5290     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5291     return buf;
5292   }
5293 no_pts:
5294   {
5295     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5296     return buf;
5297   }
5298 clipped:
5299   {
5300     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5301     gst_buffer_unref (buf);
5302     return NULL;
5303   }
5304 }
5305
5306 static GstBuffer *
5307 gst_qtdemux_align_buffer (GstQTDemux * demux,
5308     GstBuffer * buffer, gsize alignment)
5309 {
5310   GstMapInfo map;
5311
5312   gst_buffer_map (buffer, &map, GST_MAP_READ);
5313
5314   if (map.size < sizeof (guintptr)) {
5315     gst_buffer_unmap (buffer, &map);
5316     return buffer;
5317   }
5318
5319   if (((guintptr) map.data) & (alignment - 1)) {
5320     GstBuffer *new_buffer;
5321     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5322
5323     new_buffer = gst_buffer_new_allocate (NULL,
5324         gst_buffer_get_size (buffer), &params);
5325
5326     /* Copy data "by hand", so ensure alignment is kept: */
5327     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5328
5329     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5330     GST_DEBUG_OBJECT (demux,
5331         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5332         alignment);
5333
5334     gst_buffer_unmap (buffer, &map);
5335     gst_buffer_unref (buffer);
5336
5337     return new_buffer;
5338   }
5339
5340   gst_buffer_unmap (buffer, &map);
5341   return buffer;
5342 }
5343
5344 /* the input buffer metadata must be writable,
5345  * but time/duration etc not yet set and need not be preserved */
5346 static GstBuffer *
5347 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5348     GstBuffer * buf)
5349 {
5350   GstMapInfo map;
5351   guint nsize = 0;
5352   gchar *str;
5353
5354   /* not many cases for now */
5355   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5356     /* send a one time dvd clut event */
5357     if (stream->pending_event && stream->pad)
5358       gst_pad_push_event (stream->pad, stream->pending_event);
5359     stream->pending_event = NULL;
5360   }
5361
5362   if (G_UNLIKELY (stream->subtype != FOURCC_text
5363           && stream->subtype != FOURCC_sbtl &&
5364           stream->subtype != FOURCC_subp)) {
5365     return buf;
5366   }
5367
5368   gst_buffer_map (buf, &map, GST_MAP_READ);
5369
5370   /* empty buffer is sent to terminate previous subtitle */
5371   if (map.size <= 2) {
5372     gst_buffer_unmap (buf, &map);
5373     gst_buffer_unref (buf);
5374     return NULL;
5375   }
5376   if (stream->subtype == FOURCC_subp) {
5377     /* That's all the processing needed for subpictures */
5378     gst_buffer_unmap (buf, &map);
5379     return buf;
5380   }
5381
5382   nsize = GST_READ_UINT16_BE (map.data);
5383   nsize = MIN (nsize, map.size - 2);
5384
5385   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5386       nsize, map.size);
5387
5388   /* takes care of UTF-8 validation or UTF-16 recognition,
5389    * no other encoding expected */
5390   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5391   gst_buffer_unmap (buf, &map);
5392   if (str) {
5393     gst_buffer_unref (buf);
5394     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5395   } else {
5396     /* this should not really happen unless the subtitle is corrupted */
5397     gst_buffer_unref (buf);
5398     buf = NULL;
5399   }
5400
5401   /* FIXME ? convert optional subsequent style info to markup */
5402
5403   return buf;
5404 }
5405
5406 /* Sets a buffer's attributes properly and pushes it downstream.
5407  * Also checks for additional actions and custom processing that may
5408  * need to be done first.
5409  */
5410 static GstFlowReturn
5411 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5412     QtDemuxStream * stream, GstBuffer * buf,
5413     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5414     gboolean keyframe, GstClockTime position, guint64 byte_position)
5415 {
5416   GstFlowReturn ret = GST_FLOW_OK;
5417
5418   /* offset the timestamps according to the edit list */
5419
5420   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5421     gchar *url;
5422     GstMapInfo map;
5423
5424     gst_buffer_map (buf, &map, GST_MAP_READ);
5425     url = g_strndup ((gchar *) map.data, map.size);
5426     gst_buffer_unmap (buf, &map);
5427     if (url != NULL && strlen (url) != 0) {
5428       /* we have RTSP redirect now */
5429       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5430           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5431               gst_structure_new ("redirect",
5432                   "new-location", G_TYPE_STRING, url, NULL)));
5433       qtdemux->posted_redirect = TRUE;
5434     } else {
5435       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5436           "posting");
5437     }
5438     g_free (url);
5439   }
5440
5441   /* position reporting */
5442   if (qtdemux->segment.rate >= 0) {
5443     qtdemux->segment.position = position;
5444     gst_qtdemux_sync_streams (qtdemux);
5445   }
5446
5447   if (G_UNLIKELY (!stream->pad)) {
5448     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5449     gst_buffer_unref (buf);
5450     goto exit;
5451   }
5452
5453   /* send out pending buffers */
5454   while (stream->buffers) {
5455     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5456
5457     if (G_UNLIKELY (stream->discont)) {
5458       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5459       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5460       stream->discont = FALSE;
5461     } else {
5462       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5463     }
5464
5465     if (stream->alignment > 1)
5466       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5467     gst_pad_push (stream->pad, buffer);
5468
5469     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5470   }
5471
5472   /* we're going to modify the metadata */
5473   buf = gst_buffer_make_writable (buf);
5474
5475   if (G_UNLIKELY (stream->need_process))
5476     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5477
5478   if (!buf) {
5479     goto exit;
5480   }
5481
5482   GST_BUFFER_DTS (buf) = dts;
5483   GST_BUFFER_PTS (buf) = pts;
5484   GST_BUFFER_DURATION (buf) = duration;
5485   GST_BUFFER_OFFSET (buf) = -1;
5486   GST_BUFFER_OFFSET_END (buf) = -1;
5487
5488   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5489     gst_buffer_append_memory (buf,
5490         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5491
5492   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5493     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5494   }
5495 #if 0
5496   if (G_UNLIKELY (qtdemux->element_index)) {
5497     GstClockTime stream_time;
5498
5499     stream_time =
5500         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5501         timestamp);
5502     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5503       GST_LOG_OBJECT (qtdemux,
5504           "adding association %" GST_TIME_FORMAT "-> %"
5505           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5506       gst_index_add_association (qtdemux->element_index,
5507           qtdemux->index_id,
5508           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5509           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5510           GST_FORMAT_BYTES, byte_position, NULL);
5511     }
5512   }
5513 #endif
5514
5515   if (stream->need_clip)
5516     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5517
5518   if (G_UNLIKELY (buf == NULL))
5519     goto exit;
5520
5521   if (G_UNLIKELY (stream->discont)) {
5522     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5523     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5524     stream->discont = FALSE;
5525   } else {
5526     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5527   }
5528
5529   if (!keyframe) {
5530     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5531     stream->on_keyframe = FALSE;
5532   } else {
5533     stream->on_keyframe = TRUE;
5534   }
5535
5536
5537   GST_LOG_OBJECT (qtdemux,
5538       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5539       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5540       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5541       GST_PAD_NAME (stream->pad));
5542
5543   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5544     GstStructure *crypto_info;
5545     QtDemuxCencSampleSetInfo *info =
5546         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5547     gint index;
5548     GstEvent *event;
5549
5550     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5551       gst_pad_push_event (stream->pad, event);
5552     }
5553
5554     if (info->crypto_info == NULL) {
5555       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5556       gst_buffer_unref (buf);
5557       goto exit;
5558     }
5559
5560     /* The end of the crypto_info array matches our n_samples position,
5561      * so count backward from there */
5562     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5563     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5564       /* steal structure from array */
5565       crypto_info = g_ptr_array_index (info->crypto_info, index);
5566       g_ptr_array_index (info->crypto_info, index) = NULL;
5567       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5568           info->crypto_info->len);
5569       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5570         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5571     } else {
5572       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5573           index, stream->sample_index);
5574     }
5575   }
5576
5577   if (stream->alignment > 1)
5578     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5579
5580   ret = gst_pad_push (stream->pad, buf);
5581
5582   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5583     /* mark position in stream, we'll need this to know when to send GAP event */
5584     stream->segment.position = pts + duration;
5585   }
5586
5587 exit:
5588   return ret;
5589 }
5590
5591 static const QtDemuxRandomAccessEntry *
5592 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5593     GstClockTime pos, gboolean after)
5594 {
5595   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5596   guint n_entries = stream->n_ra_entries;
5597   guint i;
5598
5599   /* we assume the table is sorted */
5600   for (i = 0; i < n_entries; ++i) {
5601     if (entries[i].ts > pos)
5602       break;
5603   }
5604
5605   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5606    * probably okay to assume that the index lists the very first fragment */
5607   if (i == 0)
5608     return &entries[0];
5609
5610   if (after)
5611     return &entries[i];
5612   else
5613     return &entries[i - 1];
5614 }
5615
5616 static gboolean
5617 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5618 {
5619   const QtDemuxRandomAccessEntry *best_entry = NULL;
5620   guint i;
5621
5622   GST_OBJECT_LOCK (qtdemux);
5623
5624   g_assert (qtdemux->n_streams > 0);
5625
5626   /* first see if we can determine where to go to using mfra,
5627    * before we start clearing things */
5628   for (i = 0; i < qtdemux->n_streams; i++) {
5629     const QtDemuxRandomAccessEntry *entry;
5630     QtDemuxStream *stream;
5631     gboolean is_audio_or_video;
5632
5633     stream = qtdemux->streams[i];
5634
5635     if (stream->ra_entries == NULL)
5636       continue;
5637
5638     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5639       is_audio_or_video = TRUE;
5640     else
5641       is_audio_or_video = FALSE;
5642
5643     entry =
5644         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5645         stream->time_position, !is_audio_or_video);
5646
5647     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5648         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5649
5650     stream->pending_seek = entry;
5651
5652     /* decide position to jump to just based on audio/video tracks, not subs */
5653     if (!is_audio_or_video)
5654       continue;
5655
5656     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5657       best_entry = entry;
5658   }
5659
5660   /* no luck, will handle seek otherwise */
5661   if (best_entry == NULL) {
5662     GST_OBJECT_UNLOCK (qtdemux);
5663     return FALSE;
5664   }
5665
5666   /* ok, now we can prepare for processing as of located moof */
5667   for (i = 0; i < qtdemux->n_streams; i++) {
5668     QtDemuxStream *stream;
5669
5670     stream = qtdemux->streams[i];
5671
5672     g_free (stream->samples);
5673     stream->samples = NULL;
5674     stream->n_samples = 0;
5675     stream->stbl_index = -1;    /* no samples have yet been parsed */
5676     stream->sample_index = -1;
5677
5678     if (stream->protection_scheme_info) {
5679       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5680       if (stream->protection_scheme_type == FOURCC_cenc) {
5681         QtDemuxCencSampleSetInfo *info =
5682             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5683         if (info->crypto_info) {
5684           g_ptr_array_free (info->crypto_info, TRUE);
5685           info->crypto_info = NULL;
5686         }
5687       }
5688     }
5689   }
5690
5691   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5692       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5693       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5694       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5695
5696   qtdemux->moof_offset = best_entry->moof_offset;
5697
5698   qtdemux_add_fragmented_samples (qtdemux);
5699
5700   GST_OBJECT_UNLOCK (qtdemux);
5701   return TRUE;
5702 }
5703
5704 static GstFlowReturn
5705 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5706 {
5707   GstFlowReturn ret = GST_FLOW_OK;
5708   GstBuffer *buf = NULL;
5709   QtDemuxStream *stream;
5710   GstClockTime min_time;
5711   guint64 offset = 0;
5712   GstClockTime dts = GST_CLOCK_TIME_NONE;
5713   GstClockTime pts = GST_CLOCK_TIME_NONE;
5714   GstClockTime duration = 0;
5715   gboolean keyframe = FALSE;
5716   guint sample_size = 0;
5717   gboolean empty = 0;
5718   guint size;
5719   gint index;
5720   gint i;
5721
5722   gst_qtdemux_push_pending_newsegment (qtdemux);
5723
5724   if (qtdemux->fragmented_seek_pending) {
5725     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5726     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5727       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5728       qtdemux->fragmented_seek_pending = FALSE;
5729     } else {
5730       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5731     }
5732   }
5733
5734   /* Figure out the next stream sample to output, min_time is expressed in
5735    * global time and runs over the edit list segments. */
5736   min_time = G_MAXUINT64;
5737   index = -1;
5738   for (i = 0; i < qtdemux->n_streams; i++) {
5739     GstClockTime position;
5740
5741     stream = qtdemux->streams[i];
5742     position = stream->time_position;
5743
5744     /* position of -1 is EOS */
5745     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5746       min_time = position;
5747       index = i;
5748     }
5749   }
5750   /* all are EOS */
5751   if (G_UNLIKELY (index == -1)) {
5752     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5753     goto eos;
5754   }
5755
5756   /* check for segment end */
5757   if (G_UNLIKELY (qtdemux->segment.stop != -1
5758           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5759               || (qtdemux->segment.rate < 0
5760                   && qtdemux->segment.start > min_time))
5761           && qtdemux->streams[index]->on_keyframe)) {
5762     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5763     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5764     goto eos_stream;
5765   }
5766
5767   /* gap events for subtitle streams */
5768   for (i = 0; i < qtdemux->n_streams; i++) {
5769     stream = qtdemux->streams[i];
5770     if (stream->pad && (stream->subtype == FOURCC_subp
5771             || stream->subtype == FOURCC_text
5772             || stream->subtype == FOURCC_sbtl)) {
5773       /* send one second gap events until the stream catches up */
5774       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5775       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5776           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5777           stream->segment.position + GST_SECOND < min_time) {
5778         GstEvent *gap =
5779             gst_event_new_gap (stream->segment.position, GST_SECOND);
5780         gst_pad_push_event (stream->pad, gap);
5781         stream->segment.position += GST_SECOND;
5782       }
5783     }
5784   }
5785
5786   stream = qtdemux->streams[index];
5787   /* fetch info for the current sample of this stream */
5788   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5789               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5790     goto eos_stream;
5791
5792   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5793   if (stream->new_caps) {
5794     gst_qtdemux_configure_stream (qtdemux, stream);
5795     qtdemux_do_allocation (qtdemux, stream);
5796   }
5797
5798   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5799   if (G_UNLIKELY (qtdemux->
5800           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5801     if (stream->subtype == FOURCC_vide && !keyframe) {
5802       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5803       goto next;
5804     }
5805   }
5806
5807   GST_DEBUG_OBJECT (qtdemux,
5808       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5809       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5810       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5811       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5812
5813   if (G_UNLIKELY (empty)) {
5814     /* empty segment, push a gap and move to the next one */
5815     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5816     stream->segment.position = pts + duration;
5817     goto next;
5818   }
5819
5820   /* hmm, empty sample, skip and move to next sample */
5821   if (G_UNLIKELY (sample_size <= 0))
5822     goto next;
5823
5824   /* last pushed sample was out of boundary, goto next sample */
5825   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5826     goto next;
5827
5828   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5829     size = sample_size;
5830   } else {
5831     GST_DEBUG_OBJECT (qtdemux,
5832         "size %d larger than stream max_buffer_size %d, trimming",
5833         sample_size, stream->max_buffer_size);
5834     size =
5835         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5836   }
5837
5838   if (qtdemux->cenc_aux_info_offset > 0) {
5839     GstMapInfo map;
5840     GstByteReader br;
5841     GstBuffer *aux_info = NULL;
5842
5843     /* pull the data stored before the sample */
5844     ret =
5845         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5846         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5847     if (G_UNLIKELY (ret != GST_FLOW_OK))
5848       goto beach;
5849     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5850     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5851     gst_byte_reader_init (&br, map.data + 8, map.size);
5852     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5853             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5854       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5855       gst_buffer_unmap (aux_info, &map);
5856       gst_buffer_unref (aux_info);
5857       ret = GST_FLOW_ERROR;
5858       goto beach;
5859     }
5860     gst_buffer_unmap (aux_info, &map);
5861     gst_buffer_unref (aux_info);
5862   }
5863
5864   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5865       offset);
5866
5867   if (stream->use_allocator) {
5868     /* if we have a per-stream allocator, use it */
5869     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5870   }
5871
5872   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5873       size, &buf);
5874   if (G_UNLIKELY (ret != GST_FLOW_OK))
5875     goto beach;
5876
5877   if (size != sample_size) {
5878     pts += gst_util_uint64_scale_int (GST_SECOND,
5879         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5880         stream->timescale);
5881     dts +=
5882         gst_util_uint64_scale_int (GST_SECOND,
5883         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5884         stream->timescale);
5885     duration =
5886         gst_util_uint64_scale_int (GST_SECOND,
5887         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5888   }
5889
5890   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5891       dts, pts, duration, keyframe, min_time, offset);
5892
5893   if (size != sample_size) {
5894     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5895     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5896
5897     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5898         sample->timestamp +
5899         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5900     if (time_position >= segment->media_start) {
5901       /* inside the segment, update time_position, looks very familiar to
5902        * GStreamer segments, doesn't it? */
5903       stream->time_position = (time_position - segment->media_start) +
5904           segment->time;
5905     } else {
5906       /* not yet in segment, time does not yet increment. This means
5907        * that we are still prerolling keyframes to the decoder so it can
5908        * decode the first sample of the segment. */
5909       stream->time_position = segment->time;
5910     }
5911   }
5912
5913   /* combine flows */
5914   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5915   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5916    * we have no more data for the pad to push */
5917   if (ret == GST_FLOW_EOS)
5918     ret = GST_FLOW_OK;
5919
5920   stream->offset_in_sample += size;
5921   if (stream->offset_in_sample >= sample_size) {
5922     gst_qtdemux_advance_sample (qtdemux, stream);
5923   }
5924   goto beach;
5925
5926 next:
5927   gst_qtdemux_advance_sample (qtdemux, stream);
5928
5929 beach:
5930   return ret;
5931
5932   /* special cases */
5933 eos:
5934   {
5935     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5936     ret = GST_FLOW_EOS;
5937     goto beach;
5938   }
5939 eos_stream:
5940   {
5941     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5942     /* EOS will be raised if all are EOS */
5943     ret = GST_FLOW_OK;
5944     goto beach;
5945   }
5946 }
5947
5948 static void
5949 gst_qtdemux_loop (GstPad * pad)
5950 {
5951   GstQTDemux *qtdemux;
5952   guint64 cur_offset;
5953   GstFlowReturn ret;
5954
5955   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5956
5957   cur_offset = qtdemux->offset;
5958   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5959       cur_offset, qt_demux_state_string (qtdemux->state));
5960
5961   switch (qtdemux->state) {
5962     case QTDEMUX_STATE_INITIAL:
5963     case QTDEMUX_STATE_HEADER:
5964       ret = gst_qtdemux_loop_state_header (qtdemux);
5965       break;
5966     case QTDEMUX_STATE_MOVIE:
5967       ret = gst_qtdemux_loop_state_movie (qtdemux);
5968       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5969         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5970       }
5971       break;
5972     default:
5973       /* ouch */
5974       goto invalid_state;
5975   }
5976
5977   /* if something went wrong, pause */
5978   if (ret != GST_FLOW_OK)
5979     goto pause;
5980
5981 done:
5982   gst_object_unref (qtdemux);
5983   return;
5984
5985   /* ERRORS */
5986 invalid_state:
5987   {
5988     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5989         (NULL), ("streaming stopped, invalid state"));
5990     gst_pad_pause_task (pad);
5991     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5992     goto done;
5993   }
5994 pause:
5995   {
5996     const gchar *reason = gst_flow_get_name (ret);
5997
5998     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5999
6000     gst_pad_pause_task (pad);
6001
6002     /* fatal errors need special actions */
6003     /* check EOS */
6004     if (ret == GST_FLOW_EOS) {
6005       if (qtdemux->n_streams == 0) {
6006         /* we have no streams, post an error */
6007         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6008       }
6009       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6010         gint64 stop;
6011
6012         if ((stop = qtdemux->segment.stop) == -1)
6013           stop = qtdemux->segment.duration;
6014
6015         if (qtdemux->segment.rate >= 0) {
6016           GstMessage *message;
6017           GstEvent *event;
6018
6019           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6020           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6021               GST_FORMAT_TIME, stop);
6022           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6023           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6024             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6025             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6026           }
6027           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6028           gst_qtdemux_push_event (qtdemux, event);
6029         } else {
6030           GstMessage *message;
6031           GstEvent *event;
6032
6033           /*  For Reverse Playback */
6034           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6035           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6036               GST_FORMAT_TIME, qtdemux->segment.start);
6037           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6038               qtdemux->segment.start);
6039           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6040             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6041             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6042           }
6043           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6044           gst_qtdemux_push_event (qtdemux, event);
6045         }
6046       } else {
6047         GstEvent *event;
6048
6049         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6050         event = gst_event_new_eos ();
6051         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6052           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6053         gst_qtdemux_push_event (qtdemux, event);
6054       }
6055     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6056       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6057       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6058     }
6059     goto done;
6060   }
6061 }
6062
6063 /*
6064  * has_next_entry
6065  *
6066  * Returns if there are samples to be played.
6067  */
6068 static gboolean
6069 has_next_entry (GstQTDemux * demux)
6070 {
6071   QtDemuxStream *stream;
6072   int i;
6073
6074   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6075
6076   for (i = 0; i < demux->n_streams; i++) {
6077     stream = demux->streams[i];
6078
6079     if (stream->sample_index == -1) {
6080       stream->sample_index = 0;
6081       stream->offset_in_sample = 0;
6082     }
6083
6084     if (stream->sample_index >= stream->n_samples) {
6085       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6086       continue;
6087     }
6088     GST_DEBUG_OBJECT (demux, "Found a sample");
6089     return TRUE;
6090   }
6091
6092   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6093   return FALSE;
6094 }
6095
6096 /*
6097  * next_entry_size
6098  *
6099  * Returns the size of the first entry at the current offset.
6100  * If -1, there are none (which means EOS or empty file).
6101  */
6102 static guint64
6103 next_entry_size (GstQTDemux * demux)
6104 {
6105   QtDemuxStream *stream;
6106   int i;
6107   int smallidx = -1;
6108   guint64 smalloffs = (guint64) - 1;
6109   QtDemuxSample *sample;
6110
6111   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6112       demux->offset);
6113
6114   for (i = 0; i < demux->n_streams; i++) {
6115     stream = demux->streams[i];
6116
6117     if (stream->sample_index == -1) {
6118       stream->sample_index = 0;
6119       stream->offset_in_sample = 0;
6120     }
6121
6122     if (stream->sample_index >= stream->n_samples) {
6123       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6124       continue;
6125     }
6126
6127     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6128       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6129           stream->sample_index);
6130       return -1;
6131     }
6132
6133     sample = &stream->samples[stream->sample_index];
6134
6135     GST_LOG_OBJECT (demux,
6136         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6137         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6138         sample->offset, sample->size);
6139
6140     if (((smalloffs == -1)
6141             || (sample->offset < smalloffs)) && (sample->size)) {
6142       smallidx = i;
6143       smalloffs = sample->offset;
6144     }
6145   }
6146
6147   GST_LOG_OBJECT (demux,
6148       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6149       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6150
6151   if (smallidx == -1)
6152     return -1;
6153
6154   stream = demux->streams[smallidx];
6155   sample = &stream->samples[stream->sample_index];
6156
6157   if (sample->offset >= demux->offset) {
6158     demux->todrop = sample->offset - demux->offset;
6159     return sample->size + demux->todrop;
6160   }
6161
6162   GST_DEBUG_OBJECT (demux,
6163       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6164   return -1;
6165 }
6166
6167 static void
6168 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6169 {
6170   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6171
6172   gst_element_post_message (GST_ELEMENT_CAST (demux),
6173       gst_message_new_element (GST_OBJECT_CAST (demux),
6174           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6175 }
6176
6177 static gboolean
6178 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6179 {
6180   GstEvent *event;
6181   gboolean res = 0;
6182
6183   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6184
6185   event =
6186       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6187       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6188       GST_SEEK_TYPE_NONE, -1);
6189
6190   /* store seqnum to drop flush events, they don't need to reach downstream */
6191   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6192   res = gst_pad_push_event (demux->sinkpad, event);
6193   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6194
6195   return res;
6196 }
6197
6198 /* check for seekable upstream, above and beyond a mere query */
6199 static void
6200 gst_qtdemux_check_seekability (GstQTDemux * demux)
6201 {
6202   GstQuery *query;
6203   gboolean seekable = FALSE;
6204   gint64 start = -1, stop = -1;
6205
6206   if (demux->upstream_size)
6207     return;
6208
6209   if (demux->upstream_format_is_time)
6210     return;
6211
6212   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6213   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6214     GST_DEBUG_OBJECT (demux, "seeking query failed");
6215     goto done;
6216   }
6217
6218   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6219
6220   /* try harder to query upstream size if we didn't get it the first time */
6221   if (seekable && stop == -1) {
6222     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6223     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6224   }
6225
6226   /* if upstream doesn't know the size, it's likely that it's not seekable in
6227    * practice even if it technically may be seekable */
6228   if (seekable && (start != 0 || stop <= start)) {
6229     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6230     seekable = FALSE;
6231   }
6232
6233 done:
6234   gst_query_unref (query);
6235
6236   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6237       G_GUINT64_FORMAT ")", seekable, start, stop);
6238   demux->upstream_seekable = seekable;
6239   demux->upstream_size = seekable ? stop : -1;
6240 }
6241
6242 static void
6243 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6244 {
6245   g_return_if_fail (bytes <= demux->todrop);
6246
6247   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6248   gst_adapter_flush (demux->adapter, bytes);
6249   demux->neededbytes -= bytes;
6250   demux->offset += bytes;
6251   demux->todrop -= bytes;
6252 }
6253
6254 static void
6255 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6256 {
6257   if (G_UNLIKELY (demux->pending_newsegment)) {
6258     gint i;
6259
6260     gst_qtdemux_push_pending_newsegment (demux);
6261     /* clear to send tags on all streams */
6262     for (i = 0; i < demux->n_streams; i++) {
6263       QtDemuxStream *stream;
6264       stream = demux->streams[i];
6265       gst_qtdemux_push_tags (demux, stream);
6266       if (CUR_STREAM (stream)->sparse) {
6267         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6268         gst_pad_push_event (stream->pad,
6269             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6270       }
6271     }
6272   }
6273 }
6274
6275 static void
6276 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6277     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6278 {
6279   GstClockTime ts, dur;
6280   GstEvent *gap;
6281
6282   ts = pos;
6283   dur =
6284       stream->segments[segment_index].duration - (pos -
6285       stream->segments[segment_index].time);
6286   gap = gst_event_new_gap (ts, dur);
6287   stream->time_position += dur;
6288
6289   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6290       "segment: %" GST_PTR_FORMAT, gap);
6291   gst_pad_push_event (stream->pad, gap);
6292 }
6293
6294 static void
6295 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6296     QtDemuxStream * stream)
6297 {
6298   gint i;
6299
6300   /* Push any initial gap segments before proceeding to the
6301    * 'real' data */
6302   for (i = 0; i < stream->n_segments; i++) {
6303     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6304
6305     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6306       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6307           stream->time_position);
6308     } else {
6309       /* Only support empty segment at the beginning followed by
6310        * one non-empty segment, this was checked when parsing the
6311        * edts atom, arriving here is unexpected */
6312       g_assert (i + 1 == stream->n_segments);
6313       break;
6314     }
6315   }
6316 }
6317
6318 static GstFlowReturn
6319 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6320 {
6321   GstQTDemux *demux;
6322
6323   demux = GST_QTDEMUX (parent);
6324
6325   GST_DEBUG_OBJECT (demux,
6326       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6327       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6328       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6329       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6330       gst_buffer_get_size (inbuf), demux->offset);
6331
6332   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6333     gboolean is_gap_input = FALSE;
6334     gint i;
6335
6336     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6337
6338     for (i = 0; i < demux->n_streams; i++) {
6339       demux->streams[i]->discont = TRUE;
6340     }
6341
6342     /* Check if we can land back on our feet in the case where upstream is
6343      * handling the seeking/pushing of samples with gaps in between (like
6344      * in the case of trick-mode DASH for example) */
6345     if (demux->upstream_format_is_time
6346         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6347       gint i;
6348       for (i = 0; i < demux->n_streams; i++) {
6349         guint32 res;
6350         GST_LOG_OBJECT (demux,
6351             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6352             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6353         res =
6354             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6355             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6356         if (res != -1) {
6357           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6358           GST_LOG_OBJECT (demux,
6359               "Checking if sample %d from stream %d is valid (offset:%"
6360               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6361               sample->offset, sample->size);
6362           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6363             GST_LOG_OBJECT (demux,
6364                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6365                 res);
6366             is_gap_input = TRUE;
6367             /* We can go back to standard playback mode */
6368             demux->state = QTDEMUX_STATE_MOVIE;
6369             /* Remember which sample this stream is at */
6370             demux->streams[i]->sample_index = res;
6371             /* Finally update all push-based values to the expected values */
6372             demux->neededbytes = demux->streams[i]->samples[res].size;
6373             demux->offset = GST_BUFFER_OFFSET (inbuf);
6374             demux->mdatleft =
6375                 demux->mdatsize - demux->offset + demux->mdatoffset;
6376             demux->todrop = 0;
6377           }
6378         }
6379       }
6380       if (!is_gap_input) {
6381         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6382         /* Reset state if it's a real discont */
6383         demux->neededbytes = 16;
6384         demux->state = QTDEMUX_STATE_INITIAL;
6385         demux->offset = GST_BUFFER_OFFSET (inbuf);
6386         gst_adapter_clear (demux->adapter);
6387       }
6388     }
6389     /* Reverse fragmented playback, need to flush all we have before
6390      * consuming a new fragment.
6391      * The samples array have the timestamps calculated by accumulating the
6392      * durations but this won't work for reverse playback of fragments as
6393      * the timestamps of a subsequent fragment should be smaller than the
6394      * previously received one. */
6395     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6396       gst_qtdemux_process_adapter (demux, TRUE);
6397       for (i = 0; i < demux->n_streams; i++)
6398         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6399     }
6400   }
6401
6402   gst_adapter_push (demux->adapter, inbuf);
6403
6404   GST_DEBUG_OBJECT (demux,
6405       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6406       demux->neededbytes, gst_adapter_available (demux->adapter));
6407
6408   return gst_qtdemux_process_adapter (demux, FALSE);
6409 }
6410
6411 static GstFlowReturn
6412 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6413 {
6414   GstFlowReturn ret = GST_FLOW_OK;
6415
6416   /* we never really mean to buffer that much */
6417   if (demux->neededbytes == -1) {
6418     goto eos;
6419   }
6420
6421   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6422       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6423
6424 #ifndef GST_DISABLE_GST_DEBUG
6425     {
6426       guint64 discont_offset, distance_from_discont;
6427
6428       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6429       distance_from_discont =
6430           gst_adapter_distance_from_discont (demux->adapter);
6431
6432       GST_DEBUG_OBJECT (demux,
6433           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6434           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6435           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6436           demux->offset, discont_offset, distance_from_discont);
6437     }
6438 #endif
6439
6440     switch (demux->state) {
6441       case QTDEMUX_STATE_INITIAL:{
6442         const guint8 *data;
6443         guint32 fourcc;
6444         guint64 size;
6445
6446         gst_qtdemux_check_seekability (demux);
6447
6448         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6449
6450         /* get fourcc/length, set neededbytes */
6451         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6452             &size, &fourcc);
6453         gst_adapter_unmap (demux->adapter);
6454         data = NULL;
6455         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6456             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6457         if (size == 0) {
6458           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6459               (_("This file is invalid and cannot be played.")),
6460               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6461                   GST_FOURCC_ARGS (fourcc)));
6462           ret = GST_FLOW_ERROR;
6463           break;
6464         }
6465         if (fourcc == FOURCC_mdat) {
6466           gint next_entry = next_entry_size (demux);
6467           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6468             /* we have the headers, start playback */
6469             demux->state = QTDEMUX_STATE_MOVIE;
6470             demux->neededbytes = next_entry;
6471             demux->mdatleft = size;
6472             demux->mdatsize = demux->mdatleft;
6473           } else {
6474             /* no headers yet, try to get them */
6475             guint bs;
6476             gboolean res;
6477             guint64 old, target;
6478
6479           buffer_data:
6480             old = demux->offset;
6481             target = old + size;
6482
6483             /* try to jump over the atom with a seek */
6484             /* only bother if it seems worth doing so,
6485              * and avoids possible upstream/server problems */
6486             if (demux->upstream_seekable &&
6487                 demux->upstream_size > 4 * (1 << 20)) {
6488               res = qtdemux_seek_offset (demux, target);
6489             } else {
6490               GST_DEBUG_OBJECT (demux, "skipping seek");
6491               res = FALSE;
6492             }
6493
6494             if (res) {
6495               GST_DEBUG_OBJECT (demux, "seek success");
6496               /* remember the offset fo the first mdat so we can seek back to it
6497                * after we have the headers */
6498               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6499                 demux->first_mdat = old;
6500                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6501                     demux->first_mdat);
6502               }
6503               /* seek worked, continue reading */
6504               demux->offset = target;
6505               demux->neededbytes = 16;
6506               demux->state = QTDEMUX_STATE_INITIAL;
6507             } else {
6508               /* seek failed, need to buffer */
6509               demux->offset = old;
6510               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6511               /* there may be multiple mdat (or alike) buffers */
6512               /* sanity check */
6513               if (demux->mdatbuffer)
6514                 bs = gst_buffer_get_size (demux->mdatbuffer);
6515               else
6516                 bs = 0;
6517               if (size + bs > 10 * (1 << 20))
6518                 goto no_moov;
6519               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6520               demux->neededbytes = size;
6521               if (!demux->mdatbuffer)
6522                 demux->mdatoffset = demux->offset;
6523             }
6524           }
6525         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6526           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6527               (_("This file is invalid and cannot be played.")),
6528               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6529                   GST_FOURCC_ARGS (fourcc), size));
6530           ret = GST_FLOW_ERROR;
6531           break;
6532         } else {
6533           /* this means we already started buffering and still no moov header,
6534            * let's continue buffering everything till we get moov */
6535           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6536                   || fourcc == FOURCC_moof))
6537             goto buffer_data;
6538           demux->neededbytes = size;
6539           demux->state = QTDEMUX_STATE_HEADER;
6540         }
6541         break;
6542       }
6543       case QTDEMUX_STATE_HEADER:{
6544         const guint8 *data;
6545         guint32 fourcc;
6546
6547         GST_DEBUG_OBJECT (demux, "In header");
6548
6549         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6550
6551         /* parse the header */
6552         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6553             &fourcc);
6554         if (fourcc == FOURCC_moov) {
6555           gint n;
6556
6557           /* in usual fragmented setup we could try to scan for more
6558            * and end up at the the moov (after mdat) again */
6559           if (demux->got_moov && demux->n_streams > 0 &&
6560               (!demux->fragmented
6561                   || demux->last_moov_offset == demux->offset)) {
6562             GST_DEBUG_OBJECT (demux,
6563                 "Skipping moov atom as we have (this) one already");
6564           } else {
6565             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6566
6567             if (demux->got_moov && demux->fragmented) {
6568               GST_DEBUG_OBJECT (demux,
6569                   "Got a second moov, clean up data from old one");
6570               if (demux->moov_node_compressed) {
6571                 g_node_destroy (demux->moov_node_compressed);
6572                 if (demux->moov_node)
6573                   g_free (demux->moov_node->data);
6574               }
6575               demux->moov_node_compressed = NULL;
6576               if (demux->moov_node)
6577                 g_node_destroy (demux->moov_node);
6578               demux->moov_node = NULL;
6579             } else {
6580               /* prepare newsegment to send when streaming actually starts */
6581               if (!demux->pending_newsegment) {
6582                 demux->pending_newsegment =
6583                     gst_event_new_segment (&demux->segment);
6584                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6585                   gst_event_set_seqnum (demux->pending_newsegment,
6586                       demux->segment_seqnum);
6587               }
6588             }
6589
6590             demux->last_moov_offset = demux->offset;
6591
6592             qtdemux_parse_moov (demux, data, demux->neededbytes);
6593             qtdemux_node_dump (demux, demux->moov_node);
6594             qtdemux_parse_tree (demux);
6595             qtdemux_prepare_streams (demux);
6596             if (!demux->got_moov)
6597               qtdemux_expose_streams (demux);
6598             else {
6599
6600               for (n = 0; n < demux->n_streams; n++) {
6601                 QtDemuxStream *stream = demux->streams[n];
6602
6603                 gst_qtdemux_configure_stream (demux, stream);
6604               }
6605             }
6606
6607             demux->got_moov = TRUE;
6608             gst_qtdemux_check_send_pending_segment (demux);
6609
6610             /* fragmented streams headers shouldn't contain edts atoms */
6611             if (!demux->fragmented) {
6612               for (n = 0; n < demux->n_streams; n++) {
6613                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6614                     demux->streams[n]);
6615               }
6616             }
6617
6618             if (demux->moov_node_compressed) {
6619               g_node_destroy (demux->moov_node_compressed);
6620               g_free (demux->moov_node->data);
6621             }
6622             demux->moov_node_compressed = NULL;
6623             g_node_destroy (demux->moov_node);
6624             demux->moov_node = NULL;
6625             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6626           }
6627         } else if (fourcc == FOURCC_moof) {
6628           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6629             guint64 dist = 0;
6630             GstClockTime prev_pts;
6631             guint64 prev_offset;
6632             guint64 adapter_discont_offset, adapter_discont_dist;
6633
6634             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6635
6636             /*
6637              * The timestamp of the moof buffer is relevant as some scenarios
6638              * won't have the initial timestamp in the atoms. Whenever a new
6639              * buffer has started, we get that buffer's PTS and use it as a base
6640              * timestamp for the trun entries.
6641              *
6642              * To keep track of the current buffer timestamp and starting point
6643              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6644              * from the beggining of the buffer, with the distance and demux->offset
6645              * we know if it is still the same buffer or not.
6646              */
6647             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6648             prev_offset = demux->offset - dist;
6649             if (demux->fragment_start_offset == -1
6650                 || prev_offset > demux->fragment_start_offset) {
6651               demux->fragment_start_offset = prev_offset;
6652               demux->fragment_start = prev_pts;
6653               GST_DEBUG_OBJECT (demux,
6654                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6655                   GST_TIME_FORMAT, demux->fragment_start_offset,
6656                   GST_TIME_ARGS (demux->fragment_start));
6657             }
6658
6659             /* We can't use prev_offset() here because this would require
6660              * upstream to set consistent and correct offsets on all buffers
6661              * since the discont. Nothing ever did that in the past and we
6662              * would break backwards compatibility here then.
6663              * Instead take the offset we had at the last discont and count
6664              * the bytes from there. This works with old code as there would
6665              * be no discont between moov and moof, and also works with
6666              * adaptivedemux which correctly sets offset and will set the
6667              * DISCONT flag accordingly when needed.
6668              *
6669              * We also only do this for upstream TIME segments as otherwise
6670              * there are potential backwards compatibility problems with
6671              * seeking in PUSH mode and upstream providing inconsistent
6672              * timestamps. */
6673             adapter_discont_offset =
6674                 gst_adapter_offset_at_discont (demux->adapter);
6675             adapter_discont_dist =
6676                 gst_adapter_distance_from_discont (demux->adapter);
6677
6678             GST_DEBUG_OBJECT (demux,
6679                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6680                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6681                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6682
6683             if (demux->upstream_format_is_time) {
6684               demux->moof_offset = adapter_discont_offset;
6685               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6686                 demux->moof_offset += adapter_discont_dist;
6687               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6688                 demux->moof_offset = demux->offset;
6689             } else {
6690               demux->moof_offset = demux->offset;
6691             }
6692
6693             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6694                     demux->moof_offset, NULL)) {
6695               gst_adapter_unmap (demux->adapter);
6696               ret = GST_FLOW_ERROR;
6697               goto done;
6698             }
6699             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6700             if (demux->mss_mode && !demux->exposed) {
6701               if (!demux->pending_newsegment) {
6702                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6703                 demux->pending_newsegment =
6704                     gst_event_new_segment (&demux->segment);
6705                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6706                   gst_event_set_seqnum (demux->pending_newsegment,
6707                       demux->segment_seqnum);
6708               }
6709               qtdemux_expose_streams (demux);
6710             }
6711           } else {
6712             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6713           }
6714         } else if (fourcc == FOURCC_ftyp) {
6715           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6716           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6717         } else if (fourcc == FOURCC_uuid) {
6718           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6719           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6720         } else if (fourcc == FOURCC_sidx) {
6721           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6722           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6723         } else {
6724           switch (fourcc) {
6725             case FOURCC_styp:
6726               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6727                * FALLTHROUGH */
6728             case FOURCC_skip:
6729             case FOURCC_free:
6730               /* [free] and [skip] are padding atoms */
6731               GST_DEBUG_OBJECT (demux,
6732                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6733                   GST_FOURCC_ARGS (fourcc));
6734               break;
6735             default:
6736               GST_WARNING_OBJECT (demux,
6737                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6738                   GST_FOURCC_ARGS (fourcc));
6739               /* Let's jump that one and go back to initial state */
6740               break;
6741           }
6742         }
6743         gst_adapter_unmap (demux->adapter);
6744         data = NULL;
6745
6746         if (demux->mdatbuffer && demux->n_streams) {
6747           gsize remaining_data_size = 0;
6748
6749           /* the mdat was before the header */
6750           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6751               demux->n_streams, demux->mdatbuffer);
6752           /* restore our adapter/offset view of things with upstream;
6753            * put preceding buffered data ahead of current moov data.
6754            * This should also handle evil mdat, moov, mdat cases and alike */
6755           gst_adapter_flush (demux->adapter, demux->neededbytes);
6756
6757           /* Store any remaining data after the mdat for later usage */
6758           remaining_data_size = gst_adapter_available (demux->adapter);
6759           if (remaining_data_size > 0) {
6760             g_assert (demux->restoredata_buffer == NULL);
6761             demux->restoredata_buffer =
6762                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6763             demux->restoredata_offset = demux->offset + demux->neededbytes;
6764             GST_DEBUG_OBJECT (demux,
6765                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6766                 G_GUINT64_FORMAT, remaining_data_size,
6767                 demux->restoredata_offset);
6768           }
6769
6770           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6771           demux->mdatbuffer = NULL;
6772           demux->offset = demux->mdatoffset;
6773           demux->neededbytes = next_entry_size (demux);
6774           demux->state = QTDEMUX_STATE_MOVIE;
6775           demux->mdatleft = gst_adapter_available (demux->adapter);
6776           demux->mdatsize = demux->mdatleft;
6777         } else {
6778           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6779           gst_adapter_flush (demux->adapter, demux->neededbytes);
6780
6781           /* only go back to the mdat if there are samples to play */
6782           if (demux->got_moov && demux->first_mdat != -1
6783               && has_next_entry (demux)) {
6784             gboolean res;
6785
6786             /* we need to seek back */
6787             res = qtdemux_seek_offset (demux, demux->first_mdat);
6788             if (res) {
6789               demux->offset = demux->first_mdat;
6790             } else {
6791               GST_DEBUG_OBJECT (demux, "Seek back failed");
6792             }
6793           } else {
6794             demux->offset += demux->neededbytes;
6795           }
6796           demux->neededbytes = 16;
6797           demux->state = QTDEMUX_STATE_INITIAL;
6798         }
6799
6800         break;
6801       }
6802       case QTDEMUX_STATE_BUFFER_MDAT:{
6803         GstBuffer *buf;
6804         guint8 fourcc[4];
6805
6806         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6807             demux->offset);
6808         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6809         gst_buffer_extract (buf, 0, fourcc, 4);
6810         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6811             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6812         if (demux->mdatbuffer)
6813           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6814         else
6815           demux->mdatbuffer = buf;
6816         demux->offset += demux->neededbytes;
6817         demux->neededbytes = 16;
6818         demux->state = QTDEMUX_STATE_INITIAL;
6819         gst_qtdemux_post_progress (demux, 1, 1);
6820
6821         break;
6822       }
6823       case QTDEMUX_STATE_MOVIE:{
6824         QtDemuxStream *stream = NULL;
6825         QtDemuxSample *sample;
6826         int i = -1;
6827         GstClockTime dts, pts, duration;
6828         gboolean keyframe;
6829
6830         GST_DEBUG_OBJECT (demux,
6831             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6832
6833         if (demux->fragmented) {
6834           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6835               demux->mdatleft);
6836           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6837             /* if needed data starts within this atom,
6838              * then it should not exceed this atom */
6839             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6840               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6841                   (_("This file is invalid and cannot be played.")),
6842                   ("sample data crosses atom boundary"));
6843               ret = GST_FLOW_ERROR;
6844               break;
6845             }
6846             demux->mdatleft -= demux->neededbytes;
6847           } else {
6848             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6849             /* so we are dropping more than left in this atom */
6850             gst_qtdemux_drop_data (demux, demux->mdatleft);
6851             demux->mdatleft = 0;
6852
6853             /* need to resume atom parsing so we do not miss any other pieces */
6854             demux->state = QTDEMUX_STATE_INITIAL;
6855             demux->neededbytes = 16;
6856
6857             /* check if there was any stored post mdat data from previous buffers */
6858             if (demux->restoredata_buffer) {
6859               g_assert (gst_adapter_available (demux->adapter) == 0);
6860
6861               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6862               demux->restoredata_buffer = NULL;
6863               demux->offset = demux->restoredata_offset;
6864             }
6865
6866             break;
6867           }
6868         }
6869
6870         if (demux->todrop) {
6871           if (demux->cenc_aux_info_offset > 0) {
6872             GstByteReader br;
6873             const guint8 *data;
6874
6875             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6876             data = gst_adapter_map (demux->adapter, demux->todrop);
6877             gst_byte_reader_init (&br, data + 8, demux->todrop);
6878             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6879                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6880               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6881               ret = GST_FLOW_ERROR;
6882               gst_adapter_unmap (demux->adapter);
6883               g_free (demux->cenc_aux_info_sizes);
6884               demux->cenc_aux_info_sizes = NULL;
6885               goto done;
6886             }
6887             demux->cenc_aux_info_offset = 0;
6888             g_free (demux->cenc_aux_info_sizes);
6889             demux->cenc_aux_info_sizes = NULL;
6890             gst_adapter_unmap (demux->adapter);
6891           }
6892           gst_qtdemux_drop_data (demux, demux->todrop);
6893         }
6894
6895         /* first buffer? */
6896         /* initial newsegment sent here after having added pads,
6897          * possible others in sink_event */
6898         gst_qtdemux_check_send_pending_segment (demux);
6899
6900         /* Figure out which stream this packet belongs to */
6901         for (i = 0; i < demux->n_streams; i++) {
6902           stream = demux->streams[i];
6903           if (stream->sample_index >= stream->n_samples)
6904             continue;
6905           GST_LOG_OBJECT (demux,
6906               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6907               " / size:%d)", i, stream->sample_index,
6908               stream->samples[stream->sample_index].offset,
6909               stream->samples[stream->sample_index].size);
6910
6911           if (stream->samples[stream->sample_index].offset == demux->offset)
6912             break;
6913         }
6914
6915         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6916           goto unknown_stream;
6917
6918         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6919
6920         if (stream->new_caps) {
6921           gst_qtdemux_configure_stream (demux, stream);
6922         }
6923
6924         /* Put data in a buffer, set timestamps, caps, ... */
6925         sample = &stream->samples[stream->sample_index];
6926
6927         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6928           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6929               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6930
6931           dts = QTSAMPLE_DTS (stream, sample);
6932           pts = QTSAMPLE_PTS (stream, sample);
6933           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6934           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6935
6936           /* check for segment end */
6937           if (G_UNLIKELY (demux->segment.stop != -1
6938                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6939             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6940             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6941
6942             /* skip this data, stream is EOS */
6943             gst_adapter_flush (demux->adapter, demux->neededbytes);
6944             demux->offset += demux->neededbytes;
6945
6946             /* check if all streams are eos */
6947             ret = GST_FLOW_EOS;
6948             for (i = 0; i < demux->n_streams; i++) {
6949               if (!STREAM_IS_EOS (demux->streams[i])) {
6950                 ret = GST_FLOW_OK;
6951                 break;
6952               }
6953             }
6954           } else {
6955             GstBuffer *outbuf;
6956
6957             outbuf =
6958                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6959
6960             /* FIXME: should either be an assert or a plain check */
6961             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6962
6963             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6964                 dts, pts, duration, keyframe, dts, demux->offset);
6965           }
6966
6967           /* combine flows */
6968           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6969         } else {
6970           /* skip this data, stream is EOS */
6971           gst_adapter_flush (demux->adapter, demux->neededbytes);
6972         }
6973
6974         stream->sample_index++;
6975         stream->offset_in_sample = 0;
6976
6977         /* update current offset and figure out size of next buffer */
6978         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6979             demux->offset, demux->neededbytes);
6980         demux->offset += demux->neededbytes;
6981         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6982             demux->offset);
6983
6984
6985         if (ret == GST_FLOW_EOS) {
6986           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6987           demux->neededbytes = -1;
6988           goto eos;
6989         }
6990
6991         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6992           if (demux->fragmented) {
6993             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6994             /* there may be more to follow, only finish this atom */
6995             demux->todrop = demux->mdatleft;
6996             demux->neededbytes = demux->todrop;
6997             break;
6998           }
6999           goto eos;
7000         }
7001         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7002           goto non_ok_unlinked_flow;
7003         }
7004         break;
7005       }
7006       default:
7007         goto invalid_state;
7008     }
7009   }
7010
7011   /* when buffering movie data, at least show user something is happening */
7012   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7013       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7014     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7015         demux->neededbytes);
7016   }
7017 done:
7018
7019   return ret;
7020
7021   /* ERRORS */
7022 non_ok_unlinked_flow:
7023   {
7024     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7025         gst_flow_get_name (ret));
7026     return ret;
7027   }
7028 unknown_stream:
7029   {
7030     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7031     ret = GST_FLOW_ERROR;
7032     goto done;
7033   }
7034 eos:
7035   {
7036     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7037     ret = GST_FLOW_EOS;
7038     goto done;
7039   }
7040 invalid_state:
7041   {
7042     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7043         (NULL), ("qtdemuxer invalid state %d", demux->state));
7044     ret = GST_FLOW_ERROR;
7045     goto done;
7046   }
7047 no_moov:
7048   {
7049     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7050         (NULL), ("no 'moov' atom within the first 10 MB"));
7051     ret = GST_FLOW_ERROR;
7052     goto done;
7053   }
7054 }
7055
7056 static gboolean
7057 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7058 {
7059   GstQuery *query;
7060   gboolean pull_mode;
7061
7062   query = gst_query_new_scheduling ();
7063
7064   if (!gst_pad_peer_query (sinkpad, query)) {
7065     gst_query_unref (query);
7066     goto activate_push;
7067   }
7068
7069   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7070       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7071   gst_query_unref (query);
7072
7073   if (!pull_mode)
7074     goto activate_push;
7075
7076   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7077   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7078
7079 activate_push:
7080   {
7081     GST_DEBUG_OBJECT (sinkpad, "activating push");
7082     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7083   }
7084 }
7085
7086 static gboolean
7087 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7088     GstPadMode mode, gboolean active)
7089 {
7090   gboolean res;
7091   GstQTDemux *demux = GST_QTDEMUX (parent);
7092
7093   switch (mode) {
7094     case GST_PAD_MODE_PUSH:
7095       demux->pullbased = FALSE;
7096       res = TRUE;
7097       break;
7098     case GST_PAD_MODE_PULL:
7099       if (active) {
7100         demux->pullbased = TRUE;
7101         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7102             sinkpad, NULL);
7103       } else {
7104         res = gst_pad_stop_task (sinkpad);
7105       }
7106       break;
7107     default:
7108       res = FALSE;
7109       break;
7110   }
7111   return res;
7112 }
7113
7114 #ifdef HAVE_ZLIB
7115 static void *
7116 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7117 {
7118   guint8 *buffer;
7119   z_stream z;
7120   int ret;
7121
7122   memset (&z, 0, sizeof (z));
7123   z.zalloc = NULL;
7124   z.zfree = NULL;
7125   z.opaque = NULL;
7126
7127   if ((ret = inflateInit (&z)) != Z_OK) {
7128     GST_ERROR ("inflateInit() returned %d", ret);
7129     return NULL;
7130   }
7131
7132   z.next_in = z_buffer;
7133   z.avail_in = z_length;
7134
7135   buffer = (guint8 *) g_malloc (*length);
7136   z.avail_out = *length;
7137   z.next_out = (Bytef *) buffer;
7138   do {
7139     ret = inflate (&z, Z_NO_FLUSH);
7140     if (ret == Z_STREAM_END) {
7141       break;
7142     } else if (ret != Z_OK) {
7143       GST_WARNING ("inflate() returned %d", ret);
7144       break;
7145     }
7146
7147     *length += 4096;
7148     buffer = (guint8 *) g_realloc (buffer, *length);
7149     z.next_out = (Bytef *) (buffer + z.total_out);
7150     z.avail_out += 4096;
7151   } while (z.avail_in > 0);
7152
7153   if (ret != Z_STREAM_END) {
7154     g_free (buffer);
7155     buffer = NULL;
7156     *length = 0;
7157   } else {
7158     *length = z.total_out;
7159   }
7160
7161   inflateEnd (&z);
7162
7163   return buffer;
7164 }
7165 #endif /* HAVE_ZLIB */
7166
7167 static gboolean
7168 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7169 {
7170   GNode *cmov;
7171
7172   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7173
7174   /* counts as header data */
7175   qtdemux->header_size += length;
7176
7177   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7178   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7179
7180   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7181   if (cmov) {
7182     guint32 method;
7183     GNode *dcom;
7184     GNode *cmvd;
7185     guint32 dcom_len;
7186
7187     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7188     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7189     if (dcom == NULL || cmvd == NULL)
7190       goto invalid_compression;
7191
7192     dcom_len = QT_UINT32 (dcom->data);
7193     if (dcom_len < 12)
7194       goto invalid_compression;
7195
7196     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7197     switch (method) {
7198 #ifdef HAVE_ZLIB
7199       case FOURCC_zlib:{
7200         guint uncompressed_length;
7201         guint compressed_length;
7202         guint8 *buf;
7203         guint32 cmvd_len;
7204
7205         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7206         if (cmvd_len < 12)
7207           goto invalid_compression;
7208
7209         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7210         compressed_length = cmvd_len - 12;
7211         GST_LOG ("length = %u", uncompressed_length);
7212
7213         buf =
7214             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7215             compressed_length, &uncompressed_length);
7216
7217         if (buf) {
7218           qtdemux->moov_node_compressed = qtdemux->moov_node;
7219           qtdemux->moov_node = g_node_new (buf);
7220
7221           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7222               uncompressed_length);
7223         }
7224         break;
7225       }
7226 #endif /* HAVE_ZLIB */
7227       default:
7228         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7229             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7230         break;
7231     }
7232   }
7233   return TRUE;
7234
7235   /* ERRORS */
7236 invalid_compression:
7237   {
7238     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7239     return FALSE;
7240   }
7241 }
7242
7243 static gboolean
7244 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7245     const guint8 * end)
7246 {
7247   while (G_UNLIKELY (buf < end)) {
7248     GNode *child;
7249     guint32 len;
7250
7251     if (G_UNLIKELY (buf + 4 > end)) {
7252       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7253       break;
7254     }
7255     len = QT_UINT32 (buf);
7256     if (G_UNLIKELY (len == 0)) {
7257       GST_LOG_OBJECT (qtdemux, "empty container");
7258       break;
7259     }
7260     if (G_UNLIKELY (len < 8)) {
7261       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7262       break;
7263     }
7264     if (G_UNLIKELY (len > (end - buf))) {
7265       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7266           (gint) (end - buf));
7267       break;
7268     }
7269
7270     child = g_node_new ((guint8 *) buf);
7271     g_node_append (node, child);
7272     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7273     qtdemux_parse_node (qtdemux, child, buf, len);
7274
7275     buf += len;
7276   }
7277   return TRUE;
7278 }
7279
7280 static gboolean
7281 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7282     GNode * xdxt)
7283 {
7284   int len = QT_UINT32 (xdxt->data);
7285   guint8 *buf = xdxt->data;
7286   guint8 *end = buf + len;
7287   GstBuffer *buffer;
7288
7289   /* skip size and type */
7290   buf += 8;
7291   end -= 8;
7292
7293   while (buf < end) {
7294     gint size;
7295     guint32 type;
7296
7297     size = QT_UINT32 (buf);
7298     type = QT_FOURCC (buf + 4);
7299
7300     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7301
7302     if (buf + size > end || size <= 0)
7303       break;
7304
7305     buf += 8;
7306     size -= 8;
7307
7308     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7309         GST_FOURCC_ARGS (type));
7310
7311     switch (type) {
7312       case FOURCC_tCtH:
7313         buffer = gst_buffer_new_and_alloc (size);
7314         gst_buffer_fill (buffer, 0, buf, size);
7315         stream->buffers = g_slist_append (stream->buffers, buffer);
7316         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7317         break;
7318       case FOURCC_tCt_:
7319         buffer = gst_buffer_new_and_alloc (size);
7320         gst_buffer_fill (buffer, 0, buf, size);
7321         stream->buffers = g_slist_append (stream->buffers, buffer);
7322         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7323         break;
7324       case FOURCC_tCtC:
7325         buffer = gst_buffer_new_and_alloc (size);
7326         gst_buffer_fill (buffer, 0, buf, size);
7327         stream->buffers = g_slist_append (stream->buffers, buffer);
7328         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7329         break;
7330       default:
7331         GST_WARNING_OBJECT (qtdemux,
7332             "unknown theora cookie %" GST_FOURCC_FORMAT,
7333             GST_FOURCC_ARGS (type));
7334         break;
7335     }
7336     buf += size;
7337   }
7338   return TRUE;
7339 }
7340
7341 static gboolean
7342 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7343     guint length)
7344 {
7345   guint32 fourcc = 0;
7346   guint32 node_length = 0;
7347   const QtNodeType *type;
7348   const guint8 *end;
7349
7350   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7351
7352   if (G_UNLIKELY (length < 8))
7353     goto not_enough_data;
7354
7355   node_length = QT_UINT32 (buffer);
7356   fourcc = QT_FOURCC (buffer + 4);
7357
7358   /* ignore empty nodes */
7359   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7360     return TRUE;
7361
7362   type = qtdemux_type_get (fourcc);
7363
7364   end = buffer + length;
7365
7366   GST_LOG_OBJECT (qtdemux,
7367       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7368       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7369
7370   if (node_length > length)
7371     goto broken_atom_size;
7372
7373   if (type->flags & QT_FLAG_CONTAINER) {
7374     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7375   } else {
7376     switch (fourcc) {
7377       case FOURCC_stsd:
7378       {
7379         if (node_length < 20) {
7380           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7381           break;
7382         }
7383         GST_DEBUG_OBJECT (qtdemux,
7384             "parsing stsd (sample table, sample description) atom");
7385         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7386         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7387         break;
7388       }
7389       case FOURCC_mp4a:
7390       case FOURCC_alac:
7391       case FOURCC_fLaC:
7392       {
7393         guint32 version;
7394         guint32 offset;
7395         guint min_size;
7396
7397         /* also read alac (or whatever) in stead of mp4a in the following,
7398          * since a similar layout is used in other cases as well */
7399         if (fourcc == FOURCC_mp4a)
7400           min_size = 20;
7401         else if (fourcc == FOURCC_fLaC)
7402           min_size = 86;
7403         else
7404           min_size = 40;
7405
7406         /* There are two things we might encounter here: a true mp4a atom, and
7407            an mp4a entry in an stsd atom. The latter is what we're interested
7408            in, and it looks like an atom, but isn't really one. The true mp4a
7409            atom is short, so we detect it based on length here. */
7410         if (length < min_size) {
7411           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7412               GST_FOURCC_ARGS (fourcc));
7413           break;
7414         }
7415
7416         /* 'version' here is the sound sample description version. Types 0 and
7417            1 are documented in the QTFF reference, but type 2 is not: it's
7418            described in Apple header files instead (struct SoundDescriptionV2
7419            in Movies.h) */
7420         version = QT_UINT16 (buffer + 16);
7421
7422         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7423             GST_FOURCC_ARGS (fourcc), version);
7424
7425         /* parse any esds descriptors */
7426         switch (version) {
7427           case 0:
7428             offset = 0x24;
7429             break;
7430           case 1:
7431             offset = 0x34;
7432             break;
7433           case 2:
7434             offset = 0x48;
7435             break;
7436           default:
7437             GST_WARNING_OBJECT (qtdemux,
7438                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7439                 GST_FOURCC_ARGS (fourcc), version);
7440             offset = 0;
7441             break;
7442         }
7443         if (offset)
7444           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7445         break;
7446       }
7447       case FOURCC_mp4v:
7448       case FOURCC_MP4V:
7449       case FOURCC_fmp4:
7450       case FOURCC_FMP4:
7451       case FOURCC_apcs:
7452       case FOURCC_apch:
7453       case FOURCC_apcn:
7454       case FOURCC_apco:
7455       case FOURCC_ap4h:
7456       case FOURCC_xvid:
7457       case FOURCC_XVID:
7458       case FOURCC_H264:
7459       case FOURCC_avc1:
7460       case FOURCC_avc3:
7461       case FOURCC_H265:
7462       case FOURCC_hvc1:
7463       case FOURCC_hev1:
7464       case FOURCC_mjp2:
7465       case FOURCC_encv:
7466       {
7467         guint32 version;
7468         guint32 str_len;
7469
7470         /* codec_data is contained inside these atoms, which all have
7471          * the same format. */
7472         /* video sample description size is 86 bytes without extension.
7473          * node_length have to be bigger than 86 bytes because video sample
7474          * description can include extenstions such as esds, fiel, glbl, etc. */
7475         if (node_length < 86) {
7476           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7477               " sample description length too short (%u < 86)",
7478               GST_FOURCC_ARGS (fourcc), node_length);
7479           break;
7480         }
7481
7482         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7483             GST_FOURCC_ARGS (fourcc));
7484
7485         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7486          *              its data format.
7487          * revision level (2 bytes) : must be set to 0. */
7488         version = QT_UINT32 (buffer + 16);
7489         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7490
7491         /* compressor name : PASCAL string and informative purposes
7492          * first byte : the number of bytes to be displayed.
7493          *              it has to be less than 32 because it is reserved
7494          *              space of 32 bytes total including itself. */
7495         str_len = QT_UINT8 (buffer + 50);
7496         if (str_len < 32)
7497           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7498               (char *) buffer + 51);
7499         else
7500           GST_WARNING_OBJECT (qtdemux,
7501               "compressorname length too big (%u > 31)", str_len);
7502
7503         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7504             end - buffer);
7505         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7506         break;
7507       }
7508       case FOURCC_meta:
7509       {
7510         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7511         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7512         break;
7513       }
7514       case FOURCC_mp4s:
7515       {
7516         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7517         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7518         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7519         break;
7520       }
7521       case FOURCC_XiTh:
7522       {
7523         guint32 version;
7524         guint32 offset;
7525
7526         if (length < 16) {
7527           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7528               GST_FOURCC_ARGS (fourcc));
7529           break;
7530         }
7531
7532         version = QT_UINT32 (buffer + 12);
7533         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7534
7535         switch (version) {
7536           case 0x00000001:
7537             offset = 0x62;
7538             break;
7539           default:
7540             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7541             offset = 0;
7542             break;
7543         }
7544         if (offset) {
7545           if (length < offset) {
7546             GST_WARNING_OBJECT (qtdemux,
7547                 "skipping too small %" GST_FOURCC_FORMAT " box",
7548                 GST_FOURCC_ARGS (fourcc));
7549             break;
7550           }
7551           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7552         }
7553         break;
7554       }
7555       case FOURCC_in24:
7556       {
7557         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7558         break;
7559       }
7560       case FOURCC_uuid:
7561       {
7562         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7563         break;
7564       }
7565       case FOURCC_enca:
7566       {
7567         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7568         break;
7569       }
7570       default:
7571         if (!strcmp (type->name, "unknown"))
7572           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7573         break;
7574     }
7575   }
7576   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7577       GST_FOURCC_ARGS (fourcc));
7578   return TRUE;
7579
7580 /* ERRORS */
7581 not_enough_data:
7582   {
7583     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7584         (_("This file is corrupt and cannot be played.")),
7585         ("Not enough data for an atom header, got only %u bytes", length));
7586     return FALSE;
7587   }
7588 broken_atom_size:
7589   {
7590     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7591         (_("This file is corrupt and cannot be played.")),
7592         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7593             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7594             length));
7595     return FALSE;
7596   }
7597 }
7598
7599 static GNode *
7600 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7601 {
7602   GNode *child;
7603   guint8 *buffer;
7604   guint32 child_fourcc;
7605
7606   for (child = g_node_first_child (node); child;
7607       child = g_node_next_sibling (child)) {
7608     buffer = (guint8 *) child->data;
7609
7610     child_fourcc = QT_FOURCC (buffer + 4);
7611
7612     if (G_UNLIKELY (child_fourcc == fourcc)) {
7613       return child;
7614     }
7615   }
7616   return NULL;
7617 }
7618
7619 static GNode *
7620 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7621     GstByteReader * parser)
7622 {
7623   GNode *child;
7624   guint8 *buffer;
7625   guint32 child_fourcc, child_len;
7626
7627   for (child = g_node_first_child (node); child;
7628       child = g_node_next_sibling (child)) {
7629     buffer = (guint8 *) child->data;
7630
7631     child_len = QT_UINT32 (buffer);
7632     child_fourcc = QT_FOURCC (buffer + 4);
7633
7634     if (G_UNLIKELY (child_fourcc == fourcc)) {
7635       if (G_UNLIKELY (child_len < (4 + 4)))
7636         return NULL;
7637       /* FIXME: must verify if atom length < parent atom length */
7638       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7639       return child;
7640     }
7641   }
7642   return NULL;
7643 }
7644
7645 static GNode *
7646 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7647 {
7648   return g_node_nth_child (node, index);
7649 }
7650
7651 static GNode *
7652 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7653     GstByteReader * parser)
7654 {
7655   GNode *child;
7656   guint8 *buffer;
7657   guint32 child_fourcc, child_len;
7658
7659   for (child = g_node_next_sibling (node); child;
7660       child = g_node_next_sibling (child)) {
7661     buffer = (guint8 *) child->data;
7662
7663     child_fourcc = QT_FOURCC (buffer + 4);
7664
7665     if (child_fourcc == fourcc) {
7666       if (parser) {
7667         child_len = QT_UINT32 (buffer);
7668         if (G_UNLIKELY (child_len < (4 + 4)))
7669           return NULL;
7670         /* FIXME: must verify if atom length < parent atom length */
7671         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7672       }
7673       return child;
7674     }
7675   }
7676   return NULL;
7677 }
7678
7679 static GNode *
7680 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7681 {
7682   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7683 }
7684
7685 static void
7686 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7687 {
7688 /* FIXME: This can only reliably work if demuxers have a
7689  * separate streaming thread per srcpad. This should be
7690  * done in a demuxer base class, which integrates parts
7691  * of multiqueue
7692  *
7693  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7694  */
7695 #if 0
7696   GstQuery *query;
7697
7698   query = gst_query_new_allocation (stream->caps, FALSE);
7699
7700   if (!gst_pad_peer_query (stream->pad, query)) {
7701     /* not a problem, just debug a little */
7702     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7703   }
7704
7705   if (stream->allocator)
7706     gst_object_unref (stream->allocator);
7707
7708   if (gst_query_get_n_allocation_params (query) > 0) {
7709     /* try the allocator */
7710     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7711         &stream->params);
7712     stream->use_allocator = TRUE;
7713   } else {
7714     stream->allocator = NULL;
7715     gst_allocation_params_init (&stream->params);
7716     stream->use_allocator = FALSE;
7717   }
7718   gst_query_unref (query);
7719 #endif
7720 }
7721
7722 static gboolean
7723 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7724     QtDemuxStream * stream)
7725 {
7726   GstStructure *s;
7727   const gchar *selected_system;
7728
7729   g_return_val_if_fail (qtdemux != NULL, FALSE);
7730   g_return_val_if_fail (stream != NULL, FALSE);
7731   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7732       FALSE);
7733
7734   if (stream->protection_scheme_type != FOURCC_cenc) {
7735     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7736     return FALSE;
7737   }
7738   if (qtdemux->protection_system_ids == NULL) {
7739     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7740         "cenc protection system information has been found");
7741     return FALSE;
7742   }
7743   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7744   selected_system = gst_protection_select_system ((const gchar **)
7745       qtdemux->protection_system_ids->pdata);
7746   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7747       qtdemux->protection_system_ids->len - 1);
7748   if (!selected_system) {
7749     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7750         "suitable decryptor element has been found");
7751     return FALSE;
7752   }
7753
7754   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7755   if (!gst_structure_has_name (s, "application/x-cenc")) {
7756     gst_structure_set (s,
7757         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7758         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7759         NULL);
7760     gst_structure_set_name (s, "application/x-cenc");
7761   }
7762   return TRUE;
7763 }
7764
7765 static gboolean
7766 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7767 {
7768   if (stream->subtype == FOURCC_vide) {
7769     /* fps is calculated base on the duration of the average framerate since
7770      * qt does not have a fixed framerate. */
7771     gboolean fps_available = TRUE;
7772
7773     if ((stream->n_samples == 1 && stream->first_duration == 0)
7774         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
7775       /* still frame */
7776       CUR_STREAM (stream)->fps_n = 0;
7777       CUR_STREAM (stream)->fps_d = 1;
7778     } else {
7779       if (stream->duration == 0 || stream->n_samples < 2) {
7780         CUR_STREAM (stream)->fps_n = stream->timescale;
7781         CUR_STREAM (stream)->fps_d = 1;
7782         fps_available = FALSE;
7783       } else {
7784         GstClockTime avg_duration;
7785         guint64 duration;
7786         guint32 n_samples;
7787
7788         /* duration and n_samples can be updated for fragmented format
7789          * so, framerate of fragmented format is calculated using data in a moof */
7790         if (qtdemux->fragmented && stream->n_samples_moof > 0
7791             && stream->duration_moof > 0) {
7792           n_samples = stream->n_samples_moof;
7793           duration = stream->duration_moof;
7794         } else {
7795           n_samples = stream->n_samples;
7796           duration = stream->duration;
7797         }
7798
7799         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7800         /* stream->duration is guint64, timescale, n_samples are guint32 */
7801         avg_duration =
7802             gst_util_uint64_scale_round (duration -
7803             stream->first_duration, GST_SECOND,
7804             (guint64) (stream->timescale) * (n_samples - 1));
7805
7806         GST_LOG_OBJECT (qtdemux,
7807             "Calculating avg sample duration based on stream (or moof) duration %"
7808             G_GUINT64_FORMAT
7809             " minus first sample %u, leaving %d samples gives %"
7810             GST_TIME_FORMAT, duration, stream->first_duration,
7811             n_samples - 1, GST_TIME_ARGS (avg_duration));
7812
7813         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7814             &CUR_STREAM (stream)->fps_d);
7815
7816         GST_DEBUG_OBJECT (qtdemux,
7817             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7818             stream->timescale, CUR_STREAM (stream)->fps_n,
7819             CUR_STREAM (stream)->fps_d);
7820       }
7821     }
7822
7823     if (CUR_STREAM (stream)->caps) {
7824       CUR_STREAM (stream)->caps =
7825           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7826
7827       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7828           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7829           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7830
7831       /* set framerate if calculated framerate is reliable */
7832       if (fps_available) {
7833         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7834             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7835             CUR_STREAM (stream)->fps_d, NULL);
7836       }
7837
7838       /* calculate pixel-aspect-ratio using display width and height */
7839       GST_DEBUG_OBJECT (qtdemux,
7840           "video size %dx%d, target display size %dx%d",
7841           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7842           stream->display_width, stream->display_height);
7843       /* qt file might have pasp atom */
7844       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7845         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7846             CUR_STREAM (stream)->par_h);
7847         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7848             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7849             CUR_STREAM (stream)->par_h, NULL);
7850       } else if (stream->display_width > 0 && stream->display_height > 0
7851           && CUR_STREAM (stream)->width > 0
7852           && CUR_STREAM (stream)->height > 0) {
7853         gint n, d;
7854
7855         /* calculate the pixel aspect ratio using the display and pixel w/h */
7856         n = stream->display_width * CUR_STREAM (stream)->height;
7857         d = stream->display_height * CUR_STREAM (stream)->width;
7858         if (n == d)
7859           n = d = 1;
7860         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7861         CUR_STREAM (stream)->par_w = n;
7862         CUR_STREAM (stream)->par_h = d;
7863         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7864             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7865             CUR_STREAM (stream)->par_h, NULL);
7866       }
7867
7868       if (CUR_STREAM (stream)->interlace_mode > 0) {
7869         if (CUR_STREAM (stream)->interlace_mode == 1) {
7870           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7871               G_TYPE_STRING, "progressive", NULL);
7872         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7873           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7874               G_TYPE_STRING, "interleaved", NULL);
7875           if (CUR_STREAM (stream)->field_order == 9) {
7876             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7877                 G_TYPE_STRING, "top-field-first", NULL);
7878           } else if (CUR_STREAM (stream)->field_order == 14) {
7879             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7880                 G_TYPE_STRING, "bottom-field-first", NULL);
7881           }
7882         }
7883       }
7884
7885       /* Create incomplete colorimetry here if needed */
7886       if (CUR_STREAM (stream)->colorimetry.range ||
7887           CUR_STREAM (stream)->colorimetry.matrix ||
7888           CUR_STREAM (stream)->colorimetry.transfer
7889           || CUR_STREAM (stream)->colorimetry.primaries) {
7890         gchar *colorimetry =
7891             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7892         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7893             G_TYPE_STRING, colorimetry, NULL);
7894         g_free (colorimetry);
7895       }
7896
7897       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7898         guint par_w = 1, par_h = 1;
7899
7900         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7901           par_w = CUR_STREAM (stream)->par_w;
7902           par_h = CUR_STREAM (stream)->par_h;
7903         }
7904
7905         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7906                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7907                 par_h)) {
7908           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7909         }
7910
7911         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7912             "multiview-mode", G_TYPE_STRING,
7913             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7914             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7915             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7916       }
7917     }
7918   }
7919
7920   else if (stream->subtype == FOURCC_soun) {
7921     if (CUR_STREAM (stream)->caps) {
7922       CUR_STREAM (stream)->caps =
7923           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7924       if (CUR_STREAM (stream)->rate > 0)
7925         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7926             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7927       if (CUR_STREAM (stream)->n_channels > 0)
7928         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7929             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7930       if (CUR_STREAM (stream)->n_channels > 2) {
7931         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7932          * correctly; this is just the minimum we can do - assume
7933          * we don't actually have any channel positions. */
7934         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7935             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7936       }
7937     }
7938   }
7939
7940   if (stream->pad) {
7941     GstCaps *prev_caps = NULL;
7942
7943     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7944     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7945     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7946     gst_pad_set_active (stream->pad, TRUE);
7947
7948     gst_pad_use_fixed_caps (stream->pad);
7949
7950     if (stream->protected) {
7951       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7952         GST_ERROR_OBJECT (qtdemux,
7953             "Failed to configure protected stream caps.");
7954         return FALSE;
7955       }
7956     }
7957
7958     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7959         CUR_STREAM (stream)->caps);
7960     if (stream->new_stream) {
7961       gchar *stream_id;
7962       GstEvent *event;
7963       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7964
7965       event =
7966           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7967           0);
7968       if (event) {
7969         gst_event_parse_stream_flags (event, &stream_flags);
7970         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7971           qtdemux->have_group_id = TRUE;
7972         else
7973           qtdemux->have_group_id = FALSE;
7974         gst_event_unref (event);
7975       } else if (!qtdemux->have_group_id) {
7976         qtdemux->have_group_id = TRUE;
7977         qtdemux->group_id = gst_util_group_id_next ();
7978       }
7979
7980       stream->new_stream = FALSE;
7981       stream_id =
7982           gst_pad_create_stream_id_printf (stream->pad,
7983           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7984       event = gst_event_new_stream_start (stream_id);
7985       if (qtdemux->have_group_id)
7986         gst_event_set_group_id (event, qtdemux->group_id);
7987       if (stream->disabled)
7988         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7989       if (CUR_STREAM (stream)->sparse) {
7990         stream_flags |= GST_STREAM_FLAG_SPARSE;
7991       } else {
7992         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7993       }
7994       gst_event_set_stream_flags (event, stream_flags);
7995       gst_pad_push_event (stream->pad, event);
7996       g_free (stream_id);
7997     }
7998
7999     prev_caps = gst_pad_get_current_caps (stream->pad);
8000
8001     if (CUR_STREAM (stream)->caps) {
8002       if (!prev_caps
8003           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8004         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8005             CUR_STREAM (stream)->caps);
8006         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8007       } else {
8008         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8009       }
8010     } else {
8011       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8012     }
8013
8014     if (prev_caps)
8015       gst_caps_unref (prev_caps);
8016     stream->new_caps = FALSE;
8017   }
8018   return TRUE;
8019 }
8020
8021 static void
8022 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8023     QtDemuxStream * stream)
8024 {
8025   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8026     return;
8027
8028   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8029       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8030   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8031           stream->stsd_entries_length)) {
8032     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8033         (_("This file is invalid and cannot be played.")),
8034         ("New sample description id is out of bounds (%d >= %d)",
8035             stream->stsd_sample_description_id, stream->stsd_entries_length));
8036   } else {
8037     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8038     stream->new_caps = TRUE;
8039   }
8040 }
8041
8042 static gboolean
8043 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8044     QtDemuxStream * stream, GstTagList * list)
8045 {
8046   gboolean ret = TRUE;
8047   /* consistent default for push based mode */
8048   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8049
8050   if (stream->subtype == FOURCC_vide) {
8051     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8052
8053     stream->pad =
8054         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8055     g_free (name);
8056
8057     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8058       gst_object_unref (stream->pad);
8059       stream->pad = NULL;
8060       ret = FALSE;
8061       goto done;
8062     }
8063
8064     qtdemux->n_video_streams++;
8065   } else if (stream->subtype == FOURCC_soun) {
8066     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8067
8068     stream->pad =
8069         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8070     g_free (name);
8071     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8072       gst_object_unref (stream->pad);
8073       stream->pad = NULL;
8074       ret = FALSE;
8075       goto done;
8076     }
8077     qtdemux->n_audio_streams++;
8078   } else if (stream->subtype == FOURCC_strm) {
8079     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8080   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8081       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8082     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8083
8084     stream->pad =
8085         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8086     g_free (name);
8087     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8088       gst_object_unref (stream->pad);
8089       stream->pad = NULL;
8090       ret = FALSE;
8091       goto done;
8092     }
8093     qtdemux->n_sub_streams++;
8094   } else if (CUR_STREAM (stream)->caps) {
8095     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8096
8097     stream->pad =
8098         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8099     g_free (name);
8100     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8101       gst_object_unref (stream->pad);
8102       stream->pad = NULL;
8103       ret = FALSE;
8104       goto done;
8105     }
8106     qtdemux->n_video_streams++;
8107   } else {
8108     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8109     goto done;
8110   }
8111
8112   if (stream->pad) {
8113     GList *l;
8114
8115     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8116         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8117     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8118     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8119
8120     if (stream->stream_tags)
8121       gst_tag_list_unref (stream->stream_tags);
8122     stream->stream_tags = list;
8123     list = NULL;
8124     /* global tags go on each pad anyway */
8125     stream->send_global_tags = TRUE;
8126     /* send upstream GST_EVENT_PROTECTION events that were received before
8127        this source pad was created */
8128     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8129       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8130   }
8131 done:
8132   if (list)
8133     gst_tag_list_unref (list);
8134   return ret;
8135 }
8136
8137 /* find next atom with @fourcc starting at @offset */
8138 static GstFlowReturn
8139 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8140     guint64 * length, guint32 fourcc)
8141 {
8142   GstFlowReturn ret;
8143   guint32 lfourcc;
8144   GstBuffer *buf;
8145
8146   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8147       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8148
8149   while (TRUE) {
8150     GstMapInfo map;
8151
8152     buf = NULL;
8153     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8154     if (G_UNLIKELY (ret != GST_FLOW_OK))
8155       goto locate_failed;
8156     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8157       /* likely EOF */
8158       ret = GST_FLOW_EOS;
8159       gst_buffer_unref (buf);
8160       goto locate_failed;
8161     }
8162     gst_buffer_map (buf, &map, GST_MAP_READ);
8163     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8164     gst_buffer_unmap (buf, &map);
8165     gst_buffer_unref (buf);
8166
8167     if (G_UNLIKELY (*length == 0)) {
8168       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8169       ret = GST_FLOW_ERROR;
8170       goto locate_failed;
8171     }
8172
8173     if (lfourcc == fourcc) {
8174       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8175           *offset);
8176       break;
8177     } else {
8178       GST_LOG_OBJECT (qtdemux,
8179           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8180           GST_FOURCC_ARGS (fourcc), *offset);
8181       *offset += *length;
8182     }
8183   }
8184
8185   return GST_FLOW_OK;
8186
8187 locate_failed:
8188   {
8189     /* might simply have had last one */
8190     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8191     return ret;
8192   }
8193 }
8194
8195 /* should only do something in pull mode */
8196 /* call with OBJECT lock */
8197 static GstFlowReturn
8198 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8199 {
8200   guint64 length, offset;
8201   GstBuffer *buf = NULL;
8202   GstFlowReturn ret = GST_FLOW_OK;
8203   GstFlowReturn res = GST_FLOW_OK;
8204   GstMapInfo map;
8205
8206   offset = qtdemux->moof_offset;
8207   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8208
8209   if (!offset) {
8210     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8211     return GST_FLOW_EOS;
8212   }
8213
8214   /* best not do pull etc with lock held */
8215   GST_OBJECT_UNLOCK (qtdemux);
8216
8217   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8218   if (ret != GST_FLOW_OK)
8219     goto flow_failed;
8220
8221   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8222   if (G_UNLIKELY (ret != GST_FLOW_OK))
8223     goto flow_failed;
8224   gst_buffer_map (buf, &map, GST_MAP_READ);
8225   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8226     gst_buffer_unmap (buf, &map);
8227     gst_buffer_unref (buf);
8228     buf = NULL;
8229     goto parse_failed;
8230   }
8231
8232   gst_buffer_unmap (buf, &map);
8233   gst_buffer_unref (buf);
8234   buf = NULL;
8235
8236   offset += length;
8237   /* look for next moof */
8238   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8239   if (G_UNLIKELY (ret != GST_FLOW_OK))
8240     goto flow_failed;
8241
8242 exit:
8243   GST_OBJECT_LOCK (qtdemux);
8244
8245   qtdemux->moof_offset = offset;
8246
8247   return res;
8248
8249 parse_failed:
8250   {
8251     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8252     offset = 0;
8253     res = GST_FLOW_ERROR;
8254     goto exit;
8255   }
8256 flow_failed:
8257   {
8258     /* maybe upstream temporarily flushing */
8259     if (ret != GST_FLOW_FLUSHING) {
8260       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8261       offset = 0;
8262     } else {
8263       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8264       /* resume at current position next time */
8265     }
8266     res = ret;
8267     goto exit;
8268   }
8269 }
8270
8271 /* initialise bytereaders for stbl sub-atoms */
8272 static gboolean
8273 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8274 {
8275   stream->stbl_index = -1;      /* no samples have yet been parsed */
8276   stream->sample_index = -1;
8277
8278   /* time-to-sample atom */
8279   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8280     goto corrupt_file;
8281
8282   /* copy atom data into a new buffer for later use */
8283   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8284
8285   /* skip version + flags */
8286   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8287       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8288     goto corrupt_file;
8289   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8290
8291   /* make sure there's enough data */
8292   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8293     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8294     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8295         stream->n_sample_times);
8296     if (!stream->n_sample_times)
8297       goto corrupt_file;
8298   }
8299
8300   /* sync sample atom */
8301   stream->stps_present = FALSE;
8302   if ((stream->stss_present =
8303           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8304               &stream->stss) ? TRUE : FALSE) == TRUE) {
8305     /* copy atom data into a new buffer for later use */
8306     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8307
8308     /* skip version + flags */
8309     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8310         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8311       goto corrupt_file;
8312
8313     if (stream->n_sample_syncs) {
8314       /* make sure there's enough data */
8315       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8316         goto corrupt_file;
8317     }
8318
8319     /* partial sync sample atom */
8320     if ((stream->stps_present =
8321             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8322                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8323       /* copy atom data into a new buffer for later use */
8324       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8325
8326       /* skip version + flags */
8327       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8328           !gst_byte_reader_get_uint32_be (&stream->stps,
8329               &stream->n_sample_partial_syncs))
8330         goto corrupt_file;
8331
8332       /* if there are no entries, the stss table contains the real
8333        * sync samples */
8334       if (stream->n_sample_partial_syncs) {
8335         /* make sure there's enough data */
8336         if (!qt_atom_parser_has_chunks (&stream->stps,
8337                 stream->n_sample_partial_syncs, 4))
8338           goto corrupt_file;
8339       }
8340     }
8341   }
8342
8343   /* sample size */
8344   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8345     goto no_samples;
8346
8347   /* copy atom data into a new buffer for later use */
8348   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8349
8350   /* skip version + flags */
8351   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8352       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8353     goto corrupt_file;
8354
8355   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8356     goto corrupt_file;
8357
8358   if (!stream->n_samples)
8359     goto no_samples;
8360
8361   /* sample-to-chunk atom */
8362   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8363     goto corrupt_file;
8364
8365   /* copy atom data into a new buffer for later use */
8366   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8367
8368   /* skip version + flags */
8369   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8370       !gst_byte_reader_get_uint32_be (&stream->stsc,
8371           &stream->n_samples_per_chunk))
8372     goto corrupt_file;
8373
8374   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8375       stream->n_samples_per_chunk);
8376
8377   /* make sure there's enough data */
8378   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8379           12))
8380     goto corrupt_file;
8381
8382
8383   /* chunk offset */
8384   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8385     stream->co_size = sizeof (guint32);
8386   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8387           &stream->stco))
8388     stream->co_size = sizeof (guint64);
8389   else
8390     goto corrupt_file;
8391
8392   /* copy atom data into a new buffer for later use */
8393   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8394
8395   /* skip version + flags */
8396   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8397     goto corrupt_file;
8398
8399   /* chunks_are_samples == TRUE means treat chunks as samples */
8400   stream->chunks_are_samples = stream->sample_size
8401       && !CUR_STREAM (stream)->sampled;
8402   if (stream->chunks_are_samples) {
8403     /* treat chunks as samples */
8404     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8405       goto corrupt_file;
8406   } else {
8407     /* skip number of entries */
8408     if (!gst_byte_reader_skip (&stream->stco, 4))
8409       goto corrupt_file;
8410
8411     /* make sure there are enough data in the stsz atom */
8412     if (!stream->sample_size) {
8413       /* different sizes for each sample */
8414       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8415         goto corrupt_file;
8416     }
8417   }
8418
8419   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8420       stream->n_samples, (guint) sizeof (QtDemuxSample),
8421       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8422
8423   if (stream->n_samples >=
8424       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8425     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8426         "be larger than %uMB (broken file?)", stream->n_samples,
8427         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8428     return FALSE;
8429   }
8430
8431   g_assert (stream->samples == NULL);
8432   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8433   if (!stream->samples) {
8434     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8435         stream->n_samples);
8436     return FALSE;
8437   }
8438
8439   /* composition time-to-sample */
8440   if ((stream->ctts_present =
8441           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8442               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8443     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8444
8445     /* copy atom data into a new buffer for later use */
8446     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8447
8448     /* skip version + flags */
8449     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8450         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8451             &stream->n_composition_times))
8452       goto corrupt_file;
8453
8454     /* make sure there's enough data */
8455     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8456             4 + 4))
8457       goto corrupt_file;
8458
8459     /* This is optional, if missing we iterate the ctts */
8460     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8461       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8462           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8463         g_free ((gpointer) cslg.data);
8464         goto corrupt_file;
8465       }
8466     } else {
8467       gint32 cslg_least = 0;
8468       guint num_entries, pos;
8469       gint i;
8470
8471       pos = gst_byte_reader_get_pos (&stream->ctts);
8472       num_entries = stream->n_composition_times;
8473
8474       stream->cslg_shift = 0;
8475
8476       for (i = 0; i < num_entries; i++) {
8477         gint32 offset;
8478
8479         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8480         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8481
8482         if (offset < cslg_least)
8483           cslg_least = offset;
8484       }
8485
8486       if (cslg_least < 0)
8487         stream->cslg_shift = ABS (cslg_least);
8488       else
8489         stream->cslg_shift = 0;
8490
8491       /* reset the reader so we can generate sample table */
8492       gst_byte_reader_set_pos (&stream->ctts, pos);
8493     }
8494   } else {
8495     /* Ensure the cslg_shift value is consistent so we can use it
8496      * unconditionnally to produce TS and Segment */
8497     stream->cslg_shift = 0;
8498   }
8499
8500   return TRUE;
8501
8502 corrupt_file:
8503   {
8504     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8505         (_("This file is corrupt and cannot be played.")), (NULL));
8506     return FALSE;
8507   }
8508 no_samples:
8509   {
8510     gst_qtdemux_stbl_free (stream);
8511     if (!qtdemux->fragmented) {
8512       /* not quite good */
8513       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8514       return FALSE;
8515     } else {
8516       /* may pick up samples elsewhere */
8517       return TRUE;
8518     }
8519   }
8520 }
8521
8522 /* collect samples from the next sample to be parsed up to sample @n for @stream
8523  * by reading the info from @stbl
8524  *
8525  * This code can be executed from both the streaming thread and the seeking
8526  * thread so it takes the object lock to protect itself
8527  */
8528 static gboolean
8529 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8530 {
8531   gint i, j, k;
8532   QtDemuxSample *samples, *first, *cur, *last;
8533   guint32 n_samples_per_chunk;
8534   guint32 n_samples;
8535
8536   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8537       GST_FOURCC_FORMAT ", pad %s",
8538       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8539       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8540
8541   n_samples = stream->n_samples;
8542
8543   if (n >= n_samples)
8544     goto out_of_samples;
8545
8546   GST_OBJECT_LOCK (qtdemux);
8547   if (n <= stream->stbl_index)
8548     goto already_parsed;
8549
8550   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8551
8552   if (!stream->stsz.data) {
8553     /* so we already parsed and passed all the moov samples;
8554      * onto fragmented ones */
8555     g_assert (qtdemux->fragmented);
8556     goto done;
8557   }
8558
8559   /* pointer to the sample table */
8560   samples = stream->samples;
8561
8562   /* starts from -1, moves to the next sample index to parse */
8563   stream->stbl_index++;
8564
8565   /* keep track of the first and last sample to fill */
8566   first = &samples[stream->stbl_index];
8567   last = &samples[n];
8568
8569   if (!stream->chunks_are_samples) {
8570     /* set the sample sizes */
8571     if (stream->sample_size == 0) {
8572       /* different sizes for each sample */
8573       for (cur = first; cur <= last; cur++) {
8574         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8575         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8576             (guint) (cur - samples), cur->size);
8577       }
8578     } else {
8579       /* samples have the same size */
8580       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8581       for (cur = first; cur <= last; cur++)
8582         cur->size = stream->sample_size;
8583     }
8584   }
8585
8586   n_samples_per_chunk = stream->n_samples_per_chunk;
8587   cur = first;
8588
8589   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8590     guint32 last_chunk;
8591
8592     if (stream->stsc_chunk_index >= stream->last_chunk
8593         || stream->stsc_chunk_index < stream->first_chunk) {
8594       stream->first_chunk =
8595           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8596       stream->samples_per_chunk =
8597           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8598       /* starts from 1 */
8599       stream->stsd_sample_description_id =
8600           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8601
8602       /* chunk numbers are counted from 1 it seems */
8603       if (G_UNLIKELY (stream->first_chunk == 0))
8604         goto corrupt_file;
8605
8606       --stream->first_chunk;
8607
8608       /* the last chunk of each entry is calculated by taking the first chunk
8609        * of the next entry; except if there is no next, where we fake it with
8610        * INT_MAX */
8611       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8612         stream->last_chunk = G_MAXUINT32;
8613       } else {
8614         stream->last_chunk =
8615             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8616         if (G_UNLIKELY (stream->last_chunk == 0))
8617           goto corrupt_file;
8618
8619         --stream->last_chunk;
8620       }
8621
8622       GST_LOG_OBJECT (qtdemux,
8623           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8624           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8625           stream->samples_per_chunk, stream->stsd_sample_description_id);
8626
8627       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8628         goto corrupt_file;
8629
8630       if (stream->last_chunk != G_MAXUINT32) {
8631         if (!qt_atom_parser_peek_sub (&stream->stco,
8632                 stream->first_chunk * stream->co_size,
8633                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8634                 &stream->co_chunk))
8635           goto corrupt_file;
8636
8637       } else {
8638         stream->co_chunk = stream->stco;
8639         if (!gst_byte_reader_skip (&stream->co_chunk,
8640                 stream->first_chunk * stream->co_size))
8641           goto corrupt_file;
8642       }
8643
8644       stream->stsc_chunk_index = stream->first_chunk;
8645     }
8646
8647     last_chunk = stream->last_chunk;
8648
8649     if (stream->chunks_are_samples) {
8650       cur = &samples[stream->stsc_chunk_index];
8651
8652       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8653         if (j > n) {
8654           /* save state */
8655           stream->stsc_chunk_index = j;
8656           goto done;
8657         }
8658
8659         cur->offset =
8660             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8661             stream->co_size);
8662
8663         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8664             "%" G_GUINT64_FORMAT, j, cur->offset);
8665
8666         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8667             CUR_STREAM (stream)->bytes_per_frame > 0) {
8668           cur->size =
8669               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8670               CUR_STREAM (stream)->samples_per_frame *
8671               CUR_STREAM (stream)->bytes_per_frame;
8672         } else {
8673           cur->size = stream->samples_per_chunk;
8674         }
8675
8676         GST_DEBUG_OBJECT (qtdemux,
8677             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8678             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8679                     stream->stco_sample_index)), cur->size);
8680
8681         cur->timestamp = stream->stco_sample_index;
8682         cur->duration = stream->samples_per_chunk;
8683         cur->keyframe = TRUE;
8684         cur++;
8685
8686         stream->stco_sample_index += stream->samples_per_chunk;
8687       }
8688       stream->stsc_chunk_index = j;
8689     } else {
8690       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8691         guint32 samples_per_chunk;
8692         guint64 chunk_offset;
8693
8694         if (!stream->stsc_sample_index
8695             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8696                 &stream->chunk_offset))
8697           goto corrupt_file;
8698
8699         samples_per_chunk = stream->samples_per_chunk;
8700         chunk_offset = stream->chunk_offset;
8701
8702         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8703           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8704               G_GUINT64_FORMAT " and size %d",
8705               (guint) (cur - samples), chunk_offset, cur->size);
8706
8707           cur->offset = chunk_offset;
8708           chunk_offset += cur->size;
8709           cur++;
8710
8711           if (G_UNLIKELY (cur > last)) {
8712             /* save state */
8713             stream->stsc_sample_index = k + 1;
8714             stream->chunk_offset = chunk_offset;
8715             stream->stsc_chunk_index = j;
8716             goto done2;
8717           }
8718         }
8719         stream->stsc_sample_index = 0;
8720       }
8721       stream->stsc_chunk_index = j;
8722     }
8723     stream->stsc_index++;
8724   }
8725
8726   if (stream->chunks_are_samples)
8727     goto ctts;
8728 done2:
8729   {
8730     guint32 n_sample_times;
8731
8732     n_sample_times = stream->n_sample_times;
8733     cur = first;
8734
8735     for (i = stream->stts_index; i < n_sample_times; i++) {
8736       guint32 stts_samples;
8737       gint32 stts_duration;
8738       gint64 stts_time;
8739
8740       if (stream->stts_sample_index >= stream->stts_samples
8741           || !stream->stts_sample_index) {
8742
8743         stream->stts_samples =
8744             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8745         stream->stts_duration =
8746             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8747
8748         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8749             i, stream->stts_samples, stream->stts_duration);
8750
8751         stream->stts_sample_index = 0;
8752       }
8753
8754       stts_samples = stream->stts_samples;
8755       stts_duration = stream->stts_duration;
8756       stts_time = stream->stts_time;
8757
8758       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8759         GST_DEBUG_OBJECT (qtdemux,
8760             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8761             (guint) (cur - samples), j,
8762             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8763
8764         cur->timestamp = stts_time;
8765         cur->duration = stts_duration;
8766
8767         /* avoid 32-bit wrap-around,
8768          * but still mind possible 'negative' duration */
8769         stts_time += (gint64) stts_duration;
8770         cur++;
8771
8772         if (G_UNLIKELY (cur > last)) {
8773           /* save values */
8774           stream->stts_time = stts_time;
8775           stream->stts_sample_index = j + 1;
8776           if (stream->stts_sample_index >= stream->stts_samples)
8777             stream->stts_index++;
8778           goto done3;
8779         }
8780       }
8781       stream->stts_sample_index = 0;
8782       stream->stts_time = stts_time;
8783       stream->stts_index++;
8784     }
8785     /* fill up empty timestamps with the last timestamp, this can happen when
8786      * the last samples do not decode and so we don't have timestamps for them.
8787      * We however look at the last timestamp to estimate the track length so we
8788      * need something in here. */
8789     for (; cur < last; cur++) {
8790       GST_DEBUG_OBJECT (qtdemux,
8791           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8792           (guint) (cur - samples),
8793           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8794       cur->timestamp = stream->stts_time;
8795       cur->duration = -1;
8796     }
8797   }
8798 done3:
8799   {
8800     /* sample sync, can be NULL */
8801     if (stream->stss_present == TRUE) {
8802       guint32 n_sample_syncs;
8803
8804       n_sample_syncs = stream->n_sample_syncs;
8805
8806       if (!n_sample_syncs) {
8807         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8808         stream->all_keyframe = TRUE;
8809       } else {
8810         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8811           /* note that the first sample is index 1, not 0 */
8812           guint32 index;
8813
8814           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8815
8816           if (G_LIKELY (index > 0 && index <= n_samples)) {
8817             index -= 1;
8818             samples[index].keyframe = TRUE;
8819             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8820             /* and exit if we have enough samples */
8821             if (G_UNLIKELY (index >= n)) {
8822               i++;
8823               break;
8824             }
8825           }
8826         }
8827         /* save state */
8828         stream->stss_index = i;
8829       }
8830
8831       /* stps marks partial sync frames like open GOP I-Frames */
8832       if (stream->stps_present == TRUE) {
8833         guint32 n_sample_partial_syncs;
8834
8835         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8836
8837         /* if there are no entries, the stss table contains the real
8838          * sync samples */
8839         if (n_sample_partial_syncs) {
8840           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8841             /* note that the first sample is index 1, not 0 */
8842             guint32 index;
8843
8844             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8845
8846             if (G_LIKELY (index > 0 && index <= n_samples)) {
8847               index -= 1;
8848               samples[index].keyframe = TRUE;
8849               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8850               /* and exit if we have enough samples */
8851               if (G_UNLIKELY (index >= n)) {
8852                 i++;
8853                 break;
8854               }
8855             }
8856           }
8857           /* save state */
8858           stream->stps_index = i;
8859         }
8860       }
8861     } else {
8862       /* no stss, all samples are keyframes */
8863       stream->all_keyframe = TRUE;
8864       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8865     }
8866   }
8867
8868 ctts:
8869   /* composition time to sample */
8870   if (stream->ctts_present == TRUE) {
8871     guint32 n_composition_times;
8872     guint32 ctts_count;
8873     gint32 ctts_soffset;
8874
8875     /* Fill in the pts_offsets */
8876     cur = first;
8877     n_composition_times = stream->n_composition_times;
8878
8879     for (i = stream->ctts_index; i < n_composition_times; i++) {
8880       if (stream->ctts_sample_index >= stream->ctts_count
8881           || !stream->ctts_sample_index) {
8882         stream->ctts_count =
8883             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8884         stream->ctts_soffset =
8885             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8886         stream->ctts_sample_index = 0;
8887       }
8888
8889       ctts_count = stream->ctts_count;
8890       ctts_soffset = stream->ctts_soffset;
8891
8892       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8893         cur->pts_offset = ctts_soffset;
8894         cur++;
8895
8896         if (G_UNLIKELY (cur > last)) {
8897           /* save state */
8898           stream->ctts_sample_index = j + 1;
8899           goto done;
8900         }
8901       }
8902       stream->ctts_sample_index = 0;
8903       stream->ctts_index++;
8904     }
8905   }
8906 done:
8907   stream->stbl_index = n;
8908   /* if index has been completely parsed, free data that is no-longer needed */
8909   if (n + 1 == stream->n_samples) {
8910     gst_qtdemux_stbl_free (stream);
8911     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8912     if (qtdemux->pullbased) {
8913       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8914       while (n + 1 == stream->n_samples)
8915         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8916           break;
8917     }
8918   }
8919   GST_OBJECT_UNLOCK (qtdemux);
8920
8921   return TRUE;
8922
8923   /* SUCCESS */
8924 already_parsed:
8925   {
8926     GST_LOG_OBJECT (qtdemux,
8927         "Tried to parse up to sample %u but this sample has already been parsed",
8928         n);
8929     /* if fragmented, there may be more */
8930     if (qtdemux->fragmented && n == stream->stbl_index)
8931       goto done;
8932     GST_OBJECT_UNLOCK (qtdemux);
8933     return TRUE;
8934   }
8935   /* ERRORS */
8936 out_of_samples:
8937   {
8938     GST_LOG_OBJECT (qtdemux,
8939         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8940         stream->n_samples);
8941     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8942         (_("This file is corrupt and cannot be played.")), (NULL));
8943     return FALSE;
8944   }
8945 corrupt_file:
8946   {
8947     GST_OBJECT_UNLOCK (qtdemux);
8948     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8949         (_("This file is corrupt and cannot be played.")), (NULL));
8950     return FALSE;
8951   }
8952 }
8953
8954 /* collect all segment info for @stream.
8955  */
8956 static gboolean
8957 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8958     GNode * trak)
8959 {
8960   GNode *edts;
8961   /* accept edts if they contain gaps at start and there is only
8962    * one media segment */
8963   gboolean allow_pushbased_edts = TRUE;
8964   gint media_segments_count = 0;
8965
8966   /* parse and prepare segment info from the edit list */
8967   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8968   stream->n_segments = 0;
8969   stream->segments = NULL;
8970   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8971     GNode *elst;
8972     gint n_segments;
8973     gint i, count, entry_size;
8974     guint64 time;
8975     GstClockTime stime;
8976     const guint8 *buffer;
8977     guint8 version;
8978     guint32 size;
8979
8980     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8981     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8982       goto done;
8983
8984     buffer = elst->data;
8985
8986     size = QT_UINT32 (buffer);
8987     /* version, flags, n_segments */
8988     if (size < 16) {
8989       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8990       goto done;
8991     }
8992     version = QT_UINT8 (buffer + 8);
8993     entry_size = (version == 1) ? 20 : 12;
8994
8995     n_segments = QT_UINT32 (buffer + 12);
8996
8997     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8998       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8999       goto done;
9000     }
9001
9002     /* we might allocate a bit too much, at least allocate 1 segment */
9003     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9004
9005     /* segments always start from 0 */
9006     time = 0;
9007     stime = 0;
9008     count = 0;
9009     buffer += 16;
9010     for (i = 0; i < n_segments; i++) {
9011       guint64 duration;
9012       guint64 media_time;
9013       gboolean time_valid = TRUE;
9014       QtDemuxSegment *segment;
9015       guint32 rate_int;
9016       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9017
9018       if (version == 1) {
9019         media_time = QT_UINT64 (buffer + 8);
9020         duration = QT_UINT64 (buffer);
9021         if (media_time == G_MAXUINT64)
9022           time_valid = FALSE;
9023       } else {
9024         media_time = QT_UINT32 (buffer + 4);
9025         duration = QT_UINT32 (buffer);
9026         if (media_time == G_MAXUINT32)
9027           time_valid = FALSE;
9028       }
9029
9030       if (time_valid)
9031         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9032
9033       segment = &stream->segments[count++];
9034
9035       /* time and duration expressed in global timescale */
9036       segment->time = stime;
9037       /* add non scaled values so we don't cause roundoff errors */
9038       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9039         time += duration;
9040         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9041         segment->duration = stime - segment->time;
9042       } else {
9043         /* zero duration does not imply media_start == media_stop
9044          * but, only specify media_start.*/
9045         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9046         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9047             && stime >= media_start) {
9048           segment->duration = stime - media_start;
9049         } else {
9050           segment->duration = GST_CLOCK_TIME_NONE;
9051         }
9052       }
9053       segment->stop_time = stime;
9054
9055       segment->trak_media_start = media_time;
9056       /* media_time expressed in stream timescale */
9057       if (time_valid) {
9058         segment->media_start = media_start;
9059         segment->media_stop = segment->media_start + segment->duration;
9060         media_segments_count++;
9061       } else {
9062         segment->media_start = GST_CLOCK_TIME_NONE;
9063         segment->media_stop = GST_CLOCK_TIME_NONE;
9064       }
9065       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9066
9067       if (rate_int <= 1) {
9068         /* 0 is not allowed, some programs write 1 instead of the floating point
9069          * value */
9070         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9071             rate_int);
9072         segment->rate = 1;
9073       } else {
9074         segment->rate = rate_int / 65536.0;
9075       }
9076
9077       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9078           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9079           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9080           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9081           i, GST_TIME_ARGS (segment->time),
9082           GST_TIME_ARGS (segment->duration),
9083           GST_TIME_ARGS (segment->media_start), media_time,
9084           GST_TIME_ARGS (segment->media_stop),
9085           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9086           stream->timescale);
9087       if (segment->stop_time > qtdemux->segment.stop) {
9088         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9089             " extends to %" GST_TIME_FORMAT
9090             " past the end of the file duration %" GST_TIME_FORMAT
9091             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9092             GST_TIME_ARGS (qtdemux->segment.stop));
9093         qtdemux->segment.stop = segment->stop_time;
9094       }
9095
9096       buffer += entry_size;
9097     }
9098     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9099     stream->n_segments = count;
9100     if (media_segments_count != 1)
9101       allow_pushbased_edts = FALSE;
9102   }
9103 done:
9104
9105   /* push based does not handle segments, so act accordingly here,
9106    * and warn if applicable */
9107   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9108     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9109     /* remove and use default one below, we stream like it anyway */
9110     g_free (stream->segments);
9111     stream->segments = NULL;
9112     stream->n_segments = 0;
9113   }
9114
9115   /* no segments, create one to play the complete trak */
9116   if (stream->n_segments == 0) {
9117     GstClockTime stream_duration =
9118         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9119
9120     if (stream->segments == NULL)
9121       stream->segments = g_new (QtDemuxSegment, 1);
9122
9123     /* represent unknown our way */
9124     if (stream_duration == 0)
9125       stream_duration = GST_CLOCK_TIME_NONE;
9126
9127     stream->segments[0].time = 0;
9128     stream->segments[0].stop_time = stream_duration;
9129     stream->segments[0].duration = stream_duration;
9130     stream->segments[0].media_start = 0;
9131     stream->segments[0].media_stop = stream_duration;
9132     stream->segments[0].rate = 1.0;
9133     stream->segments[0].trak_media_start = 0;
9134
9135     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9136         GST_TIME_ARGS (stream_duration));
9137     stream->n_segments = 1;
9138     stream->dummy_segment = TRUE;
9139   }
9140   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9141
9142   return TRUE;
9143 }
9144
9145 /*
9146  * Parses the stsd atom of a svq3 trak looking for
9147  * the SMI and gama atoms.
9148  */
9149 static void
9150 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9151     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9152 {
9153   const guint8 *_gamma = NULL;
9154   GstBuffer *_seqh = NULL;
9155   const guint8 *stsd_data = stsd_entry_data;
9156   guint32 length = QT_UINT32 (stsd_data);
9157   guint16 version;
9158
9159   if (length < 32) {
9160     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9161     goto end;
9162   }
9163
9164   stsd_data += 16;
9165   length -= 16;
9166   version = QT_UINT16 (stsd_data);
9167   if (version == 3) {
9168     if (length >= 70) {
9169       length -= 70;
9170       stsd_data += 70;
9171       while (length > 8) {
9172         guint32 fourcc, size;
9173         const guint8 *data;
9174         size = QT_UINT32 (stsd_data);
9175         fourcc = QT_FOURCC (stsd_data + 4);
9176         data = stsd_data + 8;
9177
9178         if (size == 0) {
9179           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9180               "svq3 atom parsing");
9181           goto end;
9182         }
9183
9184         switch (fourcc) {
9185           case FOURCC_gama:{
9186             if (size == 12) {
9187               _gamma = data;
9188             } else {
9189               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9190                   " for gama atom, expected 12", size);
9191             }
9192             break;
9193           }
9194           case FOURCC_SMI_:{
9195             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9196               guint32 seqh_size;
9197               if (_seqh != NULL) {
9198                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9199                     " found, ignoring");
9200               } else {
9201                 seqh_size = QT_UINT32 (data + 4);
9202                 if (seqh_size > 0) {
9203                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9204                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9205                 }
9206               }
9207             }
9208             break;
9209           }
9210           default:{
9211             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9212                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9213           }
9214         }
9215
9216         if (size <= length) {
9217           length -= size;
9218           stsd_data += size;
9219         }
9220       }
9221     } else {
9222       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9223     }
9224   } else {
9225     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9226         G_GUINT16_FORMAT, version);
9227     goto end;
9228   }
9229
9230 end:
9231   if (gamma) {
9232     *gamma = _gamma;
9233   }
9234   if (seqh) {
9235     *seqh = _seqh;
9236   } else if (_seqh) {
9237     gst_buffer_unref (_seqh);
9238   }
9239 }
9240
9241 static gchar *
9242 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9243 {
9244   GNode *dinf;
9245   GstByteReader dref;
9246   gchar *uri = NULL;
9247
9248   /*
9249    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9250    * atom that might contain a 'data' atom with the rtsp uri.
9251    * This case was reported in bug #597497, some info about
9252    * the hndl atom can be found in TN1195
9253    */
9254   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9255   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9256
9257   if (dinf) {
9258     guint32 dref_num_entries = 0;
9259     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9260         gst_byte_reader_skip (&dref, 4) &&
9261         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9262       gint i;
9263
9264       /* search dref entries for hndl atom */
9265       for (i = 0; i < dref_num_entries; i++) {
9266         guint32 size = 0, type;
9267         guint8 string_len = 0;
9268         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9269             qt_atom_parser_get_fourcc (&dref, &type)) {
9270           if (type == FOURCC_hndl) {
9271             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9272
9273             /* skip data reference handle bytes and the
9274              * following pascal string and some extra 4
9275              * bytes I have no idea what are */
9276             if (!gst_byte_reader_skip (&dref, 4) ||
9277                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9278                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9279               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9280               break;
9281             }
9282
9283             /* iterate over the atoms to find the data atom */
9284             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9285               guint32 atom_size;
9286               guint32 atom_type;
9287
9288               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9289                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9290                 if (atom_type == FOURCC_data) {
9291                   const guint8 *uri_aux = NULL;
9292
9293                   /* found the data atom that might contain the rtsp uri */
9294                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9295                       "hndl atom, interpreting it as an URI");
9296                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9297                           &uri_aux)) {
9298                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9299                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9300                     else
9301                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9302                           "didn't contain a rtsp address");
9303                   } else {
9304                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9305                         "atom contents");
9306                   }
9307                   break;
9308                 }
9309                 /* skipping to the next entry */
9310                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9311                   break;
9312               } else {
9313                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9314                     "atom header");
9315                 break;
9316               }
9317             }
9318             break;
9319           }
9320           /* skip to the next entry */
9321           if (!gst_byte_reader_skip (&dref, size - 8))
9322             break;
9323         } else {
9324           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9325         }
9326       }
9327       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9328     }
9329   }
9330   return uri;
9331 }
9332
9333 #define AMR_NB_ALL_MODES        0x81ff
9334 #define AMR_WB_ALL_MODES        0x83ff
9335 static guint
9336 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9337 {
9338   /* The 'damr' atom is of the form:
9339    *
9340    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9341    *    32 b       8 b          16 b           8 b                 8 b
9342    *
9343    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9344    * represents the highest mode used in the stream (and thus the maximum
9345    * bitrate), with a couple of special cases as seen below.
9346    */
9347
9348   /* Map of frame type ID -> bitrate */
9349   static const guint nb_bitrates[] = {
9350     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9351   };
9352   static const guint wb_bitrates[] = {
9353     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9354   };
9355   GstMapInfo map;
9356   gsize max_mode;
9357   guint16 mode_set;
9358
9359   gst_buffer_map (buf, &map, GST_MAP_READ);
9360
9361   if (map.size != 0x11) {
9362     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9363     goto bad_data;
9364   }
9365
9366   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9367     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9368         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9369     goto bad_data;
9370   }
9371
9372   mode_set = QT_UINT16 (map.data + 13);
9373
9374   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9375     max_mode = 7 + (wb ? 1 : 0);
9376   else
9377     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9378     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9379
9380   if (max_mode == -1) {
9381     GST_DEBUG ("No mode indication was found (mode set) = %x",
9382         (guint) mode_set);
9383     goto bad_data;
9384   }
9385
9386   gst_buffer_unmap (buf, &map);
9387   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9388
9389 bad_data:
9390   gst_buffer_unmap (buf, &map);
9391   return 0;
9392 }
9393
9394 static gboolean
9395 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9396     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9397 {
9398   /*
9399    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9400    * [0 1 2]
9401    * [3 4 5]
9402    * [6 7 8]
9403    */
9404
9405   if (gst_byte_reader_get_remaining (reader) < 36)
9406     return FALSE;
9407
9408   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9409   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9410   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9411   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9412   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9413   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9414   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9415   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9416   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9417
9418   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9419   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9420       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9421       matrix[2] & 0xFF);
9422   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9423       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9424       matrix[5] & 0xFF);
9425   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9426       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9427       matrix[8] & 0xFF);
9428
9429   return TRUE;
9430 }
9431
9432 static void
9433 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9434     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9435 {
9436
9437 /* [a b c]
9438  * [d e f]
9439  * [g h i]
9440  *
9441  * This macro will only compare value abdegh, it expects cfi to have already
9442  * been checked
9443  */
9444 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9445                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9446
9447   /* only handle the cases where the last column has standard values */
9448   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9449     const gchar *rotation_tag = NULL;
9450
9451     /* no rotation needed */
9452     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9453       /* NOP */
9454     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9455       rotation_tag = "rotate-90";
9456     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9457       rotation_tag = "rotate-180";
9458     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9459       rotation_tag = "rotate-270";
9460     } else {
9461       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9462     }
9463
9464     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9465         rotation_tag);
9466     if (rotation_tag != NULL) {
9467       if (*taglist == NULL)
9468         *taglist = gst_tag_list_new_empty ();
9469       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9470           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9471     }
9472   } else {
9473     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9474   }
9475 }
9476
9477 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9478  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9479  * Common Encryption (cenc), the function will also parse the tenc box (defined
9480  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9481  * (typically an enc[v|a|t|s] sample entry); the function will set
9482  * @original_fmt to the fourcc of the original unencrypted stream format.
9483  * Returns TRUE if successful; FALSE otherwise. */
9484 static gboolean
9485 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9486     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9487 {
9488   GNode *sinf;
9489   GNode *frma;
9490   GNode *schm;
9491   GNode *schi;
9492
9493   g_return_val_if_fail (qtdemux != NULL, FALSE);
9494   g_return_val_if_fail (stream != NULL, FALSE);
9495   g_return_val_if_fail (container != NULL, FALSE);
9496   g_return_val_if_fail (original_fmt != NULL, FALSE);
9497
9498   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9499   if (G_UNLIKELY (!sinf)) {
9500     if (stream->protection_scheme_type == FOURCC_cenc) {
9501       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9502           "mandatory for Common Encryption");
9503       return FALSE;
9504     }
9505     return TRUE;
9506   }
9507
9508   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9509   if (G_UNLIKELY (!frma)) {
9510     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9511     return FALSE;
9512   }
9513
9514   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9515   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9516       GST_FOURCC_ARGS (*original_fmt));
9517
9518   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9519   if (!schm) {
9520     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9521     return FALSE;
9522   }
9523   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9524   stream->protection_scheme_version =
9525       QT_UINT32 ((const guint8 *) schm->data + 16);
9526
9527   GST_DEBUG_OBJECT (qtdemux,
9528       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9529       "protection_scheme_version: %#010x",
9530       GST_FOURCC_ARGS (stream->protection_scheme_type),
9531       stream->protection_scheme_version);
9532
9533   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9534   if (!schi) {
9535     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9536     return FALSE;
9537   }
9538   if (stream->protection_scheme_type == FOURCC_cenc) {
9539     QtDemuxCencSampleSetInfo *info;
9540     GNode *tenc;
9541     const guint8 *tenc_data;
9542     guint32 isEncrypted;
9543     guint8 iv_size;
9544     const guint8 *default_kid;
9545     GstBuffer *kid_buf;
9546
9547     if (G_UNLIKELY (!stream->protection_scheme_info))
9548       stream->protection_scheme_info =
9549           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9550
9551     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9552
9553     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9554     if (!tenc) {
9555       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9556           "which is mandatory for Common Encryption");
9557       return FALSE;
9558     }
9559     tenc_data = (const guint8 *) tenc->data + 12;
9560     isEncrypted = QT_UINT24 (tenc_data);
9561     iv_size = QT_UINT8 (tenc_data + 3);
9562     default_kid = (tenc_data + 4);
9563     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9564     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9565     if (info->default_properties)
9566       gst_structure_free (info->default_properties);
9567     info->default_properties =
9568         gst_structure_new ("application/x-cenc",
9569         "iv_size", G_TYPE_UINT, iv_size,
9570         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9571         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9572     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9573         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9574     gst_buffer_unref (kid_buf);
9575   }
9576   return TRUE;
9577 }
9578
9579 /* parse the traks.
9580  * With each track we associate a new QtDemuxStream that contains all the info
9581  * about the trak.
9582  * traks that do not decode to something (like strm traks) will not have a pad.
9583  */
9584 static gboolean
9585 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9586 {
9587   GstByteReader tkhd;
9588   int offset;
9589   GNode *mdia;
9590   GNode *mdhd;
9591   GNode *hdlr;
9592   GNode *minf;
9593   GNode *stbl;
9594   GNode *stsd;
9595   GNode *mp4a;
9596   GNode *mp4v;
9597   GNode *wave;
9598   GNode *esds;
9599   GNode *pasp;
9600   GNode *colr;
9601   GNode *tref;
9602   GNode *udta;
9603   GNode *svmi;
9604   GNode *fiel;
9605
9606   QtDemuxStream *stream = NULL;
9607   gboolean new_stream = FALSE;
9608   gchar *codec = NULL;
9609   const guint8 *stsd_data;
9610   const guint8 *stsd_entry_data;
9611   guint remaining_stsd_len;
9612   guint stsd_entry_count;
9613   guint stsd_index;
9614   guint16 lang_code;            /* quicktime lang code or packed iso code */
9615   guint32 version;
9616   guint32 tkhd_flags = 0;
9617   guint8 tkhd_version = 0;
9618   guint32 w = 0, h = 0;
9619   guint32 fourcc;
9620   guint value_size, stsd_len, len;
9621   guint32 track_id;
9622   guint32 dummy;
9623
9624   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9625
9626   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9627       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9628       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9629     goto corrupt_file;
9630
9631   /* pick between 64 or 32 bits */
9632   value_size = tkhd_version == 1 ? 8 : 4;
9633   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9634       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9635     goto corrupt_file;
9636
9637   if (!qtdemux->got_moov) {
9638     if (qtdemux_find_stream (qtdemux, track_id))
9639       goto existing_stream;
9640     stream = _create_stream ();
9641     stream->track_id = track_id;
9642     new_stream = TRUE;
9643   } else {
9644     stream = qtdemux_find_stream (qtdemux, track_id);
9645     if (!stream) {
9646       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9647       goto skip_track;
9648     }
9649
9650     /* reset reused stream */
9651     gst_qtdemux_stream_reset (qtdemux, stream);
9652   }
9653   /* need defaults for fragments */
9654   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9655
9656   if ((tkhd_flags & 1) == 0)
9657     stream->disabled = TRUE;
9658
9659   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9660       tkhd_version, tkhd_flags, stream->track_id);
9661
9662   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9663     goto corrupt_file;
9664
9665   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9666     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9667     if (qtdemux->major_brand != FOURCC_mjp2 ||
9668         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9669       goto corrupt_file;
9670   }
9671
9672   len = QT_UINT32 ((guint8 *) mdhd->data);
9673   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9674   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9675   if (version == 0x01000000) {
9676     if (len < 38)
9677       goto corrupt_file;
9678     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9679     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9680     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9681   } else {
9682     if (len < 30)
9683       goto corrupt_file;
9684     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9685     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9686     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9687   }
9688
9689   if (lang_code < 0x400) {
9690     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9691   } else if (lang_code == 0x7fff) {
9692     stream->lang_id[0] = 0;     /* unspecified */
9693   } else {
9694     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9695     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9696     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9697     stream->lang_id[3] = 0;
9698   }
9699
9700   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9701       stream->timescale);
9702   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9703       stream->duration);
9704   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9705       lang_code, stream->lang_id);
9706
9707   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9708     goto corrupt_file;
9709
9710   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9711     /* chapters track reference */
9712     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9713     if (chap) {
9714       gsize length = GST_READ_UINT32_BE (chap->data);
9715       if (qtdemux->chapters_track_id)
9716         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9717
9718       if (length >= 12) {
9719         qtdemux->chapters_track_id =
9720             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9721       }
9722     }
9723   }
9724
9725   /* fragmented files may have bogus duration in moov */
9726   if (!qtdemux->fragmented &&
9727       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9728     guint64 tdur1, tdur2;
9729
9730     /* don't overflow */
9731     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9732     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9733
9734     /* HACK:
9735      * some of those trailers, nowadays, have prologue images that are
9736      * themselves video tracks as well. I haven't really found a way to
9737      * identify those yet, except for just looking at their duration. */
9738     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9739       GST_WARNING_OBJECT (qtdemux,
9740           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9741           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9742           "found, assuming preview image or something; skipping track",
9743           stream->duration, stream->timescale, qtdemux->duration,
9744           qtdemux->timescale);
9745       if (new_stream)
9746         gst_qtdemux_stream_free (qtdemux, stream);
9747       return TRUE;
9748     }
9749   }
9750
9751   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9752     goto corrupt_file;
9753
9754   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9755       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9756
9757   len = QT_UINT32 ((guint8 *) hdlr->data);
9758   if (len >= 20)
9759     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9760   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9761       GST_FOURCC_ARGS (stream->subtype));
9762
9763   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9764     goto corrupt_file;
9765
9766   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9767     goto corrupt_file;
9768
9769   /*parse svmi header if existing */
9770   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9771   if (svmi) {
9772     len = QT_UINT32 ((guint8 *) svmi->data);
9773     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9774     if (!version) {
9775       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9776       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9777       guint8 frame_type, frame_layout;
9778
9779       /* MPEG-A stereo video */
9780       if (qtdemux->major_brand == FOURCC_ss02)
9781         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9782
9783       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9784       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9785       switch (frame_type) {
9786         case 0:
9787           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9788           break;
9789         case 1:
9790           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9791           break;
9792         case 2:
9793           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9794           break;
9795         case 3:
9796           /* mode 3 is primary/secondary view sequence, ie
9797            * left/right views in separate tracks. See section 7.2
9798            * of ISO/IEC 23000-11:2009 */
9799           GST_FIXME_OBJECT (qtdemux,
9800               "Implement stereo video in separate streams");
9801       }
9802
9803       if ((frame_layout & 0x1) == 0)
9804         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9805
9806       GST_LOG_OBJECT (qtdemux,
9807           "StereoVideo: composition type: %u, is_left_first: %u",
9808           frame_type, frame_layout);
9809       stream->multiview_mode = mode;
9810       stream->multiview_flags = flags;
9811     }
9812   }
9813
9814   /* parse rest of tkhd */
9815   if (stream->subtype == FOURCC_vide) {
9816     guint32 matrix[9];
9817
9818     /* version 1 uses some 64-bit ints */
9819     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9820       goto corrupt_file;
9821
9822     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9823       goto corrupt_file;
9824
9825     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9826         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9827       goto corrupt_file;
9828
9829     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9830         &stream->stream_tags);
9831   }
9832
9833   /* parse stsd */
9834   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9835     goto corrupt_file;
9836   stsd_data = (const guint8 *) stsd->data;
9837
9838   /* stsd should at least have one entry */
9839   stsd_len = QT_UINT32 (stsd_data);
9840   if (stsd_len < 24) {
9841     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9842     if (stream->subtype == FOURCC_vivo) {
9843       if (new_stream)
9844         gst_qtdemux_stream_free (qtdemux, stream);
9845       return TRUE;
9846     } else {
9847       goto corrupt_file;
9848     }
9849   }
9850
9851   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9852   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9853   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9854   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9855
9856   stsd_entry_data = stsd_data + 16;
9857   remaining_stsd_len = stsd_len - 16;
9858   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9859     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9860
9861     /* and that entry should fit within stsd */
9862     len = QT_UINT32 (stsd_entry_data);
9863     if (len > remaining_stsd_len)
9864       goto corrupt_file;
9865
9866     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9867     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9868         GST_FOURCC_ARGS (entry->fourcc));
9869     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9870
9871     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9872       goto error_encrypted;
9873
9874     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9875       /* FIXME this looks wrong, there might be multiple children
9876        * with the same type */
9877       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9878       stream->protected = TRUE;
9879       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9880         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9881     }
9882
9883     if (stream->subtype == FOURCC_vide) {
9884       gboolean gray;
9885       gint depth, palette_size, palette_count;
9886       guint32 *palette_data = NULL;
9887
9888       entry->sampled = TRUE;
9889
9890       stream->display_width = w >> 16;
9891       stream->display_height = h >> 16;
9892
9893       offset = 16;
9894       if (len < 86)             /* TODO verify */
9895         goto corrupt_file;
9896
9897       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9898       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9899       entry->fps_n = 0;         /* this is filled in later */
9900       entry->fps_d = 0;         /* this is filled in later */
9901       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9902       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9903
9904       /* if color_table_id is 0, ctab atom must follow; however some files
9905        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9906        * if color table is not present we'll correct the value */
9907       if (entry->color_table_id == 0 &&
9908           (len < 90
9909               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9910         entry->color_table_id = -1;
9911       }
9912
9913       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9914           entry->width, entry->height, entry->bits_per_sample,
9915           entry->color_table_id);
9916
9917       depth = entry->bits_per_sample;
9918
9919       /* more than 32 bits means grayscale */
9920       gray = (depth > 32);
9921       /* low 32 bits specify the depth  */
9922       depth &= 0x1F;
9923
9924       /* different number of palette entries is determined by depth. */
9925       palette_count = 0;
9926       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9927         palette_count = (1 << depth);
9928       palette_size = palette_count * 4;
9929
9930       if (entry->color_table_id) {
9931         switch (palette_count) {
9932           case 0:
9933             break;
9934           case 2:
9935             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9936             break;
9937           case 4:
9938             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9939             break;
9940           case 16:
9941             if (gray)
9942               palette_data =
9943                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9944             else
9945               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9946             break;
9947           case 256:
9948             if (gray)
9949               palette_data =
9950                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9951             else
9952               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9953             break;
9954           default:
9955             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9956                 (_("The video in this file might not play correctly.")),
9957                 ("unsupported palette depth %d", depth));
9958             break;
9959         }
9960       } else {
9961         gint i, j, start, end;
9962
9963         if (len < 94)
9964           goto corrupt_file;
9965
9966         /* read table */
9967         start = QT_UINT32 (stsd_entry_data + offset + 70);
9968         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9969         end = QT_UINT16 (stsd_entry_data + offset + 76);
9970
9971         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9972             start, end, palette_count);
9973
9974         if (end > 255)
9975           end = 255;
9976         if (start > end)
9977           start = end;
9978
9979         if (len < 94 + (end - start) * 8)
9980           goto corrupt_file;
9981
9982         /* palette is always the same size */
9983         palette_data = g_malloc0 (256 * 4);
9984         palette_size = 256 * 4;
9985
9986         for (j = 0, i = start; i <= end; j++, i++) {
9987           guint32 a, r, g, b;
9988
9989           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9990           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9991           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9992           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9993
9994           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9995               (g & 0xff00) | (b >> 8);
9996         }
9997       }
9998
9999       if (entry->caps)
10000         gst_caps_unref (entry->caps);
10001
10002       entry->caps =
10003           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10004           &codec);
10005       if (G_UNLIKELY (!entry->caps)) {
10006         g_free (palette_data);
10007         goto unknown_stream;
10008       }
10009
10010       if (codec) {
10011         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10012             GST_TAG_VIDEO_CODEC, codec, NULL);
10013         g_free (codec);
10014         codec = NULL;
10015       }
10016
10017       if (palette_data) {
10018         GstStructure *s;
10019
10020         if (entry->rgb8_palette)
10021           gst_memory_unref (entry->rgb8_palette);
10022         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10023             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10024
10025         s = gst_caps_get_structure (entry->caps, 0);
10026
10027         /* non-raw video has a palette_data property. raw video has the palette as
10028          * an extra plane that we append to the output buffers before we push
10029          * them*/
10030         if (!gst_structure_has_name (s, "video/x-raw")) {
10031           GstBuffer *palette;
10032
10033           palette = gst_buffer_new ();
10034           gst_buffer_append_memory (palette, entry->rgb8_palette);
10035           entry->rgb8_palette = NULL;
10036
10037           gst_caps_set_simple (entry->caps, "palette_data",
10038               GST_TYPE_BUFFER, palette, NULL);
10039           gst_buffer_unref (palette);
10040         }
10041       } else if (palette_count != 0) {
10042         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10043             (NULL), ("Unsupported palette depth %d", depth));
10044       }
10045
10046       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10047           QT_UINT16 (stsd_entry_data + offset + 32));
10048
10049       esds = NULL;
10050       pasp = NULL;
10051       colr = NULL;
10052       fiel = NULL;
10053       /* pick 'the' stsd child */
10054       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10055       if (!stream->protected) {
10056         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10057           mp4v = NULL;
10058         }
10059       } else {
10060         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10061           mp4v = NULL;
10062         }
10063       }
10064
10065       if (mp4v) {
10066         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10067         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10068         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10069         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10070       }
10071
10072       if (pasp) {
10073         const guint8 *pasp_data = (const guint8 *) pasp->data;
10074         gint len = QT_UINT32 (pasp_data);
10075
10076         if (len == 16) {
10077           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10078           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10079         } else {
10080           CUR_STREAM (stream)->par_w = 0;
10081           CUR_STREAM (stream)->par_h = 0;
10082         }
10083       } else {
10084         CUR_STREAM (stream)->par_w = 0;
10085         CUR_STREAM (stream)->par_h = 0;
10086       }
10087
10088       if (fiel) {
10089         const guint8 *fiel_data = (const guint8 *) fiel->data;
10090         gint len = QT_UINT32 (fiel_data);
10091
10092         if (len == 10) {
10093           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10094           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10095         }
10096       }
10097
10098       if (colr) {
10099         const guint8 *colr_data = (const guint8 *) colr->data;
10100         gint len = QT_UINT32 (colr_data);
10101
10102         if (len == 19 || len == 18) {
10103           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10104
10105           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10106             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10107             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10108             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10109             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10110
10111             switch (primaries) {
10112               case 1:
10113                 CUR_STREAM (stream)->colorimetry.primaries =
10114                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10115                 break;
10116               case 5:
10117                 CUR_STREAM (stream)->colorimetry.primaries =
10118                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10119                 break;
10120               case 6:
10121                 CUR_STREAM (stream)->colorimetry.primaries =
10122                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10123                 break;
10124               case 9:
10125                 CUR_STREAM (stream)->colorimetry.primaries =
10126                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10127                 break;
10128               default:
10129                 break;
10130             }
10131
10132             switch (transfer_function) {
10133               case 1:
10134                 CUR_STREAM (stream)->colorimetry.transfer =
10135                     GST_VIDEO_TRANSFER_BT709;
10136                 break;
10137               case 7:
10138                 CUR_STREAM (stream)->colorimetry.transfer =
10139                     GST_VIDEO_TRANSFER_SMPTE240M;
10140                 break;
10141               default:
10142                 break;
10143             }
10144
10145             switch (matrix) {
10146               case 1:
10147                 CUR_STREAM (stream)->colorimetry.matrix =
10148                     GST_VIDEO_COLOR_MATRIX_BT709;
10149                 break;
10150               case 6:
10151                 CUR_STREAM (stream)->colorimetry.matrix =
10152                     GST_VIDEO_COLOR_MATRIX_BT601;
10153                 break;
10154               case 7:
10155                 CUR_STREAM (stream)->colorimetry.matrix =
10156                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10157                 break;
10158               case 9:
10159                 CUR_STREAM (stream)->colorimetry.matrix =
10160                     GST_VIDEO_COLOR_MATRIX_BT2020;
10161                 break;
10162               default:
10163                 break;
10164             }
10165
10166             CUR_STREAM (stream)->colorimetry.range =
10167                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10168                 GST_VIDEO_COLOR_RANGE_16_235;
10169           } else {
10170             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10171           }
10172         } else {
10173           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10174         }
10175       }
10176
10177       if (esds) {
10178         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10179             stream->stream_tags);
10180       } else {
10181         switch (fourcc) {
10182           case FOURCC_H264:
10183           case FOURCC_avc1:
10184           case FOURCC_avc3:
10185           {
10186             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10187             const guint8 *avc_data = stsd_entry_data + 0x56;
10188
10189             /* find avcC */
10190             while (len >= 0x8) {
10191               gint size;
10192
10193               if (QT_UINT32 (avc_data) <= len)
10194                 size = QT_UINT32 (avc_data) - 0x8;
10195               else
10196                 size = len - 0x8;
10197
10198               if (size < 1)
10199                 /* No real data, so break out */
10200                 break;
10201
10202               switch (QT_FOURCC (avc_data + 0x4)) {
10203                 case FOURCC_avcC:
10204                 {
10205                   /* parse, if found */
10206                   GstBuffer *buf;
10207
10208                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10209
10210                   /* First 4 bytes are the length of the atom, the next 4 bytes
10211                    * are the fourcc, the next 1 byte is the version, and the
10212                    * subsequent bytes are profile_tier_level structure like data. */
10213                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10214                       avc_data + 8 + 1, size - 1);
10215                   buf = gst_buffer_new_and_alloc (size);
10216                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10217                   gst_caps_set_simple (entry->caps,
10218                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10219                   gst_buffer_unref (buf);
10220
10221                   break;
10222                 }
10223                 case FOURCC_strf:
10224                 {
10225                   GstBuffer *buf;
10226
10227                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10228
10229                   /* First 4 bytes are the length of the atom, the next 4 bytes
10230                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10231                    * next 1 byte is the version, and the
10232                    * subsequent bytes are sequence parameter set like data. */
10233
10234                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10235                   if (size > 1) {
10236                     gst_codec_utils_h264_caps_set_level_and_profile
10237                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10238
10239                     buf = gst_buffer_new_and_alloc (size);
10240                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10241                     gst_caps_set_simple (entry->caps,
10242                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10243                     gst_buffer_unref (buf);
10244                   }
10245                   break;
10246                 }
10247                 case FOURCC_btrt:
10248                 {
10249                   guint avg_bitrate, max_bitrate;
10250
10251                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10252                   if (size < 12)
10253                     break;
10254
10255                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10256                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10257
10258                   if (!max_bitrate && !avg_bitrate)
10259                     break;
10260
10261                   /* Some muxers seem to swap the average and maximum bitrates
10262                    * (I'm looking at you, YouTube), so we swap for sanity. */
10263                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10264                     guint temp = avg_bitrate;
10265
10266                     avg_bitrate = max_bitrate;
10267                     max_bitrate = temp;
10268                   }
10269
10270                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10271                     gst_tag_list_add (stream->stream_tags,
10272                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10273                         max_bitrate, NULL);
10274                   }
10275                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10276                     gst_tag_list_add (stream->stream_tags,
10277                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10278                         NULL);
10279                   }
10280
10281                   break;
10282                 }
10283
10284                 default:
10285                   break;
10286               }
10287
10288               len -= size + 8;
10289               avc_data += size + 8;
10290             }
10291
10292             break;
10293           }
10294           case FOURCC_H265:
10295           case FOURCC_hvc1:
10296           case FOURCC_hev1:
10297           {
10298             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10299             const guint8 *hevc_data = stsd_entry_data + 0x56;
10300
10301             /* find hevc */
10302             while (len >= 0x8) {
10303               gint size;
10304
10305               if (QT_UINT32 (hevc_data) <= len)
10306                 size = QT_UINT32 (hevc_data) - 0x8;
10307               else
10308                 size = len - 0x8;
10309
10310               if (size < 1)
10311                 /* No real data, so break out */
10312                 break;
10313
10314               switch (QT_FOURCC (hevc_data + 0x4)) {
10315                 case FOURCC_hvcC:
10316                 {
10317                   /* parse, if found */
10318                   GstBuffer *buf;
10319
10320                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10321
10322                   /* First 4 bytes are the length of the atom, the next 4 bytes
10323                    * are the fourcc, the next 1 byte is the version, and the
10324                    * subsequent bytes are sequence parameter set like data. */
10325                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10326                       (entry->caps, hevc_data + 8 + 1, size - 1);
10327
10328                   buf = gst_buffer_new_and_alloc (size);
10329                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10330                   gst_caps_set_simple (entry->caps,
10331                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10332                   gst_buffer_unref (buf);
10333                   break;
10334                 }
10335                 default:
10336                   break;
10337               }
10338               len -= size + 8;
10339               hevc_data += size + 8;
10340             }
10341             break;
10342           }
10343           case FOURCC_mp4v:
10344           case FOURCC_MP4V:
10345           case FOURCC_fmp4:
10346           case FOURCC_FMP4:
10347           case FOURCC_xvid:
10348           case FOURCC_XVID:
10349           {
10350             GNode *glbl;
10351
10352             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10353                 GST_FOURCC_ARGS (fourcc));
10354
10355             /* codec data might be in glbl extension atom */
10356             glbl = mp4v ?
10357                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10358             if (glbl) {
10359               guint8 *data;
10360               GstBuffer *buf;
10361               gint len;
10362
10363               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10364               data = glbl->data;
10365               len = QT_UINT32 (data);
10366               if (len > 0x8) {
10367                 len -= 0x8;
10368                 buf = gst_buffer_new_and_alloc (len);
10369                 gst_buffer_fill (buf, 0, data + 8, len);
10370                 gst_caps_set_simple (entry->caps,
10371                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10372                 gst_buffer_unref (buf);
10373               }
10374             }
10375             break;
10376           }
10377           case FOURCC_mjp2:
10378           {
10379             /* see annex I of the jpeg2000 spec */
10380             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10381             const guint8 *data;
10382             const gchar *colorspace = NULL;
10383             gint ncomp = 0;
10384             guint32 ncomp_map = 0;
10385             gint32 *comp_map = NULL;
10386             guint32 nchan_def = 0;
10387             gint32 *chan_def = NULL;
10388
10389             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10390             /* some required atoms */
10391             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10392             if (!mjp2)
10393               break;
10394             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10395             if (!jp2h)
10396               break;
10397
10398             /* number of components; redundant with info in codestream, but useful
10399                to a muxer */
10400             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10401             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10402               break;
10403             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10404
10405             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10406             if (!colr)
10407               break;
10408             GST_DEBUG_OBJECT (qtdemux, "found colr");
10409             /* extract colour space info */
10410             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10411               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10412                 case 16:
10413                   colorspace = "sRGB";
10414                   break;
10415                 case 17:
10416                   colorspace = "GRAY";
10417                   break;
10418                 case 18:
10419                   colorspace = "sYUV";
10420                   break;
10421                 default:
10422                   colorspace = NULL;
10423                   break;
10424               }
10425             }
10426             if (!colorspace)
10427               /* colr is required, and only values 16, 17, and 18 are specified,
10428                  so error if we have no colorspace */
10429               break;
10430
10431             /* extract component mapping */
10432             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10433             if (cmap) {
10434               guint32 cmap_len = 0;
10435               int i;
10436               cmap_len = QT_UINT32 (cmap->data);
10437               if (cmap_len >= 8) {
10438                 /* normal box, subtract off header */
10439                 cmap_len -= 8;
10440                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10441                 if (cmap_len % 4 == 0) {
10442                   ncomp_map = (cmap_len / 4);
10443                   comp_map = g_new0 (gint32, ncomp_map);
10444                   for (i = 0; i < ncomp_map; i++) {
10445                     guint16 cmp;
10446                     guint8 mtyp, pcol;
10447                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10448                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10449                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10450                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10451                   }
10452                 }
10453               }
10454             }
10455             /* extract channel definitions */
10456             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10457             if (cdef) {
10458               guint32 cdef_len = 0;
10459               int i;
10460               cdef_len = QT_UINT32 (cdef->data);
10461               if (cdef_len >= 10) {
10462                 /* normal box, subtract off header and len */
10463                 cdef_len -= 10;
10464                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10465                 if (cdef_len % 6 == 0) {
10466                   nchan_def = (cdef_len / 6);
10467                   chan_def = g_new0 (gint32, nchan_def);
10468                   for (i = 0; i < nchan_def; i++)
10469                     chan_def[i] = -1;
10470                   for (i = 0; i < nchan_def; i++) {
10471                     guint16 cn, typ, asoc;
10472                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10473                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10474                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10475                     if (cn < nchan_def) {
10476                       switch (typ) {
10477                         case 0:
10478                           chan_def[cn] = asoc;
10479                           break;
10480                         case 1:
10481                           chan_def[cn] = 0;     /* alpha */
10482                           break;
10483                         default:
10484                           chan_def[cn] = -typ;
10485                       }
10486                     }
10487                   }
10488                 }
10489               }
10490             }
10491
10492             gst_caps_set_simple (entry->caps,
10493                 "num-components", G_TYPE_INT, ncomp, NULL);
10494             gst_caps_set_simple (entry->caps,
10495                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10496
10497             if (comp_map) {
10498               GValue arr = { 0, };
10499               GValue elt = { 0, };
10500               int i;
10501               g_value_init (&arr, GST_TYPE_ARRAY);
10502               g_value_init (&elt, G_TYPE_INT);
10503               for (i = 0; i < ncomp_map; i++) {
10504                 g_value_set_int (&elt, comp_map[i]);
10505                 gst_value_array_append_value (&arr, &elt);
10506               }
10507               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10508                   "component-map", &arr);
10509               g_value_unset (&elt);
10510               g_value_unset (&arr);
10511               g_free (comp_map);
10512             }
10513
10514             if (chan_def) {
10515               GValue arr = { 0, };
10516               GValue elt = { 0, };
10517               int i;
10518               g_value_init (&arr, GST_TYPE_ARRAY);
10519               g_value_init (&elt, G_TYPE_INT);
10520               for (i = 0; i < nchan_def; i++) {
10521                 g_value_set_int (&elt, chan_def[i]);
10522                 gst_value_array_append_value (&arr, &elt);
10523               }
10524               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10525                   "channel-definitions", &arr);
10526               g_value_unset (&elt);
10527               g_value_unset (&arr);
10528               g_free (chan_def);
10529             }
10530
10531             /* some optional atoms */
10532             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10533             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10534
10535             /* indicate possible fields in caps */
10536             if (field) {
10537               data = (guint8 *) field->data + 8;
10538               if (*data != 1)
10539                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10540                     (gint) * data, NULL);
10541             }
10542             /* add codec_data if provided */
10543             if (prefix) {
10544               GstBuffer *buf;
10545               gint len;
10546
10547               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10548               data = prefix->data;
10549               len = QT_UINT32 (data);
10550               if (len > 0x8) {
10551                 len -= 0x8;
10552                 buf = gst_buffer_new_and_alloc (len);
10553                 gst_buffer_fill (buf, 0, data + 8, len);
10554                 gst_caps_set_simple (entry->caps,
10555                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10556                 gst_buffer_unref (buf);
10557               }
10558             }
10559             break;
10560           }
10561           case FOURCC_SVQ3:
10562           case FOURCC_VP31:
10563           {
10564             GstBuffer *buf;
10565             GstBuffer *seqh = NULL;
10566             const guint8 *gamma_data = NULL;
10567             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10568
10569             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10570                 &seqh);
10571             if (gamma_data) {
10572               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10573                   QT_FP32 (gamma_data), NULL);
10574             }
10575             if (seqh) {
10576               /* sorry for the bad name, but we don't know what this is, other
10577                * than its own fourcc */
10578               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10579                   NULL);
10580               gst_buffer_unref (seqh);
10581             }
10582
10583             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10584             buf = gst_buffer_new_and_alloc (len);
10585             gst_buffer_fill (buf, 0, stsd_data, len);
10586             gst_caps_set_simple (entry->caps,
10587                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10588             gst_buffer_unref (buf);
10589             break;
10590           }
10591           case FOURCC_jpeg:
10592           {
10593             /* https://developer.apple.com/standards/qtff-2001.pdf,
10594              * page 92, "Video Sample Description", under table 3.1 */
10595             GstByteReader br;
10596
10597             const gint compressor_offset =
10598                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10599             const gint min_size = compressor_offset + 32 + 2 + 2;
10600             GNode *jpeg;
10601             guint32 len;
10602             guint16 color_table_id = 0;
10603             gboolean ok;
10604
10605             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10606
10607             /* recover information on interlaced/progressive */
10608             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10609             if (!jpeg)
10610               break;
10611
10612             len = QT_UINT32 (jpeg->data);
10613             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10614                 min_size);
10615             if (len >= min_size) {
10616               gst_byte_reader_init (&br, jpeg->data, len);
10617
10618               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10619               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10620               if (color_table_id != 0) {
10621                 /* the spec says there can be concatenated chunks in the data, and we want
10622                  * to find one called field. Walk through them. */
10623                 gint offset = min_size;
10624                 while (offset + 8 < len) {
10625                   guint32 size = 0, tag;
10626                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10627                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10628                   if (!ok || size < 8) {
10629                     GST_WARNING_OBJECT (qtdemux,
10630                         "Failed to walk optional chunk list");
10631                     break;
10632                   }
10633                   GST_DEBUG_OBJECT (qtdemux,
10634                       "Found optional %4.4s chunk, size %u",
10635                       (const char *) &tag, size);
10636                   if (tag == FOURCC_fiel) {
10637                     guint8 n_fields = 0, ordering = 0;
10638                     gst_byte_reader_get_uint8 (&br, &n_fields);
10639                     gst_byte_reader_get_uint8 (&br, &ordering);
10640                     if (n_fields == 1 || n_fields == 2) {
10641                       GST_DEBUG_OBJECT (qtdemux,
10642                           "Found fiel tag with %u fields, ordering %u",
10643                           n_fields, ordering);
10644                       if (n_fields == 2)
10645                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10646                             "interlace-mode", G_TYPE_STRING, "interleaved",
10647                             NULL);
10648                     } else {
10649                       GST_WARNING_OBJECT (qtdemux,
10650                           "Found fiel tag with invalid fields (%u)", n_fields);
10651                     }
10652                   }
10653                   offset += size;
10654                 }
10655               } else {
10656                 GST_DEBUG_OBJECT (qtdemux,
10657                     "Color table ID is 0, not trying to get interlacedness");
10658               }
10659             } else {
10660               GST_WARNING_OBJECT (qtdemux,
10661                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10662             }
10663
10664             break;
10665           }
10666           case FOURCC_rle_:
10667           case FOURCC_WRLE:
10668           {
10669             gst_caps_set_simple (entry->caps,
10670                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10671                 NULL);
10672             break;
10673           }
10674           case FOURCC_XiTh:
10675           {
10676             GNode *xith, *xdxt;
10677
10678             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10679             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10680             if (!xith)
10681               break;
10682
10683             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10684             if (!xdxt)
10685               break;
10686
10687             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10688             /* collect the headers and store them in a stream list so that we can
10689              * send them out first */
10690             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10691             break;
10692           }
10693           case FOURCC_ovc1:
10694           {
10695             GNode *ovc1;
10696             guint8 *ovc1_data;
10697             guint ovc1_len;
10698             GstBuffer *buf;
10699
10700             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10701             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10702             if (!ovc1)
10703               break;
10704             ovc1_data = ovc1->data;
10705             ovc1_len = QT_UINT32 (ovc1_data);
10706             if (ovc1_len <= 198) {
10707               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10708               break;
10709             }
10710             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10711             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10712             gst_caps_set_simple (entry->caps,
10713                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10714             gst_buffer_unref (buf);
10715             break;
10716           }
10717           case FOURCC_vc_1:
10718           {
10719             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10720             const guint8 *vc1_data = stsd_entry_data + 0x56;
10721
10722             /* find dvc1 */
10723             while (len >= 8) {
10724               gint size;
10725
10726               if (QT_UINT32 (vc1_data) <= len)
10727                 size = QT_UINT32 (vc1_data) - 8;
10728               else
10729                 size = len - 8;
10730
10731               if (size < 1)
10732                 /* No real data, so break out */
10733                 break;
10734
10735               switch (QT_FOURCC (vc1_data + 0x4)) {
10736                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10737                 {
10738                   GstBuffer *buf;
10739
10740                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10741                   buf = gst_buffer_new_and_alloc (size);
10742                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10743                   gst_caps_set_simple (entry->caps,
10744                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10745                   gst_buffer_unref (buf);
10746                   break;
10747                 }
10748                 default:
10749                   break;
10750               }
10751               len -= size + 8;
10752               vc1_data += size + 8;
10753             }
10754             break;
10755           }
10756           default:
10757             break;
10758         }
10759       }
10760
10761       GST_INFO_OBJECT (qtdemux,
10762           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10763           GST_FOURCC_ARGS (fourcc), entry->caps);
10764
10765     } else if (stream->subtype == FOURCC_soun) {
10766       int version, samplesize;
10767       guint16 compression_id;
10768       gboolean amrwb = FALSE;
10769
10770       offset = 16;
10771       /* sample description entry (16) + sound sample description v0 (20) */
10772       if (len < 36)
10773         goto corrupt_file;
10774
10775       version = QT_UINT32 (stsd_entry_data + offset);
10776       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10777       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10778       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10779       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10780
10781       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10782       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10783           QT_UINT32 (stsd_entry_data + offset + 4));
10784       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10785       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10786       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10787       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10788           QT_UINT16 (stsd_entry_data + offset + 14));
10789       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10790
10791       if (compression_id == 0xfffe)
10792         entry->sampled = TRUE;
10793
10794       /* first assume uncompressed audio */
10795       entry->bytes_per_sample = samplesize / 8;
10796       entry->samples_per_frame = entry->n_channels;
10797       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10798       entry->samples_per_packet = entry->samples_per_frame;
10799       entry->bytes_per_packet = entry->bytes_per_sample;
10800
10801       offset = 36;
10802       switch (fourcc) {
10803           /* Yes, these have to be hard-coded */
10804         case FOURCC_MAC6:
10805         {
10806           entry->samples_per_packet = 6;
10807           entry->bytes_per_packet = 1;
10808           entry->bytes_per_frame = 1 * entry->n_channels;
10809           entry->bytes_per_sample = 1;
10810           entry->samples_per_frame = 6 * entry->n_channels;
10811           break;
10812         }
10813         case FOURCC_MAC3:
10814         {
10815           entry->samples_per_packet = 3;
10816           entry->bytes_per_packet = 1;
10817           entry->bytes_per_frame = 1 * entry->n_channels;
10818           entry->bytes_per_sample = 1;
10819           entry->samples_per_frame = 3 * entry->n_channels;
10820           break;
10821         }
10822         case FOURCC_ima4:
10823         {
10824           entry->samples_per_packet = 64;
10825           entry->bytes_per_packet = 34;
10826           entry->bytes_per_frame = 34 * entry->n_channels;
10827           entry->bytes_per_sample = 2;
10828           entry->samples_per_frame = 64 * entry->n_channels;
10829           break;
10830         }
10831         case FOURCC_ulaw:
10832         case FOURCC_alaw:
10833         {
10834           entry->samples_per_packet = 1;
10835           entry->bytes_per_packet = 1;
10836           entry->bytes_per_frame = 1 * entry->n_channels;
10837           entry->bytes_per_sample = 1;
10838           entry->samples_per_frame = 1 * entry->n_channels;
10839           break;
10840         }
10841         case FOURCC_agsm:
10842         {
10843           entry->samples_per_packet = 160;
10844           entry->bytes_per_packet = 33;
10845           entry->bytes_per_frame = 33 * entry->n_channels;
10846           entry->bytes_per_sample = 2;
10847           entry->samples_per_frame = 160 * entry->n_channels;
10848           break;
10849         }
10850         default:
10851           break;
10852       }
10853
10854       if (version == 0x00010000) {
10855         /* sample description entry (16) + sound sample description v1 (20+16) */
10856         if (len < 52)
10857           goto corrupt_file;
10858
10859         switch (fourcc) {
10860           case FOURCC_twos:
10861           case FOURCC_sowt:
10862           case FOURCC_raw_:
10863           case FOURCC_lpcm:
10864             break;
10865           default:
10866           {
10867             /* only parse extra decoding config for non-pcm audio */
10868             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10869             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10870             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10871             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10872
10873             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10874                 entry->samples_per_packet);
10875             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10876                 entry->bytes_per_packet);
10877             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10878                 entry->bytes_per_frame);
10879             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10880                 entry->bytes_per_sample);
10881
10882             if (!entry->sampled && entry->bytes_per_packet) {
10883               entry->samples_per_frame = (entry->bytes_per_frame /
10884                   entry->bytes_per_packet) * entry->samples_per_packet;
10885               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10886                   entry->samples_per_frame);
10887             }
10888             break;
10889           }
10890         }
10891       } else if (version == 0x00020000) {
10892         union
10893         {
10894           gdouble fp;
10895           guint64 val;
10896         } qtfp;
10897
10898         /* sample description entry (16) + sound sample description v2 (56) */
10899         if (len < 72)
10900           goto corrupt_file;
10901
10902         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10903         entry->rate = qtfp.fp;
10904         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10905
10906         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10907         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10908         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10909         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10910             QT_UINT32 (stsd_entry_data + offset + 20));
10911         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10912             QT_UINT32 (stsd_entry_data + offset + 24));
10913         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10914             QT_UINT32 (stsd_entry_data + offset + 28));
10915         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10916             QT_UINT32 (stsd_entry_data + offset + 32));
10917       } else if (version != 0x00000) {
10918         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10919             version);
10920       }
10921
10922       if (entry->caps)
10923         gst_caps_unref (entry->caps);
10924
10925       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10926           stsd_entry_data + 32, len - 16, &codec);
10927
10928       switch (fourcc) {
10929         case FOURCC_in24:
10930         {
10931           GNode *enda;
10932           GNode *in24;
10933
10934           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10935
10936           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10937           if (!enda) {
10938             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10939             if (wave)
10940               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10941           }
10942           if (enda) {
10943             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10944             gst_caps_set_simple (entry->caps,
10945                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10946                 NULL);
10947           }
10948           break;
10949         }
10950         case FOURCC_owma:
10951         {
10952           const guint8 *owma_data;
10953           const gchar *codec_name = NULL;
10954           guint owma_len;
10955           GstBuffer *buf;
10956           gint version = 1;
10957           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10958           /* FIXME this should also be gst_riff_strf_auds,
10959            * but the latter one is actually missing bits-per-sample :( */
10960           typedef struct
10961           {
10962             gint16 wFormatTag;
10963             gint16 nChannels;
10964             gint32 nSamplesPerSec;
10965             gint32 nAvgBytesPerSec;
10966             gint16 nBlockAlign;
10967             gint16 wBitsPerSample;
10968             gint16 cbSize;
10969           } WAVEFORMATEX;
10970           WAVEFORMATEX *wfex;
10971
10972           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10973           owma_data = stsd_entry_data;
10974           owma_len = QT_UINT32 (owma_data);
10975           if (owma_len <= 54) {
10976             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10977             break;
10978           }
10979           wfex = (WAVEFORMATEX *) (owma_data + 36);
10980           buf = gst_buffer_new_and_alloc (owma_len - 54);
10981           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10982           if (wfex->wFormatTag == 0x0161) {
10983             codec_name = "Windows Media Audio";
10984             version = 2;
10985           } else if (wfex->wFormatTag == 0x0162) {
10986             codec_name = "Windows Media Audio 9 Pro";
10987             version = 3;
10988           } else if (wfex->wFormatTag == 0x0163) {
10989             codec_name = "Windows Media Audio 9 Lossless";
10990             /* is that correct? gstffmpegcodecmap.c is missing it, but
10991              * fluendo codec seems to support it */
10992             version = 4;
10993           }
10994
10995           gst_caps_set_simple (entry->caps,
10996               "codec_data", GST_TYPE_BUFFER, buf,
10997               "wmaversion", G_TYPE_INT, version,
10998               "block_align", G_TYPE_INT,
10999               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11000               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11001               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11002               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11003           gst_buffer_unref (buf);
11004
11005           if (codec_name) {
11006             g_free (codec);
11007             codec = g_strdup (codec_name);
11008           }
11009           break;
11010         }
11011         case FOURCC_wma_:
11012         {
11013           gint len = QT_UINT32 (stsd_entry_data) - offset;
11014           const guint8 *wfex_data = stsd_entry_data + offset;
11015           const gchar *codec_name = NULL;
11016           gint version = 1;
11017           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11018           /* FIXME this should also be gst_riff_strf_auds,
11019            * but the latter one is actually missing bits-per-sample :( */
11020           typedef struct
11021           {
11022             gint16 wFormatTag;
11023             gint16 nChannels;
11024             gint32 nSamplesPerSec;
11025             gint32 nAvgBytesPerSec;
11026             gint16 nBlockAlign;
11027             gint16 wBitsPerSample;
11028             gint16 cbSize;
11029           } WAVEFORMATEX;
11030           WAVEFORMATEX wfex;
11031
11032           /* FIXME: unify with similar wavformatex parsing code above */
11033           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11034
11035           /* find wfex */
11036           while (len >= 8) {
11037             gint size;
11038
11039             if (QT_UINT32 (wfex_data) <= len)
11040               size = QT_UINT32 (wfex_data) - 8;
11041             else
11042               size = len - 8;
11043
11044             if (size < 1)
11045               /* No real data, so break out */
11046               break;
11047
11048             switch (QT_FOURCC (wfex_data + 4)) {
11049               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11050               {
11051                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11052
11053                 if (size < 8 + 18)
11054                   break;
11055
11056                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11057                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11058                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11059                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11060                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11061                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11062                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11063
11064                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11065                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11066                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11067                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11068                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11069                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11070
11071                 if (wfex.wFormatTag == 0x0161) {
11072                   codec_name = "Windows Media Audio";
11073                   version = 2;
11074                 } else if (wfex.wFormatTag == 0x0162) {
11075                   codec_name = "Windows Media Audio 9 Pro";
11076                   version = 3;
11077                 } else if (wfex.wFormatTag == 0x0163) {
11078                   codec_name = "Windows Media Audio 9 Lossless";
11079                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11080                    * fluendo codec seems to support it */
11081                   version = 4;
11082                 }
11083
11084                 gst_caps_set_simple (entry->caps,
11085                     "wmaversion", G_TYPE_INT, version,
11086                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11087                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11088                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11089                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11090
11091                 if (size > wfex.cbSize) {
11092                   GstBuffer *buf;
11093
11094                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11095                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11096                       size - wfex.cbSize);
11097                   gst_caps_set_simple (entry->caps,
11098                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11099                   gst_buffer_unref (buf);
11100                 } else {
11101                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11102                 }
11103
11104                 if (codec_name) {
11105                   g_free (codec);
11106                   codec = g_strdup (codec_name);
11107                 }
11108                 break;
11109               }
11110               default:
11111                 break;
11112             }
11113             len -= size + 8;
11114             wfex_data += size + 8;
11115           }
11116           break;
11117         }
11118         case FOURCC_opus:
11119         {
11120           const guint8 *opus_data;
11121           guint8 *channel_mapping = NULL;
11122           guint32 rate;
11123           guint8 channels;
11124           guint8 channel_mapping_family;
11125           guint8 stream_count;
11126           guint8 coupled_count;
11127           guint8 i;
11128
11129           opus_data = stsd_entry_data;
11130
11131           channels = GST_READ_UINT8 (opus_data + 45);
11132           rate = GST_READ_UINT32_LE (opus_data + 48);
11133           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11134           stream_count = GST_READ_UINT8 (opus_data + 55);
11135           coupled_count = GST_READ_UINT8 (opus_data + 56);
11136
11137           if (channels > 0) {
11138             channel_mapping = g_malloc (channels * sizeof (guint8));
11139             for (i = 0; i < channels; i++)
11140               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11141           }
11142
11143           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11144               channel_mapping_family, stream_count, coupled_count,
11145               channel_mapping);
11146           break;
11147         }
11148         default:
11149           break;
11150       }
11151
11152       if (codec) {
11153         GstStructure *s;
11154         gint bitrate = 0;
11155
11156         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11157             GST_TAG_AUDIO_CODEC, codec, NULL);
11158         g_free (codec);
11159         codec = NULL;
11160
11161         /* some bitrate info may have ended up in caps */
11162         s = gst_caps_get_structure (entry->caps, 0);
11163         gst_structure_get_int (s, "bitrate", &bitrate);
11164         if (bitrate > 0)
11165           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11166               GST_TAG_BITRATE, bitrate, NULL);
11167       }
11168
11169       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11170       if (!stream->protected) {
11171       } else {
11172         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11173           mp4v = NULL;
11174         }
11175       }
11176       if (stream->protected && fourcc == FOURCC_mp4a) {
11177         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11178           mp4a = NULL;
11179         }
11180       } else {
11181         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11182           mp4a = NULL;
11183         }
11184       }
11185
11186       wave = NULL;
11187       esds = NULL;
11188       if (mp4a) {
11189         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11190         if (wave)
11191           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11192         if (!esds)
11193           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11194       }
11195
11196
11197       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11198          16 bits is a byte-swapped wave-style codec identifier,
11199          and we can find a WAVE header internally to a 'wave' atom here.
11200          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11201          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11202          is big-endian).
11203        */
11204       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11205         if (len < offset + 20) {
11206           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11207         } else {
11208           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11209           const guint8 *data = stsd_entry_data + offset + 16;
11210           GNode *wavenode;
11211           GNode *waveheadernode;
11212
11213           wavenode = g_node_new ((guint8 *) data);
11214           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11215             const guint8 *waveheader;
11216             guint32 headerlen;
11217
11218             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11219             if (waveheadernode) {
11220               waveheader = (const guint8 *) waveheadernode->data;
11221               headerlen = QT_UINT32 (waveheader);
11222
11223               if (headerlen > 8) {
11224                 gst_riff_strf_auds *header = NULL;
11225                 GstBuffer *headerbuf;
11226                 GstBuffer *extra;
11227
11228                 waveheader += 8;
11229                 headerlen -= 8;
11230
11231                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11232                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11233
11234                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11235                         headerbuf, &header, &extra)) {
11236                   gst_caps_unref (entry->caps);
11237                   /* FIXME: Need to do something with the channel reorder map */
11238                   entry->caps =
11239                       gst_riff_create_audio_caps (header->format, NULL, header,
11240                       extra, NULL, NULL, NULL);
11241
11242                   if (extra)
11243                     gst_buffer_unref (extra);
11244                   g_free (header);
11245                 }
11246               }
11247             } else
11248               GST_DEBUG ("Didn't find waveheadernode for this codec");
11249           }
11250           g_node_destroy (wavenode);
11251         }
11252       } else if (esds) {
11253         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11254             stream->stream_tags);
11255       } else {
11256         switch (fourcc) {
11257 #if 0
11258             /* FIXME: what is in the chunk? */
11259           case FOURCC_QDMC:
11260           {
11261             gint len = QT_UINT32 (stsd_data);
11262
11263             /* seems to be always = 116 = 0x74 */
11264             break;
11265           }
11266 #endif
11267           case FOURCC_QDM2:
11268           {
11269             gint len = QT_UINT32 (stsd_entry_data);
11270
11271             if (len > 0x3C) {
11272               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11273
11274               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11275               gst_caps_set_simple (entry->caps,
11276                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11277               gst_buffer_unref (buf);
11278             }
11279             gst_caps_set_simple (entry->caps,
11280                 "samplesize", G_TYPE_INT, samplesize, NULL);
11281             break;
11282           }
11283           case FOURCC_alac:
11284           {
11285             GNode *alac, *wave = NULL;
11286
11287             /* apparently, m4a has this atom appended directly in the stsd entry,
11288              * while mov has it in a wave atom */
11289             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11290             if (alac) {
11291               /* alac now refers to stsd entry atom */
11292               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11293               if (wave)
11294                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11295               else
11296                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11297             }
11298             if (alac) {
11299               const guint8 *alac_data = alac->data;
11300               gint len = QT_UINT32 (alac->data);
11301               GstBuffer *buf;
11302
11303               if (len < 36) {
11304                 GST_DEBUG_OBJECT (qtdemux,
11305                     "discarding alac atom with unexpected len %d", len);
11306               } else {
11307                 /* codec-data contains alac atom size and prefix,
11308                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11309                 buf = gst_buffer_new_and_alloc (len);
11310                 gst_buffer_fill (buf, 0, alac->data, len);
11311                 gst_caps_set_simple (entry->caps,
11312                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11313                 gst_buffer_unref (buf);
11314
11315                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11316                 entry->n_channels = QT_UINT8 (alac_data + 21);
11317                 entry->rate = QT_UINT32 (alac_data + 32);
11318               }
11319             }
11320             gst_caps_set_simple (entry->caps,
11321                 "samplesize", G_TYPE_INT, samplesize, NULL);
11322             break;
11323           }
11324           case FOURCC_fLaC:
11325           {
11326             /* The codingname of the sample entry is 'fLaC' */
11327             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11328
11329             if (flac) {
11330               /* The 'dfLa' box is added to the sample entry to convey
11331                  initializing information for the decoder. */
11332               const GNode *dfla =
11333                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11334
11335               if (dfla) {
11336                 const guint32 len = QT_UINT32 (dfla->data);
11337
11338                 /* Must contain at least dfLa box header (12),
11339                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11340                 if (len < 50) {
11341                   GST_DEBUG_OBJECT (qtdemux,
11342                       "discarding dfla atom with unexpected len %d", len);
11343                 } else {
11344                   /* skip dfLa header to get the METADATA_BLOCKs */
11345                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11346                   const guint32 metadata_blocks_len = len - 12;
11347
11348                   gchar *stream_marker = g_strdup ("fLaC");
11349                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11350                       strlen (stream_marker));
11351
11352                   guint32 index = 0;
11353                   guint32 remainder = 0;
11354                   guint32 block_size = 0;
11355                   gboolean is_last = FALSE;
11356
11357                   GValue array = G_VALUE_INIT;
11358                   GValue value = G_VALUE_INIT;
11359
11360                   g_value_init (&array, GST_TYPE_ARRAY);
11361                   g_value_init (&value, GST_TYPE_BUFFER);
11362
11363                   gst_value_set_buffer (&value, block);
11364                   gst_value_array_append_value (&array, &value);
11365                   g_value_reset (&value);
11366
11367                   gst_buffer_unref (block);
11368
11369                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11370                    * of data, and we haven't already finished parsing */
11371                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11372                     remainder = metadata_blocks_len - index;
11373
11374                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11375                     block_size = 4 +
11376                         (metadata_blocks[index + 1] << 16) +
11377                         (metadata_blocks[index + 2] << 8) +
11378                         metadata_blocks[index + 3];
11379
11380                     /* be careful not to read off end of box */
11381                     if (block_size > remainder) {
11382                       break;
11383                     }
11384
11385                     is_last = metadata_blocks[index] >> 7;
11386
11387                     block = gst_buffer_new_and_alloc (block_size);
11388
11389                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11390                         block_size);
11391
11392                     gst_value_set_buffer (&value, block);
11393                     gst_value_array_append_value (&array, &value);
11394                     g_value_reset (&value);
11395
11396                     gst_buffer_unref (block);
11397
11398                     index += block_size;
11399                   }
11400
11401                   /* only append the metadata if we successfully read all of it */
11402                   if (is_last) {
11403                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11404                             (stream)->caps, 0), "streamheader", &array);
11405                   } else {
11406                     GST_WARNING_OBJECT (qtdemux,
11407                         "discarding all METADATA_BLOCKs due to invalid "
11408                         "block_size %d at idx %d, rem %d", block_size, index,
11409                         remainder);
11410                   }
11411
11412                   g_value_unset (&value);
11413                   g_value_unset (&array);
11414
11415                   /* The sample rate obtained from the stsd may not be accurate
11416                    * since it cannot represent rates greater than 65535Hz, so
11417                    * override that value with the sample rate from the
11418                    * METADATA_BLOCK_STREAMINFO block */
11419                   CUR_STREAM (stream)->rate =
11420                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11421                 }
11422               }
11423             }
11424             break;
11425           }
11426           case FOURCC_sawb:
11427             /* Fallthrough! */
11428             amrwb = TRUE;
11429           case FOURCC_samr:
11430           {
11431             gint len = QT_UINT32 (stsd_entry_data);
11432
11433             if (len > 0x24) {
11434               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11435               guint bitrate;
11436
11437               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11438
11439               /* If we have enough data, let's try to get the 'damr' atom. See
11440                * the 3GPP container spec (26.244) for more details. */
11441               if ((len - 0x34) > 8 &&
11442                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11443                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11444                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11445               }
11446
11447               gst_caps_set_simple (entry->caps,
11448                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11449               gst_buffer_unref (buf);
11450             }
11451             break;
11452           }
11453           case FOURCC_mp4a:
11454           {
11455             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11456             gint len = QT_UINT32 (stsd_entry_data);
11457
11458             if (len >= 34) {
11459               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11460
11461               if (sound_version == 1) {
11462                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11463                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11464                 guint8 codec_data[2];
11465                 GstBuffer *buf;
11466                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11467
11468                 gint sample_rate_index =
11469                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11470
11471                 /* build AAC codec data */
11472                 codec_data[0] = profile << 3;
11473                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11474                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11475                 codec_data[1] |= (channels & 0xF) << 3;
11476
11477                 buf = gst_buffer_new_and_alloc (2);
11478                 gst_buffer_fill (buf, 0, codec_data, 2);
11479                 gst_caps_set_simple (entry->caps,
11480                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11481                 gst_buffer_unref (buf);
11482               }
11483             }
11484             break;
11485           }
11486           case FOURCC_lpcm:
11487             /* Fully handled elsewhere */
11488             break;
11489           default:
11490             GST_INFO_OBJECT (qtdemux,
11491                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11492             break;
11493         }
11494       }
11495       GST_INFO_OBJECT (qtdemux,
11496           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11497           GST_FOURCC_ARGS (fourcc), entry->caps);
11498
11499     } else if (stream->subtype == FOURCC_strm) {
11500       if (fourcc == FOURCC_rtsp) {
11501         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11502       } else {
11503         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11504             GST_FOURCC_ARGS (fourcc));
11505         goto unknown_stream;
11506       }
11507       entry->sampled = TRUE;
11508     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11509         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11510
11511       entry->sampled = TRUE;
11512       entry->sparse = TRUE;
11513
11514       entry->caps =
11515           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11516           &codec);
11517       if (codec) {
11518         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11519             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11520         g_free (codec);
11521         codec = NULL;
11522       }
11523
11524       /* hunt for sort-of codec data */
11525       switch (fourcc) {
11526         case FOURCC_mp4s:
11527         {
11528           GNode *mp4s = NULL;
11529           GNode *esds = NULL;
11530
11531           /* look for palette in a stsd->mp4s->esds sub-atom */
11532           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11533           if (mp4s)
11534             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11535           if (esds == NULL) {
11536             /* Invalid STSD */
11537             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11538             break;
11539           }
11540
11541           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11542               stream->stream_tags);
11543           break;
11544         }
11545         default:
11546           GST_INFO_OBJECT (qtdemux,
11547               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11548           break;
11549       }
11550       GST_INFO_OBJECT (qtdemux,
11551           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11552           GST_FOURCC_ARGS (fourcc), entry->caps);
11553     } else {
11554       /* everything in 1 sample */
11555       entry->sampled = TRUE;
11556
11557       entry->caps =
11558           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11559           &codec);
11560
11561       if (entry->caps == NULL)
11562         goto unknown_stream;
11563
11564       if (codec) {
11565         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11566             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11567         g_free (codec);
11568         codec = NULL;
11569       }
11570     }
11571
11572     /* promote to sampled format */
11573     if (entry->fourcc == FOURCC_samr) {
11574       /* force mono 8000 Hz for AMR */
11575       entry->sampled = TRUE;
11576       entry->n_channels = 1;
11577       entry->rate = 8000;
11578     } else if (entry->fourcc == FOURCC_sawb) {
11579       /* force mono 16000 Hz for AMR-WB */
11580       entry->sampled = TRUE;
11581       entry->n_channels = 1;
11582       entry->rate = 16000;
11583     } else if (entry->fourcc == FOURCC_mp4a) {
11584       entry->sampled = TRUE;
11585     }
11586
11587
11588     stsd_entry_data += len;
11589     remaining_stsd_len -= len;
11590
11591   }
11592
11593   /* collect sample information */
11594   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11595     goto samples_failed;
11596
11597   if (qtdemux->fragmented) {
11598     guint64 offset;
11599
11600     /* need all moov samples as basis; probably not many if any at all */
11601     /* prevent moof parsing taking of at this time */
11602     offset = qtdemux->moof_offset;
11603     qtdemux->moof_offset = 0;
11604     if (stream->n_samples &&
11605         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11606       qtdemux->moof_offset = offset;
11607       goto samples_failed;
11608     }
11609     qtdemux->moof_offset = 0;
11610     /* movie duration more reliable in this case (e.g. mehd) */
11611     if (qtdemux->segment.duration &&
11612         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11613       stream->duration =
11614           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11615   }
11616
11617   /* configure segments */
11618   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11619     goto segments_failed;
11620
11621   /* add some language tag, if useful */
11622   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11623       strcmp (stream->lang_id, "und")) {
11624     const gchar *lang_code;
11625
11626     /* convert ISO 639-2 code to ISO 639-1 */
11627     lang_code = gst_tag_get_language_code (stream->lang_id);
11628     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11629         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11630   }
11631
11632   /* Check for UDTA tags */
11633   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11634     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11635   }
11636
11637   /* now we are ready to add the stream */
11638   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11639     goto too_many_streams;
11640
11641   if (!qtdemux->got_moov) {
11642     qtdemux->streams[qtdemux->n_streams] = stream;
11643     qtdemux->n_streams++;
11644     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11645   }
11646
11647   return TRUE;
11648
11649 /* ERRORS */
11650 skip_track:
11651   {
11652     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11653     if (new_stream)
11654       gst_qtdemux_stream_free (qtdemux, stream);
11655     return TRUE;
11656   }
11657 corrupt_file:
11658   {
11659     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11660         (_("This file is corrupt and cannot be played.")), (NULL));
11661     if (new_stream)
11662       gst_qtdemux_stream_free (qtdemux, stream);
11663     return FALSE;
11664   }
11665 error_encrypted:
11666   {
11667     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11668     if (new_stream)
11669       gst_qtdemux_stream_free (qtdemux, stream);
11670     return FALSE;
11671   }
11672 samples_failed:
11673 segments_failed:
11674   {
11675     /* we posted an error already */
11676     /* free stbl sub-atoms */
11677     gst_qtdemux_stbl_free (stream);
11678     if (new_stream)
11679       gst_qtdemux_stream_free (qtdemux, stream);
11680     return FALSE;
11681   }
11682 existing_stream:
11683   {
11684     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11685         track_id);
11686     if (new_stream)
11687       gst_qtdemux_stream_free (qtdemux, stream);
11688     return TRUE;
11689   }
11690 unknown_stream:
11691   {
11692     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11693         GST_FOURCC_ARGS (stream->subtype));
11694     if (new_stream)
11695       gst_qtdemux_stream_free (qtdemux, stream);
11696     return TRUE;
11697   }
11698 too_many_streams:
11699   {
11700     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11701         (_("This file contains too many streams. Only playing first %d"),
11702             GST_QTDEMUX_MAX_STREAMS), (NULL));
11703     return TRUE;
11704   }
11705 }
11706
11707 /* If we can estimate the overall bitrate, and don't have information about the
11708  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11709  * the overall bitrate minus the sum of the bitrates of all other streams. This
11710  * should be useful for the common case where we have one audio and one video
11711  * stream and can estimate the bitrate of one, but not the other. */
11712 static void
11713 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11714 {
11715   QtDemuxStream *stream = NULL;
11716   gint64 size, sys_bitrate, sum_bitrate = 0;
11717   GstClockTime duration;
11718   gint i;
11719   guint bitrate;
11720
11721   if (qtdemux->fragmented)
11722     return;
11723
11724   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11725
11726   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11727       || size <= 0) {
11728     GST_DEBUG_OBJECT (qtdemux,
11729         "Size in bytes of the stream not known - bailing");
11730     return;
11731   }
11732
11733   /* Subtract the header size */
11734   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11735       size, qtdemux->header_size);
11736
11737   if (size < qtdemux->header_size)
11738     return;
11739
11740   size = size - qtdemux->header_size;
11741
11742   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11743     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11744     return;
11745   }
11746
11747   for (i = 0; i < qtdemux->n_streams; i++) {
11748     switch (qtdemux->streams[i]->subtype) {
11749       case FOURCC_soun:
11750       case FOURCC_vide:
11751         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11752             CUR_STREAM (qtdemux->streams[i])->caps);
11753         /* retrieve bitrate, prefer avg then max */
11754         bitrate = 0;
11755         if (qtdemux->streams[i]->stream_tags) {
11756           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11757                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
11758             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11759           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11760                   GST_TAG_NOMINAL_BITRATE, &bitrate))
11761             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11762           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11763                   GST_TAG_BITRATE, &bitrate))
11764             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11765         }
11766         if (bitrate)
11767           sum_bitrate += bitrate;
11768         else {
11769           if (stream) {
11770             GST_DEBUG_OBJECT (qtdemux,
11771                 ">1 stream with unknown bitrate - bailing");
11772             return;
11773           } else
11774             stream = qtdemux->streams[i];
11775         }
11776
11777       default:
11778         /* For other subtypes, we assume no significant impact on bitrate */
11779         break;
11780     }
11781   }
11782
11783   if (!stream) {
11784     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11785     return;
11786   }
11787
11788   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11789
11790   if (sys_bitrate < sum_bitrate) {
11791     /* This can happen, since sum_bitrate might be derived from maximum
11792      * bitrates and not average bitrates */
11793     GST_DEBUG_OBJECT (qtdemux,
11794         "System bitrate less than sum bitrate - bailing");
11795     return;
11796   }
11797
11798   bitrate = sys_bitrate - sum_bitrate;
11799   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11800       ", Stream bitrate = %u", sys_bitrate, bitrate);
11801
11802   if (!stream->stream_tags)
11803     stream->stream_tags = gst_tag_list_new_empty ();
11804   else
11805     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11806
11807   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11808       GST_TAG_BITRATE, bitrate, NULL);
11809 }
11810
11811 static GstFlowReturn
11812 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11813 {
11814   gint i;
11815   GstFlowReturn ret = GST_FLOW_OK;
11816
11817   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11818
11819   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11820     QtDemuxStream *stream = qtdemux->streams[i];
11821     guint32 sample_num = 0;
11822
11823     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11824         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11825
11826     if (qtdemux->fragmented) {
11827       /* need all moov samples first */
11828       GST_OBJECT_LOCK (qtdemux);
11829       while (stream->n_samples == 0)
11830         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11831           break;
11832       GST_OBJECT_UNLOCK (qtdemux);
11833     } else {
11834       /* discard any stray moof */
11835       qtdemux->moof_offset = 0;
11836     }
11837
11838     /* prepare braking */
11839     if (ret != GST_FLOW_ERROR)
11840       ret = GST_FLOW_OK;
11841
11842     /* in pull mode, we should have parsed some sample info by now;
11843      * and quite some code will not handle no samples.
11844      * in push mode, we'll just have to deal with it */
11845     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11846       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11847       gst_qtdemux_remove_stream (qtdemux, i);
11848       i--;
11849       continue;
11850     }
11851
11852     /* parse the initial sample for use in setting the frame rate cap */
11853     while (sample_num == 0 && sample_num < stream->n_samples) {
11854       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11855         break;
11856       ++sample_num;
11857     }
11858     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11859       stream->first_duration = stream->samples[0].duration;
11860       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11861           stream->track_id, stream->first_duration);
11862     }
11863   }
11864
11865   return ret;
11866 }
11867
11868 static GstFlowReturn
11869 qtdemux_expose_streams (GstQTDemux * qtdemux)
11870 {
11871   gint i;
11872   GSList *oldpads = NULL;
11873   GSList *iter;
11874
11875   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11876
11877   for (i = 0; i < qtdemux->n_streams; i++) {
11878     QtDemuxStream *stream = qtdemux->streams[i];
11879     GstPad *oldpad = stream->pad;
11880     GstTagList *list;
11881
11882     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11883         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11884
11885     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11886         stream->track_id == qtdemux->chapters_track_id) {
11887       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11888          so that it doesn't look like a subtitle track */
11889       gst_qtdemux_remove_stream (qtdemux, i);
11890       i--;
11891       continue;
11892     }
11893
11894     /* now we have all info and can expose */
11895     list = stream->stream_tags;
11896     stream->stream_tags = NULL;
11897     if (oldpad)
11898       oldpads = g_slist_prepend (oldpads, oldpad);
11899     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11900       return GST_FLOW_ERROR;
11901   }
11902
11903   gst_qtdemux_guess_bitrate (qtdemux);
11904
11905   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11906
11907   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11908     GstPad *oldpad = iter->data;
11909     GstEvent *event;
11910
11911     event = gst_event_new_eos ();
11912     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
11913       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11914
11915     gst_pad_push_event (oldpad, event);
11916     gst_pad_set_active (oldpad, FALSE);
11917     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11918     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11919     gst_object_unref (oldpad);
11920   }
11921
11922   /* check if we should post a redirect in case there is a single trak
11923    * and it is a redirecting trak */
11924   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11925     GstMessage *m;
11926
11927     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11928         "an external content");
11929     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11930         gst_structure_new ("redirect",
11931             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11932             NULL));
11933     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11934     qtdemux->posted_redirect = TRUE;
11935   }
11936
11937   for (i = 0; i < qtdemux->n_streams; i++) {
11938     QtDemuxStream *stream = qtdemux->streams[i];
11939
11940     qtdemux_do_allocation (qtdemux, stream);
11941   }
11942
11943   qtdemux->exposed = TRUE;
11944   return GST_FLOW_OK;
11945 }
11946
11947 /* check if major or compatible brand is 3GP */
11948 static inline gboolean
11949 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11950 {
11951   if (major) {
11952     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11953         FOURCC_3g__);
11954   } else if (qtdemux->comp_brands != NULL) {
11955     GstMapInfo map;
11956     guint8 *data;
11957     gsize size;
11958     gboolean res = FALSE;
11959
11960     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11961     data = map.data;
11962     size = map.size;
11963     while (size >= 4) {
11964       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11965           FOURCC_3g__);
11966       data += 4;
11967       size -= 4;
11968     }
11969     gst_buffer_unmap (qtdemux->comp_brands, &map);
11970     return res;
11971   } else {
11972     return FALSE;
11973   }
11974 }
11975
11976 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11977 static inline gboolean
11978 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11979 {
11980   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11981       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11982       || fourcc == FOURCC_albm;
11983 }
11984
11985 static void
11986 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11987     const char *tag, const char *dummy, GNode * node)
11988 {
11989   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11990   int offset;
11991   char *name;
11992   gchar *data;
11993   gdouble longitude, latitude, altitude;
11994   gint len;
11995
11996   len = QT_UINT32 (node->data);
11997   if (len <= 14)
11998     goto short_read;
11999
12000   data = node->data;
12001   offset = 14;
12002
12003   /* TODO: language code skipped */
12004
12005   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12006
12007   if (!name) {
12008     /* do not alarm in trivial case, but bail out otherwise */
12009     if (*(data + offset) != 0) {
12010       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12011           "giving up", tag);
12012     }
12013   } else {
12014     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12015         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12016     offset += strlen (name);
12017     g_free (name);
12018   }
12019
12020   if (len < offset + 2 + 4 + 4 + 4)
12021     goto short_read;
12022
12023   /* +1 +1 = skip null-terminator and location role byte */
12024   offset += 1 + 1;
12025   /* table in spec says unsigned, semantics say negative has meaning ... */
12026   longitude = QT_SFP32 (data + offset);
12027
12028   offset += 4;
12029   latitude = QT_SFP32 (data + offset);
12030
12031   offset += 4;
12032   altitude = QT_SFP32 (data + offset);
12033
12034   /* one invalid means all are invalid */
12035   if (longitude >= -180.0 && longitude <= 180.0 &&
12036       latitude >= -90.0 && latitude <= 90.0) {
12037     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12038         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12039         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12040         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12041   }
12042
12043   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12044
12045   return;
12046
12047   /* ERRORS */
12048 short_read:
12049   {
12050     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12051     return;
12052   }
12053 }
12054
12055
12056 static void
12057 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12058     const char *tag, const char *dummy, GNode * node)
12059 {
12060   guint16 y;
12061   GDate *date;
12062   gint len;
12063
12064   len = QT_UINT32 (node->data);
12065   if (len < 14)
12066     return;
12067
12068   y = QT_UINT16 ((guint8 *) node->data + 12);
12069   if (y == 0) {
12070     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12071     return;
12072   }
12073   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12074
12075   date = g_date_new_dmy (1, 1, y);
12076   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12077   g_date_free (date);
12078 }
12079
12080 static void
12081 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12082     const char *tag, const char *dummy, GNode * node)
12083 {
12084   int offset;
12085   char *tag_str = NULL;
12086   guint8 *entity;
12087   guint16 table;
12088   gint len;
12089
12090   len = QT_UINT32 (node->data);
12091   if (len <= 20)
12092     goto short_read;
12093
12094   offset = 12;
12095   entity = (guint8 *) node->data + offset;
12096   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12097     GST_DEBUG_OBJECT (qtdemux,
12098         "classification info: %c%c%c%c invalid classification entity",
12099         entity[0], entity[1], entity[2], entity[3]);
12100     return;
12101   }
12102
12103   offset += 4;
12104   table = QT_UINT16 ((guint8 *) node->data + offset);
12105
12106   /* Language code skipped */
12107
12108   offset += 4;
12109
12110   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12111    * XXXX: classification entity, fixed length 4 chars.
12112    * Y[YYYY]: classification table, max 5 chars.
12113    */
12114   tag_str = g_strdup_printf ("----://%u/%s",
12115       table, (char *) node->data + offset);
12116
12117   /* memcpy To be sure we're preserving byte order */
12118   memcpy (tag_str, entity, 4);
12119   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12120
12121   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12122
12123   g_free (tag_str);
12124
12125   return;
12126
12127   /* ERRORS */
12128 short_read:
12129   {
12130     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12131     return;
12132   }
12133 }
12134
12135 static gboolean
12136 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12137     const char *tag, const char *dummy, GNode * node)
12138 {
12139   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12140   GNode *data;
12141   char *s;
12142   int len;
12143   guint32 type;
12144   int offset;
12145   gboolean ret = TRUE;
12146   const gchar *charset = NULL;
12147
12148   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12149   if (data) {
12150     len = QT_UINT32 (data->data);
12151     type = QT_UINT32 ((guint8 *) data->data + 8);
12152     if (type == 0x00000001 && len > 16) {
12153       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12154           env_vars);
12155       if (s) {
12156         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12157         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12158         g_free (s);
12159       } else {
12160         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12161       }
12162     }
12163   } else {
12164     len = QT_UINT32 (node->data);
12165     type = QT_UINT32 ((guint8 *) node->data + 4);
12166     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12167       gint str_len;
12168       gint lang_code;
12169
12170       /* Type starts with the (C) symbol, so the next data is a list
12171        * of (string size(16), language code(16), string) */
12172
12173       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12174       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12175
12176       /* the string + fourcc + size + 2 16bit fields,
12177        * means that there are more tags in this atom */
12178       if (len > str_len + 8 + 4) {
12179         /* TODO how to represent the same tag in different languages? */
12180         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12181             "text alternatives, reading only first one");
12182       }
12183
12184       offset = 12;
12185       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12186       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12187
12188       if (lang_code < 0x800) {  /* MAC encoded string */
12189         charset = "mac";
12190       }
12191     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12192             QT_FOURCC ((guint8 *) node->data + 4))) {
12193       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12194
12195       /* we go for 3GP style encoding if major brands claims so,
12196        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12197       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12198           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12199               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12200         offset = 14;
12201         /* 16-bit Language code is ignored here as well */
12202         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12203       } else {
12204         goto normal;
12205       }
12206     } else {
12207     normal:
12208       offset = 8;
12209       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12210       ret = FALSE;              /* may have to fallback */
12211     }
12212     if (charset) {
12213       GError *err = NULL;
12214
12215       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12216           charset, NULL, NULL, &err);
12217       if (err) {
12218         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12219             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12220             err->message);
12221         g_error_free (err);
12222       }
12223     } else {
12224       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12225           len - offset, env_vars);
12226     }
12227     if (s) {
12228       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12229       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12230       g_free (s);
12231       ret = TRUE;
12232     } else {
12233       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12234     }
12235   }
12236   return ret;
12237 }
12238
12239 static void
12240 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12241     const char *tag, const char *dummy, GNode * node)
12242 {
12243   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12244 }
12245
12246 static void
12247 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12248     const char *tag, const char *dummy, GNode * node)
12249 {
12250   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12251   guint8 *data;
12252   char *s, *t, *k = NULL;
12253   int len;
12254   int offset;
12255   int count;
12256
12257   /* first try normal string tag if major brand not 3GP */
12258   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12259     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12260       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12261        * let's try it 3gpp way after minor safety check */
12262       data = node->data;
12263       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12264         return;
12265     } else
12266       return;
12267   }
12268
12269   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12270
12271   data = node->data;
12272
12273   len = QT_UINT32 (data);
12274   if (len < 15)
12275     goto short_read;
12276
12277   count = QT_UINT8 (data + 14);
12278   offset = 15;
12279   for (; count; count--) {
12280     gint slen;
12281
12282     if (offset + 1 > len)
12283       goto short_read;
12284     slen = QT_UINT8 (data + offset);
12285     offset += 1;
12286     if (offset + slen > len)
12287       goto short_read;
12288     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12289         slen, env_vars);
12290     if (s) {
12291       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12292       if (k) {
12293         t = g_strjoin (",", k, s, NULL);
12294         g_free (s);
12295         g_free (k);
12296         k = t;
12297       } else {
12298         k = s;
12299       }
12300     } else {
12301       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12302     }
12303     offset += slen;
12304   }
12305
12306 done:
12307   if (k) {
12308     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12309     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12310   }
12311   g_free (k);
12312
12313   return;
12314
12315   /* ERRORS */
12316 short_read:
12317   {
12318     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12319     goto done;
12320   }
12321 }
12322
12323 static void
12324 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12325     const char *tag1, const char *tag2, GNode * node)
12326 {
12327   GNode *data;
12328   int len;
12329   int type;
12330   int n1, n2;
12331
12332   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12333   if (data) {
12334     len = QT_UINT32 (data->data);
12335     type = QT_UINT32 ((guint8 *) data->data + 8);
12336     if (type == 0x00000000 && len >= 22) {
12337       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12338       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12339       if (n1 > 0) {
12340         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12341         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12342       }
12343       if (n2 > 0) {
12344         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12345         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12346       }
12347     }
12348   }
12349 }
12350
12351 static void
12352 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12353     const char *tag1, const char *dummy, GNode * node)
12354 {
12355   GNode *data;
12356   int len;
12357   int type;
12358   int n1;
12359
12360   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12361   if (data) {
12362     len = QT_UINT32 (data->data);
12363     type = QT_UINT32 ((guint8 *) data->data + 8);
12364     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12365     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12366     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12367       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12368       if (n1) {
12369         /* do not add bpm=0 */
12370         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12371         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12372             NULL);
12373       }
12374     }
12375   }
12376 }
12377
12378 static void
12379 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12380     const char *tag1, const char *dummy, GNode * node)
12381 {
12382   GNode *data;
12383   int len;
12384   int type;
12385   guint32 num;
12386
12387   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12388   if (data) {
12389     len = QT_UINT32 (data->data);
12390     type = QT_UINT32 ((guint8 *) data->data + 8);
12391     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12392     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12393     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12394       num = QT_UINT32 ((guint8 *) data->data + 16);
12395       if (num) {
12396         /* do not add num=0 */
12397         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12398         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12399       }
12400     }
12401   }
12402 }
12403
12404 static void
12405 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12406     const char *tag1, const char *dummy, GNode * node)
12407 {
12408   GNode *data;
12409   int len;
12410   int type;
12411   GstSample *sample;
12412
12413   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12414   if (data) {
12415     len = QT_UINT32 (data->data);
12416     type = QT_UINT32 ((guint8 *) data->data + 8);
12417     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12418     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12419       GstTagImageType image_type;
12420
12421       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12422         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12423       else
12424         image_type = GST_TAG_IMAGE_TYPE_NONE;
12425
12426       if ((sample =
12427               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12428                   len - 16, image_type))) {
12429         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12430         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12431         gst_sample_unref (sample);
12432       }
12433     }
12434   }
12435 }
12436
12437 static void
12438 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12439     const char *tag, const char *dummy, GNode * node)
12440 {
12441   GNode *data;
12442   char *s;
12443   int len;
12444   int type;
12445
12446   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12447   if (data) {
12448     len = QT_UINT32 (data->data);
12449     type = QT_UINT32 ((guint8 *) data->data + 8);
12450     if (type == 0x00000001 && len > 16) {
12451       guint y, m = 1, d = 1;
12452       gint ret;
12453
12454       s = g_strndup ((char *) data->data + 16, len - 16);
12455       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12456       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12457       if (ret >= 1 && y > 1500 && y < 3000) {
12458         GDate *date;
12459
12460         date = g_date_new_dmy (d, m, y);
12461         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12462         g_date_free (date);
12463       } else {
12464         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12465       }
12466       g_free (s);
12467     }
12468   }
12469 }
12470
12471 static void
12472 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12473     const char *tag, const char *dummy, GNode * node)
12474 {
12475   GNode *data;
12476
12477   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12478
12479   /* re-route to normal string tag if major brand says so
12480    * or no data atom and compatible brand suggests so */
12481   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12482       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12483     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12484     return;
12485   }
12486
12487   if (data) {
12488     guint len, type, n;
12489
12490     len = QT_UINT32 (data->data);
12491     type = QT_UINT32 ((guint8 *) data->data + 8);
12492     if (type == 0x00000000 && len >= 18) {
12493       n = QT_UINT16 ((guint8 *) data->data + 16);
12494       if (n > 0) {
12495         const gchar *genre;
12496
12497         genre = gst_tag_id3_genre_get (n - 1);
12498         if (genre != NULL) {
12499           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12500           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12501         }
12502       }
12503     }
12504   }
12505 }
12506
12507 static void
12508 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12509     const gchar * tag, guint8 * data, guint32 datasize)
12510 {
12511   gdouble value;
12512   gchar *datacopy;
12513
12514   /* make a copy to have \0 at the end */
12515   datacopy = g_strndup ((gchar *) data, datasize);
12516
12517   /* convert the str to double */
12518   if (sscanf (datacopy, "%lf", &value) == 1) {
12519     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12520     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12521   } else {
12522     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12523         datacopy);
12524   }
12525   g_free (datacopy);
12526 }
12527
12528
12529 static void
12530 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12531     const char *tag, const char *tag_bis, GNode * node)
12532 {
12533   GNode *mean;
12534   GNode *name;
12535   GNode *data;
12536   guint32 meansize;
12537   guint32 namesize;
12538   guint32 datatype;
12539   guint32 datasize;
12540   const gchar *meanstr;
12541   const gchar *namestr;
12542
12543   /* checking the whole ---- atom size for consistency */
12544   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12545     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12546     return;
12547   }
12548
12549   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12550   if (!mean) {
12551     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12552     return;
12553   }
12554
12555   meansize = QT_UINT32 (mean->data);
12556   if (meansize <= 12) {
12557     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12558     return;
12559   }
12560   meanstr = ((gchar *) mean->data) + 12;
12561   meansize -= 12;
12562
12563   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12564   if (!name) {
12565     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12566     return;
12567   }
12568
12569   namesize = QT_UINT32 (name->data);
12570   if (namesize <= 12) {
12571     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12572     return;
12573   }
12574   namestr = ((gchar *) name->data) + 12;
12575   namesize -= 12;
12576
12577   /*
12578    * Data atom is:
12579    * uint32 - size
12580    * uint32 - name
12581    * uint8  - version
12582    * uint24 - data type
12583    * uint32 - all 0
12584    * rest   - the data
12585    */
12586   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12587   if (!data) {
12588     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12589     return;
12590   }
12591   datasize = QT_UINT32 (data->data);
12592   if (datasize <= 16) {
12593     GST_WARNING_OBJECT (demux, "Data atom too small");
12594     return;
12595   }
12596   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12597
12598   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12599       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12600     static const struct
12601     {
12602       const gchar name[28];
12603       const gchar tag[28];
12604     } tags[] = {
12605       {
12606       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12607       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12608       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12609       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12610       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12611       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12612       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12613       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12614     };
12615     int i;
12616
12617     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12618       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12619         switch (gst_tag_get_type (tags[i].tag)) {
12620           case G_TYPE_DOUBLE:
12621             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12622                 ((guint8 *) data->data) + 16, datasize - 16);
12623             break;
12624           case G_TYPE_STRING:
12625             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12626             break;
12627           default:
12628             /* not reached */
12629             break;
12630         }
12631         break;
12632       }
12633     }
12634     if (i == G_N_ELEMENTS (tags))
12635       goto unknown_tag;
12636   } else {
12637     goto unknown_tag;
12638   }
12639
12640   return;
12641
12642 /* errors */
12643 unknown_tag:
12644 #ifndef GST_DISABLE_GST_DEBUG
12645   {
12646     gchar *namestr_dbg;
12647     gchar *meanstr_dbg;
12648
12649     meanstr_dbg = g_strndup (meanstr, meansize);
12650     namestr_dbg = g_strndup (namestr, namesize);
12651
12652     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12653         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12654
12655     g_free (namestr_dbg);
12656     g_free (meanstr_dbg);
12657   }
12658 #endif
12659   return;
12660 }
12661
12662 static void
12663 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12664     const char *tag_bis, GNode * node)
12665 {
12666   guint8 *data;
12667   GstBuffer *buf;
12668   guint len;
12669   GstTagList *id32_taglist = NULL;
12670
12671   GST_LOG_OBJECT (demux, "parsing ID32");
12672
12673   data = node->data;
12674   len = GST_READ_UINT32_BE (data);
12675
12676   /* need at least full box and language tag */
12677   if (len < 12 + 2)
12678     return;
12679
12680   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12681   gst_buffer_fill (buf, 0, data + 14, len - 14);
12682
12683   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12684   if (id32_taglist) {
12685     GST_LOG_OBJECT (demux, "parsing ok");
12686     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12687     gst_tag_list_unref (id32_taglist);
12688   } else {
12689     GST_LOG_OBJECT (demux, "parsing failed");
12690   }
12691
12692   gst_buffer_unref (buf);
12693 }
12694
12695 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12696     const char *tag, const char *tag_bis, GNode * node);
12697
12698 /* unmapped tags
12699 FOURCC_pcst -> if media is a podcast -> bool
12700 FOURCC_cpil -> if media is part of a compilation -> bool
12701 FOURCC_pgap -> if media is part of a gapless context -> bool
12702 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12703 */
12704
12705 static const struct
12706 {
12707   guint32 fourcc;
12708   const gchar *gst_tag;
12709   const gchar *gst_tag_bis;
12710   const GstQTDemuxAddTagFunc func;
12711 } add_funcs[] = {
12712   {
12713   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12714   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12715   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12716   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12717   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12718   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12719   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12720   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12721   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12722   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12723   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12724   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12725   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12726   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12727   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12728   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12729   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12730   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12731   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12732   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12733   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12734   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12735   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12736         qtdemux_tag_add_num}, {
12737   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12738         qtdemux_tag_add_num}, {
12739   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12740   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12741   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12742   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12743   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12744   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12745   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12746   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12747   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12748   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12749   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12750   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12751   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12752   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12753   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12754   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12755   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12756   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12757         qtdemux_tag_add_classification}, {
12758   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12759   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12760   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12761
12762     /* This is a special case, some tags are stored in this
12763      * 'reverse dns naming', according to:
12764      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12765      * bug #614471
12766      */
12767   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12768     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12769   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12770 };
12771
12772 struct _GstQtDemuxTagList
12773 {
12774   GstQTDemux *demux;
12775   GstTagList *taglist;
12776 };
12777 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12778
12779 static void
12780 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12781 {
12782   gint len;
12783   guint8 *data;
12784   GstBuffer *buf;
12785   gchar *media_type;
12786   const gchar *style;
12787   GstSample *sample;
12788   GstStructure *s;
12789   guint i;
12790   guint8 ndata[4];
12791   GstQTDemux *demux = qtdemuxtaglist->demux;
12792   GstTagList *taglist = qtdemuxtaglist->taglist;
12793
12794   data = node->data;
12795   len = QT_UINT32 (data);
12796   buf = gst_buffer_new_and_alloc (len);
12797   gst_buffer_fill (buf, 0, data, len);
12798
12799   /* heuristic to determine style of tag */
12800   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12801       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12802     style = "itunes";
12803   else if (demux->major_brand == FOURCC_qt__)
12804     style = "quicktime";
12805   /* fall back to assuming iso/3gp tag style */
12806   else
12807     style = "iso";
12808
12809   /* santize the name for the caps. */
12810   for (i = 0; i < 4; i++) {
12811     guint8 d = data[4 + i];
12812     if (g_ascii_isalnum (d))
12813       ndata[i] = g_ascii_tolower (d);
12814     else
12815       ndata[i] = '_';
12816   }
12817
12818   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12819       ndata[0], ndata[1], ndata[2], ndata[3]);
12820   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12821
12822   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12823   sample = gst_sample_new (buf, NULL, NULL, s);
12824   gst_buffer_unref (buf);
12825   g_free (media_type);
12826
12827   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12828       len, s);
12829
12830   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12831       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12832
12833   gst_sample_unref (sample);
12834 }
12835
12836 static void
12837 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12838 {
12839   GNode *meta;
12840   GNode *ilst;
12841   GNode *xmp_;
12842   GNode *node;
12843   gint i;
12844   GstQtDemuxTagList demuxtaglist;
12845
12846   demuxtaglist.demux = qtdemux;
12847   demuxtaglist.taglist = taglist;
12848
12849   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12850   if (meta != NULL) {
12851     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12852     if (ilst == NULL) {
12853       GST_LOG_OBJECT (qtdemux, "no ilst");
12854       return;
12855     }
12856   } else {
12857     ilst = udta;
12858     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12859   }
12860
12861   i = 0;
12862   while (i < G_N_ELEMENTS (add_funcs)) {
12863     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12864     if (node) {
12865       gint len;
12866
12867       len = QT_UINT32 (node->data);
12868       if (len < 12) {
12869         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12870             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12871       } else {
12872         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12873             add_funcs[i].gst_tag_bis, node);
12874       }
12875       g_node_destroy (node);
12876     } else {
12877       i++;
12878     }
12879   }
12880
12881   /* parsed nodes have been removed, pass along remainder as blob */
12882   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12883       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12884
12885   /* parse up XMP_ node if existing */
12886   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12887   if (xmp_ != NULL) {
12888     GstBuffer *buf;
12889     GstTagList *xmptaglist;
12890
12891     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12892         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12893     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12894     gst_buffer_unref (buf);
12895
12896     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12897   } else {
12898     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12899   }
12900 }
12901
12902 typedef struct
12903 {
12904   GstStructure *structure;      /* helper for sort function */
12905   gchar *location;
12906   guint min_req_bitrate;
12907   guint min_req_qt_version;
12908 } GstQtReference;
12909
12910 static gint
12911 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12912 {
12913   GstQtReference *ref_a = (GstQtReference *) a;
12914   GstQtReference *ref_b = (GstQtReference *) b;
12915
12916   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12917     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12918
12919   /* known bitrates go before unknown; higher bitrates go first */
12920   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12921 }
12922
12923 /* sort the redirects and post a message for the application.
12924  */
12925 static void
12926 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12927 {
12928   GstQtReference *best;
12929   GstStructure *s;
12930   GstMessage *msg;
12931   GValue list_val = { 0, };
12932   GList *l;
12933
12934   g_assert (references != NULL);
12935
12936   references = g_list_sort (references, qtdemux_redirects_sort_func);
12937
12938   best = (GstQtReference *) references->data;
12939
12940   g_value_init (&list_val, GST_TYPE_LIST);
12941
12942   for (l = references; l != NULL; l = l->next) {
12943     GstQtReference *ref = (GstQtReference *) l->data;
12944     GValue struct_val = { 0, };
12945
12946     ref->structure = gst_structure_new ("redirect",
12947         "new-location", G_TYPE_STRING, ref->location, NULL);
12948
12949     if (ref->min_req_bitrate > 0) {
12950       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12951           ref->min_req_bitrate, NULL);
12952     }
12953
12954     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12955     g_value_set_boxed (&struct_val, ref->structure);
12956     gst_value_list_append_value (&list_val, &struct_val);
12957     g_value_unset (&struct_val);
12958     /* don't free anything here yet, since we need best->structure below */
12959   }
12960
12961   g_assert (best != NULL);
12962   s = gst_structure_copy (best->structure);
12963
12964   if (g_list_length (references) > 1) {
12965     gst_structure_set_value (s, "locations", &list_val);
12966   }
12967
12968   g_value_unset (&list_val);
12969
12970   for (l = references; l != NULL; l = l->next) {
12971     GstQtReference *ref = (GstQtReference *) l->data;
12972
12973     gst_structure_free (ref->structure);
12974     g_free (ref->location);
12975     g_free (ref);
12976   }
12977   g_list_free (references);
12978
12979   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12980   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12981   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12982   qtdemux->posted_redirect = TRUE;
12983 }
12984
12985 /* look for redirect nodes, collect all redirect information and
12986  * process it.
12987  */
12988 static gboolean
12989 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12990 {
12991   GNode *rmra, *rmda, *rdrf;
12992
12993   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12994   if (rmra) {
12995     GList *redirects = NULL;
12996
12997     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12998     while (rmda) {
12999       GstQtReference ref = { NULL, NULL, 0, 0 };
13000       GNode *rmdr, *rmvc;
13001
13002       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13003         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13004         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13005             ref.min_req_bitrate);
13006       }
13007
13008       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13009         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13010         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13011
13012 #ifndef GST_DISABLE_GST_DEBUG
13013         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13014 #endif
13015         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13016
13017         GST_LOG_OBJECT (qtdemux,
13018             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13019             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13020             bitmask, check_type);
13021         if (package == FOURCC_qtim && check_type == 0) {
13022           ref.min_req_qt_version = version;
13023         }
13024       }
13025
13026       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13027       if (rdrf) {
13028         guint32 ref_type;
13029         guint8 *ref_data;
13030         guint ref_len;
13031
13032         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13033         if (ref_len > 20) {
13034           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13035           ref_data = (guint8 *) rdrf->data + 20;
13036           if (ref_type == FOURCC_alis) {
13037             guint record_len, record_version, fn_len;
13038
13039             if (ref_len > 70) {
13040               /* MacOSX alias record, google for alias-layout.txt */
13041               record_len = QT_UINT16 (ref_data + 4);
13042               record_version = QT_UINT16 (ref_data + 4 + 2);
13043               fn_len = QT_UINT8 (ref_data + 50);
13044               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13045                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13046               }
13047             } else {
13048               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13049                   ref_len);
13050             }
13051           } else if (ref_type == FOURCC_url_) {
13052             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13053           } else {
13054             GST_DEBUG_OBJECT (qtdemux,
13055                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13056                 GST_FOURCC_ARGS (ref_type));
13057           }
13058           if (ref.location != NULL) {
13059             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13060             redirects =
13061                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13062           } else {
13063             GST_WARNING_OBJECT (qtdemux,
13064                 "Failed to extract redirect location from rdrf atom");
13065           }
13066         } else {
13067           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13068         }
13069       }
13070
13071       /* look for others */
13072       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13073     }
13074
13075     if (redirects != NULL) {
13076       qtdemux_process_redirects (qtdemux, redirects);
13077     }
13078   }
13079   return TRUE;
13080 }
13081
13082 static GstTagList *
13083 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13084 {
13085   const gchar *fmt;
13086
13087   if (tags == NULL) {
13088     tags = gst_tag_list_new_empty ();
13089     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13090   }
13091
13092   if (qtdemux->major_brand == FOURCC_mjp2)
13093     fmt = "Motion JPEG 2000";
13094   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13095     fmt = "3GP";
13096   else if (qtdemux->major_brand == FOURCC_qt__)
13097     fmt = "Quicktime";
13098   else if (qtdemux->fragmented)
13099     fmt = "ISO fMP4";
13100   else
13101     fmt = "ISO MP4/M4A";
13102
13103   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13104       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13105
13106   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13107       fmt, NULL);
13108
13109   return tags;
13110 }
13111
13112 /* we have read the complete moov node now.
13113  * This function parses all of the relevant info, creates the traks and
13114  * prepares all data structures for playback
13115  */
13116 static gboolean
13117 qtdemux_parse_tree (GstQTDemux * qtdemux)
13118 {
13119   GNode *mvhd;
13120   GNode *trak;
13121   GNode *udta;
13122   GNode *mvex;
13123   GstClockTime duration;
13124   GNode *pssh;
13125   guint64 creation_time;
13126   GstDateTime *datetime = NULL;
13127   gint version;
13128
13129   /* make sure we have a usable taglist */
13130   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13131
13132   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13133   if (mvhd == NULL) {
13134     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13135     return qtdemux_parse_redirects (qtdemux);
13136   }
13137
13138   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13139   if (version == 1) {
13140     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13141     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13142     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13143   } else if (version == 0) {
13144     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13145     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13146     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13147   } else {
13148     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13149     return FALSE;
13150   }
13151
13152   /* Moving qt creation time (secs since 1904) to unix time */
13153   if (creation_time != 0) {
13154     /* Try to use epoch first as it should be faster and more commonly found */
13155     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13156       GTimeVal now;
13157
13158       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13159       /* some data cleansing sanity */
13160       g_get_current_time (&now);
13161       if (now.tv_sec + 24 * 3600 < creation_time) {
13162         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13163       } else {
13164         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13165       }
13166     } else {
13167       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13168       GDateTime *dt, *dt_local;
13169
13170       dt = g_date_time_add_seconds (base_dt, creation_time);
13171       dt_local = g_date_time_to_local (dt);
13172       datetime = gst_date_time_new_from_g_date_time (dt_local);
13173
13174       g_date_time_unref (base_dt);
13175       g_date_time_unref (dt);
13176     }
13177   }
13178   if (datetime) {
13179     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13180     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13181         datetime, NULL);
13182     gst_date_time_unref (datetime);
13183   }
13184
13185   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13186   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13187
13188   /* check for fragmented file and get some (default) data */
13189   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13190   if (mvex) {
13191     GNode *mehd;
13192     GstByteReader mehd_data;
13193
13194     /* let track parsing or anyone know weird stuff might happen ... */
13195     qtdemux->fragmented = TRUE;
13196
13197     /* compensate for total duration */
13198     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13199     if (mehd)
13200       qtdemux_parse_mehd (qtdemux, &mehd_data);
13201   }
13202
13203   /* set duration in the segment info */
13204   gst_qtdemux_get_duration (qtdemux, &duration);
13205   if (duration) {
13206     qtdemux->segment.duration = duration;
13207     /* also do not exceed duration; stop is set that way post seek anyway,
13208      * and segment activation falls back to duration,
13209      * whereas loop only checks stop, so let's align this here as well */
13210     qtdemux->segment.stop = duration;
13211   }
13212
13213   /* parse all traks */
13214   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13215   while (trak) {
13216     qtdemux_parse_trak (qtdemux, trak);
13217     /* iterate all siblings */
13218     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13219   }
13220
13221   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13222
13223   /* find tags */
13224   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13225   if (udta) {
13226     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13227   } else {
13228     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13229   }
13230
13231   /* maybe also some tags in meta box */
13232   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13233   if (udta) {
13234     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13235     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13236   } else {
13237     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13238   }
13239
13240   /* parse any protection system info */
13241   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13242   while (pssh) {
13243     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13244     qtdemux_parse_pssh (qtdemux, pssh);
13245     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13246   }
13247
13248   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13249
13250   return TRUE;
13251 }
13252
13253 /* taken from ffmpeg */
13254 static int
13255 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13256 {
13257   int count = 4;
13258   int len = 0;
13259
13260   while (count--) {
13261     int c;
13262
13263     if (ptr >= end)
13264       return -1;
13265
13266     c = *ptr++;
13267     len = (len << 7) | (c & 0x7f);
13268     if (!(c & 0x80))
13269       break;
13270   }
13271   *end_out = ptr;
13272   return len;
13273 }
13274
13275 /* this can change the codec originally present in @list */
13276 static void
13277 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13278     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13279 {
13280   int len = QT_UINT32 (esds->data);
13281   guint8 *ptr = esds->data;
13282   guint8 *end = ptr + len;
13283   int tag;
13284   guint8 *data_ptr = NULL;
13285   int data_len = 0;
13286   guint8 object_type_id = 0;
13287   const char *codec_name = NULL;
13288   GstCaps *caps = NULL;
13289
13290   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13291   ptr += 8;
13292   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13293   ptr += 4;
13294   while (ptr + 1 < end) {
13295     tag = QT_UINT8 (ptr);
13296     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13297     ptr++;
13298     len = read_descr_size (ptr, end, &ptr);
13299     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13300
13301     /* Check the stated amount of data is available for reading */
13302     if (len < 0 || ptr + len > end)
13303       break;
13304
13305     switch (tag) {
13306       case ES_DESCRIPTOR_TAG:
13307         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13308         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13309         ptr += 3;
13310         break;
13311       case DECODER_CONFIG_DESC_TAG:{
13312         guint max_bitrate, avg_bitrate;
13313
13314         object_type_id = QT_UINT8 (ptr);
13315         max_bitrate = QT_UINT32 (ptr + 5);
13316         avg_bitrate = QT_UINT32 (ptr + 9);
13317         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13318         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13319         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13320         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13321         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13322         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13323           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13324               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13325         }
13326         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13327           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13328               avg_bitrate, NULL);
13329         }
13330         ptr += 13;
13331         break;
13332       }
13333       case DECODER_SPECIFIC_INFO_TAG:
13334         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13335         if (object_type_id == 0xe0 && len == 0x40) {
13336           guint8 *data;
13337           GstStructure *s;
13338           guint32 clut[16];
13339           gint i;
13340
13341           GST_DEBUG_OBJECT (qtdemux,
13342               "Have VOBSUB palette. Creating palette event");
13343           /* move to decConfigDescr data and read palette */
13344           data = ptr;
13345           for (i = 0; i < 16; i++) {
13346             clut[i] = QT_UINT32 (data);
13347             data += 4;
13348           }
13349
13350           s = gst_structure_new ("application/x-gst-dvd", "event",
13351               G_TYPE_STRING, "dvd-spu-clut-change",
13352               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13353               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13354               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13355               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13356               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13357               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13358               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13359               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13360               NULL);
13361
13362           /* store event and trigger custom processing */
13363           stream->pending_event =
13364               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13365         } else {
13366           /* Generic codec_data handler puts it on the caps */
13367           data_ptr = ptr;
13368           data_len = len;
13369         }
13370
13371         ptr += len;
13372         break;
13373       case SL_CONFIG_DESC_TAG:
13374         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13375         ptr += 1;
13376         break;
13377       default:
13378         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13379             tag);
13380         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13381         ptr += len;
13382         break;
13383     }
13384   }
13385
13386   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13387    * in use, and should also be used to override some other parameters for some
13388    * codecs. */
13389   switch (object_type_id) {
13390     case 0x20:                 /* MPEG-4 */
13391       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13392        * profile_and_level_indication */
13393       if (data_ptr != NULL && data_len >= 5 &&
13394           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13395         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13396             data_ptr + 4, data_len - 4);
13397       }
13398       break;                    /* Nothing special needed here */
13399     case 0x21:                 /* H.264 */
13400       codec_name = "H.264 / AVC";
13401       caps = gst_caps_new_simple ("video/x-h264",
13402           "stream-format", G_TYPE_STRING, "avc",
13403           "alignment", G_TYPE_STRING, "au", NULL);
13404       break;
13405     case 0x40:                 /* AAC (any) */
13406     case 0x66:                 /* AAC Main */
13407     case 0x67:                 /* AAC LC */
13408     case 0x68:                 /* AAC SSR */
13409       /* Override channels and rate based on the codec_data, as it's often
13410        * wrong. */
13411       /* Only do so for basic setup without HE-AAC extension */
13412       if (data_ptr && data_len == 2) {
13413         guint channels, rate;
13414
13415         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13416         if (channels > 0)
13417           entry->n_channels = channels;
13418
13419         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13420         if (rate > 0)
13421           entry->rate = rate;
13422       }
13423
13424       /* Set level and profile if possible */
13425       if (data_ptr != NULL && data_len >= 2) {
13426         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13427             data_ptr, data_len);
13428       } else {
13429         const gchar *profile_str = NULL;
13430         GstBuffer *buffer;
13431         GstMapInfo map;
13432         guint8 *codec_data;
13433         gint rate_idx, profile;
13434
13435         /* No codec_data, let's invent something.
13436          * FIXME: This is wrong for SBR! */
13437
13438         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13439
13440         buffer = gst_buffer_new_and_alloc (2);
13441         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13442         codec_data = map.data;
13443
13444         rate_idx =
13445             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13446             (stream)->rate);
13447
13448         switch (object_type_id) {
13449           case 0x66:
13450             profile_str = "main";
13451             profile = 0;
13452             break;
13453           case 0x67:
13454             profile_str = "lc";
13455             profile = 1;
13456             break;
13457           case 0x68:
13458             profile_str = "ssr";
13459             profile = 2;
13460             break;
13461           default:
13462             profile = 3;
13463             break;
13464         }
13465
13466         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13467         codec_data[1] =
13468             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13469
13470         gst_buffer_unmap (buffer, &map);
13471         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13472             GST_TYPE_BUFFER, buffer, NULL);
13473         gst_buffer_unref (buffer);
13474
13475         if (profile_str) {
13476           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13477               G_TYPE_STRING, profile_str, NULL);
13478         }
13479       }
13480       break;
13481     case 0x60:                 /* MPEG-2, various profiles */
13482     case 0x61:
13483     case 0x62:
13484     case 0x63:
13485     case 0x64:
13486     case 0x65:
13487       codec_name = "MPEG-2 video";
13488       caps = gst_caps_new_simple ("video/mpeg",
13489           "mpegversion", G_TYPE_INT, 2,
13490           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13491       break;
13492     case 0x69:                 /* MPEG-2 BC audio */
13493     case 0x6B:                 /* MPEG-1 audio */
13494       caps = gst_caps_new_simple ("audio/mpeg",
13495           "mpegversion", G_TYPE_INT, 1, NULL);
13496       codec_name = "MPEG-1 audio";
13497       break;
13498     case 0x6A:                 /* MPEG-1 */
13499       codec_name = "MPEG-1 video";
13500       caps = gst_caps_new_simple ("video/mpeg",
13501           "mpegversion", G_TYPE_INT, 1,
13502           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13503       break;
13504     case 0x6C:                 /* MJPEG */
13505       caps =
13506           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13507           NULL);
13508       codec_name = "Motion-JPEG";
13509       break;
13510     case 0x6D:                 /* PNG */
13511       caps =
13512           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13513           NULL);
13514       codec_name = "PNG still images";
13515       break;
13516     case 0x6E:                 /* JPEG2000 */
13517       codec_name = "JPEG-2000";
13518       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13519       break;
13520     case 0xA4:                 /* Dirac */
13521       codec_name = "Dirac";
13522       caps = gst_caps_new_empty_simple ("video/x-dirac");
13523       break;
13524     case 0xA5:                 /* AC3 */
13525       codec_name = "AC-3 audio";
13526       caps = gst_caps_new_simple ("audio/x-ac3",
13527           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13528       break;
13529     case 0xA9:                 /* AC3 */
13530       codec_name = "DTS audio";
13531       caps = gst_caps_new_simple ("audio/x-dts",
13532           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13533       break;
13534     case 0xE1:                 /* QCELP */
13535       /* QCELP, the codec_data is a riff tag (little endian) with
13536        * 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). */
13537       caps = gst_caps_new_empty_simple ("audio/qcelp");
13538       codec_name = "QCELP";
13539       break;
13540     default:
13541       break;
13542   }
13543
13544   /* If we have a replacement caps, then change our caps for this stream */
13545   if (caps) {
13546     gst_caps_unref (entry->caps);
13547     entry->caps = caps;
13548   }
13549
13550   if (codec_name && list)
13551     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13552         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13553
13554   /* Add the codec_data attribute to caps, if we have it */
13555   if (data_ptr) {
13556     GstBuffer *buffer;
13557
13558     buffer = gst_buffer_new_and_alloc (data_len);
13559     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13560
13561     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13562     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13563
13564     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13565         buffer, NULL);
13566     gst_buffer_unref (buffer);
13567   }
13568
13569 }
13570
13571 static inline GstCaps *
13572 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13573 {
13574   GstCaps *caps;
13575   guint i;
13576   char *s, fourstr[5];
13577
13578   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13579   for (i = 0; i < 4; i++) {
13580     if (!g_ascii_isalnum (fourstr[i]))
13581       fourstr[i] = '_';
13582   }
13583   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13584   caps = gst_caps_new_empty_simple (s);
13585   g_free (s);
13586   return caps;
13587 }
13588
13589 #define _codec(name) \
13590   do { \
13591     if (codec_name) { \
13592       *codec_name = g_strdup (name); \
13593     } \
13594   } while (0)
13595
13596 static GstCaps *
13597 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13598     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13599     const guint8 * stsd_entry_data, gchar ** codec_name)
13600 {
13601   GstCaps *caps = NULL;
13602   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13603
13604   switch (fourcc) {
13605     case FOURCC_png:
13606       _codec ("PNG still images");
13607       caps = gst_caps_new_empty_simple ("image/png");
13608       break;
13609     case FOURCC_jpeg:
13610       _codec ("JPEG still images");
13611       caps =
13612           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13613           NULL);
13614       break;
13615     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13616     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13617     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13618     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13619       _codec ("Motion-JPEG");
13620       caps =
13621           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13622           NULL);
13623       break;
13624     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13625       _codec ("Motion-JPEG format B");
13626       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13627       break;
13628     case FOURCC_mjp2:
13629       _codec ("JPEG-2000");
13630       /* override to what it should be according to spec, avoid palette_data */
13631       entry->bits_per_sample = 24;
13632       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13633       break;
13634     case FOURCC_SVQ3:
13635       _codec ("Sorensen video v.3");
13636       caps = gst_caps_new_simple ("video/x-svq",
13637           "svqversion", G_TYPE_INT, 3, NULL);
13638       break;
13639     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13640     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13641       _codec ("Sorensen video v.1");
13642       caps = gst_caps_new_simple ("video/x-svq",
13643           "svqversion", G_TYPE_INT, 1, NULL);
13644       break;
13645     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13646       caps = gst_caps_new_empty_simple ("video/x-raw");
13647       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13648       _codec ("Windows Raw RGB");
13649       stream->alignment = 32;
13650       break;
13651     case FOURCC_raw_:
13652     {
13653       guint16 bps;
13654
13655       bps = QT_UINT16 (stsd_entry_data + 82);
13656       switch (bps) {
13657         case 15:
13658           format = GST_VIDEO_FORMAT_RGB15;
13659           break;
13660         case 16:
13661           format = GST_VIDEO_FORMAT_RGB16;
13662           break;
13663         case 24:
13664           format = GST_VIDEO_FORMAT_RGB;
13665           break;
13666         case 32:
13667           format = GST_VIDEO_FORMAT_ARGB;
13668           break;
13669         default:
13670           /* unknown */
13671           break;
13672       }
13673       break;
13674     }
13675     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13676       format = GST_VIDEO_FORMAT_I420;
13677       break;
13678     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13679     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13680       format = GST_VIDEO_FORMAT_I420;
13681       break;
13682     case FOURCC_2vuy:
13683     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13684       format = GST_VIDEO_FORMAT_UYVY;
13685       break;
13686     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13687       format = GST_VIDEO_FORMAT_v308;
13688       break;
13689     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13690       format = GST_VIDEO_FORMAT_v216;
13691       break;
13692     case FOURCC_v210:
13693       format = GST_VIDEO_FORMAT_v210;
13694       break;
13695     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13696       format = GST_VIDEO_FORMAT_r210;
13697       break;
13698       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13699          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13700          format = GST_VIDEO_FORMAT_v410;
13701          break;
13702        */
13703       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13704        * but different order than AYUV
13705        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13706        format = GST_VIDEO_FORMAT_v408;
13707        break;
13708        */
13709     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13710     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13711       _codec ("MPEG-1 video");
13712       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13713           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13714       break;
13715     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13716     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13717     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13718     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13719     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13720     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13721     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13722     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13723     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13724     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13725     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13726     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13727     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13728     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13729     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13730     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13731     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13732     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13733     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13734     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13735     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13736     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13737     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13738     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13739     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13740     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13741     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13742     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13743     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13744     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13745     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13746     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13747     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13748     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13749     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13750     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13751     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13752     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13753     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13754     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13755     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13756     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13757     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13758     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13759     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13760     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13761     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13762       _codec ("MPEG-2 video");
13763       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13764           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13765       break;
13766     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13767       _codec ("GIF still images");
13768       caps = gst_caps_new_empty_simple ("image/gif");
13769       break;
13770     case FOURCC_h263:
13771     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13772     case FOURCC_s263:
13773     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13774       _codec ("H.263");
13775       /* ffmpeg uses the height/width props, don't know why */
13776       caps = gst_caps_new_simple ("video/x-h263",
13777           "variant", G_TYPE_STRING, "itu", NULL);
13778       break;
13779     case FOURCC_mp4v:
13780     case FOURCC_MP4V:
13781       _codec ("MPEG-4 video");
13782       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13783           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13784       break;
13785     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13786     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13787       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13788       caps = gst_caps_new_simple ("video/x-msmpeg",
13789           "msmpegversion", G_TYPE_INT, 43, NULL);
13790       break;
13791     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13792       _codec ("DivX 3");
13793       caps = gst_caps_new_simple ("video/x-divx",
13794           "divxversion", G_TYPE_INT, 3, NULL);
13795       break;
13796     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13797     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13798       _codec ("DivX 4");
13799       caps = gst_caps_new_simple ("video/x-divx",
13800           "divxversion", G_TYPE_INT, 4, NULL);
13801       break;
13802     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13803       _codec ("DivX 5");
13804       caps = gst_caps_new_simple ("video/x-divx",
13805           "divxversion", G_TYPE_INT, 5, NULL);
13806       break;
13807
13808     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13809       _codec ("FFV1");
13810       caps = gst_caps_new_simple ("video/x-ffv",
13811           "ffvversion", G_TYPE_INT, 1, NULL);
13812       break;
13813
13814     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13815     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13816     case FOURCC_XVID:
13817     case FOURCC_xvid:
13818     case FOURCC_FMP4:
13819     case FOURCC_fmp4:
13820     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13821       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13822           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13823       _codec ("MPEG-4");
13824       break;
13825
13826     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13827       _codec ("Cinepak");
13828       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13829       break;
13830     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13831       _codec ("Apple QuickDraw");
13832       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13833       break;
13834     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13835       _codec ("Apple video");
13836       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13837       break;
13838     case FOURCC_H264:
13839     case FOURCC_avc1:
13840       _codec ("H.264 / AVC");
13841       caps = gst_caps_new_simple ("video/x-h264",
13842           "stream-format", G_TYPE_STRING, "avc",
13843           "alignment", G_TYPE_STRING, "au", NULL);
13844       break;
13845     case FOURCC_avc3:
13846       _codec ("H.264 / AVC");
13847       caps = gst_caps_new_simple ("video/x-h264",
13848           "stream-format", G_TYPE_STRING, "avc3",
13849           "alignment", G_TYPE_STRING, "au", NULL);
13850       break;
13851     case FOURCC_H265:
13852     case FOURCC_hvc1:
13853       _codec ("H.265 / HEVC");
13854       caps = gst_caps_new_simple ("video/x-h265",
13855           "stream-format", G_TYPE_STRING, "hvc1",
13856           "alignment", G_TYPE_STRING, "au", NULL);
13857       break;
13858     case FOURCC_hev1:
13859       _codec ("H.265 / HEVC");
13860       caps = gst_caps_new_simple ("video/x-h265",
13861           "stream-format", G_TYPE_STRING, "hev1",
13862           "alignment", G_TYPE_STRING, "au", NULL);
13863       break;
13864     case FOURCC_rle_:
13865       _codec ("Run-length encoding");
13866       caps = gst_caps_new_simple ("video/x-rle",
13867           "layout", G_TYPE_STRING, "quicktime", NULL);
13868       break;
13869     case FOURCC_WRLE:
13870       _codec ("Run-length encoding");
13871       caps = gst_caps_new_simple ("video/x-rle",
13872           "layout", G_TYPE_STRING, "microsoft", NULL);
13873       break;
13874     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13875     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13876       _codec ("Indeo Video 3");
13877       caps = gst_caps_new_simple ("video/x-indeo",
13878           "indeoversion", G_TYPE_INT, 3, NULL);
13879       break;
13880     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13881     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13882       _codec ("Intel Video 4");
13883       caps = gst_caps_new_simple ("video/x-indeo",
13884           "indeoversion", G_TYPE_INT, 4, NULL);
13885       break;
13886     case FOURCC_dvcp:
13887     case FOURCC_dvc_:
13888     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13889     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13890     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13891     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13892     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13893     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13894       _codec ("DV Video");
13895       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13896           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13897       break;
13898     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13899     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13900       _codec ("DVCPro50 Video");
13901       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13902           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13903       break;
13904     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13905     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13906       _codec ("DVCProHD Video");
13907       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13908           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13909       break;
13910     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13911       _codec ("Apple Graphics (SMC)");
13912       caps = gst_caps_new_empty_simple ("video/x-smc");
13913       break;
13914     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13915       _codec ("VP3");
13916       caps = gst_caps_new_empty_simple ("video/x-vp3");
13917       break;
13918     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13919       _codec ("VP6 Flash");
13920       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13921       break;
13922     case FOURCC_XiTh:
13923       _codec ("Theora");
13924       caps = gst_caps_new_empty_simple ("video/x-theora");
13925       /* theora uses one byte of padding in the data stream because it does not
13926        * allow 0 sized packets while theora does */
13927       entry->padding = 1;
13928       break;
13929     case FOURCC_drac:
13930       _codec ("Dirac");
13931       caps = gst_caps_new_empty_simple ("video/x-dirac");
13932       break;
13933     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13934       _codec ("TIFF still images");
13935       caps = gst_caps_new_empty_simple ("image/tiff");
13936       break;
13937     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13938       _codec ("Apple Intermediate Codec");
13939       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13940       break;
13941     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13942       _codec ("AVID DNxHD");
13943       caps = gst_caps_from_string ("video/x-dnxhd");
13944       break;
13945     case FOURCC_VP80:
13946     case FOURCC_vp08:
13947       _codec ("On2 VP8");
13948       caps = gst_caps_from_string ("video/x-vp8");
13949       break;
13950     case FOURCC_vp09:
13951       _codec ("Google VP9");
13952       caps = gst_caps_from_string ("video/x-vp9");
13953       break;
13954     case FOURCC_apcs:
13955       _codec ("Apple ProRes LT");
13956       caps =
13957           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13958           NULL);
13959       break;
13960     case FOURCC_apch:
13961       _codec ("Apple ProRes HQ");
13962       caps =
13963           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13964           NULL);
13965       break;
13966     case FOURCC_apcn:
13967       _codec ("Apple ProRes");
13968       caps =
13969           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13970           "standard", NULL);
13971       break;
13972     case FOURCC_apco:
13973       _codec ("Apple ProRes Proxy");
13974       caps =
13975           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13976           "proxy", NULL);
13977       break;
13978     case FOURCC_ap4h:
13979       _codec ("Apple ProRes 4444");
13980       caps =
13981           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13982           "4444", NULL);
13983       break;
13984     case FOURCC_ap4x:
13985       _codec ("Apple ProRes 4444 XQ");
13986       caps =
13987           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13988           "4444xq", NULL);
13989       break;
13990     case FOURCC_cfhd:
13991       _codec ("GoPro CineForm");
13992       caps = gst_caps_from_string ("video/x-cineform");
13993       break;
13994     case FOURCC_vc_1:
13995     case FOURCC_ovc1:
13996       _codec ("VC-1");
13997       caps = gst_caps_new_simple ("video/x-wmv",
13998           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13999       break;
14000     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14001     default:
14002     {
14003       caps = _get_unknown_codec_name ("video", fourcc);
14004       break;
14005     }
14006   }
14007
14008   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14009     GstVideoInfo info;
14010
14011     gst_video_info_init (&info);
14012     gst_video_info_set_format (&info, format, entry->width, entry->height);
14013
14014     caps = gst_video_info_to_caps (&info);
14015     *codec_name = gst_pb_utils_get_codec_description (caps);
14016
14017     /* enable clipping for raw video streams */
14018     stream->need_clip = TRUE;
14019     stream->alignment = 32;
14020   }
14021
14022   return caps;
14023 }
14024
14025 static guint
14026 round_up_pow2 (guint n)
14027 {
14028   n = n - 1;
14029   n = n | (n >> 1);
14030   n = n | (n >> 2);
14031   n = n | (n >> 4);
14032   n = n | (n >> 8);
14033   n = n | (n >> 16);
14034   return n + 1;
14035 }
14036
14037 static GstCaps *
14038 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14039     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14040     int len, gchar ** codec_name)
14041 {
14042   GstCaps *caps;
14043   const GstStructure *s;
14044   const gchar *name;
14045   gint endian = 0;
14046   GstAudioFormat format = 0;
14047   gint depth;
14048
14049   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14050
14051   depth = entry->bytes_per_packet * 8;
14052
14053   switch (fourcc) {
14054     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14055     case FOURCC_raw_:
14056       /* 8-bit audio is unsigned */
14057       if (depth == 8)
14058         format = GST_AUDIO_FORMAT_U8;
14059       /* otherwise it's signed and big-endian just like 'twos' */
14060     case FOURCC_twos:
14061       endian = G_BIG_ENDIAN;
14062       /* fall-through */
14063     case FOURCC_sowt:
14064     {
14065       gchar *str;
14066
14067       if (!endian)
14068         endian = G_LITTLE_ENDIAN;
14069
14070       if (!format)
14071         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14072
14073       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14074       _codec (str);
14075       g_free (str);
14076
14077       caps = gst_caps_new_simple ("audio/x-raw",
14078           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14079           "layout", G_TYPE_STRING, "interleaved", NULL);
14080       stream->alignment = GST_ROUND_UP_8 (depth);
14081       stream->alignment = round_up_pow2 (stream->alignment);
14082       break;
14083     }
14084     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14085       _codec ("Raw 64-bit floating-point audio");
14086       caps = gst_caps_new_simple ("audio/x-raw",
14087           "format", G_TYPE_STRING, "F64BE",
14088           "layout", G_TYPE_STRING, "interleaved", NULL);
14089       stream->alignment = 8;
14090       break;
14091     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14092       _codec ("Raw 32-bit floating-point audio");
14093       caps = gst_caps_new_simple ("audio/x-raw",
14094           "format", G_TYPE_STRING, "F32BE",
14095           "layout", G_TYPE_STRING, "interleaved", NULL);
14096       stream->alignment = 4;
14097       break;
14098     case FOURCC_in24:
14099       _codec ("Raw 24-bit PCM audio");
14100       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14101        * endian later */
14102       caps = gst_caps_new_simple ("audio/x-raw",
14103           "format", G_TYPE_STRING, "S24BE",
14104           "layout", G_TYPE_STRING, "interleaved", NULL);
14105       stream->alignment = 4;
14106       break;
14107     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14108       _codec ("Raw 32-bit PCM audio");
14109       caps = gst_caps_new_simple ("audio/x-raw",
14110           "format", G_TYPE_STRING, "S32BE",
14111           "layout", G_TYPE_STRING, "interleaved", NULL);
14112       stream->alignment = 4;
14113       break;
14114     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14115       _codec ("Raw 16-bit PCM audio");
14116       caps = gst_caps_new_simple ("audio/x-raw",
14117           "format", G_TYPE_STRING, "S16LE",
14118           "layout", G_TYPE_STRING, "interleaved", NULL);
14119       stream->alignment = 2;
14120       break;
14121     case FOURCC_ulaw:
14122       _codec ("Mu-law audio");
14123       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14124       break;
14125     case FOURCC_alaw:
14126       _codec ("A-law audio");
14127       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14128       break;
14129     case 0x0200736d:
14130     case 0x6d730002:
14131       _codec ("Microsoft ADPCM");
14132       /* Microsoft ADPCM-ACM code 2 */
14133       caps = gst_caps_new_simple ("audio/x-adpcm",
14134           "layout", G_TYPE_STRING, "microsoft", NULL);
14135       break;
14136     case 0x1100736d:
14137     case 0x6d730011:
14138       _codec ("DVI/IMA ADPCM");
14139       caps = gst_caps_new_simple ("audio/x-adpcm",
14140           "layout", G_TYPE_STRING, "dvi", NULL);
14141       break;
14142     case 0x1700736d:
14143     case 0x6d730017:
14144       _codec ("DVI/Intel IMA ADPCM");
14145       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14146       caps = gst_caps_new_simple ("audio/x-adpcm",
14147           "layout", G_TYPE_STRING, "quicktime", NULL);
14148       break;
14149     case 0x5500736d:
14150     case 0x6d730055:
14151       /* MPEG layer 3, CBR only (pre QT4.1) */
14152     case FOURCC__mp3:
14153       _codec ("MPEG-1 layer 3");
14154       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14155       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14156           "mpegversion", G_TYPE_INT, 1, NULL);
14157       break;
14158     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14159       _codec ("MPEG-1 layer 2");
14160       /* MPEG layer 2 */
14161       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14162           "mpegversion", G_TYPE_INT, 1, NULL);
14163       break;
14164     case 0x20736d:
14165     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14166       _codec ("EAC-3 audio");
14167       caps = gst_caps_new_simple ("audio/x-eac3",
14168           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14169       entry->sampled = TRUE;
14170       break;
14171     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14172     case FOURCC_ac_3:
14173       _codec ("AC-3 audio");
14174       caps = gst_caps_new_simple ("audio/x-ac3",
14175           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14176       entry->sampled = TRUE;
14177       break;
14178     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14179     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14180       _codec ("DTS audio");
14181       caps = gst_caps_new_simple ("audio/x-dts",
14182           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14183       entry->sampled = TRUE;
14184       break;
14185     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14186     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14187       _codec ("DTS-HD audio");
14188       caps = gst_caps_new_simple ("audio/x-dts",
14189           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14190       entry->sampled = TRUE;
14191       break;
14192     case FOURCC_MAC3:
14193       _codec ("MACE-3");
14194       caps = gst_caps_new_simple ("audio/x-mace",
14195           "maceversion", G_TYPE_INT, 3, NULL);
14196       break;
14197     case FOURCC_MAC6:
14198       _codec ("MACE-6");
14199       caps = gst_caps_new_simple ("audio/x-mace",
14200           "maceversion", G_TYPE_INT, 6, NULL);
14201       break;
14202     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14203       /* ogg/vorbis */
14204       caps = gst_caps_new_empty_simple ("application/ogg");
14205       break;
14206     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14207       _codec ("DV audio");
14208       caps = gst_caps_new_empty_simple ("audio/x-dv");
14209       break;
14210     case FOURCC_mp4a:
14211       _codec ("MPEG-4 AAC audio");
14212       caps = gst_caps_new_simple ("audio/mpeg",
14213           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14214           "stream-format", G_TYPE_STRING, "raw", NULL);
14215       break;
14216     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14217       _codec ("QDesign Music");
14218       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14219       break;
14220     case FOURCC_QDM2:
14221       _codec ("QDesign Music v.2");
14222       /* FIXME: QDesign music version 2 (no constant) */
14223       if (FALSE && data) {
14224         caps = gst_caps_new_simple ("audio/x-qdm2",
14225             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14226             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14227             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14228       } else {
14229         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14230       }
14231       break;
14232     case FOURCC_agsm:
14233       _codec ("GSM audio");
14234       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14235       break;
14236     case FOURCC_samr:
14237       _codec ("AMR audio");
14238       caps = gst_caps_new_empty_simple ("audio/AMR");
14239       break;
14240     case FOURCC_sawb:
14241       _codec ("AMR-WB audio");
14242       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14243       break;
14244     case FOURCC_ima4:
14245       _codec ("Quicktime IMA ADPCM");
14246       caps = gst_caps_new_simple ("audio/x-adpcm",
14247           "layout", G_TYPE_STRING, "quicktime", NULL);
14248       break;
14249     case FOURCC_alac:
14250       _codec ("Apple lossless audio");
14251       caps = gst_caps_new_empty_simple ("audio/x-alac");
14252       break;
14253     case FOURCC_fLaC:
14254       _codec ("Free Lossless Audio Codec");
14255       caps = gst_caps_new_simple ("audio/x-flac",
14256           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14257       break;
14258     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14259       _codec ("QualComm PureVoice");
14260       caps = gst_caps_from_string ("audio/qcelp");
14261       break;
14262     case FOURCC_wma_:
14263     case FOURCC_owma:
14264       _codec ("WMA");
14265       caps = gst_caps_new_empty_simple ("audio/x-wma");
14266       break;
14267     case FOURCC_opus:
14268       _codec ("Opus");
14269       caps = gst_caps_new_empty_simple ("audio/x-opus");
14270       break;
14271     case FOURCC_lpcm:
14272     {
14273       guint32 flags = 0;
14274       guint32 depth = 0;
14275       guint32 width = 0;
14276       GstAudioFormat format;
14277       enum
14278       {
14279         FLAG_IS_FLOAT = 0x1,
14280         FLAG_IS_BIG_ENDIAN = 0x2,
14281         FLAG_IS_SIGNED = 0x4,
14282         FLAG_IS_PACKED = 0x8,
14283         FLAG_IS_ALIGNED_HIGH = 0x10,
14284         FLAG_IS_NON_INTERLEAVED = 0x20
14285       };
14286       _codec ("Raw LPCM audio");
14287
14288       if (data && len >= 36) {
14289         depth = QT_UINT32 (data + 24);
14290         flags = QT_UINT32 (data + 28);
14291         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14292       }
14293       if ((flags & FLAG_IS_FLOAT) == 0) {
14294         if (depth == 0)
14295           depth = 16;
14296         if (width == 0)
14297           width = 16;
14298         if ((flags & FLAG_IS_ALIGNED_HIGH))
14299           depth = width;
14300
14301         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14302             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14303             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14304         caps = gst_caps_new_simple ("audio/x-raw",
14305             "format", G_TYPE_STRING,
14306             format !=
14307             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14308             "UNKNOWN", "layout", G_TYPE_STRING,
14309             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14310             "interleaved", NULL);
14311         stream->alignment = GST_ROUND_UP_8 (depth);
14312         stream->alignment = round_up_pow2 (stream->alignment);
14313       } else {
14314         if (width == 0)
14315           width = 32;
14316         if (width == 64) {
14317           if (flags & FLAG_IS_BIG_ENDIAN)
14318             format = GST_AUDIO_FORMAT_F64BE;
14319           else
14320             format = GST_AUDIO_FORMAT_F64LE;
14321         } else {
14322           if (flags & FLAG_IS_BIG_ENDIAN)
14323             format = GST_AUDIO_FORMAT_F32BE;
14324           else
14325             format = GST_AUDIO_FORMAT_F32LE;
14326         }
14327         caps = gst_caps_new_simple ("audio/x-raw",
14328             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14329             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14330             "non-interleaved" : "interleaved", NULL);
14331         stream->alignment = width / 8;
14332       }
14333       break;
14334     }
14335     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14336       /* ? */
14337     default:
14338     {
14339       caps = _get_unknown_codec_name ("audio", fourcc);
14340       break;
14341     }
14342   }
14343
14344   if (caps) {
14345     GstCaps *templ_caps =
14346         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14347     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14348     gst_caps_unref (caps);
14349     gst_caps_unref (templ_caps);
14350     caps = intersection;
14351   }
14352
14353   /* enable clipping for raw audio streams */
14354   s = gst_caps_get_structure (caps, 0);
14355   name = gst_structure_get_name (s);
14356   if (g_str_has_prefix (name, "audio/x-raw")) {
14357     stream->need_clip = TRUE;
14358     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14359     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14360   }
14361   return caps;
14362 }
14363
14364 static GstCaps *
14365 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14366     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14367     const guint8 * stsd_entry_data, gchar ** codec_name)
14368 {
14369   GstCaps *caps;
14370
14371   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14372
14373   switch (fourcc) {
14374     case FOURCC_mp4s:
14375       _codec ("DVD subtitle");
14376       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14377       stream->need_process = TRUE;
14378       break;
14379     case FOURCC_text:
14380       _codec ("Quicktime timed text");
14381       goto text;
14382     case FOURCC_tx3g:
14383       _codec ("3GPP timed text");
14384     text:
14385       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14386           "utf8", NULL);
14387       /* actual text piece needs to be extracted */
14388       stream->need_process = TRUE;
14389       break;
14390     case FOURCC_stpp:
14391       _codec ("XML subtitles");
14392       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14393       break;
14394     default:
14395     {
14396       caps = _get_unknown_codec_name ("text", fourcc);
14397       break;
14398     }
14399   }
14400   return caps;
14401 }
14402
14403 static GstCaps *
14404 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14405     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14406     const guint8 * stsd_entry_data, gchar ** codec_name)
14407 {
14408   GstCaps *caps;
14409
14410   switch (fourcc) {
14411     case FOURCC_m1v:
14412       _codec ("MPEG 1 video");
14413       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14414           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14415       break;
14416     default:
14417       caps = NULL;
14418       break;
14419   }
14420   return caps;
14421 }
14422
14423 static void
14424 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14425     const gchar * system_id)
14426 {
14427   gint i;
14428
14429   if (!qtdemux->protection_system_ids)
14430     qtdemux->protection_system_ids =
14431         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14432   /* Check whether we already have an entry for this system ID. */
14433   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14434     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14435     if (g_ascii_strcasecmp (system_id, id) == 0) {
14436       return;
14437     }
14438   }
14439   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14440   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14441           -1));
14442 }