6c955754f1a508213c66b30af00f21901772beee
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define 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         res = TRUE;
912       }
913       break;
914     }
915     case GST_QUERY_FORMATS:
916       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
917       res = TRUE;
918       break;
919     case GST_QUERY_SEEKING:{
920       GstFormat fmt;
921       gboolean seekable;
922
923       /* try upstream first */
924       res = gst_pad_query_default (pad, parent, query);
925
926       if (!res) {
927         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
928         if (fmt == GST_FORMAT_TIME) {
929           GstClockTime duration;
930
931           gst_qtdemux_get_duration (qtdemux, &duration);
932           seekable = TRUE;
933           if (!qtdemux->pullbased) {
934             GstQuery *q;
935
936             /* we might be able with help from upstream */
937             seekable = FALSE;
938             q = gst_query_new_seeking (GST_FORMAT_BYTES);
939             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
940               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
941               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
942             }
943             gst_query_unref (q);
944           }
945           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
946           res = TRUE;
947         }
948       }
949       break;
950     }
951     case GST_QUERY_SEGMENT:
952     {
953       GstFormat format;
954       gint64 start, stop;
955
956       format = qtdemux->segment.format;
957
958       start =
959           gst_segment_to_stream_time (&qtdemux->segment, format,
960           qtdemux->segment.start);
961       if ((stop = qtdemux->segment.stop) == -1)
962         stop = qtdemux->segment.duration;
963       else
964         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
965
966       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
967       res = TRUE;
968       break;
969     }
970     default:
971       res = gst_pad_query_default (pad, parent, query);
972       break;
973   }
974
975   return res;
976 }
977
978 static void
979 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
980 {
981   if (G_LIKELY (stream->pad)) {
982     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
983         GST_DEBUG_PAD_NAME (stream->pad));
984
985     if (!gst_tag_list_is_empty (stream->stream_tags)) {
986       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
987           stream->stream_tags);
988       gst_pad_push_event (stream->pad,
989           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
990     }
991
992     if (G_UNLIKELY (stream->send_global_tags)) {
993       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
994           qtdemux->tag_list);
995       gst_pad_push_event (stream->pad,
996           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
997       stream->send_global_tags = FALSE;
998     }
999   }
1000 }
1001
1002 /* push event on all source pads; takes ownership of the event */
1003 static void
1004 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1005 {
1006   guint n;
1007   gboolean has_valid_stream = FALSE;
1008   GstEventType etype = GST_EVENT_TYPE (event);
1009
1010   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1011       GST_EVENT_TYPE_NAME (event));
1012
1013   for (n = 0; n < qtdemux->n_streams; n++) {
1014     GstPad *pad;
1015     QtDemuxStream *stream = qtdemux->streams[n];
1016     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1017
1018     if ((pad = stream->pad)) {
1019       has_valid_stream = TRUE;
1020
1021       if (etype == GST_EVENT_EOS) {
1022         /* let's not send twice */
1023         if (stream->sent_eos)
1024           continue;
1025         stream->sent_eos = TRUE;
1026       }
1027
1028       gst_pad_push_event (pad, gst_event_ref (event));
1029     }
1030   }
1031
1032   gst_event_unref (event);
1033
1034   /* if it is EOS and there are no pads, post an error */
1035   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1036     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1037   }
1038 }
1039
1040 /* push a pending newsegment event, if any from the streaming thread */
1041 static void
1042 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1043 {
1044   if (qtdemux->pending_newsegment) {
1045     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1046     qtdemux->pending_newsegment = NULL;
1047   }
1048 }
1049
1050 typedef struct
1051 {
1052   guint64 media_time;
1053 } FindData;
1054
1055 static gint
1056 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1057 {
1058   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1059     return 1;
1060   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1061     return 0;
1062
1063   return -1;
1064 }
1065
1066 /* find the index of the sample that includes the data for @media_time using a
1067  * binary search.  Only to be called in optimized cases of linear search below.
1068  *
1069  * Returns the index of the sample.
1070  */
1071 static guint32
1072 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1073     guint64 media_time)
1074 {
1075   QtDemuxSample *result;
1076   guint32 index;
1077
1078   /* convert media_time to mov format */
1079   media_time =
1080       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1081
1082   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1083       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1084       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1085
1086   if (G_LIKELY (result))
1087     index = result - str->samples;
1088   else
1089     index = 0;
1090
1091   return index;
1092 }
1093
1094
1095
1096 /* find the index of the sample that includes the data for @media_offset using a
1097  * linear search
1098  *
1099  * Returns the index of the sample.
1100  */
1101 static guint32
1102 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1103     QtDemuxStream * str, gint64 media_offset)
1104 {
1105   QtDemuxSample *result = str->samples;
1106   guint32 index = 0;
1107
1108   if (result == NULL || str->n_samples == 0)
1109     return -1;
1110
1111   if (media_offset == result->offset)
1112     return index;
1113
1114   result++;
1115   while (index < str->n_samples - 1) {
1116     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1117       goto parse_failed;
1118
1119     if (media_offset < result->offset)
1120       break;
1121
1122     index++;
1123     result++;
1124   }
1125   return index;
1126
1127   /* ERRORS */
1128 parse_failed:
1129   {
1130     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1131     return -1;
1132   }
1133 }
1134
1135 /* find the index of the sample that includes the data for @media_time using a
1136  * linear search, and keeping in mind that not all samples may have been parsed
1137  * yet.  If possible, it will delegate to binary search.
1138  *
1139  * Returns the index of the sample.
1140  */
1141 static guint32
1142 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1143     GstClockTime media_time)
1144 {
1145   guint32 index = 0;
1146   guint64 mov_time;
1147   QtDemuxSample *sample;
1148
1149   /* convert media_time to mov format */
1150   mov_time =
1151       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1152
1153   sample = str->samples;
1154   if (mov_time == sample->timestamp + sample->pts_offset)
1155     return index;
1156
1157   /* use faster search if requested time in already parsed range */
1158   sample = str->samples + str->stbl_index;
1159   if (str->stbl_index >= 0 &&
1160       mov_time <= (sample->timestamp + sample->pts_offset))
1161     return gst_qtdemux_find_index (qtdemux, str, media_time);
1162
1163   while (index < str->n_samples - 1) {
1164     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1165       goto parse_failed;
1166
1167     sample = str->samples + index + 1;
1168     if (mov_time < (sample->timestamp + sample->pts_offset))
1169       break;
1170
1171     index++;
1172   }
1173   return index;
1174
1175   /* ERRORS */
1176 parse_failed:
1177   {
1178     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1179     return -1;
1180   }
1181 }
1182
1183 /* find the index of the keyframe needed to decode the sample at @index
1184  * of stream @str, or of a subsequent keyframe (depending on @next)
1185  *
1186  * Returns the index of the keyframe.
1187  */
1188 static guint32
1189 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1190     guint32 index, gboolean next)
1191 {
1192   guint32 new_index = index;
1193
1194   if (index >= str->n_samples) {
1195     new_index = str->n_samples;
1196     goto beach;
1197   }
1198
1199   /* all keyframes, return index */
1200   if (str->all_keyframe) {
1201     new_index = index;
1202     goto beach;
1203   }
1204
1205   /* else search until we have a keyframe */
1206   while (new_index < str->n_samples) {
1207     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1208       goto parse_failed;
1209
1210     if (str->samples[new_index].keyframe)
1211       break;
1212
1213     if (new_index == 0)
1214       break;
1215
1216     if (next)
1217       new_index++;
1218     else
1219       new_index--;
1220   }
1221
1222   if (new_index == str->n_samples) {
1223     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1224     new_index = -1;
1225   }
1226
1227 beach:
1228   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1229       "gave %u", next ? "after" : "before", index, new_index);
1230
1231   return new_index;
1232
1233   /* ERRORS */
1234 parse_failed:
1235   {
1236     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1237     return -1;
1238   }
1239 }
1240
1241 /* find the segment for @time_position for @stream
1242  *
1243  * Returns the index of the segment containing @time_position.
1244  * Returns the last segment and sets the @eos variable to TRUE
1245  * if the time is beyond the end. @eos may be NULL
1246  */
1247 static guint32
1248 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1249     GstClockTime time_position)
1250 {
1251   gint i;
1252   guint32 seg_idx;
1253
1254   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1255       GST_TIME_ARGS (time_position));
1256
1257   seg_idx = -1;
1258   for (i = 0; i < stream->n_segments; i++) {
1259     QtDemuxSegment *segment = &stream->segments[i];
1260
1261     GST_LOG_OBJECT (stream->pad,
1262         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1263         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1264
1265     /* For the last segment we include stop_time in the last segment */
1266     if (i < stream->n_segments - 1) {
1267       if (segment->time <= time_position && time_position < segment->stop_time) {
1268         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1269         seg_idx = i;
1270         break;
1271       }
1272     } else {
1273       /* Last segment always matches */
1274       seg_idx = i;
1275       break;
1276     }
1277   }
1278   return seg_idx;
1279 }
1280
1281 /* move the stream @str to the sample position @index.
1282  *
1283  * Updates @str->sample_index and marks discontinuity if needed.
1284  */
1285 static void
1286 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1287     guint32 index)
1288 {
1289   /* no change needed */
1290   if (index == str->sample_index)
1291     return;
1292
1293   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1294       str->n_samples);
1295
1296   /* position changed, we have a discont */
1297   str->sample_index = index;
1298   str->offset_in_sample = 0;
1299   /* Each time we move in the stream we store the position where we are
1300    * starting from */
1301   str->from_sample = index;
1302   str->discont = TRUE;
1303 }
1304
1305 static void
1306 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1307     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1308 {
1309   guint64 min_offset;
1310   gint64 min_byte_offset = -1;
1311   gint n;
1312
1313   min_offset = desired_time;
1314
1315   /* for each stream, find the index of the sample in the segment
1316    * and move back to the previous keyframe. */
1317   for (n = 0; n < qtdemux->n_streams; n++) {
1318     QtDemuxStream *str;
1319     guint32 index, kindex;
1320     guint32 seg_idx;
1321     GstClockTime media_start;
1322     GstClockTime media_time;
1323     GstClockTime seg_time;
1324     QtDemuxSegment *seg;
1325     gboolean empty_segment = FALSE;
1326
1327     str = qtdemux->streams[n];
1328
1329     if (CUR_STREAM (str)->sparse && !use_sparse)
1330       continue;
1331
1332     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1333     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1334
1335     /* get segment and time in the segment */
1336     seg = &str->segments[seg_idx];
1337     seg_time = (desired_time - seg->time) * seg->rate;
1338
1339     while (QTSEGMENT_IS_EMPTY (seg)) {
1340       seg_time = 0;
1341       empty_segment = TRUE;
1342       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1343           seg_idx);
1344       seg_idx++;
1345       if (seg_idx == str->n_segments)
1346         break;
1347       seg = &str->segments[seg_idx];
1348     }
1349
1350     if (seg_idx == str->n_segments) {
1351       /* FIXME track shouldn't have the last segment as empty, but if it
1352        * happens we better handle it */
1353       continue;
1354     }
1355
1356     /* get the media time in the segment */
1357     media_start = seg->media_start + seg_time;
1358
1359     /* get the index of the sample with media time */
1360     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1361     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1362         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1363         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1364         empty_segment);
1365
1366     /* shift to next frame if we are looking for next keyframe */
1367     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1368         && index < str->stbl_index)
1369       index++;
1370
1371     if (!empty_segment) {
1372       /* find previous keyframe */
1373       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1374
1375       /* we will settle for one before if none found after */
1376       if (next && kindex == -1)
1377         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1378
1379       /* if the keyframe is at a different position, we need to update the
1380        * requested seek time */
1381       if (index != kindex) {
1382         index = kindex;
1383
1384         /* get timestamp of keyframe */
1385         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1386         GST_DEBUG_OBJECT (qtdemux,
1387             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1388             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1389             str->samples[kindex].offset);
1390
1391         /* keyframes in the segment get a chance to change the
1392          * desired_offset. keyframes out of the segment are
1393          * ignored. */
1394         if (media_time >= seg->media_start) {
1395           GstClockTime seg_time;
1396
1397           /* this keyframe is inside the segment, convert back to
1398            * segment time */
1399           seg_time = (media_time - seg->media_start) + seg->time;
1400           if ((!next && (seg_time < min_offset)) ||
1401               (next && (seg_time > min_offset)))
1402             min_offset = seg_time;
1403         }
1404       }
1405     }
1406
1407     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1408       min_byte_offset = str->samples[index].offset;
1409   }
1410
1411   if (key_time)
1412     *key_time = min_offset;
1413   if (key_offset)
1414     *key_offset = min_byte_offset;
1415 }
1416
1417 static gboolean
1418 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1419     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1420 {
1421   gboolean res;
1422
1423   g_return_val_if_fail (format != NULL, FALSE);
1424   g_return_val_if_fail (cur != NULL, FALSE);
1425   g_return_val_if_fail (stop != NULL, FALSE);
1426
1427   if (*format == GST_FORMAT_TIME)
1428     return TRUE;
1429
1430   res = TRUE;
1431   if (cur_type != GST_SEEK_TYPE_NONE)
1432     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1433   if (res && stop_type != GST_SEEK_TYPE_NONE)
1434     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1435
1436   if (res)
1437     *format = GST_FORMAT_TIME;
1438
1439   return res;
1440 }
1441
1442 /* perform seek in push based mode:
1443    find BYTE position to move to based on time and delegate to upstream
1444 */
1445 static gboolean
1446 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1447 {
1448   gdouble rate;
1449   GstFormat format;
1450   GstSeekFlags flags;
1451   GstSeekType cur_type, stop_type;
1452   gint64 cur, stop, key_cur;
1453   gboolean res;
1454   gint64 byte_cur;
1455   gint64 original_stop;
1456   guint32 seqnum;
1457
1458   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1459
1460   gst_event_parse_seek (event, &rate, &format, &flags,
1461       &cur_type, &cur, &stop_type, &stop);
1462   seqnum = gst_event_get_seqnum (event);
1463
1464   /* only forward streaming and seeking is possible */
1465   if (rate <= 0)
1466     goto unsupported_seek;
1467
1468   /* convert to TIME if needed and possible */
1469   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1470           stop_type, &stop))
1471     goto no_format;
1472
1473   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1474    * the original stop position to use when upstream pushes the new segment
1475    * for this seek */
1476   original_stop = stop;
1477   stop = -1;
1478
1479   /* find reasonable corresponding BYTE position,
1480    * also try to mind about keyframes, since we can not go back a bit for them
1481    * later on */
1482   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1483    * mostly just work, but let's not yet boldly go there  ... */
1484   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1485
1486   if (byte_cur == -1)
1487     goto abort_seek;
1488
1489   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1490       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1491       stop);
1492
1493   GST_OBJECT_LOCK (qtdemux);
1494   qtdemux->seek_offset = byte_cur;
1495   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1496     qtdemux->push_seek_start = cur;
1497   } else {
1498     qtdemux->push_seek_start = key_cur;
1499   }
1500
1501   if (stop_type == GST_SEEK_TYPE_NONE) {
1502     qtdemux->push_seek_stop = qtdemux->segment.stop;
1503   } else {
1504     qtdemux->push_seek_stop = original_stop;
1505   }
1506   GST_OBJECT_UNLOCK (qtdemux);
1507
1508   /* BYTE seek event */
1509   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1510       stop_type, stop);
1511   gst_event_set_seqnum (event, seqnum);
1512   res = gst_pad_push_event (qtdemux->sinkpad, event);
1513
1514   return res;
1515
1516   /* ERRORS */
1517 abort_seek:
1518   {
1519     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1520         "seek aborted.");
1521     return FALSE;
1522   }
1523 unsupported_seek:
1524   {
1525     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1526     return FALSE;
1527   }
1528 no_format:
1529   {
1530     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1531     return FALSE;
1532   }
1533 }
1534
1535 /* perform the seek.
1536  *
1537  * We set all segment_indexes in the streams to unknown and
1538  * adjust the time_position to the desired position. this is enough
1539  * to trigger a segment switch in the streaming thread to start
1540  * streaming from the desired position.
1541  *
1542  * Keyframe seeking is a little more complicated when dealing with
1543  * segments. Ideally we want to move to the previous keyframe in
1544  * the segment but there might not be a keyframe in the segment. In
1545  * fact, none of the segments could contain a keyframe. We take a
1546  * practical approach: seek to the previous keyframe in the segment,
1547  * if there is none, seek to the beginning of the segment.
1548  *
1549  * Called with STREAM_LOCK
1550  */
1551 static gboolean
1552 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1553     guint32 seqnum, GstSeekFlags flags)
1554 {
1555   gint64 desired_offset;
1556   gint n;
1557
1558   desired_offset = segment->position;
1559
1560   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1561       GST_TIME_ARGS (desired_offset));
1562
1563   /* may not have enough fragmented info to do this adjustment,
1564    * and we can't scan (and probably should not) at this time with
1565    * possibly flushing upstream */
1566   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1567     gint64 min_offset;
1568     gboolean next, before, after;
1569
1570     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1571     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1572     next = after && !before;
1573     if (segment->rate < 0)
1574       next = !next;
1575
1576     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1577         NULL);
1578     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1579         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1580     desired_offset = min_offset;
1581   }
1582
1583   /* and set all streams to the final position */
1584   gst_flow_combiner_reset (qtdemux->flowcombiner);
1585   qtdemux->segment_seqnum = seqnum;
1586   for (n = 0; n < qtdemux->n_streams; n++) {
1587     QtDemuxStream *stream = qtdemux->streams[n];
1588
1589     stream->time_position = desired_offset;
1590     stream->accumulated_base = 0;
1591     stream->sample_index = -1;
1592     stream->offset_in_sample = 0;
1593     stream->segment_index = -1;
1594     stream->sent_eos = FALSE;
1595
1596     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1597       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1598   }
1599   segment->position = desired_offset;
1600   segment->time = desired_offset;
1601   if (segment->rate >= 0) {
1602     segment->start = desired_offset;
1603
1604     /* we stop at the end */
1605     if (segment->stop == -1)
1606       segment->stop = segment->duration;
1607   } else {
1608     segment->stop = desired_offset;
1609   }
1610
1611   if (qtdemux->fragmented)
1612     qtdemux->fragmented_seek_pending = TRUE;
1613
1614   return TRUE;
1615 }
1616
1617 /* do a seek in pull based mode */
1618 static gboolean
1619 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1620 {
1621   gdouble rate;
1622   GstFormat format;
1623   GstSeekFlags flags;
1624   GstSeekType cur_type, stop_type;
1625   gint64 cur, stop;
1626   gboolean flush;
1627   gboolean update;
1628   GstSegment seeksegment;
1629   guint32 seqnum = 0;
1630   GstEvent *flush_event;
1631   gboolean ret;
1632
1633   if (event) {
1634     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1635
1636     gst_event_parse_seek (event, &rate, &format, &flags,
1637         &cur_type, &cur, &stop_type, &stop);
1638     seqnum = gst_event_get_seqnum (event);
1639
1640     /* we have to have a format as the segment format. Try to convert
1641      * if not. */
1642     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1643             stop_type, &stop))
1644       goto no_format;
1645
1646     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1647   } else {
1648     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1649     flags = 0;
1650   }
1651
1652   flush = flags & GST_SEEK_FLAG_FLUSH;
1653
1654   /* stop streaming, either by flushing or by pausing the task */
1655   if (flush) {
1656     flush_event = gst_event_new_flush_start ();
1657     if (seqnum)
1658       gst_event_set_seqnum (flush_event, seqnum);
1659     /* unlock upstream pull_range */
1660     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1661     /* make sure out loop function exits */
1662     gst_qtdemux_push_event (qtdemux, flush_event);
1663   } else {
1664     /* non flushing seek, pause the task */
1665     gst_pad_pause_task (qtdemux->sinkpad);
1666   }
1667
1668   /* wait for streaming to finish */
1669   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1670
1671   /* copy segment, we need this because we still need the old
1672    * segment when we close the current segment. */
1673   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1674
1675   if (event) {
1676     /* configure the segment with the seek variables */
1677     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1678     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1679             cur_type, cur, stop_type, stop, &update)) {
1680       ret = FALSE;
1681       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1682     } else {
1683       /* now do the seek */
1684       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1685     }
1686   } else {
1687     /* now do the seek */
1688     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1689   }
1690
1691   /* prepare for streaming again */
1692   if (flush) {
1693     flush_event = gst_event_new_flush_stop (TRUE);
1694     if (seqnum)
1695       gst_event_set_seqnum (flush_event, seqnum);
1696
1697     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1698     gst_qtdemux_push_event (qtdemux, flush_event);
1699   }
1700
1701   /* commit the new segment */
1702   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1703
1704   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1705     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1706         qtdemux->segment.format, qtdemux->segment.position);
1707     if (seqnum)
1708       gst_message_set_seqnum (msg, seqnum);
1709     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1710   }
1711
1712   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1713   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1714       qtdemux->sinkpad, NULL);
1715
1716   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1717
1718   return ret;
1719
1720   /* ERRORS */
1721 no_format:
1722   {
1723     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1724     return FALSE;
1725   }
1726 }
1727
1728 static gboolean
1729 qtdemux_ensure_index (GstQTDemux * qtdemux)
1730 {
1731   guint i;
1732
1733   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1734
1735   /* Build complete index */
1736   for (i = 0; i < qtdemux->n_streams; i++) {
1737     QtDemuxStream *stream = qtdemux->streams[i];
1738
1739     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1740       goto parse_error;
1741   }
1742   return TRUE;
1743
1744   /* ERRORS */
1745 parse_error:
1746   {
1747     GST_LOG_OBJECT (qtdemux,
1748         "Building complete index of stream %u for seeking failed!", i);
1749     return FALSE;
1750   }
1751 }
1752
1753 static gboolean
1754 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1755     GstEvent * event)
1756 {
1757   gboolean res = TRUE;
1758   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1759
1760   switch (GST_EVENT_TYPE (event)) {
1761     case GST_EVENT_SEEK:
1762     {
1763 #ifndef GST_DISABLE_GST_DEBUG
1764       GstClockTime ts = gst_util_get_timestamp ();
1765 #endif
1766       guint32 seqnum = gst_event_get_seqnum (event);
1767
1768       if (seqnum == qtdemux->segment_seqnum) {
1769         GST_LOG_OBJECT (pad,
1770             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1771         gst_event_unref (event);
1772         return TRUE;
1773       }
1774
1775       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1776         /* seek should be handled by upstream, we might need to re-download fragments */
1777         GST_DEBUG_OBJECT (qtdemux,
1778             "let upstream handle seek for fragmented playback");
1779         goto upstream;
1780       }
1781
1782       /* Build complete index for seeking;
1783        * if not a fragmented file at least */
1784       if (!qtdemux->fragmented)
1785         if (!qtdemux_ensure_index (qtdemux))
1786           goto index_failed;
1787 #ifndef GST_DISABLE_GST_DEBUG
1788       ts = gst_util_get_timestamp () - ts;
1789       GST_INFO_OBJECT (qtdemux,
1790           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1791 #endif
1792     }
1793       if (qtdemux->pullbased) {
1794         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1795       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1796         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1797         res = TRUE;
1798       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1799           && !qtdemux->fragmented) {
1800         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1801       } else {
1802         GST_DEBUG_OBJECT (qtdemux,
1803             "ignoring seek in push mode in current state");
1804         res = FALSE;
1805       }
1806       gst_event_unref (event);
1807       break;
1808     default:
1809     upstream:
1810       res = gst_pad_event_default (pad, parent, event);
1811       break;
1812   }
1813
1814 done:
1815   return res;
1816
1817   /* ERRORS */
1818 index_failed:
1819   {
1820     GST_ERROR_OBJECT (qtdemux, "Index failed");
1821     gst_event_unref (event);
1822     res = FALSE;
1823     goto done;
1824   }
1825 }
1826
1827 /* stream/index return sample that is min/max w.r.t. byte position,
1828  * time is min/max w.r.t. time of samples,
1829  * the latter need not be time of the former sample */
1830 static void
1831 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1832     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1833 {
1834   gint i, n, index;
1835   gint64 time, min_time;
1836   QtDemuxStream *stream;
1837
1838   min_time = -1;
1839   stream = NULL;
1840   index = -1;
1841
1842   for (n = 0; n < qtdemux->n_streams; ++n) {
1843     QtDemuxStream *str;
1844     gint inc;
1845     gboolean set_sample;
1846
1847     str = qtdemux->streams[n];
1848     set_sample = !set;
1849
1850     if (fw) {
1851       i = 0;
1852       inc = 1;
1853     } else {
1854       i = str->n_samples - 1;
1855       inc = -1;
1856     }
1857
1858     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1859       if (str->samples[i].size == 0)
1860         continue;
1861
1862       if (fw && (str->samples[i].offset < byte_pos))
1863         continue;
1864
1865       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1866         continue;
1867
1868       /* move stream to first available sample */
1869       if (set) {
1870         gst_qtdemux_move_stream (qtdemux, str, i);
1871         set_sample = TRUE;
1872       }
1873
1874       /* avoid index from sparse streams since they might be far away */
1875       if (!CUR_STREAM (str)->sparse) {
1876         /* determine min/max time */
1877         time = QTSAMPLE_PTS (str, &str->samples[i]);
1878         if (min_time == -1 || (!fw && time > min_time) ||
1879             (fw && time < min_time)) {
1880           min_time = time;
1881         }
1882
1883         /* determine stream with leading sample, to get its position */
1884         if (!stream ||
1885             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1886             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1887           stream = str;
1888           index = i;
1889         }
1890       }
1891       break;
1892     }
1893
1894     /* no sample for this stream, mark eos */
1895     if (!set_sample)
1896       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1897   }
1898
1899   if (_time)
1900     *_time = min_time;
1901   if (_stream)
1902     *_stream = stream;
1903   if (_index)
1904     *_index = index;
1905 }
1906
1907 static QtDemuxStream *
1908 _create_stream (void)
1909 {
1910   QtDemuxStream *stream;
1911
1912   stream = g_new0 (QtDemuxStream, 1);
1913   /* new streams always need a discont */
1914   stream->discont = TRUE;
1915   /* we enable clipping for raw audio/video streams */
1916   stream->need_clip = FALSE;
1917   stream->need_process = FALSE;
1918   stream->segment_index = -1;
1919   stream->time_position = 0;
1920   stream->sample_index = -1;
1921   stream->offset_in_sample = 0;
1922   stream->new_stream = TRUE;
1923   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1924   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1925   stream->protected = FALSE;
1926   stream->protection_scheme_type = 0;
1927   stream->protection_scheme_version = 0;
1928   stream->protection_scheme_info = NULL;
1929   stream->n_samples_moof = 0;
1930   stream->duration_moof = 0;
1931   stream->duration_last_moof = 0;
1932   stream->alignment = 1;
1933   stream->stream_tags = gst_tag_list_new_empty ();
1934   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1935   g_queue_init (&stream->protection_scheme_event_queue);
1936   return stream;
1937 }
1938
1939 static gboolean
1940 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1941 {
1942   GstStructure *structure;
1943   const gchar *variant;
1944   const GstCaps *mediacaps = NULL;
1945
1946   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1947
1948   structure = gst_caps_get_structure (caps, 0);
1949   variant = gst_structure_get_string (structure, "variant");
1950
1951   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1952     QtDemuxStream *stream;
1953     const GValue *value;
1954
1955     demux->fragmented = TRUE;
1956     demux->mss_mode = TRUE;
1957
1958     if (demux->n_streams > 1) {
1959       /* can't do this, we can only renegotiate for another mss format */
1960       return FALSE;
1961     }
1962
1963     value = gst_structure_get_value (structure, "media-caps");
1964     /* create stream */
1965     if (value) {
1966       const GValue *timescale_v;
1967
1968       /* TODO update when stream changes during playback */
1969
1970       if (demux->n_streams == 0) {
1971         stream = _create_stream ();
1972         demux->streams[demux->n_streams] = stream;
1973         demux->n_streams = 1;
1974       } else {
1975         stream = demux->streams[0];
1976       }
1977
1978       timescale_v = gst_structure_get_value (structure, "timescale");
1979       if (timescale_v) {
1980         stream->timescale = g_value_get_uint64 (timescale_v);
1981       } else {
1982         /* default mss timescale */
1983         stream->timescale = 10000000;
1984       }
1985       demux->timescale = stream->timescale;
1986
1987       mediacaps = gst_value_get_caps (value);
1988       if (!CUR_STREAM (stream)->caps
1989           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1990         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1991             mediacaps);
1992         stream->new_caps = TRUE;
1993       }
1994       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1995       structure = gst_caps_get_structure (mediacaps, 0);
1996       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1997         stream->subtype = FOURCC_vide;
1998
1999         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2000         gst_structure_get_int (structure, "height",
2001             &CUR_STREAM (stream)->height);
2002         gst_structure_get_fraction (structure, "framerate",
2003             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2004       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2005         gint rate = 0;
2006         stream->subtype = FOURCC_soun;
2007         gst_structure_get_int (structure, "channels",
2008             &CUR_STREAM (stream)->n_channels);
2009         gst_structure_get_int (structure, "rate", &rate);
2010         CUR_STREAM (stream)->rate = rate;
2011       }
2012     }
2013     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2014   } else {
2015     demux->mss_mode = FALSE;
2016   }
2017
2018   return TRUE;
2019 }
2020
2021 static void
2022 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2023 {
2024   gint n;
2025
2026   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2027   gst_pad_stop_task (qtdemux->sinkpad);
2028
2029   if (hard || qtdemux->upstream_format_is_time) {
2030     qtdemux->state = QTDEMUX_STATE_INITIAL;
2031     qtdemux->neededbytes = 16;
2032     qtdemux->todrop = 0;
2033     qtdemux->pullbased = FALSE;
2034     qtdemux->posted_redirect = FALSE;
2035     qtdemux->first_mdat = -1;
2036     qtdemux->header_size = 0;
2037     qtdemux->mdatoffset = -1;
2038     qtdemux->restoredata_offset = -1;
2039     if (qtdemux->mdatbuffer)
2040       gst_buffer_unref (qtdemux->mdatbuffer);
2041     if (qtdemux->restoredata_buffer)
2042       gst_buffer_unref (qtdemux->restoredata_buffer);
2043     qtdemux->mdatbuffer = NULL;
2044     qtdemux->restoredata_buffer = NULL;
2045     qtdemux->mdatleft = 0;
2046     qtdemux->mdatsize = 0;
2047     if (qtdemux->comp_brands)
2048       gst_buffer_unref (qtdemux->comp_brands);
2049     qtdemux->comp_brands = NULL;
2050     qtdemux->last_moov_offset = -1;
2051     if (qtdemux->moov_node_compressed) {
2052       g_node_destroy (qtdemux->moov_node_compressed);
2053       if (qtdemux->moov_node)
2054         g_free (qtdemux->moov_node->data);
2055     }
2056     qtdemux->moov_node_compressed = NULL;
2057     if (qtdemux->moov_node)
2058       g_node_destroy (qtdemux->moov_node);
2059     qtdemux->moov_node = NULL;
2060     if (qtdemux->tag_list)
2061       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2062     qtdemux->tag_list = gst_tag_list_new_empty ();
2063     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2064 #if 0
2065     if (qtdemux->element_index)
2066       gst_object_unref (qtdemux->element_index);
2067     qtdemux->element_index = NULL;
2068 #endif
2069     qtdemux->major_brand = 0;
2070     if (qtdemux->pending_newsegment)
2071       gst_event_unref (qtdemux->pending_newsegment);
2072     qtdemux->pending_newsegment = NULL;
2073     qtdemux->upstream_format_is_time = FALSE;
2074     qtdemux->upstream_seekable = FALSE;
2075     qtdemux->upstream_size = 0;
2076
2077     qtdemux->fragment_start = -1;
2078     qtdemux->fragment_start_offset = -1;
2079     qtdemux->duration = 0;
2080     qtdemux->moof_offset = 0;
2081     qtdemux->chapters_track_id = 0;
2082     qtdemux->have_group_id = FALSE;
2083     qtdemux->group_id = G_MAXUINT;
2084
2085     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2086         NULL);
2087     g_queue_clear (&qtdemux->protection_event_queue);
2088   }
2089   qtdemux->offset = 0;
2090   gst_adapter_clear (qtdemux->adapter);
2091   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2092   qtdemux->segment_seqnum = 0;
2093
2094   if (hard) {
2095     for (n = 0; n < qtdemux->n_streams; n++) {
2096       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2097       qtdemux->streams[n] = NULL;
2098     }
2099     qtdemux->n_streams = 0;
2100     qtdemux->n_video_streams = 0;
2101     qtdemux->n_audio_streams = 0;
2102     qtdemux->n_sub_streams = 0;
2103     qtdemux->exposed = FALSE;
2104     qtdemux->fragmented = FALSE;
2105     qtdemux->mss_mode = FALSE;
2106     gst_caps_replace (&qtdemux->media_caps, NULL);
2107     qtdemux->timescale = 0;
2108     qtdemux->got_moov = FALSE;
2109     if (qtdemux->protection_system_ids) {
2110       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2111       qtdemux->protection_system_ids = NULL;
2112     }
2113   } else if (qtdemux->mss_mode) {
2114     gst_flow_combiner_reset (qtdemux->flowcombiner);
2115     for (n = 0; n < qtdemux->n_streams; n++)
2116       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2117   } else {
2118     gst_flow_combiner_reset (qtdemux->flowcombiner);
2119     for (n = 0; n < qtdemux->n_streams; n++) {
2120       qtdemux->streams[n]->sent_eos = FALSE;
2121       qtdemux->streams[n]->time_position = 0;
2122       qtdemux->streams[n]->accumulated_base = 0;
2123     }
2124     if (!qtdemux->pending_newsegment) {
2125       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2126       if (qtdemux->segment_seqnum)
2127         gst_event_set_seqnum (qtdemux->pending_newsegment,
2128             qtdemux->segment_seqnum);
2129     }
2130   }
2131 }
2132
2133
2134 /* Maps the @segment to the qt edts internal segments and pushes
2135  * the correspnding segment event.
2136  *
2137  * If it ends up being at a empty segment, a gap will be pushed and the next
2138  * edts segment will be activated in sequence.
2139  *
2140  * To be used in push-mode only */
2141 static void
2142 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2143 {
2144   gint n, i;
2145
2146   for (n = 0; n < qtdemux->n_streams; n++) {
2147     QtDemuxStream *stream = qtdemux->streams[n];
2148
2149     stream->time_position = segment->start;
2150
2151     /* in push mode we should be guaranteed that we will have empty segments
2152      * at the beginning and then one segment after, other scenarios are not
2153      * supported and are discarded when parsing the edts */
2154     for (i = 0; i < stream->n_segments; i++) {
2155       if (stream->segments[i].stop_time > segment->start) {
2156         gst_qtdemux_activate_segment (qtdemux, stream, i,
2157             stream->time_position);
2158         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2159           /* push the empty segment and move to the next one */
2160           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2161               stream->time_position);
2162           continue;
2163         }
2164
2165         g_assert (i == stream->n_segments - 1);
2166       }
2167     }
2168   }
2169 }
2170
2171 static gboolean
2172 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2173     GstEvent * event)
2174 {
2175   GstQTDemux *demux = GST_QTDEMUX (parent);
2176   gboolean res = TRUE;
2177
2178   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2179
2180   switch (GST_EVENT_TYPE (event)) {
2181     case GST_EVENT_SEGMENT:
2182     {
2183       gint64 offset = 0;
2184       QtDemuxStream *stream;
2185       gint idx;
2186       GstSegment segment;
2187
2188       /* some debug output */
2189       gst_event_copy_segment (event, &segment);
2190       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2191           &segment);
2192
2193       /* erase any previously set segment */
2194       gst_event_replace (&demux->pending_newsegment, NULL);
2195
2196       if (segment.format == GST_FORMAT_TIME) {
2197         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2198         gst_event_replace (&demux->pending_newsegment, event);
2199         demux->upstream_format_is_time = TRUE;
2200       } else {
2201         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2202             "not in time format");
2203
2204         /* chain will send initial newsegment after pads have been added */
2205         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2206           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2207           goto exit;
2208         }
2209       }
2210
2211       /* check if this matches a time seek we received previously
2212        * FIXME for backwards compatibility reasons we use the
2213        * seek_offset here to compare. In the future we might want to
2214        * change this to use the seqnum as it uniquely should identify
2215        * the segment that corresponds to the seek. */
2216       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2217           ", received segment offset %" G_GINT64_FORMAT,
2218           demux->seek_offset, segment.start);
2219       if (segment.format == GST_FORMAT_BYTES
2220           && demux->seek_offset == segment.start) {
2221         GST_OBJECT_LOCK (demux);
2222         offset = segment.start;
2223
2224         segment.format = GST_FORMAT_TIME;
2225         segment.start = demux->push_seek_start;
2226         segment.stop = demux->push_seek_stop;
2227         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2228             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2229             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2230         GST_OBJECT_UNLOCK (demux);
2231       }
2232
2233       /* we only expect a BYTE segment, e.g. following a seek */
2234       if (segment.format == GST_FORMAT_BYTES) {
2235         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2236           offset = segment.start;
2237
2238           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2239               NULL, (gint64 *) & segment.start);
2240           if ((gint64) segment.start < 0)
2241             segment.start = 0;
2242         }
2243         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2244           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2245               NULL, (gint64 *) & segment.stop);
2246           /* keyframe seeking should already arrange for start >= stop,
2247            * but make sure in other rare cases */
2248           segment.stop = MAX (segment.stop, segment.start);
2249         }
2250       } else if (segment.format == GST_FORMAT_TIME) {
2251         /* push all data on the adapter before starting this
2252          * new segment */
2253         gst_qtdemux_process_adapter (demux, TRUE);
2254       } else {
2255         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2256         goto exit;
2257       }
2258
2259       /* We shouldn't modify upstream driven TIME FORMAT segment */
2260       if (!demux->upstream_format_is_time) {
2261         /* accept upstream's notion of segment and distribute along */
2262         segment.format = GST_FORMAT_TIME;
2263         segment.position = segment.time = segment.start;
2264         segment.duration = demux->segment.duration;
2265         segment.base = gst_segment_to_running_time (&demux->segment,
2266             GST_FORMAT_TIME, demux->segment.position);
2267       }
2268
2269       gst_segment_copy_into (&segment, &demux->segment);
2270       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2271
2272       /* map segment to internal qt segments and push on each stream */
2273       if (demux->n_streams) {
2274         if (demux->fragmented) {
2275           GstEvent *segment_event = gst_event_new_segment (&segment);
2276
2277           gst_event_replace (&demux->pending_newsegment, NULL);
2278           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2279           gst_qtdemux_push_event (demux, segment_event);
2280         } else {
2281           gst_event_replace (&demux->pending_newsegment, NULL);
2282           gst_qtdemux_map_and_push_segments (demux, &segment);
2283         }
2284       }
2285
2286       /* clear leftover in current segment, if any */
2287       gst_adapter_clear (demux->adapter);
2288
2289       /* set up streaming thread */
2290       demux->offset = offset;
2291       if (demux->upstream_format_is_time) {
2292         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2293             "set values to restart reading from a new atom");
2294         demux->neededbytes = 16;
2295         demux->todrop = 0;
2296       } else {
2297         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2298             NULL);
2299         if (stream) {
2300           demux->todrop = stream->samples[idx].offset - offset;
2301           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2302         } else {
2303           /* set up for EOS */
2304           demux->neededbytes = -1;
2305           demux->todrop = 0;
2306         }
2307       }
2308     exit:
2309       gst_event_unref (event);
2310       res = TRUE;
2311       goto drop;
2312     }
2313     case GST_EVENT_FLUSH_START:
2314     {
2315       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2316         gst_event_unref (event);
2317         goto drop;
2318       }
2319       break;
2320     }
2321     case GST_EVENT_FLUSH_STOP:
2322     {
2323       guint64 dur;
2324
2325       dur = demux->segment.duration;
2326       gst_qtdemux_reset (demux, FALSE);
2327       demux->segment.duration = dur;
2328
2329       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2330         gst_event_unref (event);
2331         goto drop;
2332       }
2333       break;
2334     }
2335     case GST_EVENT_EOS:
2336       /* If we are in push mode, and get an EOS before we've seen any streams,
2337        * then error out - we have nowhere to send the EOS */
2338       if (!demux->pullbased) {
2339         gint i;
2340         gboolean has_valid_stream = FALSE;
2341         for (i = 0; i < demux->n_streams; i++) {
2342           if (demux->streams[i]->pad != NULL) {
2343             has_valid_stream = TRUE;
2344             break;
2345           }
2346         }
2347         if (!has_valid_stream)
2348           gst_qtdemux_post_no_playable_stream_error (demux);
2349         else {
2350           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2351               (guint) gst_adapter_available (demux->adapter));
2352           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2353             res = FALSE;
2354           }
2355         }
2356       }
2357       break;
2358     case GST_EVENT_CAPS:{
2359       GstCaps *caps = NULL;
2360
2361       gst_event_parse_caps (event, &caps);
2362       gst_qtdemux_setcaps (demux, caps);
2363       res = TRUE;
2364       gst_event_unref (event);
2365       goto drop;
2366     }
2367     case GST_EVENT_PROTECTION:
2368     {
2369       const gchar *system_id = NULL;
2370
2371       gst_event_parse_protection (event, &system_id, NULL, NULL);
2372       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2373           system_id);
2374       gst_qtdemux_append_protection_system_id (demux, system_id);
2375       /* save the event for later, for source pads that have not been created */
2376       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2377       /* send it to all pads that already exist */
2378       gst_qtdemux_push_event (demux, event);
2379       res = TRUE;
2380       goto drop;
2381     }
2382     default:
2383       break;
2384   }
2385
2386   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2387
2388 drop:
2389   return res;
2390 }
2391
2392 #if 0
2393 static void
2394 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2395 {
2396   GstQTDemux *demux = GST_QTDEMUX (element);
2397
2398   GST_OBJECT_LOCK (demux);
2399   if (demux->element_index)
2400     gst_object_unref (demux->element_index);
2401   if (index) {
2402     demux->element_index = gst_object_ref (index);
2403   } else {
2404     demux->element_index = NULL;
2405   }
2406   GST_OBJECT_UNLOCK (demux);
2407   /* object lock might be taken again */
2408   if (index)
2409     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2410   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2411       demux->element_index, demux->index_id);
2412 }
2413
2414 static GstIndex *
2415 gst_qtdemux_get_index (GstElement * element)
2416 {
2417   GstIndex *result = NULL;
2418   GstQTDemux *demux = GST_QTDEMUX (element);
2419
2420   GST_OBJECT_LOCK (demux);
2421   if (demux->element_index)
2422     result = gst_object_ref (demux->element_index);
2423   GST_OBJECT_UNLOCK (demux);
2424
2425   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2426
2427   return result;
2428 }
2429 #endif
2430
2431 static void
2432 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2433 {
2434   g_free ((gpointer) stream->stco.data);
2435   stream->stco.data = NULL;
2436   g_free ((gpointer) stream->stsz.data);
2437   stream->stsz.data = NULL;
2438   g_free ((gpointer) stream->stsc.data);
2439   stream->stsc.data = NULL;
2440   g_free ((gpointer) stream->stts.data);
2441   stream->stts.data = NULL;
2442   g_free ((gpointer) stream->stss.data);
2443   stream->stss.data = NULL;
2444   g_free ((gpointer) stream->stps.data);
2445   stream->stps.data = NULL;
2446   g_free ((gpointer) stream->ctts.data);
2447   stream->ctts.data = NULL;
2448 }
2449
2450 static void
2451 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2452     QtDemuxStream * stream)
2453 {
2454   g_free (stream->segments);
2455   stream->segments = NULL;
2456   stream->segment_index = -1;
2457   stream->accumulated_base = 0;
2458 }
2459
2460 static void
2461 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2462     QtDemuxStream * stream)
2463 {
2464   g_free (stream->samples);
2465   stream->samples = NULL;
2466   gst_qtdemux_stbl_free (stream);
2467
2468   /* fragments */
2469   g_free (stream->ra_entries);
2470   stream->ra_entries = NULL;
2471   stream->n_ra_entries = 0;
2472
2473   stream->sample_index = -1;
2474   stream->stbl_index = -1;
2475   stream->n_samples = 0;
2476   stream->time_position = 0;
2477
2478   stream->n_samples_moof = 0;
2479   stream->duration_moof = 0;
2480   stream->duration_last_moof = 0;
2481 }
2482
2483 static void
2484 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2485 {
2486   gint i;
2487   if (stream->allocator)
2488     gst_object_unref (stream->allocator);
2489   while (stream->buffers) {
2490     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2491     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2492   }
2493   for (i = 0; i < stream->stsd_entries_length; i++) {
2494     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2495     if (entry->rgb8_palette) {
2496       gst_memory_unref (entry->rgb8_palette);
2497       entry->rgb8_palette = NULL;
2498     }
2499     entry->sparse = FALSE;
2500   }
2501
2502   gst_tag_list_unref (stream->stream_tags);
2503   stream->stream_tags = gst_tag_list_new_empty ();
2504   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2505   g_free (stream->redirect_uri);
2506   stream->redirect_uri = NULL;
2507   stream->sent_eos = FALSE;
2508   stream->protected = FALSE;
2509   if (stream->protection_scheme_info) {
2510     if (stream->protection_scheme_type == FOURCC_cenc) {
2511       QtDemuxCencSampleSetInfo *info =
2512           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2513       if (info->default_properties)
2514         gst_structure_free (info->default_properties);
2515       if (info->crypto_info)
2516         g_ptr_array_free (info->crypto_info, TRUE);
2517     }
2518     g_free (stream->protection_scheme_info);
2519     stream->protection_scheme_info = NULL;
2520   }
2521   stream->protection_scheme_type = 0;
2522   stream->protection_scheme_version = 0;
2523   g_queue_foreach (&stream->protection_scheme_event_queue,
2524       (GFunc) gst_event_unref, NULL);
2525   g_queue_clear (&stream->protection_scheme_event_queue);
2526   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2527   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2528 }
2529
2530 static void
2531 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2532 {
2533   gint i;
2534   gst_qtdemux_stream_clear (qtdemux, stream);
2535   for (i = 0; i < stream->stsd_entries_length; i++) {
2536     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2537     if (entry->caps) {
2538       gst_caps_unref (entry->caps);
2539       entry->caps = NULL;
2540     }
2541   }
2542   gst_tag_list_unref (stream->stream_tags);
2543   if (stream->pad) {
2544     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2545     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2546   }
2547   g_free (stream->stsd_entries);
2548   g_free (stream);
2549 }
2550
2551 static void
2552 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2553 {
2554   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2555
2556   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2557   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2558   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2559   qtdemux->n_streams--;
2560 }
2561
2562 static GstStateChangeReturn
2563 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2564 {
2565   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2566   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2567
2568   switch (transition) {
2569     case GST_STATE_CHANGE_PAUSED_TO_READY:
2570       break;
2571     default:
2572       break;
2573   }
2574
2575   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2576
2577   switch (transition) {
2578     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2579       gst_qtdemux_reset (qtdemux, TRUE);
2580       break;
2581     }
2582     default:
2583       break;
2584   }
2585
2586   return result;
2587 }
2588
2589 static void
2590 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2591 {
2592   /* counts as header data */
2593   qtdemux->header_size += length;
2594
2595   /* only consider at least a sufficiently complete ftyp atom */
2596   if (length >= 20) {
2597     GstBuffer *buf;
2598
2599     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2600     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2601         GST_FOURCC_ARGS (qtdemux->major_brand));
2602     if (qtdemux->comp_brands)
2603       gst_buffer_unref (qtdemux->comp_brands);
2604     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2605     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2606   }
2607 }
2608
2609 static void
2610 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2611     GstTagList * xmptaglist)
2612 {
2613   /* Strip out bogus fields */
2614   if (xmptaglist) {
2615     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2616       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2617       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2618     } else {
2619       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2620     }
2621
2622     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2623
2624     /* prioritize native tags using _KEEP mode */
2625     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2626     gst_tag_list_unref (xmptaglist);
2627   }
2628 }
2629
2630 static void
2631 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2632     guint offset)
2633 {
2634   GstByteReader br;
2635   guint8 version;
2636   guint32 flags = 0;
2637   guint i;
2638   guint8 iv_size = 8;
2639   QtDemuxStream *stream;
2640   GstStructure *structure;
2641   QtDemuxCencSampleSetInfo *ss_info = NULL;
2642   const gchar *system_id;
2643   gboolean uses_sub_sample_encryption = FALSE;
2644
2645   if (qtdemux->n_streams == 0)
2646     return;
2647
2648   stream = qtdemux->streams[0];
2649
2650   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2651   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2652     GST_WARNING_OBJECT (qtdemux,
2653         "Attempting PIFF box parsing on an unencrypted stream.");
2654     return;
2655   }
2656
2657   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2658       G_TYPE_STRING, &system_id, NULL);
2659   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2660
2661   stream->protected = TRUE;
2662   stream->protection_scheme_type = FOURCC_cenc;
2663
2664   if (!stream->protection_scheme_info)
2665     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2666
2667   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2668
2669   if (ss_info->default_properties)
2670     gst_structure_free (ss_info->default_properties);
2671
2672   ss_info->default_properties =
2673       gst_structure_new ("application/x-cenc",
2674       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2675
2676   if (ss_info->crypto_info) {
2677     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2678     g_ptr_array_free (ss_info->crypto_info, TRUE);
2679     ss_info->crypto_info = NULL;
2680   }
2681
2682   /* skip UUID */
2683   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2684
2685   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2686     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2687     return;
2688   }
2689
2690   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2691     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2692     return;
2693   }
2694
2695   if ((flags & 0x000001)) {
2696     guint32 algorithm_id = 0;
2697     const guint8 *kid;
2698     GstBuffer *kid_buf;
2699     gboolean is_encrypted = TRUE;
2700
2701     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2702       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2703       return;
2704     }
2705
2706     algorithm_id >>= 8;
2707     if (algorithm_id == 0) {
2708       is_encrypted = FALSE;
2709     } else if (algorithm_id == 1) {
2710       /* FIXME: maybe store this in properties? */
2711       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2712     } else if (algorithm_id == 2) {
2713       /* FIXME: maybe store this in properties? */
2714       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2715     }
2716
2717     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2718       return;
2719
2720     if (!gst_byte_reader_get_data (&br, 16, &kid))
2721       return;
2722
2723     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2724     gst_buffer_fill (kid_buf, 0, kid, 16);
2725     if (ss_info->default_properties)
2726       gst_structure_free (ss_info->default_properties);
2727     ss_info->default_properties =
2728         gst_structure_new ("application/x-cenc",
2729         "iv_size", G_TYPE_UINT, iv_size,
2730         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2731         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2732     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2733         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2734     gst_buffer_unref (kid_buf);
2735   } else if ((flags & 0x000002)) {
2736     uses_sub_sample_encryption = TRUE;
2737   }
2738
2739   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2740     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2741     return;
2742   }
2743
2744   ss_info->crypto_info =
2745       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2746       (GDestroyNotify) qtdemux_gst_structure_free);
2747
2748   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2749     GstStructure *properties;
2750     guint8 *data;
2751     GstBuffer *buf;
2752
2753     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2754     if (properties == NULL) {
2755       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2756       return;
2757     }
2758
2759     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2760       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2761       gst_structure_free (properties);
2762       return;
2763     }
2764     buf = gst_buffer_new_wrapped (data, iv_size);
2765     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2766     gst_buffer_unref (buf);
2767
2768     if (uses_sub_sample_encryption) {
2769       guint16 n_subsamples;
2770
2771       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2772           || n_subsamples == 0) {
2773         GST_ERROR_OBJECT (qtdemux,
2774             "failed to get subsample count for sample %u", i);
2775         gst_structure_free (properties);
2776         return;
2777       }
2778       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2779       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2780         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2781             i);
2782         gst_structure_free (properties);
2783         return;
2784       }
2785       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2786       gst_structure_set (properties,
2787           "subsample_count", G_TYPE_UINT, n_subsamples,
2788           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2789       gst_buffer_unref (buf);
2790     } else {
2791       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2792     }
2793
2794     g_ptr_array_add (ss_info->crypto_info, properties);
2795   }
2796 }
2797
2798 static void
2799 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2800 {
2801   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2802     0x97, 0xA9, 0x42, 0xE8,
2803     0x9C, 0x71, 0x99, 0x94,
2804     0x91, 0xE3, 0xAF, 0xAC
2805   };
2806   static const guint8 playready_uuid[] = {
2807     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2808     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2809   };
2810
2811   static const guint8 piff_sample_encryption_uuid[] = {
2812     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2813     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2814   };
2815
2816   guint offset;
2817
2818   /* counts as header data */
2819   qtdemux->header_size += length;
2820
2821   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2822
2823   if (length <= offset + 16) {
2824     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2825     return;
2826   }
2827
2828   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2829     GstBuffer *buf;
2830     GstTagList *taglist;
2831
2832     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2833         length - offset - 16, NULL);
2834     taglist = gst_tag_list_from_xmp_buffer (buf);
2835     gst_buffer_unref (buf);
2836
2837     /* make sure we have a usable taglist */
2838     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2839
2840     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2841
2842   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2843     int len;
2844     const gunichar2 *s_utf16;
2845     char *contents;
2846
2847     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2848     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2849     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2850     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2851
2852     g_free (contents);
2853
2854     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2855         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2856         (NULL));
2857   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2858     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2859   } else {
2860     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2861         GST_READ_UINT32_LE (buffer + offset),
2862         GST_READ_UINT32_LE (buffer + offset + 4),
2863         GST_READ_UINT32_LE (buffer + offset + 8),
2864         GST_READ_UINT32_LE (buffer + offset + 12));
2865   }
2866 }
2867
2868 static void
2869 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2870 {
2871   GstSidxParser sidx_parser;
2872   GstIsoffParserResult res;
2873   guint consumed;
2874
2875   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2876
2877   res =
2878       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2879       &consumed);
2880   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2881   if (res == GST_ISOFF_QT_PARSER_DONE) {
2882     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2883   }
2884   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2885 }
2886
2887 /* caller verifies at least 8 bytes in buf */
2888 static void
2889 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2890     guint64 * plength, guint32 * pfourcc)
2891 {
2892   guint64 length;
2893   guint32 fourcc;
2894
2895   length = QT_UINT32 (data);
2896   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2897   fourcc = QT_FOURCC (data + 4);
2898   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2899
2900   if (length == 0) {
2901     length = G_MAXUINT64;
2902   } else if (length == 1 && size >= 16) {
2903     /* this means we have an extended size, which is the 64 bit value of
2904      * the next 8 bytes */
2905     length = QT_UINT64 (data + 8);
2906     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2907   }
2908
2909   if (plength)
2910     *plength = length;
2911   if (pfourcc)
2912     *pfourcc = fourcc;
2913 }
2914
2915 static gboolean
2916 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2917 {
2918   guint32 version = 0;
2919   GstClockTime duration = 0;
2920
2921   if (!gst_byte_reader_get_uint32_be (br, &version))
2922     goto failed;
2923
2924   version >>= 24;
2925   if (version == 1) {
2926     if (!gst_byte_reader_get_uint64_be (br, &duration))
2927       goto failed;
2928   } else {
2929     guint32 dur = 0;
2930
2931     if (!gst_byte_reader_get_uint32_be (br, &dur))
2932       goto failed;
2933     duration = dur;
2934   }
2935
2936   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2937   qtdemux->duration = duration;
2938
2939   return TRUE;
2940
2941 failed:
2942   {
2943     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2944     return FALSE;
2945   }
2946 }
2947
2948 static gboolean
2949 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2950     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2951 {
2952   if (!stream->parsed_trex && qtdemux->moov_node) {
2953     GNode *mvex, *trex;
2954     GstByteReader trex_data;
2955
2956     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2957     if (mvex) {
2958       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2959           &trex_data);
2960       while (trex) {
2961         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2962
2963         /* skip version/flags */
2964         if (!gst_byte_reader_skip (&trex_data, 4))
2965           goto next;
2966         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2967           goto next;
2968         if (id != stream->track_id)
2969           goto next;
2970         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2971           goto next;
2972         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2973           goto next;
2974         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2975           goto next;
2976         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2977           goto next;
2978
2979         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2980             "duration %d,  size %d, flags 0x%x", stream->track_id,
2981             dur, size, flags);
2982
2983         stream->parsed_trex = TRUE;
2984         stream->def_sample_description_index = sdi;
2985         stream->def_sample_duration = dur;
2986         stream->def_sample_size = size;
2987         stream->def_sample_flags = flags;
2988
2989       next:
2990         /* iterate all siblings */
2991         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2992             &trex_data);
2993       }
2994     }
2995   }
2996
2997   *ds_duration = stream->def_sample_duration;
2998   *ds_size = stream->def_sample_size;
2999   *ds_flags = stream->def_sample_flags;
3000
3001   /* even then, above values are better than random ... */
3002   if (G_UNLIKELY (!stream->parsed_trex)) {
3003     GST_WARNING_OBJECT (qtdemux,
3004         "failed to find fragment defaults for stream %d", stream->track_id);
3005     return FALSE;
3006   }
3007
3008   return TRUE;
3009 }
3010
3011 /* This method should be called whenever a more accurate duration might
3012  * have been found. It will update all relevant variables if/where needed
3013  */
3014 static void
3015 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3016 {
3017   guint i;
3018   guint64 movdur;
3019   GstClockTime prevdur;
3020
3021   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3022
3023   if (movdur > qtdemux->duration) {
3024     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3025     GST_DEBUG_OBJECT (qtdemux,
3026         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3027         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3028     qtdemux->duration = movdur;
3029     GST_DEBUG_OBJECT (qtdemux,
3030         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3031         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3032         GST_TIME_ARGS (qtdemux->segment.stop));
3033     if (qtdemux->segment.duration == prevdur) {
3034       /* If the current segment has duration/stop identical to previous duration
3035        * update them also (because they were set at that point in time with
3036        * the wrong duration */
3037       /* We convert the value *from* the timescale version to avoid rounding errors */
3038       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3039       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3040       qtdemux->segment.duration = fixeddur;
3041       qtdemux->segment.stop = fixeddur;
3042     }
3043   }
3044   for (i = 0; i < qtdemux->n_streams; i++) {
3045     QtDemuxStream *stream = qtdemux->streams[i];
3046     if (stream) {
3047       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3048       if (movdur > stream->duration) {
3049         GST_DEBUG_OBJECT (qtdemux,
3050             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3051             GST_TIME_ARGS (duration));
3052         stream->duration = movdur;
3053         if (stream->dummy_segment) {
3054           /* Update all dummy values to new duration */
3055           stream->segments[0].stop_time = duration;
3056           stream->segments[0].duration = duration;
3057           stream->segments[0].media_stop = duration;
3058
3059           /* let downstream know we possibly have a new stop time */
3060           if (stream->segment_index != -1) {
3061             GstClockTime pos;
3062
3063             if (qtdemux->segment.rate >= 0) {
3064               pos = stream->segment.start;
3065             } else {
3066               pos = stream->segment.stop;
3067             }
3068
3069             gst_qtdemux_stream_update_segment (qtdemux, stream,
3070                 stream->segment_index, pos, NULL, NULL);
3071           }
3072         }
3073       }
3074     }
3075   }
3076 }
3077
3078 static gboolean
3079 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3080     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3081     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3082     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3083     gboolean has_tfdt)
3084 {
3085   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3086   guint64 timestamp;
3087   gint32 data_offset = 0;
3088   guint32 flags = 0, first_flags = 0, samples_count = 0;
3089   gint i;
3090   guint8 *data;
3091   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3092   QtDemuxSample *sample;
3093   gboolean ismv = FALSE;
3094   gint64 initial_offset;
3095
3096   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3097       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3098       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3099       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3100
3101   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3102     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3103     return TRUE;
3104   }
3105
3106   /* presence of stss or not can't really tell us much,
3107    * and flags and so on tend to be marginally reliable in these files */
3108   if (stream->subtype == FOURCC_soun) {
3109     GST_DEBUG_OBJECT (qtdemux,
3110         "sound track in fragmented file; marking all keyframes");
3111     stream->all_keyframe = TRUE;
3112   }
3113
3114   if (!gst_byte_reader_skip (trun, 1) ||
3115       !gst_byte_reader_get_uint24_be (trun, &flags))
3116     goto fail;
3117
3118   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3119     goto fail;
3120
3121   if (flags & TR_DATA_OFFSET) {
3122     /* note this is really signed */
3123     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3124       goto fail;
3125     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3126     /* default base offset = first byte of moof */
3127     if (*base_offset == -1) {
3128       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3129       *base_offset = moof_offset;
3130     }
3131     *running_offset = *base_offset + data_offset;
3132   } else {
3133     /* if no offset at all, that would mean data starts at moof start,
3134      * which is a bit wrong and is ismv crappy way, so compensate
3135      * assuming data is in mdat following moof */
3136     if (*base_offset == -1) {
3137       *base_offset = moof_offset + moof_length + 8;
3138       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3139       ismv = TRUE;
3140     }
3141     if (*running_offset == -1)
3142       *running_offset = *base_offset;
3143   }
3144
3145   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3146       *running_offset);
3147   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3148       data_offset, flags, samples_count);
3149
3150   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3151     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3152       GST_DEBUG_OBJECT (qtdemux,
3153           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3154       flags ^= TR_FIRST_SAMPLE_FLAGS;
3155     } else {
3156       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3157         goto fail;
3158       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3159     }
3160   }
3161
3162   /* FIXME ? spec says other bits should also be checked to determine
3163    * entry size (and prefix size for that matter) */
3164   entry_size = 0;
3165   dur_offset = size_offset = 0;
3166   if (flags & TR_SAMPLE_DURATION) {
3167     GST_LOG_OBJECT (qtdemux, "entry duration present");
3168     dur_offset = entry_size;
3169     entry_size += 4;
3170   }
3171   if (flags & TR_SAMPLE_SIZE) {
3172     GST_LOG_OBJECT (qtdemux, "entry size present");
3173     size_offset = entry_size;
3174     entry_size += 4;
3175   }
3176   if (flags & TR_SAMPLE_FLAGS) {
3177     GST_LOG_OBJECT (qtdemux, "entry flags present");
3178     flags_offset = entry_size;
3179     entry_size += 4;
3180   }
3181   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3182     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3183     ct_offset = entry_size;
3184     entry_size += 4;
3185   }
3186
3187   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3188     goto fail;
3189   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3190
3191   if (stream->n_samples + samples_count >=
3192       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3193     goto index_too_big;
3194
3195   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3196       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3197       (stream->n_samples + samples_count) *
3198       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3199
3200   /* create a new array of samples if it's the first sample parsed */
3201   if (stream->n_samples == 0) {
3202     g_assert (stream->samples == NULL);
3203     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3204     /* or try to reallocate it with space enough to insert the new samples */
3205   } else
3206     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3207         stream->n_samples + samples_count);
3208   if (stream->samples == NULL)
3209     goto out_of_memory;
3210
3211   if (qtdemux->fragment_start != -1) {
3212     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3213     qtdemux->fragment_start = -1;
3214   } else {
3215     if (stream->n_samples == 0) {
3216       if (decode_ts > 0) {
3217         timestamp = decode_ts;
3218       } else if (stream->pending_seek != NULL) {
3219         /* if we don't have a timestamp from a tfdt box, we'll use the one
3220          * from the mfra seek table */
3221         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3222             GST_TIME_ARGS (stream->pending_seek->ts));
3223
3224         /* FIXME: this is not fully correct, the timestamp refers to the random
3225          * access sample refered to in the tfra entry, which may not necessarily
3226          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3227         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3228       } else {
3229         timestamp = 0;
3230       }
3231
3232       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3233       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3234           GST_TIME_ARGS (gst_ts));
3235     } else {
3236       /* subsequent fragments extend stream */
3237       timestamp =
3238           stream->samples[stream->n_samples - 1].timestamp +
3239           stream->samples[stream->n_samples - 1].duration;
3240
3241       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3242        * difference (1 sec.) between decode_ts and timestamp, prefer the
3243        * former */
3244       if (has_tfdt && !qtdemux->upstream_format_is_time
3245           && ABSDIFF (decode_ts, timestamp) >
3246           MAX (stream->duration_last_moof / 2,
3247               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3248         GST_INFO_OBJECT (qtdemux,
3249             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3250             ") are significantly different (more than %" GST_TIME_FORMAT
3251             "), using decode_ts",
3252             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3253             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3254             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3255                     MAX (stream->duration_last_moof / 2,
3256                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3257         timestamp = decode_ts;
3258       }
3259
3260       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3261       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3262           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3263     }
3264   }
3265
3266   initial_offset = *running_offset;
3267
3268   sample = stream->samples + stream->n_samples;
3269   for (i = 0; i < samples_count; i++) {
3270     guint32 dur, size, sflags, ct;
3271
3272     /* first read sample data */
3273     if (flags & TR_SAMPLE_DURATION) {
3274       dur = QT_UINT32 (data + dur_offset);
3275     } else {
3276       dur = d_sample_duration;
3277     }
3278     if (flags & TR_SAMPLE_SIZE) {
3279       size = QT_UINT32 (data + size_offset);
3280     } else {
3281       size = d_sample_size;
3282     }
3283     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3284       if (i == 0) {
3285         sflags = first_flags;
3286       } else {
3287         sflags = d_sample_flags;
3288       }
3289     } else if (flags & TR_SAMPLE_FLAGS) {
3290       sflags = QT_UINT32 (data + flags_offset);
3291     } else {
3292       sflags = d_sample_flags;
3293     }
3294     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3295       ct = QT_UINT32 (data + ct_offset);
3296     } else {
3297       ct = 0;
3298     }
3299     data += entry_size;
3300
3301     /* fill the sample information */
3302     sample->offset = *running_offset;
3303     sample->pts_offset = ct;
3304     sample->size = size;
3305     sample->timestamp = timestamp;
3306     sample->duration = dur;
3307     /* sample-is-difference-sample */
3308     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3309      * now idea how it relates to bitfield other than massive LE/BE confusion */
3310     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3311     *running_offset += size;
3312     timestamp += dur;
3313     stream->duration_moof += dur;
3314     sample++;
3315   }
3316
3317   /* Update total duration if needed */
3318   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3319
3320   /* Pre-emptively figure out size of mdat based on trun information.
3321    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3322    * size, else we will still be able to use this when dealing with gap'ed
3323    * input */
3324   qtdemux->mdatleft = *running_offset - initial_offset;
3325   qtdemux->mdatoffset = initial_offset;
3326   qtdemux->mdatsize = qtdemux->mdatleft;
3327
3328   stream->n_samples += samples_count;
3329   stream->n_samples_moof += samples_count;
3330
3331   if (stream->pending_seek != NULL)
3332     stream->pending_seek = NULL;
3333
3334   return TRUE;
3335
3336 fail:
3337   {
3338     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3339     return FALSE;
3340   }
3341 out_of_memory:
3342   {
3343     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3344         stream->n_samples);
3345     return FALSE;
3346   }
3347 index_too_big:
3348   {
3349     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3350         "be larger than %uMB (broken file?)", stream->n_samples,
3351         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3352     return FALSE;
3353   }
3354 }
3355
3356 /* find stream with @id */
3357 static inline QtDemuxStream *
3358 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3359 {
3360   QtDemuxStream *stream;
3361   gint i;
3362
3363   /* check */
3364   if (G_UNLIKELY (!id)) {
3365     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3366     return NULL;
3367   }
3368
3369   /* try to get it fast and simple */
3370   if (G_LIKELY (id <= qtdemux->n_streams)) {
3371     stream = qtdemux->streams[id - 1];
3372     if (G_LIKELY (stream->track_id == id))
3373       return stream;
3374   }
3375
3376   /* linear search otherwise */
3377   for (i = 0; i < qtdemux->n_streams; i++) {
3378     stream = qtdemux->streams[i];
3379     if (stream->track_id == id)
3380       return stream;
3381   }
3382   if (qtdemux->mss_mode) {
3383     /* mss should have only 1 stream anyway */
3384     return qtdemux->streams[0];
3385   }
3386
3387   return NULL;
3388 }
3389
3390 static gboolean
3391 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3392     guint32 * fragment_number)
3393 {
3394   if (!gst_byte_reader_skip (mfhd, 4))
3395     goto fail;
3396   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3397     goto fail;
3398   return TRUE;
3399 fail:
3400   {
3401     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3402     return FALSE;
3403   }
3404 }
3405
3406 static gboolean
3407 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3408     QtDemuxStream ** stream, guint32 * default_sample_duration,
3409     guint32 * default_sample_size, guint32 * default_sample_flags,
3410     gint64 * base_offset)
3411 {
3412   guint32 flags = 0;
3413   guint32 track_id = 0;
3414
3415   if (!gst_byte_reader_skip (tfhd, 1) ||
3416       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3417     goto invalid_track;
3418
3419   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3420     goto invalid_track;
3421
3422   *stream = qtdemux_find_stream (qtdemux, track_id);
3423   if (G_UNLIKELY (!*stream))
3424     goto unknown_stream;
3425
3426   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3427     *base_offset = qtdemux->moof_offset;
3428
3429   if (flags & TF_BASE_DATA_OFFSET)
3430     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3431       goto invalid_track;
3432
3433   /* obtain stream defaults */
3434   qtdemux_parse_trex (qtdemux, *stream,
3435       default_sample_duration, default_sample_size, default_sample_flags);
3436
3437   (*stream)->stsd_sample_description_id =
3438       (*stream)->def_sample_description_index - 1;
3439
3440   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3441     guint32 sample_description_index;
3442     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3443       goto invalid_track;
3444     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3445   }
3446
3447   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3448     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3449       goto invalid_track;
3450
3451   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3452     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3453       goto invalid_track;
3454
3455   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3456     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3457       goto invalid_track;
3458
3459   return TRUE;
3460
3461 invalid_track:
3462   {
3463     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3464     return FALSE;
3465   }
3466 unknown_stream:
3467   {
3468     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3469     return TRUE;
3470   }
3471 }
3472
3473 static gboolean
3474 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3475     guint64 * decode_time)
3476 {
3477   guint32 version = 0;
3478
3479   if (!gst_byte_reader_get_uint32_be (br, &version))
3480     return FALSE;
3481
3482   version >>= 24;
3483   if (version == 1) {
3484     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3485       goto failed;
3486   } else {
3487     guint32 dec_time = 0;
3488     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3489       goto failed;
3490     *decode_time = dec_time;
3491   }
3492
3493   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3494       *decode_time);
3495
3496   return TRUE;
3497
3498 failed:
3499   {
3500     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3501     return FALSE;
3502   }
3503 }
3504
3505 /* Returns a pointer to a GstStructure containing the properties of
3506  * the stream sample identified by @sample_index. The caller must unref
3507  * the returned object after use. Returns NULL if unsuccessful. */
3508 static GstStructure *
3509 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3510     QtDemuxStream * stream, guint sample_index)
3511 {
3512   QtDemuxCencSampleSetInfo *info = NULL;
3513
3514   g_return_val_if_fail (stream != NULL, NULL);
3515   g_return_val_if_fail (stream->protected, NULL);
3516   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3517
3518   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3519
3520   /* Currently, cenc properties for groups of samples are not supported, so
3521    * simply return a copy of the default sample properties */
3522   return gst_structure_copy (info->default_properties);
3523 }
3524
3525 /* Parses the sizes of sample auxiliary information contained within a stream,
3526  * as given in a saiz box. Returns array of sample_count guint8 size values,
3527  * or NULL on failure */
3528 static guint8 *
3529 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3530     GstByteReader * br, guint32 * sample_count)
3531 {
3532   guint32 flags = 0;
3533   guint8 *info_sizes;
3534   guint8 default_info_size;
3535
3536   g_return_val_if_fail (qtdemux != NULL, NULL);
3537   g_return_val_if_fail (stream != NULL, NULL);
3538   g_return_val_if_fail (br != NULL, NULL);
3539   g_return_val_if_fail (sample_count != NULL, NULL);
3540
3541   if (!gst_byte_reader_get_uint32_be (br, &flags))
3542     return NULL;
3543
3544   if (flags & 0x1) {
3545     /* aux_info_type and aux_info_type_parameter are ignored */
3546     if (!gst_byte_reader_skip (br, 8))
3547       return NULL;
3548   }
3549
3550   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3551     return NULL;
3552   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3553
3554   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3555     return NULL;
3556   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3557
3558
3559   if (default_info_size == 0) {
3560     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3561       return NULL;
3562     }
3563   } else {
3564     info_sizes = g_new (guint8, *sample_count);
3565     memset (info_sizes, default_info_size, *sample_count);
3566   }
3567
3568   return info_sizes;
3569 }
3570
3571 /* Parses the offset of sample auxiliary information contained within a stream,
3572  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3573 static gboolean
3574 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3575     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3576     guint64 * offset)
3577 {
3578   guint8 version = 0;
3579   guint32 flags = 0;
3580   guint32 aux_info_type = 0;
3581   guint32 aux_info_type_parameter = 0;
3582   guint32 entry_count;
3583   guint32 off_32;
3584   guint64 off_64;
3585   const guint8 *aux_info_type_data = NULL;
3586
3587   g_return_val_if_fail (qtdemux != NULL, FALSE);
3588   g_return_val_if_fail (stream != NULL, FALSE);
3589   g_return_val_if_fail (br != NULL, FALSE);
3590   g_return_val_if_fail (offset != NULL, FALSE);
3591
3592   if (!gst_byte_reader_get_uint8 (br, &version))
3593     return FALSE;
3594
3595   if (!gst_byte_reader_get_uint24_be (br, &flags))
3596     return FALSE;
3597
3598   if (flags & 0x1) {
3599
3600     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3601       return FALSE;
3602     aux_info_type = QT_FOURCC (aux_info_type_data);
3603
3604     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3605       return FALSE;
3606   } else if (stream->protected) {
3607     aux_info_type = stream->protection_scheme_type;
3608   } else {
3609     aux_info_type = CUR_STREAM (stream)->fourcc;
3610   }
3611
3612   if (info_type)
3613     *info_type = aux_info_type;
3614   if (info_type_parameter)
3615     *info_type_parameter = aux_info_type_parameter;
3616
3617   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3618       "aux_info_type_parameter:  %#06x",
3619       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3620
3621   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3622     return FALSE;
3623
3624   if (entry_count != 1) {
3625     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3626     return FALSE;
3627   }
3628
3629   if (version == 0) {
3630     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3631       return FALSE;
3632     *offset = (guint64) off_32;
3633   } else {
3634     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3635       return FALSE;
3636     *offset = off_64;
3637   }
3638
3639   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3640   return TRUE;
3641 }
3642
3643 static void
3644 qtdemux_gst_structure_free (GstStructure * gststructure)
3645 {
3646   if (gststructure) {
3647     gst_structure_free (gststructure);
3648   }
3649 }
3650
3651 /* Parses auxiliary information relating to samples protected using Common
3652  * Encryption (cenc); the format of this information is defined in
3653  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3654 static gboolean
3655 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3656     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3657 {
3658   QtDemuxCencSampleSetInfo *ss_info = NULL;
3659   guint8 size;
3660   gint i;
3661   GPtrArray *old_crypto_info = NULL;
3662   guint old_entries = 0;
3663
3664   g_return_val_if_fail (qtdemux != NULL, FALSE);
3665   g_return_val_if_fail (stream != NULL, FALSE);
3666   g_return_val_if_fail (br != NULL, FALSE);
3667   g_return_val_if_fail (stream->protected, FALSE);
3668   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3669
3670   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3671
3672   if (ss_info->crypto_info) {
3673     old_crypto_info = ss_info->crypto_info;
3674     /* Count number of non-null entries remaining at the tail end */
3675     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3676       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3677         break;
3678       old_entries++;
3679     }
3680   }
3681
3682   ss_info->crypto_info =
3683       g_ptr_array_new_full (sample_count + old_entries,
3684       (GDestroyNotify) qtdemux_gst_structure_free);
3685
3686   /* We preserve old entries because we parse the next moof in advance
3687    * of consuming all samples from the previous moof, and otherwise
3688    * we'd discard the corresponding crypto info for the samples
3689    * from the previous fragment. */
3690   if (old_entries) {
3691     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3692         old_entries);
3693     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3694       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3695               i));
3696       g_ptr_array_index (old_crypto_info, i) = NULL;
3697     }
3698   }
3699
3700   if (old_crypto_info) {
3701     /* Everything now belongs to the new array */
3702     g_ptr_array_free (old_crypto_info, TRUE);
3703   }
3704
3705   for (i = 0; i < sample_count; ++i) {
3706     GstStructure *properties;
3707     guint16 n_subsamples = 0;
3708     guint8 *data;
3709     guint iv_size;
3710     GstBuffer *buf;
3711
3712     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3713     if (properties == NULL) {
3714       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3715       return FALSE;
3716     }
3717     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3718       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3719       gst_structure_free (properties);
3720       return FALSE;
3721     }
3722     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3723       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3724       gst_structure_free (properties);
3725       return FALSE;
3726     }
3727     buf = gst_buffer_new_wrapped (data, iv_size);
3728     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3729     gst_buffer_unref (buf);
3730     size = info_sizes[i];
3731     if (size > iv_size) {
3732       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3733           || !(n_subsamples > 0)) {
3734         gst_structure_free (properties);
3735         GST_ERROR_OBJECT (qtdemux,
3736             "failed to get subsample count for sample %u", i);
3737         return FALSE;
3738       }
3739       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3740       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3741         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3742             i);
3743         gst_structure_free (properties);
3744         return FALSE;
3745       }
3746       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3747       if (!buf) {
3748         gst_structure_free (properties);
3749         return FALSE;
3750       }
3751       gst_structure_set (properties,
3752           "subsample_count", G_TYPE_UINT, n_subsamples,
3753           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3754       gst_buffer_unref (buf);
3755     } else {
3756       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3757     }
3758     g_ptr_array_add (ss_info->crypto_info, properties);
3759   }
3760   return TRUE;
3761 }
3762
3763 /* Converts a UUID in raw byte form to a string representation, as defined in
3764  * RFC 4122. The caller takes ownership of the returned string and is
3765  * responsible for freeing it after use. */
3766 static gchar *
3767 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3768 {
3769   const guint8 *uuid = (const guint8 *) uuid_bytes;
3770
3771   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3772       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3773       uuid[0], uuid[1], uuid[2], uuid[3],
3774       uuid[4], uuid[5], uuid[6], uuid[7],
3775       uuid[8], uuid[9], uuid[10], uuid[11],
3776       uuid[12], uuid[13], uuid[14], uuid[15]);
3777 }
3778
3779 /* Parses a Protection System Specific Header box (pssh), as defined in the
3780  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3781  * information needed by a specific content protection system in order to
3782  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3783  * otherwise. */
3784 static gboolean
3785 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3786 {
3787   gchar *sysid_string;
3788   guint32 pssh_size = QT_UINT32 (node->data);
3789   GstBuffer *pssh = NULL;
3790   GstEvent *event = NULL;
3791   guint32 parent_box_type;
3792   gint i;
3793
3794   if (G_UNLIKELY (pssh_size < 32U)) {
3795     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3796     return FALSE;
3797   }
3798
3799   sysid_string =
3800       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3801
3802   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3803
3804   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3805   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3806       gst_buffer_get_size (pssh));
3807
3808   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3809
3810   /* Push an event containing the pssh box onto the queues of all streams. */
3811   event = gst_event_new_protection (sysid_string, pssh,
3812       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3813   for (i = 0; i < qtdemux->n_streams; ++i) {
3814     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3815         gst_event_ref (event));
3816   }
3817   g_free (sysid_string);
3818   gst_event_unref (event);
3819   gst_buffer_unref (pssh);
3820   return TRUE;
3821 }
3822
3823 static gboolean
3824 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3825     guint64 moof_offset, QtDemuxStream * stream)
3826 {
3827   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3828   GNode *uuid_node;
3829   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3830   GNode *saiz_node, *saio_node, *pssh_node;
3831   GstByteReader saiz_data, saio_data;
3832   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3833   gint64 base_offset, running_offset;
3834   guint32 frag_num;
3835
3836   /* NOTE @stream ignored */
3837
3838   moof_node = g_node_new ((guint8 *) buffer);
3839   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3840   qtdemux_node_dump (qtdemux, moof_node);
3841
3842   /* Get fragment number from mfhd and check it's valid */
3843   mfhd_node =
3844       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3845   if (mfhd_node == NULL)
3846     goto missing_mfhd;
3847   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3848     goto fail;
3849   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3850
3851   /* unknown base_offset to start with */
3852   base_offset = running_offset = -1;
3853   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3854   while (traf_node) {
3855     guint64 decode_time = 0;
3856
3857     /* Fragment Header node */
3858     tfhd_node =
3859         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3860         &tfhd_data);
3861     if (!tfhd_node)
3862       goto missing_tfhd;
3863     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3864             &ds_size, &ds_flags, &base_offset))
3865       goto missing_tfhd;
3866
3867     /* The following code assumes at most a single set of sample auxiliary
3868      * data in the fragment (consisting of a saiz box and a corresponding saio
3869      * box); in theory, however, there could be multiple sets of sample
3870      * auxiliary data in a fragment. */
3871     saiz_node =
3872         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3873         &saiz_data);
3874     if (saiz_node) {
3875       guint32 info_type = 0;
3876       guint64 offset = 0;
3877       guint32 info_type_parameter = 0;
3878
3879       g_free (qtdemux->cenc_aux_info_sizes);
3880
3881       qtdemux->cenc_aux_info_sizes =
3882           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3883           &qtdemux->cenc_aux_sample_count);
3884       if (qtdemux->cenc_aux_info_sizes == NULL) {
3885         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3886         goto fail;
3887       }
3888       saio_node =
3889           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3890           &saio_data);
3891       if (!saio_node) {
3892         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3893         g_free (qtdemux->cenc_aux_info_sizes);
3894         qtdemux->cenc_aux_info_sizes = NULL;
3895         goto fail;
3896       }
3897
3898       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3899                   &info_type, &info_type_parameter, &offset))) {
3900         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3901         g_free (qtdemux->cenc_aux_info_sizes);
3902         qtdemux->cenc_aux_info_sizes = NULL;
3903         goto fail;
3904       }
3905       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3906         offset += (guint64) (base_offset - qtdemux->moof_offset);
3907       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3908         GstByteReader br;
3909         if (offset > length) {
3910           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3911           qtdemux->cenc_aux_info_offset = offset;
3912         } else {
3913           gst_byte_reader_init (&br, buffer + offset, length - offset);
3914           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3915                   qtdemux->cenc_aux_info_sizes,
3916                   qtdemux->cenc_aux_sample_count)) {
3917             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3918             g_free (qtdemux->cenc_aux_info_sizes);
3919             qtdemux->cenc_aux_info_sizes = NULL;
3920             goto fail;
3921           }
3922         }
3923       }
3924     }
3925
3926     tfdt_node =
3927         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3928         &tfdt_data);
3929     if (tfdt_node) {
3930       /* We'll use decode_time to interpolate timestamps
3931        * in case the input timestamps are missing */
3932       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3933
3934       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3935           " (%" GST_TIME_FORMAT ")", decode_time,
3936           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3937                   decode_time) : GST_CLOCK_TIME_NONE));
3938
3939       /* Discard the fragment buffer timestamp info to avoid using it.
3940        * Rely on tfdt instead as it is more accurate than the timestamp
3941        * that is fetched from a manifest/playlist and is usually
3942        * less accurate. */
3943       qtdemux->fragment_start = -1;
3944     }
3945
3946     if (G_UNLIKELY (!stream)) {
3947       /* we lost track of offset, we'll need to regain it,
3948        * but can delay complaining until later or avoid doing so altogether */
3949       base_offset = -2;
3950       goto next;
3951     }
3952     if (G_UNLIKELY (base_offset < -1))
3953       goto lost_offset;
3954
3955     if (qtdemux->upstream_format_is_time)
3956       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3957
3958     /* initialise moof sample data */
3959     stream->n_samples_moof = 0;
3960     stream->duration_last_moof = stream->duration_moof;
3961     stream->duration_moof = 0;
3962
3963     /* Track Run node */
3964     trun_node =
3965         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3966         &trun_data);
3967     while (trun_node) {
3968       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3969           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3970           &running_offset, decode_time, (tfdt_node != NULL));
3971       /* iterate all siblings */
3972       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3973           &trun_data);
3974     }
3975
3976     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3977     if (uuid_node) {
3978       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3979       guint32 box_length = QT_UINT32 (uuid_buffer);
3980
3981       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3982     }
3983
3984     /* if no new base_offset provided for next traf,
3985      * base is end of current traf */
3986     base_offset = running_offset;
3987     running_offset = -1;
3988
3989     if (stream->n_samples_moof && stream->duration_moof)
3990       stream->new_caps = TRUE;
3991
3992   next:
3993     /* iterate all siblings */
3994     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3995   }
3996
3997   /* parse any protection system info */
3998   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3999   while (pssh_node) {
4000     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4001     qtdemux_parse_pssh (qtdemux, pssh_node);
4002     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4003   }
4004
4005   g_node_destroy (moof_node);
4006   return TRUE;
4007
4008 missing_tfhd:
4009   {
4010     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4011     goto fail;
4012   }
4013 missing_mfhd:
4014   {
4015     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4016     goto fail;
4017   }
4018 lost_offset:
4019   {
4020     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4021     goto fail;
4022   }
4023 fail:
4024   {
4025     g_node_destroy (moof_node);
4026     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4027         (_("This file is corrupt and cannot be played.")), (NULL));
4028     return FALSE;
4029   }
4030 }
4031
4032 #if 0
4033 /* might be used if some day we actually use mfra & co
4034  * for random access to fragments,
4035  * but that will require quite some modifications and much less relying
4036  * on a sample array */
4037 #endif
4038
4039 static gboolean
4040 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4041 {
4042   QtDemuxStream *stream;
4043   guint32 ver_flags, track_id, len, num_entries, i;
4044   guint value_size, traf_size, trun_size, sample_size;
4045   guint64 time = 0, moof_offset = 0;
4046 #if 0
4047   GstBuffer *buf = NULL;
4048   GstFlowReturn ret;
4049 #endif
4050   GstByteReader tfra;
4051
4052   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4053
4054   if (!gst_byte_reader_skip (&tfra, 8))
4055     return FALSE;
4056
4057   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4058     return FALSE;
4059
4060   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4061       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4062       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4063     return FALSE;
4064
4065   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4066
4067   stream = qtdemux_find_stream (qtdemux, track_id);
4068   if (stream == NULL)
4069     goto unknown_trackid;
4070
4071   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4072   sample_size = (len & 3) + 1;
4073   trun_size = ((len & 12) >> 2) + 1;
4074   traf_size = ((len & 48) >> 4) + 1;
4075
4076   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4077       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4078
4079   if (num_entries == 0)
4080     goto no_samples;
4081
4082   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4083           value_size + value_size + traf_size + trun_size + sample_size))
4084     goto corrupt_file;
4085
4086   g_free (stream->ra_entries);
4087   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4088   stream->n_ra_entries = num_entries;
4089
4090   for (i = 0; i < num_entries; i++) {
4091     qt_atom_parser_get_offset (&tfra, value_size, &time);
4092     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4093     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4094     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4095     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4096
4097     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4098
4099     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4100         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4101
4102     stream->ra_entries[i].ts = time;
4103     stream->ra_entries[i].moof_offset = moof_offset;
4104
4105     /* don't want to go through the entire file and read all moofs at startup */
4106 #if 0
4107     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4108     if (ret != GST_FLOW_OK)
4109       goto corrupt_file;
4110     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4111         moof_offset, stream);
4112     gst_buffer_unref (buf);
4113 #endif
4114   }
4115
4116   check_update_duration (qtdemux, time);
4117
4118   return TRUE;
4119
4120 /* ERRORS */
4121 unknown_trackid:
4122   {
4123     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4124     return FALSE;
4125   }
4126 corrupt_file:
4127   {
4128     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4129     return FALSE;
4130   }
4131 no_samples:
4132   {
4133     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4134     return FALSE;
4135   }
4136 }
4137
4138 static gboolean
4139 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4140 {
4141   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4142   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4143   GstBuffer *mfro = NULL, *mfra = NULL;
4144   GstFlowReturn flow;
4145   gboolean ret = FALSE;
4146   GNode *mfra_node, *tfra_node;
4147   guint64 mfra_offset = 0;
4148   guint32 fourcc, mfra_size;
4149   gint64 len;
4150
4151   /* query upstream size in bytes */
4152   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4153     goto size_query_failed;
4154
4155   /* mfro box should be at the very end of the file */
4156   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4157   if (flow != GST_FLOW_OK)
4158     goto exit;
4159
4160   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4161
4162   fourcc = QT_FOURCC (mfro_map.data + 4);
4163   if (fourcc != FOURCC_mfro)
4164     goto exit;
4165
4166   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4167   if (mfro_map.size < 16)
4168     goto invalid_mfro_size;
4169
4170   mfra_size = QT_UINT32 (mfro_map.data + 12);
4171   if (mfra_size >= len)
4172     goto invalid_mfra_size;
4173
4174   mfra_offset = len - mfra_size;
4175
4176   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4177       mfra_offset, mfra_size);
4178
4179   /* now get and parse mfra box */
4180   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4181   if (flow != GST_FLOW_OK)
4182     goto broken_file;
4183
4184   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4185
4186   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4187   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4188
4189   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4190
4191   while (tfra_node) {
4192     qtdemux_parse_tfra (qtdemux, tfra_node);
4193     /* iterate all siblings */
4194     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4195   }
4196   g_node_destroy (mfra_node);
4197
4198   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4199   ret = TRUE;
4200
4201 exit:
4202
4203   if (mfro) {
4204     if (mfro_map.memory != NULL)
4205       gst_buffer_unmap (mfro, &mfro_map);
4206     gst_buffer_unref (mfro);
4207   }
4208   if (mfra) {
4209     if (mfra_map.memory != NULL)
4210       gst_buffer_unmap (mfra, &mfra_map);
4211     gst_buffer_unref (mfra);
4212   }
4213   return ret;
4214
4215 /* ERRORS */
4216 size_query_failed:
4217   {
4218     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4219     goto exit;
4220   }
4221 invalid_mfro_size:
4222   {
4223     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4224     goto exit;
4225   }
4226 invalid_mfra_size:
4227   {
4228     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4229     goto exit;
4230   }
4231 broken_file:
4232   {
4233     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4234     goto exit;
4235   }
4236 }
4237
4238 static guint64
4239 add_offset (guint64 offset, guint64 advance)
4240 {
4241   /* Avoid 64-bit overflow by clamping */
4242   if (offset > G_MAXUINT64 - advance)
4243     return G_MAXUINT64;
4244   return offset + advance;
4245 }
4246
4247 static GstFlowReturn
4248 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4249 {
4250   guint64 length = 0;
4251   guint32 fourcc = 0;
4252   GstBuffer *buf = NULL;
4253   GstFlowReturn ret = GST_FLOW_OK;
4254   guint64 cur_offset = qtdemux->offset;
4255   GstMapInfo map;
4256
4257   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4258   if (G_UNLIKELY (ret != GST_FLOW_OK))
4259     goto beach;
4260   gst_buffer_map (buf, &map, GST_MAP_READ);
4261   if (G_LIKELY (map.size >= 8))
4262     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4263   gst_buffer_unmap (buf, &map);
4264   gst_buffer_unref (buf);
4265
4266   /* maybe we already got most we needed, so only consider this eof */
4267   if (G_UNLIKELY (length == 0)) {
4268     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4269         (_("Invalid atom size.")),
4270         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4271             GST_FOURCC_ARGS (fourcc)));
4272     ret = GST_FLOW_EOS;
4273     goto beach;
4274   }
4275
4276   switch (fourcc) {
4277     case FOURCC_moof:
4278       /* record for later parsing when needed */
4279       if (!qtdemux->moof_offset) {
4280         qtdemux->moof_offset = qtdemux->offset;
4281       }
4282       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4283         /* FIXME */
4284       } else {
4285         qtdemux->offset += length;      /* skip moof and keep going */
4286       }
4287       if (qtdemux->got_moov) {
4288         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4289         ret = GST_FLOW_EOS;
4290         goto beach;
4291       }
4292       break;
4293     case FOURCC_mdat:
4294     case FOURCC_free:
4295     case FOURCC_wide:
4296     case FOURCC_PICT:
4297     case FOURCC_pnot:
4298     {
4299       GST_LOG_OBJECT (qtdemux,
4300           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4301           GST_FOURCC_ARGS (fourcc), cur_offset);
4302       qtdemux->offset = add_offset (qtdemux->offset, length);
4303       break;
4304     }
4305     case FOURCC_moov:
4306     {
4307       GstBuffer *moov = NULL;
4308
4309       if (qtdemux->got_moov) {
4310         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4311         qtdemux->offset = add_offset (qtdemux->offset, length);
4312         goto beach;
4313       }
4314
4315       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4316       if (ret != GST_FLOW_OK)
4317         goto beach;
4318       gst_buffer_map (moov, &map, GST_MAP_READ);
4319
4320       if (length != map.size) {
4321         /* Some files have a 'moov' atom at the end of the file which contains
4322          * a terminal 'free' atom where the body of the atom is missing.
4323          * Check for, and permit, this special case.
4324          */
4325         if (map.size >= 8) {
4326           guint8 *final_data = map.data + (map.size - 8);
4327           guint32 final_length = QT_UINT32 (final_data);
4328           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4329
4330           if (final_fourcc == FOURCC_free
4331               && map.size + final_length - 8 == length) {
4332             /* Ok, we've found that special case. Allocate a new buffer with
4333              * that free atom actually present. */
4334             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4335             gst_buffer_fill (newmoov, 0, map.data, map.size);
4336             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4337             gst_buffer_unmap (moov, &map);
4338             gst_buffer_unref (moov);
4339             moov = newmoov;
4340             gst_buffer_map (moov, &map, GST_MAP_READ);
4341           }
4342         }
4343       }
4344
4345       if (length != map.size) {
4346         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4347             (_("This file is incomplete and cannot be played.")),
4348             ("We got less than expected (received %" G_GSIZE_FORMAT
4349                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4350                 (guint) length, cur_offset));
4351         gst_buffer_unmap (moov, &map);
4352         gst_buffer_unref (moov);
4353         ret = GST_FLOW_ERROR;
4354         goto beach;
4355       }
4356       qtdemux->offset += length;
4357
4358       qtdemux_parse_moov (qtdemux, map.data, length);
4359       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4360
4361       qtdemux_parse_tree (qtdemux);
4362       if (qtdemux->moov_node_compressed) {
4363         g_node_destroy (qtdemux->moov_node_compressed);
4364         g_free (qtdemux->moov_node->data);
4365       }
4366       qtdemux->moov_node_compressed = NULL;
4367       g_node_destroy (qtdemux->moov_node);
4368       qtdemux->moov_node = NULL;
4369       gst_buffer_unmap (moov, &map);
4370       gst_buffer_unref (moov);
4371       qtdemux->got_moov = TRUE;
4372
4373       break;
4374     }
4375     case FOURCC_ftyp:
4376     {
4377       GstBuffer *ftyp = NULL;
4378
4379       /* extract major brand; might come in handy for ISO vs QT issues */
4380       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4381       if (ret != GST_FLOW_OK)
4382         goto beach;
4383       qtdemux->offset += length;
4384       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4385       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4386       gst_buffer_unmap (ftyp, &map);
4387       gst_buffer_unref (ftyp);
4388       break;
4389     }
4390     case FOURCC_uuid:
4391     {
4392       GstBuffer *uuid = NULL;
4393
4394       /* uuid are extension atoms */
4395       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4396       if (ret != GST_FLOW_OK)
4397         goto beach;
4398       qtdemux->offset += length;
4399       gst_buffer_map (uuid, &map, GST_MAP_READ);
4400       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4401       gst_buffer_unmap (uuid, &map);
4402       gst_buffer_unref (uuid);
4403       break;
4404     }
4405     case FOURCC_sidx:
4406     {
4407       GstBuffer *sidx = NULL;
4408       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4409       if (ret != GST_FLOW_OK)
4410         goto beach;
4411       qtdemux->offset += length;
4412       gst_buffer_map (sidx, &map, GST_MAP_READ);
4413       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4414       gst_buffer_unmap (sidx, &map);
4415       gst_buffer_unref (sidx);
4416       break;
4417     }
4418     default:
4419     {
4420       GstBuffer *unknown = NULL;
4421
4422       GST_LOG_OBJECT (qtdemux,
4423           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4424           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4425           cur_offset);
4426       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4427       if (ret != GST_FLOW_OK)
4428         goto beach;
4429       gst_buffer_map (unknown, &map, GST_MAP_READ);
4430       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4431       gst_buffer_unmap (unknown, &map);
4432       gst_buffer_unref (unknown);
4433       qtdemux->offset += length;
4434       break;
4435     }
4436   }
4437
4438 beach:
4439   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4440     /* digested all data, show what we have */
4441     qtdemux_prepare_streams (qtdemux);
4442     ret = qtdemux_expose_streams (qtdemux);
4443
4444     qtdemux->state = QTDEMUX_STATE_MOVIE;
4445     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4446         qtdemux->state);
4447     return ret;
4448   }
4449   return ret;
4450 }
4451
4452 /* Seeks to the previous keyframe of the indexed stream and
4453  * aligns other streams with respect to the keyframe timestamp
4454  * of indexed stream. Only called in case of Reverse Playback
4455  */
4456 static GstFlowReturn
4457 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4458 {
4459   guint8 n = 0;
4460   guint32 seg_idx = 0, k_index = 0;
4461   guint32 ref_seg_idx, ref_k_index;
4462   GstClockTime k_pos = 0, last_stop = 0;
4463   QtDemuxSegment *seg = NULL;
4464   QtDemuxStream *ref_str = NULL;
4465   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4466   guint64 target_ts;
4467
4468   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4469    * and finally align all the other streams on that timestamp with their
4470    * respective keyframes */
4471   for (n = 0; n < qtdemux->n_streams; n++) {
4472     QtDemuxStream *str = qtdemux->streams[n];
4473
4474     /* No candidate yet, take the first stream */
4475     if (!ref_str) {
4476       ref_str = str;
4477       continue;
4478     }
4479
4480     /* So that stream has a segment, we prefer video streams */
4481     if (str->subtype == FOURCC_vide) {
4482       ref_str = str;
4483       break;
4484     }
4485   }
4486
4487   if (G_UNLIKELY (!ref_str)) {
4488     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4489     goto eos;
4490   }
4491
4492   if (G_UNLIKELY (!ref_str->from_sample)) {
4493     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4494     goto eos;
4495   }
4496
4497   /* So that stream has been playing from from_sample to to_sample. We will
4498    * get the timestamp of the previous sample and search for a keyframe before
4499    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4500   if (ref_str->subtype == FOURCC_vide) {
4501     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4502         ref_str->from_sample - 1, FALSE);
4503   } else {
4504     if (ref_str->from_sample >= 10)
4505       k_index = ref_str->from_sample - 10;
4506     else
4507       k_index = 0;
4508   }
4509
4510   target_ts =
4511       ref_str->samples[k_index].timestamp +
4512       ref_str->samples[k_index].pts_offset;
4513
4514   /* get current segment for that stream */
4515   seg = &ref_str->segments[ref_str->segment_index];
4516   /* Use segment start in original timescale for comparisons */
4517   seg_media_start_mov = seg->trak_media_start;
4518
4519   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4520       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4521       k_index, target_ts, seg_media_start_mov,
4522       GST_TIME_ARGS (seg->media_start));
4523
4524   /* Crawl back through segments to find the one containing this I frame */
4525   while (target_ts < seg_media_start_mov) {
4526     GST_DEBUG_OBJECT (qtdemux,
4527         "keyframe position (sample %u) is out of segment %u " " target %"
4528         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4529         ref_str->segment_index, target_ts, seg_media_start_mov);
4530
4531     if (G_UNLIKELY (!ref_str->segment_index)) {
4532       /* Reached first segment, let's consider it's EOS */
4533       goto eos;
4534     }
4535     ref_str->segment_index--;
4536     seg = &ref_str->segments[ref_str->segment_index];
4537     /* Use segment start in original timescale for comparisons */
4538     seg_media_start_mov = seg->trak_media_start;
4539   }
4540   /* Calculate time position of the keyframe and where we should stop */
4541   k_pos =
4542       QTSTREAMTIME_TO_GSTTIME (ref_str,
4543       target_ts - seg->trak_media_start) + seg->time;
4544   last_stop =
4545       QTSTREAMTIME_TO_GSTTIME (ref_str,
4546       ref_str->samples[ref_str->from_sample].timestamp -
4547       seg->trak_media_start) + seg->time;
4548
4549   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4550       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4551       k_index, GST_TIME_ARGS (k_pos));
4552
4553   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4554   qtdemux->segment.position = last_stop;
4555   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4556       GST_TIME_ARGS (last_stop));
4557
4558   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4559     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4560     goto eos;
4561   }
4562
4563   ref_seg_idx = ref_str->segment_index;
4564   ref_k_index = k_index;
4565
4566   /* Align them all on this */
4567   for (n = 0; n < qtdemux->n_streams; n++) {
4568     guint32 index = 0;
4569     GstClockTime seg_time = 0;
4570     QtDemuxStream *str = qtdemux->streams[n];
4571
4572     /* aligning reference stream again might lead to backing up to yet another
4573      * keyframe (due to timestamp rounding issues),
4574      * potentially putting more load on downstream; so let's try to avoid */
4575     if (str == ref_str) {
4576       seg_idx = ref_seg_idx;
4577       seg = &str->segments[seg_idx];
4578       k_index = ref_k_index;
4579       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4580           "sample at index %d", n, ref_str->segment_index, k_index);
4581     } else {
4582       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4583       GST_DEBUG_OBJECT (qtdemux,
4584           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4585           seg_idx, GST_TIME_ARGS (k_pos));
4586
4587       /* get segment and time in the segment */
4588       seg = &str->segments[seg_idx];
4589       seg_time = k_pos - seg->time;
4590
4591       /* get the media time in the segment.
4592        * No adjustment for empty "filler" segments */
4593       if (seg->media_start != GST_CLOCK_TIME_NONE)
4594         seg_time += seg->media_start;
4595
4596       /* get the index of the sample with media time */
4597       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4598       GST_DEBUG_OBJECT (qtdemux,
4599           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4600           GST_TIME_ARGS (seg_time), index);
4601
4602       /* find previous keyframe */
4603       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4604     }
4605
4606     /* Remember until where we want to go */
4607     str->to_sample = str->from_sample - 1;
4608     /* Define our time position */
4609     target_ts =
4610         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4611     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4612     if (seg->media_start != GST_CLOCK_TIME_NONE)
4613       str->time_position -= seg->media_start;
4614
4615     /* Now seek back in time */
4616     gst_qtdemux_move_stream (qtdemux, str, k_index);
4617     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4618         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4619         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4620   }
4621
4622   return GST_FLOW_OK;
4623
4624 eos:
4625   return GST_FLOW_EOS;
4626 }
4627
4628 /*
4629  * Gets the current qt segment start, stop and position for the
4630  * given time offset. This is used in update_segment()
4631  */
4632 static void
4633 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4634     QtDemuxStream * stream, GstClockTime offset,
4635     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4636 {
4637   GstClockTime seg_time;
4638   GstClockTime start, stop, time;
4639   QtDemuxSegment *segment;
4640
4641   segment = &stream->segments[stream->segment_index];
4642
4643   /* get time in this segment */
4644   seg_time = (offset - segment->time) * segment->rate;
4645
4646   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4647       GST_TIME_ARGS (seg_time));
4648
4649   if (G_UNLIKELY (seg_time > segment->duration)) {
4650     GST_LOG_OBJECT (stream->pad,
4651         "seg_time > segment->duration %" GST_TIME_FORMAT,
4652         GST_TIME_ARGS (segment->duration));
4653     seg_time = segment->duration;
4654   }
4655
4656   /* qtdemux->segment.stop is in outside-time-realm, whereas
4657    * segment->media_stop is in track-time-realm.
4658    *
4659    * In order to compare the two, we need to bring segment.stop
4660    * into the track-time-realm
4661    *
4662    * FIXME - does this comment still hold? Don't see any conversion here */
4663
4664   stop = qtdemux->segment.stop;
4665   if (stop == GST_CLOCK_TIME_NONE)
4666     stop = qtdemux->segment.duration;
4667   if (stop == GST_CLOCK_TIME_NONE)
4668     stop = segment->media_stop;
4669   else
4670     stop =
4671         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4672
4673   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4674     start = segment->time + seg_time;
4675     time = offset;
4676     stop = start - seg_time + segment->duration;
4677   } else if (qtdemux->segment.rate >= 0) {
4678     start = MIN (segment->media_start + seg_time, stop);
4679     time = offset;
4680   } else {
4681     if (segment->media_start >= qtdemux->segment.start) {
4682       time = segment->time;
4683     } else {
4684       time = segment->time + (qtdemux->segment.start - segment->media_start);
4685     }
4686
4687     start = MAX (segment->media_start, qtdemux->segment.start);
4688     stop = MIN (segment->media_start + seg_time, stop);
4689   }
4690
4691   *_start = start;
4692   *_stop = stop;
4693   *_time = time;
4694 }
4695
4696 /*
4697  * Updates the qt segment used for the stream and pushes a new segment event
4698  * downstream on this stream's pad.
4699  */
4700 static gboolean
4701 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4702     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4703     GstClockTime * _stop)
4704 {
4705   QtDemuxSegment *segment;
4706   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4707   gdouble rate;
4708   GstEvent *event;
4709
4710   /* update the current segment */
4711   stream->segment_index = seg_idx;
4712
4713   /* get the segment */
4714   segment = &stream->segments[seg_idx];
4715
4716   if (G_UNLIKELY (offset < segment->time)) {
4717     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4718         GST_TIME_ARGS (segment->time));
4719     return FALSE;
4720   }
4721
4722   /* segment lies beyond total indicated duration */
4723   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4724           segment->time > qtdemux->segment.duration)) {
4725     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4726         " < segment->time %" GST_TIME_FORMAT,
4727         GST_TIME_ARGS (qtdemux->segment.duration),
4728         GST_TIME_ARGS (segment->time));
4729     return FALSE;
4730   }
4731
4732   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4733       &start, &stop, &time);
4734
4735   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4736       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4737       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4738
4739   /* combine global rate with that of the segment */
4740   rate = segment->rate * qtdemux->segment.rate;
4741
4742   /* Copy flags from main segment */
4743   stream->segment.flags = qtdemux->segment.flags;
4744
4745   /* update the segment values used for clipping */
4746   stream->segment.offset = qtdemux->segment.offset;
4747   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4748   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4749   stream->segment.rate = rate;
4750   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4751       stream->cslg_shift);
4752   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4753       stream->cslg_shift);
4754   stream->segment.time = time;
4755   stream->segment.position = stream->segment.start;
4756
4757   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4758       &stream->segment);
4759
4760   /* now prepare and send the segment */
4761   if (stream->pad) {
4762     event = gst_event_new_segment (&stream->segment);
4763     if (qtdemux->segment_seqnum) {
4764       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4765     }
4766     gst_pad_push_event (stream->pad, event);
4767     /* assume we can send more data now */
4768     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4769     /* clear to send tags on this pad now */
4770     gst_qtdemux_push_tags (qtdemux, stream);
4771   }
4772
4773   if (_start)
4774     *_start = start;
4775   if (_stop)
4776     *_stop = stop;
4777
4778   return TRUE;
4779 }
4780
4781 /* activate the given segment number @seg_idx of @stream at time @offset.
4782  * @offset is an absolute global position over all the segments.
4783  *
4784  * This will push out a NEWSEGMENT event with the right values and
4785  * position the stream index to the first decodable sample before
4786  * @offset.
4787  */
4788 static gboolean
4789 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4790     guint32 seg_idx, GstClockTime offset)
4791 {
4792   QtDemuxSegment *segment;
4793   guint32 index, kf_index;
4794   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4795
4796   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4797       seg_idx, GST_TIME_ARGS (offset));
4798
4799   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4800           &start, &stop))
4801     return FALSE;
4802
4803   segment = &stream->segments[stream->segment_index];
4804
4805   /* in the fragmented case, we pick a fragment that starts before our
4806    * desired position and rely on downstream to wait for a keyframe
4807    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4808    * tfra entries tells us which trun/sample the key unit is in, but we don't
4809    * make use of this additional information at the moment) */
4810   if (qtdemux->fragmented) {
4811     stream->to_sample = G_MAXUINT32;
4812     return TRUE;
4813   }
4814
4815   /* We don't need to look for a sample in push-based */
4816   if (!qtdemux->pullbased)
4817     return TRUE;
4818
4819   /* and move to the keyframe before the indicated media time of the
4820    * segment */
4821   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4822     if (qtdemux->segment.rate >= 0) {
4823       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4824       stream->to_sample = G_MAXUINT32;
4825       GST_DEBUG_OBJECT (stream->pad,
4826           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4827           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4828           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4829     } else {
4830       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4831       stream->to_sample = index;
4832       GST_DEBUG_OBJECT (stream->pad,
4833           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4834           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4835           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4836     }
4837   } else {
4838     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4839         "this is an empty segment");
4840     return TRUE;
4841   }
4842
4843   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4844    * encountered an error and printed a message so we return appropriately */
4845   if (index == -1)
4846     return FALSE;
4847
4848   /* we're at the right spot */
4849   if (index == stream->sample_index) {
4850     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4851     return TRUE;
4852   }
4853
4854   /* find keyframe of the target index */
4855   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4856
4857 /* *INDENT-OFF* */
4858 /* indent does stupid stuff with stream->samples[].timestamp */
4859
4860   /* if we move forwards, we don't have to go back to the previous
4861    * keyframe since we already sent that. We can also just jump to
4862    * the keyframe right before the target index if there is one. */
4863   if (index > stream->sample_index) {
4864     /* moving forwards check if we move past a keyframe */
4865     if (kf_index > stream->sample_index) {
4866       GST_DEBUG_OBJECT (stream->pad,
4867            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4868            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4869            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4870       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4871     } else {
4872       GST_DEBUG_OBJECT (stream->pad,
4873           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4874           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4875           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4876     }
4877   } else {
4878     GST_DEBUG_OBJECT (stream->pad,
4879         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4880         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4881         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4882     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4883   }
4884
4885 /* *INDENT-ON* */
4886
4887   return TRUE;
4888 }
4889
4890 /* prepare to get the current sample of @stream, getting essential values.
4891  *
4892  * This function will also prepare and send the segment when needed.
4893  *
4894  * Return FALSE if the stream is EOS.
4895  *
4896  * PULL-BASED
4897  */
4898 static gboolean
4899 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4900     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4901     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4902     gboolean * keyframe)
4903 {
4904   QtDemuxSample *sample;
4905   GstClockTime time_position;
4906   guint32 seg_idx;
4907
4908   g_return_val_if_fail (stream != NULL, FALSE);
4909
4910   time_position = stream->time_position;
4911   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4912     goto eos;
4913
4914   seg_idx = stream->segment_index;
4915   if (G_UNLIKELY (seg_idx == -1)) {
4916     /* find segment corresponding to time_position if we are looking
4917      * for a segment. */
4918     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4919   }
4920
4921   /* different segment, activate it, sample_index will be set. */
4922   if (G_UNLIKELY (stream->segment_index != seg_idx))
4923     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4924
4925   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4926                   segment_index]))) {
4927     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4928
4929     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4930         " prepare empty sample");
4931
4932     *empty = TRUE;
4933     *pts = *dts = time_position;
4934     *duration = seg->duration - (time_position - seg->time);
4935
4936     return TRUE;
4937   }
4938
4939   *empty = FALSE;
4940
4941   if (stream->sample_index == -1)
4942     stream->sample_index = 0;
4943
4944   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4945       stream->sample_index, stream->n_samples);
4946
4947   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4948     if (!qtdemux->fragmented)
4949       goto eos;
4950
4951     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4952     do {
4953       GstFlowReturn flow;
4954
4955       GST_OBJECT_LOCK (qtdemux);
4956       flow = qtdemux_add_fragmented_samples (qtdemux);
4957       GST_OBJECT_UNLOCK (qtdemux);
4958
4959       if (flow != GST_FLOW_OK)
4960         goto eos;
4961     }
4962     while (stream->sample_index >= stream->n_samples);
4963   }
4964
4965   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4966     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4967         stream->sample_index);
4968     return FALSE;
4969   }
4970
4971   /* now get the info for the sample we're at */
4972   sample = &stream->samples[stream->sample_index];
4973
4974   *dts = QTSAMPLE_DTS (stream, sample);
4975   *pts = QTSAMPLE_PTS (stream, sample);
4976   *offset = sample->offset;
4977   *size = sample->size;
4978   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4979   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4980
4981   return TRUE;
4982
4983   /* special cases */
4984 eos:
4985   {
4986     stream->time_position = GST_CLOCK_TIME_NONE;
4987     return FALSE;
4988   }
4989 }
4990
4991 /* move to the next sample in @stream.
4992  *
4993  * Moves to the next segment when needed.
4994  */
4995 static void
4996 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4997 {
4998   QtDemuxSample *sample;
4999   QtDemuxSegment *segment;
5000
5001   /* get current segment */
5002   segment = &stream->segments[stream->segment_index];
5003
5004   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5005     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5006     goto next_segment;
5007   }
5008
5009   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5010     /* Mark the stream as EOS */
5011     GST_DEBUG_OBJECT (qtdemux,
5012         "reached max allowed sample %u, mark EOS", stream->to_sample);
5013     stream->time_position = GST_CLOCK_TIME_NONE;
5014     return;
5015   }
5016
5017   /* move to next sample */
5018   stream->sample_index++;
5019   stream->offset_in_sample = 0;
5020
5021   /* reached the last sample, we need the next segment */
5022   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5023     goto next_segment;
5024
5025   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5026     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5027         stream->sample_index);
5028     return;
5029   }
5030
5031   /* get next sample */
5032   sample = &stream->samples[stream->sample_index];
5033
5034   /* see if we are past the segment */
5035   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5036     goto next_segment;
5037
5038   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5039     /* inside the segment, update time_position, looks very familiar to
5040      * GStreamer segments, doesn't it? */
5041     stream->time_position =
5042         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5043   } else {
5044     /* not yet in segment, time does not yet increment. This means
5045      * that we are still prerolling keyframes to the decoder so it can
5046      * decode the first sample of the segment. */
5047     stream->time_position = segment->time;
5048   }
5049   return;
5050
5051   /* move to the next segment */
5052 next_segment:
5053   {
5054     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5055
5056     if (stream->segment_index == stream->n_segments - 1) {
5057       /* are we at the end of the last segment, we're EOS */
5058       stream->time_position = GST_CLOCK_TIME_NONE;
5059     } else {
5060       /* else we're only at the end of the current segment */
5061       stream->time_position = segment->stop_time;
5062     }
5063     /* make sure we select a new segment */
5064
5065     /* accumulate previous segments */
5066     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5067       stream->accumulated_base +=
5068           (stream->segment.stop -
5069           stream->segment.start) / ABS (stream->segment.rate);
5070
5071     stream->segment_index = -1;
5072   }
5073 }
5074
5075 static void
5076 gst_qtdemux_sync_streams (GstQTDemux * demux)
5077 {
5078   gint i;
5079
5080   if (demux->n_streams <= 1)
5081     return;
5082
5083   for (i = 0; i < demux->n_streams; i++) {
5084     QtDemuxStream *stream;
5085     GstClockTime end_time;
5086
5087     stream = demux->streams[i];
5088
5089     if (!stream->pad)
5090       continue;
5091
5092     /* TODO advance time on subtitle streams here, if any some day */
5093
5094     /* some clips/trailers may have unbalanced streams at the end,
5095      * so send EOS on shorter stream to prevent stalling others */
5096
5097     /* do not mess with EOS if SEGMENT seeking */
5098     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5099       continue;
5100
5101     if (demux->pullbased) {
5102       /* loop mode is sample time based */
5103       if (!STREAM_IS_EOS (stream))
5104         continue;
5105     } else {
5106       /* push mode is byte position based */
5107       if (stream->n_samples &&
5108           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5109         continue;
5110     }
5111
5112     if (stream->sent_eos)
5113       continue;
5114
5115     /* only act if some gap */
5116     end_time = stream->segments[stream->n_segments - 1].stop_time;
5117     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5118         ", stream end: %" GST_TIME_FORMAT,
5119         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5120     if (GST_CLOCK_TIME_IS_VALID (end_time)
5121         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5122       GstEvent *event;
5123
5124       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5125           GST_PAD_NAME (stream->pad));
5126       stream->sent_eos = TRUE;
5127       event = gst_event_new_eos ();
5128       if (demux->segment_seqnum)
5129         gst_event_set_seqnum (event, demux->segment_seqnum);
5130       gst_pad_push_event (stream->pad, event);
5131     }
5132   }
5133 }
5134
5135 /* EOS and NOT_LINKED need to be combined. This means that we return:
5136  *
5137  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5138  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5139  */
5140 static GstFlowReturn
5141 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5142     GstFlowReturn ret)
5143 {
5144   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5145
5146   if (stream->pad)
5147     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5148         ret);
5149   else
5150     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5151
5152   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5153   return ret;
5154 }
5155
5156 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5157  * completely clipped
5158  *
5159  * Should be used only with raw buffers */
5160 static GstBuffer *
5161 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5162     GstBuffer * buf)
5163 {
5164   guint64 start, stop, cstart, cstop, diff;
5165   GstClockTime pts, duration;
5166   gsize size, osize;
5167   gint num_rate, denom_rate;
5168   gint frame_size;
5169   gboolean clip_data;
5170   guint offset;
5171
5172   osize = size = gst_buffer_get_size (buf);
5173   offset = 0;
5174
5175   /* depending on the type, setup the clip parameters */
5176   if (stream->subtype == FOURCC_soun) {
5177     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5178     num_rate = GST_SECOND;
5179     denom_rate = (gint) CUR_STREAM (stream)->rate;
5180     clip_data = TRUE;
5181   } else if (stream->subtype == FOURCC_vide) {
5182     frame_size = size;
5183     num_rate = CUR_STREAM (stream)->fps_n;
5184     denom_rate = CUR_STREAM (stream)->fps_d;
5185     clip_data = FALSE;
5186   } else
5187     goto wrong_type;
5188
5189   if (frame_size <= 0)
5190     goto bad_frame_size;
5191
5192   /* we can only clip if we have a valid pts */
5193   pts = GST_BUFFER_PTS (buf);
5194   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5195     goto no_pts;
5196
5197   duration = GST_BUFFER_DURATION (buf);
5198
5199   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5200     duration =
5201         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5202   }
5203
5204   start = pts;
5205   stop = start + duration;
5206
5207   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5208               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5209     goto clipped;
5210
5211   /* see if some clipping happened */
5212   diff = cstart - start;
5213   if (diff > 0) {
5214     pts += diff;
5215     duration -= diff;
5216
5217     if (clip_data) {
5218       /* bring clipped time to samples and to bytes */
5219       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5220       diff *= frame_size;
5221
5222       GST_DEBUG_OBJECT (qtdemux,
5223           "clipping start to %" GST_TIME_FORMAT " %"
5224           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5225
5226       offset = diff;
5227       size -= diff;
5228     }
5229   }
5230   diff = stop - cstop;
5231   if (diff > 0) {
5232     duration -= diff;
5233
5234     if (clip_data) {
5235       /* bring clipped time to samples and then to bytes */
5236       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5237       diff *= frame_size;
5238       GST_DEBUG_OBJECT (qtdemux,
5239           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5240           " bytes", GST_TIME_ARGS (cstop), diff);
5241       size -= diff;
5242     }
5243   }
5244
5245   if (offset != 0 || size != osize)
5246     gst_buffer_resize (buf, offset, size);
5247
5248   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5249   GST_BUFFER_PTS (buf) = pts;
5250   GST_BUFFER_DURATION (buf) = duration;
5251
5252   return buf;
5253
5254   /* dropped buffer */
5255 wrong_type:
5256   {
5257     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5258     return buf;
5259   }
5260 bad_frame_size:
5261   {
5262     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5263     return buf;
5264   }
5265 no_pts:
5266   {
5267     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5268     return buf;
5269   }
5270 clipped:
5271   {
5272     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5273     gst_buffer_unref (buf);
5274     return NULL;
5275   }
5276 }
5277
5278 static GstBuffer *
5279 gst_qtdemux_align_buffer (GstQTDemux * demux,
5280     GstBuffer * buffer, gsize alignment)
5281 {
5282   GstMapInfo map;
5283
5284   gst_buffer_map (buffer, &map, GST_MAP_READ);
5285
5286   if (map.size < sizeof (guintptr)) {
5287     gst_buffer_unmap (buffer, &map);
5288     return buffer;
5289   }
5290
5291   if (((guintptr) map.data) & (alignment - 1)) {
5292     GstBuffer *new_buffer;
5293     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5294
5295     new_buffer = gst_buffer_new_allocate (NULL,
5296         gst_buffer_get_size (buffer), &params);
5297
5298     /* Copy data "by hand", so ensure alignment is kept: */
5299     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5300
5301     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5302     GST_DEBUG_OBJECT (demux,
5303         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5304         alignment);
5305
5306     gst_buffer_unmap (buffer, &map);
5307     gst_buffer_unref (buffer);
5308
5309     return new_buffer;
5310   }
5311
5312   gst_buffer_unmap (buffer, &map);
5313   return buffer;
5314 }
5315
5316 /* the input buffer metadata must be writable,
5317  * but time/duration etc not yet set and need not be preserved */
5318 static GstBuffer *
5319 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5320     GstBuffer * buf)
5321 {
5322   GstMapInfo map;
5323   guint nsize = 0;
5324   gchar *str;
5325
5326   /* not many cases for now */
5327   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5328     /* send a one time dvd clut event */
5329     if (stream->pending_event && stream->pad)
5330       gst_pad_push_event (stream->pad, stream->pending_event);
5331     stream->pending_event = NULL;
5332   }
5333
5334   if (G_UNLIKELY (stream->subtype != FOURCC_text
5335           && stream->subtype != FOURCC_sbtl &&
5336           stream->subtype != FOURCC_subp)) {
5337     return buf;
5338   }
5339
5340   gst_buffer_map (buf, &map, GST_MAP_READ);
5341
5342   /* empty buffer is sent to terminate previous subtitle */
5343   if (map.size <= 2) {
5344     gst_buffer_unmap (buf, &map);
5345     gst_buffer_unref (buf);
5346     return NULL;
5347   }
5348   if (stream->subtype == FOURCC_subp) {
5349     /* That's all the processing needed for subpictures */
5350     gst_buffer_unmap (buf, &map);
5351     return buf;
5352   }
5353
5354   nsize = GST_READ_UINT16_BE (map.data);
5355   nsize = MIN (nsize, map.size - 2);
5356
5357   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5358       nsize, map.size);
5359
5360   /* takes care of UTF-8 validation or UTF-16 recognition,
5361    * no other encoding expected */
5362   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5363   gst_buffer_unmap (buf, &map);
5364   if (str) {
5365     gst_buffer_unref (buf);
5366     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5367   } else {
5368     /* this should not really happen unless the subtitle is corrupted */
5369     gst_buffer_unref (buf);
5370     buf = NULL;
5371   }
5372
5373   /* FIXME ? convert optional subsequent style info to markup */
5374
5375   return buf;
5376 }
5377
5378 /* Sets a buffer's attributes properly and pushes it downstream.
5379  * Also checks for additional actions and custom processing that may
5380  * need to be done first.
5381  */
5382 static GstFlowReturn
5383 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5384     QtDemuxStream * stream, GstBuffer * buf,
5385     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5386     gboolean keyframe, GstClockTime position, guint64 byte_position)
5387 {
5388   GstFlowReturn ret = GST_FLOW_OK;
5389
5390   /* offset the timestamps according to the edit list */
5391
5392   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5393     gchar *url;
5394     GstMapInfo map;
5395
5396     gst_buffer_map (buf, &map, GST_MAP_READ);
5397     url = g_strndup ((gchar *) map.data, map.size);
5398     gst_buffer_unmap (buf, &map);
5399     if (url != NULL && strlen (url) != 0) {
5400       /* we have RTSP redirect now */
5401       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5402           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5403               gst_structure_new ("redirect",
5404                   "new-location", G_TYPE_STRING, url, NULL)));
5405       qtdemux->posted_redirect = TRUE;
5406     } else {
5407       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5408           "posting");
5409     }
5410     g_free (url);
5411   }
5412
5413   /* position reporting */
5414   if (qtdemux->segment.rate >= 0) {
5415     qtdemux->segment.position = position;
5416     gst_qtdemux_sync_streams (qtdemux);
5417   }
5418
5419   if (G_UNLIKELY (!stream->pad)) {
5420     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5421     gst_buffer_unref (buf);
5422     goto exit;
5423   }
5424
5425   /* send out pending buffers */
5426   while (stream->buffers) {
5427     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5428
5429     if (G_UNLIKELY (stream->discont)) {
5430       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5431       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5432       stream->discont = FALSE;
5433     } else {
5434       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5435     }
5436
5437     if (stream->alignment > 1)
5438       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5439     gst_pad_push (stream->pad, buffer);
5440
5441     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5442   }
5443
5444   /* we're going to modify the metadata */
5445   buf = gst_buffer_make_writable (buf);
5446
5447   if (G_UNLIKELY (stream->need_process))
5448     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5449
5450   if (!buf) {
5451     goto exit;
5452   }
5453
5454   GST_BUFFER_DTS (buf) = dts;
5455   GST_BUFFER_PTS (buf) = pts;
5456   GST_BUFFER_DURATION (buf) = duration;
5457   GST_BUFFER_OFFSET (buf) = -1;
5458   GST_BUFFER_OFFSET_END (buf) = -1;
5459
5460   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5461     gst_buffer_append_memory (buf,
5462         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5463
5464   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5465     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5466   }
5467 #if 0
5468   if (G_UNLIKELY (qtdemux->element_index)) {
5469     GstClockTime stream_time;
5470
5471     stream_time =
5472         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5473         timestamp);
5474     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5475       GST_LOG_OBJECT (qtdemux,
5476           "adding association %" GST_TIME_FORMAT "-> %"
5477           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5478       gst_index_add_association (qtdemux->element_index,
5479           qtdemux->index_id,
5480           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5481           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5482           GST_FORMAT_BYTES, byte_position, NULL);
5483     }
5484   }
5485 #endif
5486
5487   if (stream->need_clip)
5488     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5489
5490   if (G_UNLIKELY (buf == NULL))
5491     goto exit;
5492
5493   if (G_UNLIKELY (stream->discont)) {
5494     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5495     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5496     stream->discont = FALSE;
5497   } else {
5498     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5499   }
5500
5501   if (!keyframe) {
5502     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5503     stream->on_keyframe = FALSE;
5504   } else {
5505     stream->on_keyframe = TRUE;
5506   }
5507
5508
5509   GST_LOG_OBJECT (qtdemux,
5510       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5511       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5512       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5513       GST_PAD_NAME (stream->pad));
5514
5515   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5516     GstStructure *crypto_info;
5517     QtDemuxCencSampleSetInfo *info =
5518         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5519     gint index;
5520     GstEvent *event;
5521
5522     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5523       gst_pad_push_event (stream->pad, event);
5524     }
5525
5526     if (info->crypto_info == NULL) {
5527       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5528       gst_buffer_unref (buf);
5529       goto exit;
5530     }
5531
5532     /* The end of the crypto_info array matches our n_samples position,
5533      * so count backward from there */
5534     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5535     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5536       /* steal structure from array */
5537       crypto_info = g_ptr_array_index (info->crypto_info, index);
5538       g_ptr_array_index (info->crypto_info, index) = NULL;
5539       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5540           info->crypto_info->len);
5541       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5542         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5543     } else {
5544       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5545           index, stream->sample_index);
5546     }
5547   }
5548
5549   if (stream->alignment > 1)
5550     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5551
5552   ret = gst_pad_push (stream->pad, buf);
5553
5554   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5555     /* mark position in stream, we'll need this to know when to send GAP event */
5556     stream->segment.position = pts + duration;
5557   }
5558
5559 exit:
5560   return ret;
5561 }
5562
5563 static const QtDemuxRandomAccessEntry *
5564 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5565     GstClockTime pos, gboolean after)
5566 {
5567   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5568   guint n_entries = stream->n_ra_entries;
5569   guint i;
5570
5571   /* we assume the table is sorted */
5572   for (i = 0; i < n_entries; ++i) {
5573     if (entries[i].ts > pos)
5574       break;
5575   }
5576
5577   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5578    * probably okay to assume that the index lists the very first fragment */
5579   if (i == 0)
5580     return &entries[0];
5581
5582   if (after)
5583     return &entries[i];
5584   else
5585     return &entries[i - 1];
5586 }
5587
5588 static gboolean
5589 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5590 {
5591   const QtDemuxRandomAccessEntry *best_entry = NULL;
5592   guint i;
5593
5594   GST_OBJECT_LOCK (qtdemux);
5595
5596   g_assert (qtdemux->n_streams > 0);
5597
5598   for (i = 0; i < qtdemux->n_streams; i++) {
5599     const QtDemuxRandomAccessEntry *entry;
5600     QtDemuxStream *stream;
5601     gboolean is_audio_or_video;
5602
5603     stream = qtdemux->streams[i];
5604
5605     g_free (stream->samples);
5606     stream->samples = NULL;
5607     stream->n_samples = 0;
5608     stream->stbl_index = -1;    /* no samples have yet been parsed */
5609     stream->sample_index = -1;
5610
5611     if (stream->protection_scheme_info) {
5612       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5613       if (stream->protection_scheme_type == FOURCC_cenc) {
5614         QtDemuxCencSampleSetInfo *info =
5615             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5616         if (info->crypto_info) {
5617           g_ptr_array_free (info->crypto_info, TRUE);
5618           info->crypto_info = NULL;
5619         }
5620       }
5621     }
5622
5623     if (stream->ra_entries == NULL)
5624       continue;
5625
5626     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5627       is_audio_or_video = TRUE;
5628     else
5629       is_audio_or_video = FALSE;
5630
5631     entry =
5632         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5633         stream->time_position, !is_audio_or_video);
5634
5635     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5636         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5637
5638     stream->pending_seek = entry;
5639
5640     /* decide position to jump to just based on audio/video tracks, not subs */
5641     if (!is_audio_or_video)
5642       continue;
5643
5644     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5645       best_entry = entry;
5646   }
5647
5648   if (best_entry == NULL) {
5649     GST_OBJECT_UNLOCK (qtdemux);
5650     return FALSE;
5651   }
5652
5653   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5654       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5655       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5656       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5657
5658   qtdemux->moof_offset = best_entry->moof_offset;
5659
5660   qtdemux_add_fragmented_samples (qtdemux);
5661
5662   GST_OBJECT_UNLOCK (qtdemux);
5663   return TRUE;
5664 }
5665
5666 static GstFlowReturn
5667 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5668 {
5669   GstFlowReturn ret = GST_FLOW_OK;
5670   GstBuffer *buf = NULL;
5671   QtDemuxStream *stream;
5672   GstClockTime min_time;
5673   guint64 offset = 0;
5674   GstClockTime dts = GST_CLOCK_TIME_NONE;
5675   GstClockTime pts = GST_CLOCK_TIME_NONE;
5676   GstClockTime duration = 0;
5677   gboolean keyframe = FALSE;
5678   guint sample_size = 0;
5679   gboolean empty = 0;
5680   guint size;
5681   gint index;
5682   gint i;
5683
5684   gst_qtdemux_push_pending_newsegment (qtdemux);
5685
5686   if (qtdemux->fragmented_seek_pending) {
5687     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5688     gst_qtdemux_do_fragmented_seek (qtdemux);
5689     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5690     qtdemux->fragmented_seek_pending = FALSE;
5691   }
5692
5693   /* Figure out the next stream sample to output, min_time is expressed in
5694    * global time and runs over the edit list segments. */
5695   min_time = G_MAXUINT64;
5696   index = -1;
5697   for (i = 0; i < qtdemux->n_streams; i++) {
5698     GstClockTime position;
5699
5700     stream = qtdemux->streams[i];
5701     position = stream->time_position;
5702
5703     /* position of -1 is EOS */
5704     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5705       min_time = position;
5706       index = i;
5707     }
5708   }
5709   /* all are EOS */
5710   if (G_UNLIKELY (index == -1)) {
5711     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5712     goto eos;
5713   }
5714
5715   /* check for segment end */
5716   if (G_UNLIKELY (qtdemux->segment.stop != -1
5717           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5718               || (qtdemux->segment.rate < 0
5719                   && qtdemux->segment.start > min_time))
5720           && qtdemux->streams[index]->on_keyframe)) {
5721     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5722     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5723     goto eos_stream;
5724   }
5725
5726   /* gap events for subtitle streams */
5727   for (i = 0; i < qtdemux->n_streams; i++) {
5728     stream = qtdemux->streams[i];
5729     if (stream->pad && (stream->subtype == FOURCC_subp
5730             || stream->subtype == FOURCC_text
5731             || stream->subtype == FOURCC_sbtl)) {
5732       /* send one second gap events until the stream catches up */
5733       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5734       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5735           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5736           stream->segment.position + GST_SECOND < min_time) {
5737         GstEvent *gap =
5738             gst_event_new_gap (stream->segment.position, GST_SECOND);
5739         gst_pad_push_event (stream->pad, gap);
5740         stream->segment.position += GST_SECOND;
5741       }
5742     }
5743   }
5744
5745   stream = qtdemux->streams[index];
5746   /* fetch info for the current sample of this stream */
5747   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5748               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5749     goto eos_stream;
5750
5751   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5752   if (stream->new_caps) {
5753     gst_qtdemux_configure_stream (qtdemux, stream);
5754     qtdemux_do_allocation (qtdemux, stream);
5755   }
5756
5757   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5758   if (G_UNLIKELY (qtdemux->
5759           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5760     if (stream->subtype == FOURCC_vide && !keyframe) {
5761       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5762       goto next;
5763     }
5764   }
5765
5766   GST_DEBUG_OBJECT (qtdemux,
5767       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5768       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5769       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5770       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5771
5772   if (G_UNLIKELY (empty)) {
5773     /* empty segment, push a gap and move to the next one */
5774     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5775     stream->segment.position = pts + duration;
5776     goto next;
5777   }
5778
5779   /* hmm, empty sample, skip and move to next sample */
5780   if (G_UNLIKELY (sample_size <= 0))
5781     goto next;
5782
5783   /* last pushed sample was out of boundary, goto next sample */
5784   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5785     goto next;
5786
5787   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5788     size = sample_size;
5789   } else {
5790     GST_DEBUG_OBJECT (qtdemux,
5791         "size %d larger than stream max_buffer_size %d, trimming",
5792         sample_size, stream->max_buffer_size);
5793     size =
5794         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5795   }
5796
5797   if (qtdemux->cenc_aux_info_offset > 0) {
5798     GstMapInfo map;
5799     GstByteReader br;
5800     GstBuffer *aux_info = NULL;
5801
5802     /* pull the data stored before the sample */
5803     ret =
5804         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5805         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5806     if (G_UNLIKELY (ret != GST_FLOW_OK))
5807       goto beach;
5808     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5809     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5810     gst_byte_reader_init (&br, map.data + 8, map.size);
5811     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5812             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5813       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5814       gst_buffer_unmap (aux_info, &map);
5815       gst_buffer_unref (aux_info);
5816       ret = GST_FLOW_ERROR;
5817       goto beach;
5818     }
5819     gst_buffer_unmap (aux_info, &map);
5820     gst_buffer_unref (aux_info);
5821   }
5822
5823   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5824       offset);
5825
5826   if (stream->use_allocator) {
5827     /* if we have a per-stream allocator, use it */
5828     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5829   }
5830
5831   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5832       size, &buf);
5833   if (G_UNLIKELY (ret != GST_FLOW_OK))
5834     goto beach;
5835
5836   if (size != sample_size) {
5837     pts += gst_util_uint64_scale_int (GST_SECOND,
5838         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5839         stream->timescale);
5840     dts +=
5841         gst_util_uint64_scale_int (GST_SECOND,
5842         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5843         stream->timescale);
5844     duration =
5845         gst_util_uint64_scale_int (GST_SECOND,
5846         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5847   }
5848
5849   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5850       dts, pts, duration, keyframe, min_time, offset);
5851
5852   if (size != sample_size) {
5853     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5854     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5855
5856     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5857         sample->timestamp +
5858         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5859     if (time_position >= segment->media_start) {
5860       /* inside the segment, update time_position, looks very familiar to
5861        * GStreamer segments, doesn't it? */
5862       stream->time_position = (time_position - segment->media_start) +
5863           segment->time;
5864     } else {
5865       /* not yet in segment, time does not yet increment. This means
5866        * that we are still prerolling keyframes to the decoder so it can
5867        * decode the first sample of the segment. */
5868       stream->time_position = segment->time;
5869     }
5870   }
5871
5872   /* combine flows */
5873   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5874   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5875    * we have no more data for the pad to push */
5876   if (ret == GST_FLOW_EOS)
5877     ret = GST_FLOW_OK;
5878
5879   stream->offset_in_sample += size;
5880   if (stream->offset_in_sample >= sample_size) {
5881     gst_qtdemux_advance_sample (qtdemux, stream);
5882   }
5883   goto beach;
5884
5885 next:
5886   gst_qtdemux_advance_sample (qtdemux, stream);
5887
5888 beach:
5889   return ret;
5890
5891   /* special cases */
5892 eos:
5893   {
5894     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5895     ret = GST_FLOW_EOS;
5896     goto beach;
5897   }
5898 eos_stream:
5899   {
5900     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5901     /* EOS will be raised if all are EOS */
5902     ret = GST_FLOW_OK;
5903     goto beach;
5904   }
5905 }
5906
5907 static void
5908 gst_qtdemux_loop (GstPad * pad)
5909 {
5910   GstQTDemux *qtdemux;
5911   guint64 cur_offset;
5912   GstFlowReturn ret;
5913
5914   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5915
5916   cur_offset = qtdemux->offset;
5917   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5918       cur_offset, qt_demux_state_string (qtdemux->state));
5919
5920   switch (qtdemux->state) {
5921     case QTDEMUX_STATE_INITIAL:
5922     case QTDEMUX_STATE_HEADER:
5923       ret = gst_qtdemux_loop_state_header (qtdemux);
5924       break;
5925     case QTDEMUX_STATE_MOVIE:
5926       ret = gst_qtdemux_loop_state_movie (qtdemux);
5927       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5928         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5929       }
5930       break;
5931     default:
5932       /* ouch */
5933       goto invalid_state;
5934   }
5935
5936   /* if something went wrong, pause */
5937   if (ret != GST_FLOW_OK)
5938     goto pause;
5939
5940 done:
5941   gst_object_unref (qtdemux);
5942   return;
5943
5944   /* ERRORS */
5945 invalid_state:
5946   {
5947     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5948         (NULL), ("streaming stopped, invalid state"));
5949     gst_pad_pause_task (pad);
5950     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5951     goto done;
5952   }
5953 pause:
5954   {
5955     const gchar *reason = gst_flow_get_name (ret);
5956
5957     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5958
5959     gst_pad_pause_task (pad);
5960
5961     /* fatal errors need special actions */
5962     /* check EOS */
5963     if (ret == GST_FLOW_EOS) {
5964       if (qtdemux->n_streams == 0) {
5965         /* we have no streams, post an error */
5966         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5967       }
5968       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5969         gint64 stop;
5970
5971         if ((stop = qtdemux->segment.stop) == -1)
5972           stop = qtdemux->segment.duration;
5973
5974         if (qtdemux->segment.rate >= 0) {
5975           GstMessage *message;
5976           GstEvent *event;
5977
5978           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5979           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5980               GST_FORMAT_TIME, stop);
5981           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5982           if (qtdemux->segment_seqnum) {
5983             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5984             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5985           }
5986           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5987           gst_qtdemux_push_event (qtdemux, event);
5988         } else {
5989           GstMessage *message;
5990           GstEvent *event;
5991
5992           /*  For Reverse Playback */
5993           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5994           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5995               GST_FORMAT_TIME, qtdemux->segment.start);
5996           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5997               qtdemux->segment.start);
5998           if (qtdemux->segment_seqnum) {
5999             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6000             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6001           }
6002           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6003           gst_qtdemux_push_event (qtdemux, event);
6004         }
6005       } else {
6006         GstEvent *event;
6007
6008         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6009         event = gst_event_new_eos ();
6010         if (qtdemux->segment_seqnum)
6011           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6012         gst_qtdemux_push_event (qtdemux, event);
6013       }
6014     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6015       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6016       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6017     }
6018     goto done;
6019   }
6020 }
6021
6022 /*
6023  * has_next_entry
6024  *
6025  * Returns if there are samples to be played.
6026  */
6027 static gboolean
6028 has_next_entry (GstQTDemux * demux)
6029 {
6030   QtDemuxStream *stream;
6031   int i;
6032
6033   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6034
6035   for (i = 0; i < demux->n_streams; i++) {
6036     stream = demux->streams[i];
6037
6038     if (stream->sample_index == -1) {
6039       stream->sample_index = 0;
6040       stream->offset_in_sample = 0;
6041     }
6042
6043     if (stream->sample_index >= stream->n_samples) {
6044       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6045       continue;
6046     }
6047     GST_DEBUG_OBJECT (demux, "Found a sample");
6048     return TRUE;
6049   }
6050
6051   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6052   return FALSE;
6053 }
6054
6055 /*
6056  * next_entry_size
6057  *
6058  * Returns the size of the first entry at the current offset.
6059  * If -1, there are none (which means EOS or empty file).
6060  */
6061 static guint64
6062 next_entry_size (GstQTDemux * demux)
6063 {
6064   QtDemuxStream *stream;
6065   int i;
6066   int smallidx = -1;
6067   guint64 smalloffs = (guint64) - 1;
6068   QtDemuxSample *sample;
6069
6070   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6071       demux->offset);
6072
6073   for (i = 0; i < demux->n_streams; i++) {
6074     stream = demux->streams[i];
6075
6076     if (stream->sample_index == -1) {
6077       stream->sample_index = 0;
6078       stream->offset_in_sample = 0;
6079     }
6080
6081     if (stream->sample_index >= stream->n_samples) {
6082       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6083       continue;
6084     }
6085
6086     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6087       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6088           stream->sample_index);
6089       return -1;
6090     }
6091
6092     sample = &stream->samples[stream->sample_index];
6093
6094     GST_LOG_OBJECT (demux,
6095         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6096         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6097         sample->offset, sample->size);
6098
6099     if (((smalloffs == -1)
6100             || (sample->offset < smalloffs)) && (sample->size)) {
6101       smallidx = i;
6102       smalloffs = sample->offset;
6103     }
6104   }
6105
6106   GST_LOG_OBJECT (demux,
6107       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6108       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6109
6110   if (smallidx == -1)
6111     return -1;
6112
6113   stream = demux->streams[smallidx];
6114   sample = &stream->samples[stream->sample_index];
6115
6116   if (sample->offset >= demux->offset) {
6117     demux->todrop = sample->offset - demux->offset;
6118     return sample->size + demux->todrop;
6119   }
6120
6121   GST_DEBUG_OBJECT (demux,
6122       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6123   return -1;
6124 }
6125
6126 static void
6127 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6128 {
6129   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6130
6131   gst_element_post_message (GST_ELEMENT_CAST (demux),
6132       gst_message_new_element (GST_OBJECT_CAST (demux),
6133           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6134 }
6135
6136 static gboolean
6137 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6138 {
6139   GstEvent *event;
6140   gboolean res = 0;
6141
6142   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6143
6144   event =
6145       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6146       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6147       GST_SEEK_TYPE_NONE, -1);
6148
6149   /* store seqnum to drop flush events, they don't need to reach downstream */
6150   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6151   res = gst_pad_push_event (demux->sinkpad, event);
6152   demux->offset_seek_seqnum = 0;
6153
6154   return res;
6155 }
6156
6157 /* check for seekable upstream, above and beyond a mere query */
6158 static void
6159 gst_qtdemux_check_seekability (GstQTDemux * demux)
6160 {
6161   GstQuery *query;
6162   gboolean seekable = FALSE;
6163   gint64 start = -1, stop = -1;
6164
6165   if (demux->upstream_size)
6166     return;
6167
6168   if (demux->upstream_format_is_time)
6169     return;
6170
6171   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6172   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6173     GST_DEBUG_OBJECT (demux, "seeking query failed");
6174     goto done;
6175   }
6176
6177   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6178
6179   /* try harder to query upstream size if we didn't get it the first time */
6180   if (seekable && stop == -1) {
6181     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6182     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6183   }
6184
6185   /* if upstream doesn't know the size, it's likely that it's not seekable in
6186    * practice even if it technically may be seekable */
6187   if (seekable && (start != 0 || stop <= start)) {
6188     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6189     seekable = FALSE;
6190   }
6191
6192 done:
6193   gst_query_unref (query);
6194
6195   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6196       G_GUINT64_FORMAT ")", seekable, start, stop);
6197   demux->upstream_seekable = seekable;
6198   demux->upstream_size = seekable ? stop : -1;
6199 }
6200
6201 static void
6202 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6203 {
6204   g_return_if_fail (bytes <= demux->todrop);
6205
6206   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6207   gst_adapter_flush (demux->adapter, bytes);
6208   demux->neededbytes -= bytes;
6209   demux->offset += bytes;
6210   demux->todrop -= bytes;
6211 }
6212
6213 static void
6214 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6215 {
6216   if (G_UNLIKELY (demux->pending_newsegment)) {
6217     gint i;
6218
6219     gst_qtdemux_push_pending_newsegment (demux);
6220     /* clear to send tags on all streams */
6221     for (i = 0; i < demux->n_streams; i++) {
6222       QtDemuxStream *stream;
6223       stream = demux->streams[i];
6224       gst_qtdemux_push_tags (demux, stream);
6225       if (CUR_STREAM (stream)->sparse) {
6226         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6227         gst_pad_push_event (stream->pad,
6228             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6229       }
6230     }
6231   }
6232 }
6233
6234 static void
6235 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6236     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6237 {
6238   GstClockTime ts, dur;
6239   GstEvent *gap;
6240
6241   ts = pos;
6242   dur =
6243       stream->segments[segment_index].duration - (pos -
6244       stream->segments[segment_index].time);
6245   gap = gst_event_new_gap (ts, dur);
6246   stream->time_position += dur;
6247
6248   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6249       "segment: %" GST_PTR_FORMAT, gap);
6250   gst_pad_push_event (stream->pad, gap);
6251 }
6252
6253 static void
6254 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6255     QtDemuxStream * stream)
6256 {
6257   gint i;
6258
6259   /* Push any initial gap segments before proceeding to the
6260    * 'real' data */
6261   for (i = 0; i < stream->n_segments; i++) {
6262     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6263
6264     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6265       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6266           stream->time_position);
6267     } else {
6268       /* Only support empty segment at the beginning followed by
6269        * one non-empty segment, this was checked when parsing the
6270        * edts atom, arriving here is unexpected */
6271       g_assert (i + 1 == stream->n_segments);
6272       break;
6273     }
6274   }
6275 }
6276
6277 static GstFlowReturn
6278 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6279 {
6280   GstQTDemux *demux;
6281
6282   demux = GST_QTDEMUX (parent);
6283
6284   GST_DEBUG_OBJECT (demux,
6285       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6286       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6287       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6288       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6289       gst_buffer_get_size (inbuf), demux->offset);
6290
6291   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6292     gboolean is_gap_input = FALSE;
6293     gint i;
6294
6295     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6296
6297     for (i = 0; i < demux->n_streams; i++) {
6298       demux->streams[i]->discont = TRUE;
6299     }
6300
6301     /* Check if we can land back on our feet in the case where upstream is
6302      * handling the seeking/pushing of samples with gaps in between (like
6303      * in the case of trick-mode DASH for example) */
6304     if (demux->upstream_format_is_time
6305         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6306       gint i;
6307       for (i = 0; i < demux->n_streams; i++) {
6308         guint32 res;
6309         GST_LOG_OBJECT (demux,
6310             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6311             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6312         res =
6313             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6314             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6315         if (res != -1) {
6316           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6317           GST_LOG_OBJECT (demux,
6318               "Checking if sample %d from stream %d is valid (offset:%"
6319               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6320               sample->offset, sample->size);
6321           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6322             GST_LOG_OBJECT (demux,
6323                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6324                 res);
6325             is_gap_input = TRUE;
6326             /* We can go back to standard playback mode */
6327             demux->state = QTDEMUX_STATE_MOVIE;
6328             /* Remember which sample this stream is at */
6329             demux->streams[i]->sample_index = res;
6330             /* Finally update all push-based values to the expected values */
6331             demux->neededbytes = demux->streams[i]->samples[res].size;
6332             demux->offset = GST_BUFFER_OFFSET (inbuf);
6333             demux->mdatleft =
6334                 demux->mdatsize - demux->offset + demux->mdatoffset;
6335             demux->todrop = 0;
6336           }
6337         }
6338       }
6339       if (!is_gap_input) {
6340         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6341         /* Reset state if it's a real discont */
6342         demux->neededbytes = 16;
6343         demux->state = QTDEMUX_STATE_INITIAL;
6344         demux->offset = GST_BUFFER_OFFSET (inbuf);
6345         gst_adapter_clear (demux->adapter);
6346       }
6347     }
6348     /* Reverse fragmented playback, need to flush all we have before
6349      * consuming a new fragment.
6350      * The samples array have the timestamps calculated by accumulating the
6351      * durations but this won't work for reverse playback of fragments as
6352      * the timestamps of a subsequent fragment should be smaller than the
6353      * previously received one. */
6354     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6355       gst_qtdemux_process_adapter (demux, TRUE);
6356       for (i = 0; i < demux->n_streams; i++)
6357         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6358     }
6359   }
6360
6361   gst_adapter_push (demux->adapter, inbuf);
6362
6363   GST_DEBUG_OBJECT (demux,
6364       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6365       demux->neededbytes, gst_adapter_available (demux->adapter));
6366
6367   return gst_qtdemux_process_adapter (demux, FALSE);
6368 }
6369
6370 static GstFlowReturn
6371 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6372 {
6373   GstFlowReturn ret = GST_FLOW_OK;
6374
6375   /* we never really mean to buffer that much */
6376   if (demux->neededbytes == -1) {
6377     goto eos;
6378   }
6379
6380   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6381       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6382
6383 #ifndef GST_DISABLE_GST_DEBUG
6384     {
6385       guint64 discont_offset, distance_from_discont;
6386
6387       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6388       distance_from_discont =
6389           gst_adapter_distance_from_discont (demux->adapter);
6390
6391       GST_DEBUG_OBJECT (demux,
6392           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6393           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6394           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6395           demux->offset, discont_offset, distance_from_discont);
6396     }
6397 #endif
6398
6399     switch (demux->state) {
6400       case QTDEMUX_STATE_INITIAL:{
6401         const guint8 *data;
6402         guint32 fourcc;
6403         guint64 size;
6404
6405         gst_qtdemux_check_seekability (demux);
6406
6407         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6408
6409         /* get fourcc/length, set neededbytes */
6410         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6411             &size, &fourcc);
6412         gst_adapter_unmap (demux->adapter);
6413         data = NULL;
6414         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6415             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6416         if (size == 0) {
6417           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6418               (_("This file is invalid and cannot be played.")),
6419               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6420                   GST_FOURCC_ARGS (fourcc)));
6421           ret = GST_FLOW_ERROR;
6422           break;
6423         }
6424         if (fourcc == FOURCC_mdat) {
6425           gint next_entry = next_entry_size (demux);
6426           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6427             /* we have the headers, start playback */
6428             demux->state = QTDEMUX_STATE_MOVIE;
6429             demux->neededbytes = next_entry;
6430             demux->mdatleft = size;
6431             demux->mdatsize = demux->mdatleft;
6432           } else {
6433             /* no headers yet, try to get them */
6434             guint bs;
6435             gboolean res;
6436             guint64 old, target;
6437
6438           buffer_data:
6439             old = demux->offset;
6440             target = old + size;
6441
6442             /* try to jump over the atom with a seek */
6443             /* only bother if it seems worth doing so,
6444              * and avoids possible upstream/server problems */
6445             if (demux->upstream_seekable &&
6446                 demux->upstream_size > 4 * (1 << 20)) {
6447               res = qtdemux_seek_offset (demux, target);
6448             } else {
6449               GST_DEBUG_OBJECT (demux, "skipping seek");
6450               res = FALSE;
6451             }
6452
6453             if (res) {
6454               GST_DEBUG_OBJECT (demux, "seek success");
6455               /* remember the offset fo the first mdat so we can seek back to it
6456                * after we have the headers */
6457               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6458                 demux->first_mdat = old;
6459                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6460                     demux->first_mdat);
6461               }
6462               /* seek worked, continue reading */
6463               demux->offset = target;
6464               demux->neededbytes = 16;
6465               demux->state = QTDEMUX_STATE_INITIAL;
6466             } else {
6467               /* seek failed, need to buffer */
6468               demux->offset = old;
6469               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6470               /* there may be multiple mdat (or alike) buffers */
6471               /* sanity check */
6472               if (demux->mdatbuffer)
6473                 bs = gst_buffer_get_size (demux->mdatbuffer);
6474               else
6475                 bs = 0;
6476               if (size + bs > 10 * (1 << 20))
6477                 goto no_moov;
6478               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6479               demux->neededbytes = size;
6480               if (!demux->mdatbuffer)
6481                 demux->mdatoffset = demux->offset;
6482             }
6483           }
6484         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6485           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6486               (_("This file is invalid and cannot be played.")),
6487               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6488                   GST_FOURCC_ARGS (fourcc), size));
6489           ret = GST_FLOW_ERROR;
6490           break;
6491         } else {
6492           /* this means we already started buffering and still no moov header,
6493            * let's continue buffering everything till we get moov */
6494           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6495                   || fourcc == FOURCC_moof))
6496             goto buffer_data;
6497           demux->neededbytes = size;
6498           demux->state = QTDEMUX_STATE_HEADER;
6499         }
6500         break;
6501       }
6502       case QTDEMUX_STATE_HEADER:{
6503         const guint8 *data;
6504         guint32 fourcc;
6505
6506         GST_DEBUG_OBJECT (demux, "In header");
6507
6508         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6509
6510         /* parse the header */
6511         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6512             &fourcc);
6513         if (fourcc == FOURCC_moov) {
6514           gint n;
6515
6516           /* in usual fragmented setup we could try to scan for more
6517            * and end up at the the moov (after mdat) again */
6518           if (demux->got_moov && demux->n_streams > 0 &&
6519               (!demux->fragmented
6520                   || demux->last_moov_offset == demux->offset)) {
6521             GST_DEBUG_OBJECT (demux,
6522                 "Skipping moov atom as we have (this) one already");
6523           } else {
6524             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6525
6526             if (demux->got_moov && demux->fragmented) {
6527               GST_DEBUG_OBJECT (demux,
6528                   "Got a second moov, clean up data from old one");
6529               if (demux->moov_node_compressed) {
6530                 g_node_destroy (demux->moov_node_compressed);
6531                 if (demux->moov_node)
6532                   g_free (demux->moov_node->data);
6533               }
6534               demux->moov_node_compressed = NULL;
6535               if (demux->moov_node)
6536                 g_node_destroy (demux->moov_node);
6537               demux->moov_node = NULL;
6538             } else {
6539               /* prepare newsegment to send when streaming actually starts */
6540               if (!demux->pending_newsegment) {
6541                 demux->pending_newsegment =
6542                     gst_event_new_segment (&demux->segment);
6543                 if (demux->segment_seqnum)
6544                   gst_event_set_seqnum (demux->pending_newsegment,
6545                       demux->segment_seqnum);
6546               }
6547             }
6548
6549             demux->last_moov_offset = demux->offset;
6550
6551             qtdemux_parse_moov (demux, data, demux->neededbytes);
6552             qtdemux_node_dump (demux, demux->moov_node);
6553             qtdemux_parse_tree (demux);
6554             qtdemux_prepare_streams (demux);
6555             if (!demux->got_moov)
6556               qtdemux_expose_streams (demux);
6557             else {
6558
6559               for (n = 0; n < demux->n_streams; n++) {
6560                 QtDemuxStream *stream = demux->streams[n];
6561
6562                 gst_qtdemux_configure_stream (demux, stream);
6563               }
6564             }
6565
6566             demux->got_moov = TRUE;
6567             gst_qtdemux_check_send_pending_segment (demux);
6568
6569             /* fragmented streams headers shouldn't contain edts atoms */
6570             if (!demux->fragmented) {
6571               for (n = 0; n < demux->n_streams; n++) {
6572                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6573                     demux->streams[n]);
6574               }
6575             }
6576
6577             if (demux->moov_node_compressed) {
6578               g_node_destroy (demux->moov_node_compressed);
6579               g_free (demux->moov_node->data);
6580             }
6581             demux->moov_node_compressed = NULL;
6582             g_node_destroy (demux->moov_node);
6583             demux->moov_node = NULL;
6584             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6585           }
6586         } else if (fourcc == FOURCC_moof) {
6587           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6588             guint64 dist = 0;
6589             GstClockTime prev_pts;
6590             guint64 prev_offset;
6591             guint64 adapter_discont_offset, adapter_discont_dist;
6592
6593             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6594
6595             /*
6596              * The timestamp of the moof buffer is relevant as some scenarios
6597              * won't have the initial timestamp in the atoms. Whenever a new
6598              * buffer has started, we get that buffer's PTS and use it as a base
6599              * timestamp for the trun entries.
6600              *
6601              * To keep track of the current buffer timestamp and starting point
6602              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6603              * from the beggining of the buffer, with the distance and demux->offset
6604              * we know if it is still the same buffer or not.
6605              */
6606             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6607             prev_offset = demux->offset - dist;
6608             if (demux->fragment_start_offset == -1
6609                 || prev_offset > demux->fragment_start_offset) {
6610               demux->fragment_start_offset = prev_offset;
6611               demux->fragment_start = prev_pts;
6612               GST_DEBUG_OBJECT (demux,
6613                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6614                   GST_TIME_FORMAT, demux->fragment_start_offset,
6615                   GST_TIME_ARGS (demux->fragment_start));
6616             }
6617
6618             /* We can't use prev_offset() here because this would require
6619              * upstream to set consistent and correct offsets on all buffers
6620              * since the discont. Nothing ever did that in the past and we
6621              * would break backwards compatibility here then.
6622              * Instead take the offset we had at the last discont and count
6623              * the bytes from there. This works with old code as there would
6624              * be no discont between moov and moof, and also works with
6625              * adaptivedemux which correctly sets offset and will set the
6626              * DISCONT flag accordingly when needed.
6627              *
6628              * We also only do this for upstream TIME segments as otherwise
6629              * there are potential backwards compatibility problems with
6630              * seeking in PUSH mode and upstream providing inconsistent
6631              * timestamps. */
6632             adapter_discont_offset =
6633                 gst_adapter_offset_at_discont (demux->adapter);
6634             adapter_discont_dist =
6635                 gst_adapter_distance_from_discont (demux->adapter);
6636
6637             GST_DEBUG_OBJECT (demux,
6638                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6639                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6640                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6641
6642             if (demux->upstream_format_is_time) {
6643               demux->moof_offset = adapter_discont_offset;
6644               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6645                 demux->moof_offset += adapter_discont_dist;
6646               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6647                 demux->moof_offset = demux->offset;
6648             } else {
6649               demux->moof_offset = demux->offset;
6650             }
6651
6652             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6653                     demux->moof_offset, NULL)) {
6654               gst_adapter_unmap (demux->adapter);
6655               ret = GST_FLOW_ERROR;
6656               goto done;
6657             }
6658             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6659             if (demux->mss_mode && !demux->exposed) {
6660               if (!demux->pending_newsegment) {
6661                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6662                 demux->pending_newsegment =
6663                     gst_event_new_segment (&demux->segment);
6664                 if (demux->segment_seqnum)
6665                   gst_event_set_seqnum (demux->pending_newsegment,
6666                       demux->segment_seqnum);
6667               }
6668               qtdemux_expose_streams (demux);
6669             }
6670           } else {
6671             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6672           }
6673         } else if (fourcc == FOURCC_ftyp) {
6674           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6675           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6676         } else if (fourcc == FOURCC_uuid) {
6677           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6678           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6679         } else if (fourcc == FOURCC_sidx) {
6680           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6681           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6682         } else {
6683           switch (fourcc) {
6684             case FOURCC_styp:
6685               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6686                * FALLTHROUGH */
6687             case FOURCC_free:
6688               /* [free] is a padding atom */
6689               GST_DEBUG_OBJECT (demux,
6690                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6691                   GST_FOURCC_ARGS (fourcc));
6692               break;
6693             default:
6694               GST_WARNING_OBJECT (demux,
6695                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6696                   GST_FOURCC_ARGS (fourcc));
6697               /* Let's jump that one and go back to initial state */
6698               break;
6699           }
6700         }
6701         gst_adapter_unmap (demux->adapter);
6702         data = NULL;
6703
6704         if (demux->mdatbuffer && demux->n_streams) {
6705           gsize remaining_data_size = 0;
6706
6707           /* the mdat was before the header */
6708           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6709               demux->n_streams, demux->mdatbuffer);
6710           /* restore our adapter/offset view of things with upstream;
6711            * put preceding buffered data ahead of current moov data.
6712            * This should also handle evil mdat, moov, mdat cases and alike */
6713           gst_adapter_flush (demux->adapter, demux->neededbytes);
6714
6715           /* Store any remaining data after the mdat for later usage */
6716           remaining_data_size = gst_adapter_available (demux->adapter);
6717           if (remaining_data_size > 0) {
6718             g_assert (demux->restoredata_buffer == NULL);
6719             demux->restoredata_buffer =
6720                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6721             demux->restoredata_offset = demux->offset + demux->neededbytes;
6722             GST_DEBUG_OBJECT (demux,
6723                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6724                 G_GUINT64_FORMAT, remaining_data_size,
6725                 demux->restoredata_offset);
6726           }
6727
6728           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6729           demux->mdatbuffer = NULL;
6730           demux->offset = demux->mdatoffset;
6731           demux->neededbytes = next_entry_size (demux);
6732           demux->state = QTDEMUX_STATE_MOVIE;
6733           demux->mdatleft = gst_adapter_available (demux->adapter);
6734           demux->mdatsize = demux->mdatleft;
6735         } else {
6736           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6737           gst_adapter_flush (demux->adapter, demux->neededbytes);
6738
6739           /* only go back to the mdat if there are samples to play */
6740           if (demux->got_moov && demux->first_mdat != -1
6741               && has_next_entry (demux)) {
6742             gboolean res;
6743
6744             /* we need to seek back */
6745             res = qtdemux_seek_offset (demux, demux->first_mdat);
6746             if (res) {
6747               demux->offset = demux->first_mdat;
6748             } else {
6749               GST_DEBUG_OBJECT (demux, "Seek back failed");
6750             }
6751           } else {
6752             demux->offset += demux->neededbytes;
6753           }
6754           demux->neededbytes = 16;
6755           demux->state = QTDEMUX_STATE_INITIAL;
6756         }
6757
6758         break;
6759       }
6760       case QTDEMUX_STATE_BUFFER_MDAT:{
6761         GstBuffer *buf;
6762         guint8 fourcc[4];
6763
6764         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6765             demux->offset);
6766         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6767         gst_buffer_extract (buf, 0, fourcc, 4);
6768         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6769             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6770         if (demux->mdatbuffer)
6771           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6772         else
6773           demux->mdatbuffer = buf;
6774         demux->offset += demux->neededbytes;
6775         demux->neededbytes = 16;
6776         demux->state = QTDEMUX_STATE_INITIAL;
6777         gst_qtdemux_post_progress (demux, 1, 1);
6778
6779         break;
6780       }
6781       case QTDEMUX_STATE_MOVIE:{
6782         QtDemuxStream *stream = NULL;
6783         QtDemuxSample *sample;
6784         int i = -1;
6785         GstClockTime dts, pts, duration;
6786         gboolean keyframe;
6787
6788         GST_DEBUG_OBJECT (demux,
6789             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6790
6791         if (demux->fragmented) {
6792           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6793               demux->mdatleft);
6794           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6795             /* if needed data starts within this atom,
6796              * then it should not exceed this atom */
6797             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6798               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6799                   (_("This file is invalid and cannot be played.")),
6800                   ("sample data crosses atom boundary"));
6801               ret = GST_FLOW_ERROR;
6802               break;
6803             }
6804             demux->mdatleft -= demux->neededbytes;
6805           } else {
6806             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6807             /* so we are dropping more than left in this atom */
6808             gst_qtdemux_drop_data (demux, demux->mdatleft);
6809             demux->mdatleft = 0;
6810
6811             /* need to resume atom parsing so we do not miss any other pieces */
6812             demux->state = QTDEMUX_STATE_INITIAL;
6813             demux->neededbytes = 16;
6814
6815             /* check if there was any stored post mdat data from previous buffers */
6816             if (demux->restoredata_buffer) {
6817               g_assert (gst_adapter_available (demux->adapter) == 0);
6818
6819               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6820               demux->restoredata_buffer = NULL;
6821               demux->offset = demux->restoredata_offset;
6822             }
6823
6824             break;
6825           }
6826         }
6827
6828         if (demux->todrop) {
6829           if (demux->cenc_aux_info_offset > 0) {
6830             GstByteReader br;
6831             const guint8 *data;
6832
6833             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6834             data = gst_adapter_map (demux->adapter, demux->todrop);
6835             gst_byte_reader_init (&br, data + 8, demux->todrop);
6836             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6837                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6838               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6839               ret = GST_FLOW_ERROR;
6840               gst_adapter_unmap (demux->adapter);
6841               g_free (demux->cenc_aux_info_sizes);
6842               demux->cenc_aux_info_sizes = NULL;
6843               goto done;
6844             }
6845             demux->cenc_aux_info_offset = 0;
6846             g_free (demux->cenc_aux_info_sizes);
6847             demux->cenc_aux_info_sizes = NULL;
6848             gst_adapter_unmap (demux->adapter);
6849           }
6850           gst_qtdemux_drop_data (demux, demux->todrop);
6851         }
6852
6853         /* first buffer? */
6854         /* initial newsegment sent here after having added pads,
6855          * possible others in sink_event */
6856         gst_qtdemux_check_send_pending_segment (demux);
6857
6858         /* Figure out which stream this packet belongs to */
6859         for (i = 0; i < demux->n_streams; i++) {
6860           stream = demux->streams[i];
6861           if (stream->sample_index >= stream->n_samples)
6862             continue;
6863           GST_LOG_OBJECT (demux,
6864               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6865               " / size:%d)", i, stream->sample_index,
6866               stream->samples[stream->sample_index].offset,
6867               stream->samples[stream->sample_index].size);
6868
6869           if (stream->samples[stream->sample_index].offset == demux->offset)
6870             break;
6871         }
6872
6873         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6874           goto unknown_stream;
6875
6876         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6877
6878         if (stream->new_caps) {
6879           gst_qtdemux_configure_stream (demux, stream);
6880         }
6881
6882         /* Put data in a buffer, set timestamps, caps, ... */
6883         sample = &stream->samples[stream->sample_index];
6884
6885         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6886           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6887               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6888
6889           dts = QTSAMPLE_DTS (stream, sample);
6890           pts = QTSAMPLE_PTS (stream, sample);
6891           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6892           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6893
6894           /* check for segment end */
6895           if (G_UNLIKELY (demux->segment.stop != -1
6896                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6897             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6898             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6899
6900             /* skip this data, stream is EOS */
6901             gst_adapter_flush (demux->adapter, demux->neededbytes);
6902             demux->offset += demux->neededbytes;
6903
6904             /* check if all streams are eos */
6905             ret = GST_FLOW_EOS;
6906             for (i = 0; i < demux->n_streams; i++) {
6907               if (!STREAM_IS_EOS (demux->streams[i])) {
6908                 ret = GST_FLOW_OK;
6909                 break;
6910               }
6911             }
6912           } else {
6913             GstBuffer *outbuf;
6914
6915             outbuf =
6916                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6917
6918             /* FIXME: should either be an assert or a plain check */
6919             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6920
6921             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6922                 dts, pts, duration, keyframe, dts, demux->offset);
6923           }
6924
6925           /* combine flows */
6926           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6927         } else {
6928           /* skip this data, stream is EOS */
6929           gst_adapter_flush (demux->adapter, demux->neededbytes);
6930         }
6931
6932         stream->sample_index++;
6933         stream->offset_in_sample = 0;
6934
6935         /* update current offset and figure out size of next buffer */
6936         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6937             demux->offset, demux->neededbytes);
6938         demux->offset += demux->neededbytes;
6939         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6940             demux->offset);
6941
6942
6943         if (ret == GST_FLOW_EOS) {
6944           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6945           demux->neededbytes = -1;
6946           goto eos;
6947         }
6948
6949         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6950           if (demux->fragmented) {
6951             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6952             /* there may be more to follow, only finish this atom */
6953             demux->todrop = demux->mdatleft;
6954             demux->neededbytes = demux->todrop;
6955             break;
6956           }
6957           goto eos;
6958         }
6959         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6960           goto non_ok_unlinked_flow;
6961         }
6962         break;
6963       }
6964       default:
6965         goto invalid_state;
6966     }
6967   }
6968
6969   /* when buffering movie data, at least show user something is happening */
6970   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6971       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6972     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6973         demux->neededbytes);
6974   }
6975 done:
6976
6977   return ret;
6978
6979   /* ERRORS */
6980 non_ok_unlinked_flow:
6981   {
6982     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6983         gst_flow_get_name (ret));
6984     return ret;
6985   }
6986 unknown_stream:
6987   {
6988     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6989     ret = GST_FLOW_ERROR;
6990     goto done;
6991   }
6992 eos:
6993   {
6994     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6995     ret = GST_FLOW_EOS;
6996     goto done;
6997   }
6998 invalid_state:
6999   {
7000     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7001         (NULL), ("qtdemuxer invalid state %d", demux->state));
7002     ret = GST_FLOW_ERROR;
7003     goto done;
7004   }
7005 no_moov:
7006   {
7007     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7008         (NULL), ("no 'moov' atom within the first 10 MB"));
7009     ret = GST_FLOW_ERROR;
7010     goto done;
7011   }
7012 }
7013
7014 static gboolean
7015 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7016 {
7017   GstQuery *query;
7018   gboolean pull_mode;
7019
7020   query = gst_query_new_scheduling ();
7021
7022   if (!gst_pad_peer_query (sinkpad, query)) {
7023     gst_query_unref (query);
7024     goto activate_push;
7025   }
7026
7027   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7028       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7029   gst_query_unref (query);
7030
7031   if (!pull_mode)
7032     goto activate_push;
7033
7034   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7035   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7036
7037 activate_push:
7038   {
7039     GST_DEBUG_OBJECT (sinkpad, "activating push");
7040     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7041   }
7042 }
7043
7044 static gboolean
7045 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7046     GstPadMode mode, gboolean active)
7047 {
7048   gboolean res;
7049   GstQTDemux *demux = GST_QTDEMUX (parent);
7050
7051   switch (mode) {
7052     case GST_PAD_MODE_PUSH:
7053       demux->pullbased = FALSE;
7054       res = TRUE;
7055       break;
7056     case GST_PAD_MODE_PULL:
7057       if (active) {
7058         demux->pullbased = TRUE;
7059         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7060             sinkpad, NULL);
7061       } else {
7062         res = gst_pad_stop_task (sinkpad);
7063       }
7064       break;
7065     default:
7066       res = FALSE;
7067       break;
7068   }
7069   return res;
7070 }
7071
7072 #ifdef HAVE_ZLIB
7073 static void *
7074 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7075 {
7076   guint8 *buffer;
7077   z_stream z;
7078   int ret;
7079
7080   memset (&z, 0, sizeof (z));
7081   z.zalloc = NULL;
7082   z.zfree = NULL;
7083   z.opaque = NULL;
7084
7085   if ((ret = inflateInit (&z)) != Z_OK) {
7086     GST_ERROR ("inflateInit() returned %d", ret);
7087     return NULL;
7088   }
7089
7090   z.next_in = z_buffer;
7091   z.avail_in = z_length;
7092
7093   buffer = (guint8 *) g_malloc (*length);
7094   z.avail_out = *length;
7095   z.next_out = (Bytef *) buffer;
7096   do {
7097     ret = inflate (&z, Z_NO_FLUSH);
7098     if (ret == Z_STREAM_END) {
7099       break;
7100     } else if (ret != Z_OK) {
7101       GST_WARNING ("inflate() returned %d", ret);
7102       break;
7103     }
7104
7105     *length += 4096;
7106     buffer = (guint8 *) g_realloc (buffer, *length);
7107     z.next_out = (Bytef *) (buffer + z.total_out);
7108     z.avail_out += 4096;
7109   } while (z.avail_in > 0);
7110
7111   if (ret != Z_STREAM_END) {
7112     g_free (buffer);
7113     buffer = NULL;
7114     *length = 0;
7115   } else {
7116     *length = z.total_out;
7117   }
7118
7119   inflateEnd (&z);
7120
7121   return buffer;
7122 }
7123 #endif /* HAVE_ZLIB */
7124
7125 static gboolean
7126 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7127 {
7128   GNode *cmov;
7129
7130   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7131
7132   /* counts as header data */
7133   qtdemux->header_size += length;
7134
7135   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7136   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7137
7138   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7139   if (cmov) {
7140     guint32 method;
7141     GNode *dcom;
7142     GNode *cmvd;
7143     guint32 dcom_len;
7144
7145     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7146     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7147     if (dcom == NULL || cmvd == NULL)
7148       goto invalid_compression;
7149
7150     dcom_len = QT_UINT32 (dcom->data);
7151     if (dcom_len < 12)
7152       goto invalid_compression;
7153
7154     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7155     switch (method) {
7156 #ifdef HAVE_ZLIB
7157       case FOURCC_zlib:{
7158         guint uncompressed_length;
7159         guint compressed_length;
7160         guint8 *buf;
7161         guint32 cmvd_len;
7162
7163         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7164         if (cmvd_len < 12)
7165           goto invalid_compression;
7166
7167         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7168         compressed_length = cmvd_len - 12;
7169         GST_LOG ("length = %u", uncompressed_length);
7170
7171         buf =
7172             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7173             compressed_length, &uncompressed_length);
7174
7175         if (buf) {
7176           qtdemux->moov_node_compressed = qtdemux->moov_node;
7177           qtdemux->moov_node = g_node_new (buf);
7178
7179           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7180               uncompressed_length);
7181         }
7182         break;
7183       }
7184 #endif /* HAVE_ZLIB */
7185       default:
7186         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7187             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7188         break;
7189     }
7190   }
7191   return TRUE;
7192
7193   /* ERRORS */
7194 invalid_compression:
7195   {
7196     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7197     return FALSE;
7198   }
7199 }
7200
7201 static gboolean
7202 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7203     const guint8 * end)
7204 {
7205   while (G_UNLIKELY (buf < end)) {
7206     GNode *child;
7207     guint32 len;
7208
7209     if (G_UNLIKELY (buf + 4 > end)) {
7210       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7211       break;
7212     }
7213     len = QT_UINT32 (buf);
7214     if (G_UNLIKELY (len == 0)) {
7215       GST_LOG_OBJECT (qtdemux, "empty container");
7216       break;
7217     }
7218     if (G_UNLIKELY (len < 8)) {
7219       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7220       break;
7221     }
7222     if (G_UNLIKELY (len > (end - buf))) {
7223       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7224           (gint) (end - buf));
7225       break;
7226     }
7227
7228     child = g_node_new ((guint8 *) buf);
7229     g_node_append (node, child);
7230     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7231     qtdemux_parse_node (qtdemux, child, buf, len);
7232
7233     buf += len;
7234   }
7235   return TRUE;
7236 }
7237
7238 static gboolean
7239 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7240     GNode * xdxt)
7241 {
7242   int len = QT_UINT32 (xdxt->data);
7243   guint8 *buf = xdxt->data;
7244   guint8 *end = buf + len;
7245   GstBuffer *buffer;
7246
7247   /* skip size and type */
7248   buf += 8;
7249   end -= 8;
7250
7251   while (buf < end) {
7252     gint size;
7253     guint32 type;
7254
7255     size = QT_UINT32 (buf);
7256     type = QT_FOURCC (buf + 4);
7257
7258     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7259
7260     if (buf + size > end || size <= 0)
7261       break;
7262
7263     buf += 8;
7264     size -= 8;
7265
7266     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7267         GST_FOURCC_ARGS (type));
7268
7269     switch (type) {
7270       case FOURCC_tCtH:
7271         buffer = gst_buffer_new_and_alloc (size);
7272         gst_buffer_fill (buffer, 0, buf, size);
7273         stream->buffers = g_slist_append (stream->buffers, buffer);
7274         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7275         break;
7276       case FOURCC_tCt_:
7277         buffer = gst_buffer_new_and_alloc (size);
7278         gst_buffer_fill (buffer, 0, buf, size);
7279         stream->buffers = g_slist_append (stream->buffers, buffer);
7280         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7281         break;
7282       case FOURCC_tCtC:
7283         buffer = gst_buffer_new_and_alloc (size);
7284         gst_buffer_fill (buffer, 0, buf, size);
7285         stream->buffers = g_slist_append (stream->buffers, buffer);
7286         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7287         break;
7288       default:
7289         GST_WARNING_OBJECT (qtdemux,
7290             "unknown theora cookie %" GST_FOURCC_FORMAT,
7291             GST_FOURCC_ARGS (type));
7292         break;
7293     }
7294     buf += size;
7295   }
7296   return TRUE;
7297 }
7298
7299 static gboolean
7300 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7301     guint length)
7302 {
7303   guint32 fourcc = 0;
7304   guint32 node_length = 0;
7305   const QtNodeType *type;
7306   const guint8 *end;
7307
7308   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7309
7310   if (G_UNLIKELY (length < 8))
7311     goto not_enough_data;
7312
7313   node_length = QT_UINT32 (buffer);
7314   fourcc = QT_FOURCC (buffer + 4);
7315
7316   /* ignore empty nodes */
7317   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7318     return TRUE;
7319
7320   type = qtdemux_type_get (fourcc);
7321
7322   end = buffer + length;
7323
7324   GST_LOG_OBJECT (qtdemux,
7325       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7326       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7327
7328   if (node_length > length)
7329     goto broken_atom_size;
7330
7331   if (type->flags & QT_FLAG_CONTAINER) {
7332     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7333   } else {
7334     switch (fourcc) {
7335       case FOURCC_stsd:
7336       {
7337         if (node_length < 20) {
7338           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7339           break;
7340         }
7341         GST_DEBUG_OBJECT (qtdemux,
7342             "parsing stsd (sample table, sample description) atom");
7343         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7344         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7345         break;
7346       }
7347       case FOURCC_mp4a:
7348       case FOURCC_alac:
7349       case FOURCC_fLaC:
7350       {
7351         guint32 version;
7352         guint32 offset;
7353         guint min_size;
7354
7355         /* also read alac (or whatever) in stead of mp4a in the following,
7356          * since a similar layout is used in other cases as well */
7357         if (fourcc == FOURCC_mp4a)
7358           min_size = 20;
7359         else if (fourcc == FOURCC_fLaC)
7360           min_size = 86;
7361         else
7362           min_size = 40;
7363
7364         /* There are two things we might encounter here: a true mp4a atom, and
7365            an mp4a entry in an stsd atom. The latter is what we're interested
7366            in, and it looks like an atom, but isn't really one. The true mp4a
7367            atom is short, so we detect it based on length here. */
7368         if (length < min_size) {
7369           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7370               GST_FOURCC_ARGS (fourcc));
7371           break;
7372         }
7373
7374         /* 'version' here is the sound sample description version. Types 0 and
7375            1 are documented in the QTFF reference, but type 2 is not: it's
7376            described in Apple header files instead (struct SoundDescriptionV2
7377            in Movies.h) */
7378         version = QT_UINT16 (buffer + 16);
7379
7380         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7381             GST_FOURCC_ARGS (fourcc), version);
7382
7383         /* parse any esds descriptors */
7384         switch (version) {
7385           case 0:
7386             offset = 0x24;
7387             break;
7388           case 1:
7389             offset = 0x34;
7390             break;
7391           case 2:
7392             offset = 0x48;
7393             break;
7394           default:
7395             GST_WARNING_OBJECT (qtdemux,
7396                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7397                 GST_FOURCC_ARGS (fourcc), version);
7398             offset = 0;
7399             break;
7400         }
7401         if (offset)
7402           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7403         break;
7404       }
7405       case FOURCC_mp4v:
7406       case FOURCC_MP4V:
7407       case FOURCC_fmp4:
7408       case FOURCC_FMP4:
7409       case FOURCC_apcs:
7410       case FOURCC_apch:
7411       case FOURCC_apcn:
7412       case FOURCC_apco:
7413       case FOURCC_ap4h:
7414       case FOURCC_xvid:
7415       case FOURCC_XVID:
7416       case FOURCC_H264:
7417       case FOURCC_avc1:
7418       case FOURCC_avc3:
7419       case FOURCC_H265:
7420       case FOURCC_hvc1:
7421       case FOURCC_hev1:
7422       case FOURCC_mjp2:
7423       case FOURCC_encv:
7424       {
7425         guint32 version;
7426         guint32 str_len;
7427
7428         /* codec_data is contained inside these atoms, which all have
7429          * the same format. */
7430         /* video sample description size is 86 bytes without extension.
7431          * node_length have to be bigger than 86 bytes because video sample
7432          * description can include extenstions such as esds, fiel, glbl, etc. */
7433         if (node_length < 86) {
7434           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7435               " sample description length too short (%u < 86)",
7436               GST_FOURCC_ARGS (fourcc), node_length);
7437           break;
7438         }
7439
7440         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7441             GST_FOURCC_ARGS (fourcc));
7442
7443         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7444          *              its data format.
7445          * revision level (2 bytes) : must be set to 0. */
7446         version = QT_UINT32 (buffer + 16);
7447         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7448
7449         /* compressor name : PASCAL string and informative purposes
7450          * first byte : the number of bytes to be displayed.
7451          *              it has to be less than 32 because it is reserved
7452          *              space of 32 bytes total including itself. */
7453         str_len = QT_UINT8 (buffer + 50);
7454         if (str_len < 32)
7455           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7456               (char *) buffer + 51);
7457         else
7458           GST_WARNING_OBJECT (qtdemux,
7459               "compressorname length too big (%u > 31)", str_len);
7460
7461         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7462             end - buffer);
7463         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7464         break;
7465       }
7466       case FOURCC_meta:
7467       {
7468         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7469         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7470         break;
7471       }
7472       case FOURCC_mp4s:
7473       {
7474         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7475         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7476         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7477         break;
7478       }
7479       case FOURCC_XiTh:
7480       {
7481         guint32 version;
7482         guint32 offset;
7483
7484         if (length < 16) {
7485           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7486               GST_FOURCC_ARGS (fourcc));
7487           break;
7488         }
7489
7490         version = QT_UINT32 (buffer + 12);
7491         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7492
7493         switch (version) {
7494           case 0x00000001:
7495             offset = 0x62;
7496             break;
7497           default:
7498             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7499             offset = 0;
7500             break;
7501         }
7502         if (offset) {
7503           if (length < offset) {
7504             GST_WARNING_OBJECT (qtdemux,
7505                 "skipping too small %" GST_FOURCC_FORMAT " box",
7506                 GST_FOURCC_ARGS (fourcc));
7507             break;
7508           }
7509           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7510         }
7511         break;
7512       }
7513       case FOURCC_in24:
7514       {
7515         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7516         break;
7517       }
7518       case FOURCC_uuid:
7519       {
7520         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7521         break;
7522       }
7523       case FOURCC_enca:
7524       {
7525         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7526         break;
7527       }
7528       default:
7529         if (!strcmp (type->name, "unknown"))
7530           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7531         break;
7532     }
7533   }
7534   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7535       GST_FOURCC_ARGS (fourcc));
7536   return TRUE;
7537
7538 /* ERRORS */
7539 not_enough_data:
7540   {
7541     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7542         (_("This file is corrupt and cannot be played.")),
7543         ("Not enough data for an atom header, got only %u bytes", length));
7544     return FALSE;
7545   }
7546 broken_atom_size:
7547   {
7548     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7549         (_("This file is corrupt and cannot be played.")),
7550         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7551             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7552             length));
7553     return FALSE;
7554   }
7555 }
7556
7557 static GNode *
7558 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7559 {
7560   GNode *child;
7561   guint8 *buffer;
7562   guint32 child_fourcc;
7563
7564   for (child = g_node_first_child (node); child;
7565       child = g_node_next_sibling (child)) {
7566     buffer = (guint8 *) child->data;
7567
7568     child_fourcc = QT_FOURCC (buffer + 4);
7569
7570     if (G_UNLIKELY (child_fourcc == fourcc)) {
7571       return child;
7572     }
7573   }
7574   return NULL;
7575 }
7576
7577 static GNode *
7578 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7579     GstByteReader * parser)
7580 {
7581   GNode *child;
7582   guint8 *buffer;
7583   guint32 child_fourcc, child_len;
7584
7585   for (child = g_node_first_child (node); child;
7586       child = g_node_next_sibling (child)) {
7587     buffer = (guint8 *) child->data;
7588
7589     child_len = QT_UINT32 (buffer);
7590     child_fourcc = QT_FOURCC (buffer + 4);
7591
7592     if (G_UNLIKELY (child_fourcc == fourcc)) {
7593       if (G_UNLIKELY (child_len < (4 + 4)))
7594         return NULL;
7595       /* FIXME: must verify if atom length < parent atom length */
7596       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7597       return child;
7598     }
7599   }
7600   return NULL;
7601 }
7602
7603 static GNode *
7604 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7605 {
7606   return g_node_nth_child (node, index);
7607 }
7608
7609 static GNode *
7610 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7611     GstByteReader * parser)
7612 {
7613   GNode *child;
7614   guint8 *buffer;
7615   guint32 child_fourcc, child_len;
7616
7617   for (child = g_node_next_sibling (node); child;
7618       child = g_node_next_sibling (child)) {
7619     buffer = (guint8 *) child->data;
7620
7621     child_fourcc = QT_FOURCC (buffer + 4);
7622
7623     if (child_fourcc == fourcc) {
7624       if (parser) {
7625         child_len = QT_UINT32 (buffer);
7626         if (G_UNLIKELY (child_len < (4 + 4)))
7627           return NULL;
7628         /* FIXME: must verify if atom length < parent atom length */
7629         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7630       }
7631       return child;
7632     }
7633   }
7634   return NULL;
7635 }
7636
7637 static GNode *
7638 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7639 {
7640   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7641 }
7642
7643 static void
7644 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7645 {
7646 /* FIXME: This can only reliably work if demuxers have a
7647  * separate streaming thread per srcpad. This should be
7648  * done in a demuxer base class, which integrates parts
7649  * of multiqueue
7650  *
7651  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7652  */
7653 #if 0
7654   GstQuery *query;
7655
7656   query = gst_query_new_allocation (stream->caps, FALSE);
7657
7658   if (!gst_pad_peer_query (stream->pad, query)) {
7659     /* not a problem, just debug a little */
7660     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7661   }
7662
7663   if (stream->allocator)
7664     gst_object_unref (stream->allocator);
7665
7666   if (gst_query_get_n_allocation_params (query) > 0) {
7667     /* try the allocator */
7668     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7669         &stream->params);
7670     stream->use_allocator = TRUE;
7671   } else {
7672     stream->allocator = NULL;
7673     gst_allocation_params_init (&stream->params);
7674     stream->use_allocator = FALSE;
7675   }
7676   gst_query_unref (query);
7677 #endif
7678 }
7679
7680 static gboolean
7681 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7682     QtDemuxStream * stream)
7683 {
7684   GstStructure *s;
7685   const gchar *selected_system;
7686
7687   g_return_val_if_fail (qtdemux != NULL, FALSE);
7688   g_return_val_if_fail (stream != NULL, FALSE);
7689   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7690       FALSE);
7691
7692   if (stream->protection_scheme_type != FOURCC_cenc) {
7693     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7694     return FALSE;
7695   }
7696   if (qtdemux->protection_system_ids == NULL) {
7697     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7698         "cenc protection system information has been found");
7699     return FALSE;
7700   }
7701   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7702   selected_system = gst_protection_select_system ((const gchar **)
7703       qtdemux->protection_system_ids->pdata);
7704   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7705       qtdemux->protection_system_ids->len - 1);
7706   if (!selected_system) {
7707     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7708         "suitable decryptor element has been found");
7709     return FALSE;
7710   }
7711
7712   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7713   if (!gst_structure_has_name (s, "application/x-cenc")) {
7714     gst_structure_set (s,
7715         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7716         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7717         NULL);
7718     gst_structure_set_name (s, "application/x-cenc");
7719   }
7720   return TRUE;
7721 }
7722
7723 static gboolean
7724 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7725 {
7726   if (stream->subtype == FOURCC_vide) {
7727     /* fps is calculated base on the duration of the average framerate since
7728      * qt does not have a fixed framerate. */
7729     gboolean fps_available = TRUE;
7730
7731     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7732       /* still frame */
7733       CUR_STREAM (stream)->fps_n = 0;
7734       CUR_STREAM (stream)->fps_d = 1;
7735     } else {
7736       if (stream->duration == 0 || stream->n_samples < 2) {
7737         CUR_STREAM (stream)->fps_n = stream->timescale;
7738         CUR_STREAM (stream)->fps_d = 1;
7739         fps_available = FALSE;
7740       } else {
7741         GstClockTime avg_duration;
7742         guint64 duration;
7743         guint32 n_samples;
7744
7745         /* duration and n_samples can be updated for fragmented format
7746          * so, framerate of fragmented format is calculated using data in a moof */
7747         if (qtdemux->fragmented && stream->n_samples_moof > 0
7748             && stream->duration_moof > 0) {
7749           n_samples = stream->n_samples_moof;
7750           duration = stream->duration_moof;
7751         } else {
7752           n_samples = stream->n_samples;
7753           duration = stream->duration;
7754         }
7755
7756         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7757         /* stream->duration is guint64, timescale, n_samples are guint32 */
7758         avg_duration =
7759             gst_util_uint64_scale_round (duration -
7760             stream->first_duration, GST_SECOND,
7761             (guint64) (stream->timescale) * (n_samples - 1));
7762
7763         GST_LOG_OBJECT (qtdemux,
7764             "Calculating avg sample duration based on stream (or moof) duration %"
7765             G_GUINT64_FORMAT
7766             " minus first sample %u, leaving %d samples gives %"
7767             GST_TIME_FORMAT, duration, stream->first_duration,
7768             n_samples - 1, GST_TIME_ARGS (avg_duration));
7769
7770         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7771             &CUR_STREAM (stream)->fps_d);
7772
7773         GST_DEBUG_OBJECT (qtdemux,
7774             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7775             stream->timescale, CUR_STREAM (stream)->fps_n,
7776             CUR_STREAM (stream)->fps_d);
7777       }
7778     }
7779
7780     if (CUR_STREAM (stream)->caps) {
7781       CUR_STREAM (stream)->caps =
7782           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7783
7784       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7785           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7786           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7787
7788       /* set framerate if calculated framerate is reliable */
7789       if (fps_available) {
7790         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7791             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7792             CUR_STREAM (stream)->fps_d, NULL);
7793       }
7794
7795       /* calculate pixel-aspect-ratio using display width and height */
7796       GST_DEBUG_OBJECT (qtdemux,
7797           "video size %dx%d, target display size %dx%d",
7798           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7799           stream->display_width, stream->display_height);
7800       /* qt file might have pasp atom */
7801       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7802         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7803             CUR_STREAM (stream)->par_h);
7804         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7805             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7806             CUR_STREAM (stream)->par_h, NULL);
7807       } else if (stream->display_width > 0 && stream->display_height > 0
7808           && CUR_STREAM (stream)->width > 0
7809           && CUR_STREAM (stream)->height > 0) {
7810         gint n, d;
7811
7812         /* calculate the pixel aspect ratio using the display and pixel w/h */
7813         n = stream->display_width * CUR_STREAM (stream)->height;
7814         d = stream->display_height * CUR_STREAM (stream)->width;
7815         if (n == d)
7816           n = d = 1;
7817         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7818         CUR_STREAM (stream)->par_w = n;
7819         CUR_STREAM (stream)->par_h = d;
7820         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7821             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7822             CUR_STREAM (stream)->par_h, NULL);
7823       }
7824
7825       if (CUR_STREAM (stream)->interlace_mode > 0) {
7826         if (CUR_STREAM (stream)->interlace_mode == 1) {
7827           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7828               G_TYPE_STRING, "progressive", NULL);
7829         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7830           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7831               G_TYPE_STRING, "interleaved", NULL);
7832           if (CUR_STREAM (stream)->field_order == 9) {
7833             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7834                 G_TYPE_STRING, "top-field-first", NULL);
7835           } else if (CUR_STREAM (stream)->field_order == 14) {
7836             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7837                 G_TYPE_STRING, "bottom-field-first", NULL);
7838           }
7839         }
7840       }
7841
7842       /* Create incomplete colorimetry here if needed */
7843       if (CUR_STREAM (stream)->colorimetry.range ||
7844           CUR_STREAM (stream)->colorimetry.matrix ||
7845           CUR_STREAM (stream)->colorimetry.transfer
7846           || CUR_STREAM (stream)->colorimetry.primaries) {
7847         gchar *colorimetry =
7848             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7849         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7850             G_TYPE_STRING, colorimetry, NULL);
7851         g_free (colorimetry);
7852       }
7853
7854       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7855         guint par_w = 1, par_h = 1;
7856
7857         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7858           par_w = CUR_STREAM (stream)->par_w;
7859           par_h = CUR_STREAM (stream)->par_h;
7860         }
7861
7862         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7863                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7864                 par_h)) {
7865           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7866         }
7867
7868         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7869             "multiview-mode", G_TYPE_STRING,
7870             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7871             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7872             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7873       }
7874     }
7875   }
7876
7877   else if (stream->subtype == FOURCC_soun) {
7878     if (CUR_STREAM (stream)->caps) {
7879       CUR_STREAM (stream)->caps =
7880           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7881       if (CUR_STREAM (stream)->rate > 0)
7882         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7883             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7884       if (CUR_STREAM (stream)->n_channels > 0)
7885         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7886             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7887       if (CUR_STREAM (stream)->n_channels > 2) {
7888         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7889          * correctly; this is just the minimum we can do - assume
7890          * we don't actually have any channel positions. */
7891         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7892             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7893       }
7894     }
7895   }
7896
7897   if (stream->pad) {
7898     GstCaps *prev_caps = NULL;
7899
7900     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7901     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7902     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7903     gst_pad_set_active (stream->pad, TRUE);
7904
7905     gst_pad_use_fixed_caps (stream->pad);
7906
7907     if (stream->protected) {
7908       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7909         GST_ERROR_OBJECT (qtdemux,
7910             "Failed to configure protected stream caps.");
7911         return FALSE;
7912       }
7913     }
7914
7915     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7916         CUR_STREAM (stream)->caps);
7917     if (stream->new_stream) {
7918       gchar *stream_id;
7919       GstEvent *event;
7920       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7921
7922       event =
7923           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7924           0);
7925       if (event) {
7926         gst_event_parse_stream_flags (event, &stream_flags);
7927         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7928           qtdemux->have_group_id = TRUE;
7929         else
7930           qtdemux->have_group_id = FALSE;
7931         gst_event_unref (event);
7932       } else if (!qtdemux->have_group_id) {
7933         qtdemux->have_group_id = TRUE;
7934         qtdemux->group_id = gst_util_group_id_next ();
7935       }
7936
7937       stream->new_stream = FALSE;
7938       stream_id =
7939           gst_pad_create_stream_id_printf (stream->pad,
7940           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7941       event = gst_event_new_stream_start (stream_id);
7942       if (qtdemux->have_group_id)
7943         gst_event_set_group_id (event, qtdemux->group_id);
7944       if (stream->disabled)
7945         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7946       if (CUR_STREAM (stream)->sparse) {
7947         stream_flags |= GST_STREAM_FLAG_SPARSE;
7948       } else {
7949         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7950       }
7951       gst_event_set_stream_flags (event, stream_flags);
7952       gst_pad_push_event (stream->pad, event);
7953       g_free (stream_id);
7954     }
7955
7956     prev_caps = gst_pad_get_current_caps (stream->pad);
7957
7958     if (CUR_STREAM (stream)->caps) {
7959       if (!prev_caps
7960           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7961         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7962             CUR_STREAM (stream)->caps);
7963         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7964       } else {
7965         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7966       }
7967     } else {
7968       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7969     }
7970
7971     if (prev_caps)
7972       gst_caps_unref (prev_caps);
7973     stream->new_caps = FALSE;
7974   }
7975   return TRUE;
7976 }
7977
7978 static void
7979 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
7980     QtDemuxStream * stream)
7981 {
7982   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
7983     return;
7984
7985   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
7986       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
7987   if (G_UNLIKELY (stream->stsd_sample_description_id >=
7988           stream->stsd_entries_length)) {
7989     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7990         (_("This file is invalid and cannot be played.")),
7991         ("New sample description id is out of bounds (%d >= %d)",
7992             stream->stsd_sample_description_id, stream->stsd_entries_length));
7993   } else {
7994     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
7995     stream->new_caps = TRUE;
7996   }
7997 }
7998
7999 static gboolean
8000 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8001     QtDemuxStream * stream, GstTagList * list)
8002 {
8003   gboolean ret = TRUE;
8004   /* consistent default for push based mode */
8005   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8006
8007   if (stream->subtype == FOURCC_vide) {
8008     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8009
8010     stream->pad =
8011         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8012     g_free (name);
8013
8014     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8015       gst_object_unref (stream->pad);
8016       stream->pad = NULL;
8017       ret = FALSE;
8018       goto done;
8019     }
8020
8021     qtdemux->n_video_streams++;
8022   } else if (stream->subtype == FOURCC_soun) {
8023     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8024
8025     stream->pad =
8026         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8027     g_free (name);
8028     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8029       gst_object_unref (stream->pad);
8030       stream->pad = NULL;
8031       ret = FALSE;
8032       goto done;
8033     }
8034     qtdemux->n_audio_streams++;
8035   } else if (stream->subtype == FOURCC_strm) {
8036     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8037   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8038       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8039     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8040
8041     stream->pad =
8042         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8043     g_free (name);
8044     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8045       gst_object_unref (stream->pad);
8046       stream->pad = NULL;
8047       ret = FALSE;
8048       goto done;
8049     }
8050     qtdemux->n_sub_streams++;
8051   } else if (CUR_STREAM (stream)->caps) {
8052     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8053
8054     stream->pad =
8055         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8056     g_free (name);
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     qtdemux->n_video_streams++;
8064   } else {
8065     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8066     goto done;
8067   }
8068
8069   if (stream->pad) {
8070     GList *l;
8071
8072     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8073         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8074     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8075     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8076
8077     if (stream->stream_tags)
8078       gst_tag_list_unref (stream->stream_tags);
8079     stream->stream_tags = list;
8080     list = NULL;
8081     /* global tags go on each pad anyway */
8082     stream->send_global_tags = TRUE;
8083     /* send upstream GST_EVENT_PROTECTION events that were received before
8084        this source pad was created */
8085     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8086       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8087   }
8088 done:
8089   if (list)
8090     gst_tag_list_unref (list);
8091   return ret;
8092 }
8093
8094 /* find next atom with @fourcc starting at @offset */
8095 static GstFlowReturn
8096 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8097     guint64 * length, guint32 fourcc)
8098 {
8099   GstFlowReturn ret;
8100   guint32 lfourcc;
8101   GstBuffer *buf;
8102
8103   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8104       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8105
8106   while (TRUE) {
8107     GstMapInfo map;
8108
8109     buf = NULL;
8110     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8111     if (G_UNLIKELY (ret != GST_FLOW_OK))
8112       goto locate_failed;
8113     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8114       /* likely EOF */
8115       ret = GST_FLOW_EOS;
8116       gst_buffer_unref (buf);
8117       goto locate_failed;
8118     }
8119     gst_buffer_map (buf, &map, GST_MAP_READ);
8120     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8121     gst_buffer_unmap (buf, &map);
8122     gst_buffer_unref (buf);
8123
8124     if (G_UNLIKELY (*length == 0)) {
8125       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8126       ret = GST_FLOW_ERROR;
8127       goto locate_failed;
8128     }
8129
8130     if (lfourcc == fourcc) {
8131       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8132           *offset);
8133       break;
8134     } else {
8135       GST_LOG_OBJECT (qtdemux,
8136           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8137           GST_FOURCC_ARGS (fourcc), *offset);
8138       *offset += *length;
8139     }
8140   }
8141
8142   return GST_FLOW_OK;
8143
8144 locate_failed:
8145   {
8146     /* might simply have had last one */
8147     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8148     return ret;
8149   }
8150 }
8151
8152 /* should only do something in pull mode */
8153 /* call with OBJECT lock */
8154 static GstFlowReturn
8155 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8156 {
8157   guint64 length, offset;
8158   GstBuffer *buf = NULL;
8159   GstFlowReturn ret = GST_FLOW_OK;
8160   GstFlowReturn res = GST_FLOW_OK;
8161   GstMapInfo map;
8162
8163   offset = qtdemux->moof_offset;
8164   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8165
8166   if (!offset) {
8167     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8168     return GST_FLOW_EOS;
8169   }
8170
8171   /* best not do pull etc with lock held */
8172   GST_OBJECT_UNLOCK (qtdemux);
8173
8174   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8175   if (ret != GST_FLOW_OK)
8176     goto flow_failed;
8177
8178   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8179   if (G_UNLIKELY (ret != GST_FLOW_OK))
8180     goto flow_failed;
8181   gst_buffer_map (buf, &map, GST_MAP_READ);
8182   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8183     gst_buffer_unmap (buf, &map);
8184     gst_buffer_unref (buf);
8185     buf = NULL;
8186     goto parse_failed;
8187   }
8188
8189   gst_buffer_unmap (buf, &map);
8190   gst_buffer_unref (buf);
8191   buf = NULL;
8192
8193   offset += length;
8194   /* look for next moof */
8195   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8196   if (G_UNLIKELY (ret != GST_FLOW_OK))
8197     goto flow_failed;
8198
8199 exit:
8200   GST_OBJECT_LOCK (qtdemux);
8201
8202   qtdemux->moof_offset = offset;
8203
8204   return res;
8205
8206 parse_failed:
8207   {
8208     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8209     offset = 0;
8210     res = GST_FLOW_ERROR;
8211     goto exit;
8212   }
8213 flow_failed:
8214   {
8215     /* maybe upstream temporarily flushing */
8216     if (ret != GST_FLOW_FLUSHING) {
8217       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8218       offset = 0;
8219     } else {
8220       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8221       /* resume at current position next time */
8222     }
8223     res = ret;
8224     goto exit;
8225   }
8226 }
8227
8228 /* initialise bytereaders for stbl sub-atoms */
8229 static gboolean
8230 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8231 {
8232   stream->stbl_index = -1;      /* no samples have yet been parsed */
8233   stream->sample_index = -1;
8234
8235   /* time-to-sample atom */
8236   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8237     goto corrupt_file;
8238
8239   /* copy atom data into a new buffer for later use */
8240   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8241
8242   /* skip version + flags */
8243   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8244       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8245     goto corrupt_file;
8246   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8247
8248   /* make sure there's enough data */
8249   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8250     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8251     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8252         stream->n_sample_times);
8253     if (!stream->n_sample_times)
8254       goto corrupt_file;
8255   }
8256
8257   /* sync sample atom */
8258   stream->stps_present = FALSE;
8259   if ((stream->stss_present =
8260           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8261               &stream->stss) ? TRUE : FALSE) == TRUE) {
8262     /* copy atom data into a new buffer for later use */
8263     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8264
8265     /* skip version + flags */
8266     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8267         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8268       goto corrupt_file;
8269
8270     if (stream->n_sample_syncs) {
8271       /* make sure there's enough data */
8272       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8273         goto corrupt_file;
8274     }
8275
8276     /* partial sync sample atom */
8277     if ((stream->stps_present =
8278             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8279                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8280       /* copy atom data into a new buffer for later use */
8281       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8282
8283       /* skip version + flags */
8284       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8285           !gst_byte_reader_get_uint32_be (&stream->stps,
8286               &stream->n_sample_partial_syncs))
8287         goto corrupt_file;
8288
8289       /* if there are no entries, the stss table contains the real
8290        * sync samples */
8291       if (stream->n_sample_partial_syncs) {
8292         /* make sure there's enough data */
8293         if (!qt_atom_parser_has_chunks (&stream->stps,
8294                 stream->n_sample_partial_syncs, 4))
8295           goto corrupt_file;
8296       }
8297     }
8298   }
8299
8300   /* sample size */
8301   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8302     goto no_samples;
8303
8304   /* copy atom data into a new buffer for later use */
8305   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8306
8307   /* skip version + flags */
8308   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8309       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8310     goto corrupt_file;
8311
8312   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8313     goto corrupt_file;
8314
8315   if (!stream->n_samples)
8316     goto no_samples;
8317
8318   /* sample-to-chunk atom */
8319   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8320     goto corrupt_file;
8321
8322   /* copy atom data into a new buffer for later use */
8323   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8324
8325   /* skip version + flags */
8326   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8327       !gst_byte_reader_get_uint32_be (&stream->stsc,
8328           &stream->n_samples_per_chunk))
8329     goto corrupt_file;
8330
8331   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8332       stream->n_samples_per_chunk);
8333
8334   /* make sure there's enough data */
8335   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8336           12))
8337     goto corrupt_file;
8338
8339
8340   /* chunk offset */
8341   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8342     stream->co_size = sizeof (guint32);
8343   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8344           &stream->stco))
8345     stream->co_size = sizeof (guint64);
8346   else
8347     goto corrupt_file;
8348
8349   /* copy atom data into a new buffer for later use */
8350   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8351
8352   /* skip version + flags */
8353   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8354     goto corrupt_file;
8355
8356   /* chunks_are_samples == TRUE means treat chunks as samples */
8357   stream->chunks_are_samples = stream->sample_size
8358       && !CUR_STREAM (stream)->sampled;
8359   if (stream->chunks_are_samples) {
8360     /* treat chunks as samples */
8361     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8362       goto corrupt_file;
8363   } else {
8364     /* skip number of entries */
8365     if (!gst_byte_reader_skip (&stream->stco, 4))
8366       goto corrupt_file;
8367
8368     /* make sure there are enough data in the stsz atom */
8369     if (!stream->sample_size) {
8370       /* different sizes for each sample */
8371       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8372         goto corrupt_file;
8373     }
8374   }
8375
8376   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8377       stream->n_samples, (guint) sizeof (QtDemuxSample),
8378       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8379
8380   if (stream->n_samples >=
8381       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8382     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8383         "be larger than %uMB (broken file?)", stream->n_samples,
8384         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8385     return FALSE;
8386   }
8387
8388   g_assert (stream->samples == NULL);
8389   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8390   if (!stream->samples) {
8391     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8392         stream->n_samples);
8393     return FALSE;
8394   }
8395
8396   /* composition time-to-sample */
8397   if ((stream->ctts_present =
8398           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8399               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8400     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8401
8402     /* copy atom data into a new buffer for later use */
8403     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8404
8405     /* skip version + flags */
8406     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8407         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8408             &stream->n_composition_times))
8409       goto corrupt_file;
8410
8411     /* make sure there's enough data */
8412     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8413             4 + 4))
8414       goto corrupt_file;
8415
8416     /* This is optional, if missing we iterate the ctts */
8417     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8418       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8419           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8420         g_free ((gpointer) cslg.data);
8421         goto corrupt_file;
8422       }
8423     } else {
8424       gint32 cslg_least = 0;
8425       guint num_entries, pos;
8426       gint i;
8427
8428       pos = gst_byte_reader_get_pos (&stream->ctts);
8429       num_entries = stream->n_composition_times;
8430
8431       stream->cslg_shift = 0;
8432
8433       for (i = 0; i < num_entries; i++) {
8434         gint32 offset;
8435
8436         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8437         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8438
8439         if (offset < cslg_least)
8440           cslg_least = offset;
8441       }
8442
8443       if (cslg_least < 0)
8444         stream->cslg_shift = ABS (cslg_least);
8445       else
8446         stream->cslg_shift = 0;
8447
8448       /* reset the reader so we can generate sample table */
8449       gst_byte_reader_set_pos (&stream->ctts, pos);
8450     }
8451   } else {
8452     /* Ensure the cslg_shift value is consistent so we can use it
8453      * unconditionnally to produce TS and Segment */
8454     stream->cslg_shift = 0;
8455   }
8456
8457   return TRUE;
8458
8459 corrupt_file:
8460   {
8461     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8462         (_("This file is corrupt and cannot be played.")), (NULL));
8463     return FALSE;
8464   }
8465 no_samples:
8466   {
8467     gst_qtdemux_stbl_free (stream);
8468     if (!qtdemux->fragmented) {
8469       /* not quite good */
8470       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8471       return FALSE;
8472     } else {
8473       /* may pick up samples elsewhere */
8474       return TRUE;
8475     }
8476   }
8477 }
8478
8479 /* collect samples from the next sample to be parsed up to sample @n for @stream
8480  * by reading the info from @stbl
8481  *
8482  * This code can be executed from both the streaming thread and the seeking
8483  * thread so it takes the object lock to protect itself
8484  */
8485 static gboolean
8486 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8487 {
8488   gint i, j, k;
8489   QtDemuxSample *samples, *first, *cur, *last;
8490   guint32 n_samples_per_chunk;
8491   guint32 n_samples;
8492
8493   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8494       GST_FOURCC_FORMAT ", pad %s",
8495       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8496       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8497
8498   n_samples = stream->n_samples;
8499
8500   if (n >= n_samples)
8501     goto out_of_samples;
8502
8503   GST_OBJECT_LOCK (qtdemux);
8504   if (n <= stream->stbl_index)
8505     goto already_parsed;
8506
8507   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8508
8509   if (!stream->stsz.data) {
8510     /* so we already parsed and passed all the moov samples;
8511      * onto fragmented ones */
8512     g_assert (qtdemux->fragmented);
8513     goto done;
8514   }
8515
8516   /* pointer to the sample table */
8517   samples = stream->samples;
8518
8519   /* starts from -1, moves to the next sample index to parse */
8520   stream->stbl_index++;
8521
8522   /* keep track of the first and last sample to fill */
8523   first = &samples[stream->stbl_index];
8524   last = &samples[n];
8525
8526   if (!stream->chunks_are_samples) {
8527     /* set the sample sizes */
8528     if (stream->sample_size == 0) {
8529       /* different sizes for each sample */
8530       for (cur = first; cur <= last; cur++) {
8531         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8532         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8533             (guint) (cur - samples), cur->size);
8534       }
8535     } else {
8536       /* samples have the same size */
8537       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8538       for (cur = first; cur <= last; cur++)
8539         cur->size = stream->sample_size;
8540     }
8541   }
8542
8543   n_samples_per_chunk = stream->n_samples_per_chunk;
8544   cur = first;
8545
8546   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8547     guint32 last_chunk;
8548
8549     if (stream->stsc_chunk_index >= stream->last_chunk
8550         || stream->stsc_chunk_index < stream->first_chunk) {
8551       stream->first_chunk =
8552           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8553       stream->samples_per_chunk =
8554           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8555       /* starts from 1 */
8556       stream->stsd_sample_description_id =
8557           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8558
8559       /* chunk numbers are counted from 1 it seems */
8560       if (G_UNLIKELY (stream->first_chunk == 0))
8561         goto corrupt_file;
8562
8563       --stream->first_chunk;
8564
8565       /* the last chunk of each entry is calculated by taking the first chunk
8566        * of the next entry; except if there is no next, where we fake it with
8567        * INT_MAX */
8568       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8569         stream->last_chunk = G_MAXUINT32;
8570       } else {
8571         stream->last_chunk =
8572             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8573         if (G_UNLIKELY (stream->last_chunk == 0))
8574           goto corrupt_file;
8575
8576         --stream->last_chunk;
8577       }
8578
8579       GST_LOG_OBJECT (qtdemux,
8580           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8581           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8582           stream->samples_per_chunk, stream->stsd_sample_description_id);
8583
8584       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8585         goto corrupt_file;
8586
8587       if (stream->last_chunk != G_MAXUINT32) {
8588         if (!qt_atom_parser_peek_sub (&stream->stco,
8589                 stream->first_chunk * stream->co_size,
8590                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8591                 &stream->co_chunk))
8592           goto corrupt_file;
8593
8594       } else {
8595         stream->co_chunk = stream->stco;
8596         if (!gst_byte_reader_skip (&stream->co_chunk,
8597                 stream->first_chunk * stream->co_size))
8598           goto corrupt_file;
8599       }
8600
8601       stream->stsc_chunk_index = stream->first_chunk;
8602     }
8603
8604     last_chunk = stream->last_chunk;
8605
8606     if (stream->chunks_are_samples) {
8607       cur = &samples[stream->stsc_chunk_index];
8608
8609       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8610         if (j > n) {
8611           /* save state */
8612           stream->stsc_chunk_index = j;
8613           goto done;
8614         }
8615
8616         cur->offset =
8617             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8618             stream->co_size);
8619
8620         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8621             "%" G_GUINT64_FORMAT, j, cur->offset);
8622
8623         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8624             CUR_STREAM (stream)->bytes_per_frame > 0) {
8625           cur->size =
8626               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8627               CUR_STREAM (stream)->samples_per_frame *
8628               CUR_STREAM (stream)->bytes_per_frame;
8629         } else {
8630           cur->size = stream->samples_per_chunk;
8631         }
8632
8633         GST_DEBUG_OBJECT (qtdemux,
8634             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8635             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8636                     stream->stco_sample_index)), cur->size);
8637
8638         cur->timestamp = stream->stco_sample_index;
8639         cur->duration = stream->samples_per_chunk;
8640         cur->keyframe = TRUE;
8641         cur++;
8642
8643         stream->stco_sample_index += stream->samples_per_chunk;
8644       }
8645       stream->stsc_chunk_index = j;
8646     } else {
8647       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8648         guint32 samples_per_chunk;
8649         guint64 chunk_offset;
8650
8651         if (!stream->stsc_sample_index
8652             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8653                 &stream->chunk_offset))
8654           goto corrupt_file;
8655
8656         samples_per_chunk = stream->samples_per_chunk;
8657         chunk_offset = stream->chunk_offset;
8658
8659         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8660           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8661               G_GUINT64_FORMAT " and size %d",
8662               (guint) (cur - samples), chunk_offset, cur->size);
8663
8664           cur->offset = chunk_offset;
8665           chunk_offset += cur->size;
8666           cur++;
8667
8668           if (G_UNLIKELY (cur > last)) {
8669             /* save state */
8670             stream->stsc_sample_index = k + 1;
8671             stream->chunk_offset = chunk_offset;
8672             stream->stsc_chunk_index = j;
8673             goto done2;
8674           }
8675         }
8676         stream->stsc_sample_index = 0;
8677       }
8678       stream->stsc_chunk_index = j;
8679     }
8680     stream->stsc_index++;
8681   }
8682
8683   if (stream->chunks_are_samples)
8684     goto ctts;
8685 done2:
8686   {
8687     guint32 n_sample_times;
8688
8689     n_sample_times = stream->n_sample_times;
8690     cur = first;
8691
8692     for (i = stream->stts_index; i < n_sample_times; i++) {
8693       guint32 stts_samples;
8694       gint32 stts_duration;
8695       gint64 stts_time;
8696
8697       if (stream->stts_sample_index >= stream->stts_samples
8698           || !stream->stts_sample_index) {
8699
8700         stream->stts_samples =
8701             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8702         stream->stts_duration =
8703             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8704
8705         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8706             i, stream->stts_samples, stream->stts_duration);
8707
8708         stream->stts_sample_index = 0;
8709       }
8710
8711       stts_samples = stream->stts_samples;
8712       stts_duration = stream->stts_duration;
8713       stts_time = stream->stts_time;
8714
8715       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8716         GST_DEBUG_OBJECT (qtdemux,
8717             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8718             (guint) (cur - samples), j,
8719             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8720
8721         cur->timestamp = stts_time;
8722         cur->duration = stts_duration;
8723
8724         /* avoid 32-bit wrap-around,
8725          * but still mind possible 'negative' duration */
8726         stts_time += (gint64) stts_duration;
8727         cur++;
8728
8729         if (G_UNLIKELY (cur > last)) {
8730           /* save values */
8731           stream->stts_time = stts_time;
8732           stream->stts_sample_index = j + 1;
8733           if (stream->stts_sample_index >= stream->stts_samples)
8734             stream->stts_index++;
8735           goto done3;
8736         }
8737       }
8738       stream->stts_sample_index = 0;
8739       stream->stts_time = stts_time;
8740       stream->stts_index++;
8741     }
8742     /* fill up empty timestamps with the last timestamp, this can happen when
8743      * the last samples do not decode and so we don't have timestamps for them.
8744      * We however look at the last timestamp to estimate the track length so we
8745      * need something in here. */
8746     for (; cur < last; cur++) {
8747       GST_DEBUG_OBJECT (qtdemux,
8748           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8749           (guint) (cur - samples),
8750           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8751       cur->timestamp = stream->stts_time;
8752       cur->duration = -1;
8753     }
8754   }
8755 done3:
8756   {
8757     /* sample sync, can be NULL */
8758     if (stream->stss_present == TRUE) {
8759       guint32 n_sample_syncs;
8760
8761       n_sample_syncs = stream->n_sample_syncs;
8762
8763       if (!n_sample_syncs) {
8764         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8765         stream->all_keyframe = TRUE;
8766       } else {
8767         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8768           /* note that the first sample is index 1, not 0 */
8769           guint32 index;
8770
8771           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8772
8773           if (G_LIKELY (index > 0 && index <= n_samples)) {
8774             index -= 1;
8775             samples[index].keyframe = TRUE;
8776             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8777             /* and exit if we have enough samples */
8778             if (G_UNLIKELY (index >= n)) {
8779               i++;
8780               break;
8781             }
8782           }
8783         }
8784         /* save state */
8785         stream->stss_index = i;
8786       }
8787
8788       /* stps marks partial sync frames like open GOP I-Frames */
8789       if (stream->stps_present == TRUE) {
8790         guint32 n_sample_partial_syncs;
8791
8792         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8793
8794         /* if there are no entries, the stss table contains the real
8795          * sync samples */
8796         if (n_sample_partial_syncs) {
8797           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8798             /* note that the first sample is index 1, not 0 */
8799             guint32 index;
8800
8801             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8802
8803             if (G_LIKELY (index > 0 && index <= n_samples)) {
8804               index -= 1;
8805               samples[index].keyframe = TRUE;
8806               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8807               /* and exit if we have enough samples */
8808               if (G_UNLIKELY (index >= n)) {
8809                 i++;
8810                 break;
8811               }
8812             }
8813           }
8814           /* save state */
8815           stream->stps_index = i;
8816         }
8817       }
8818     } else {
8819       /* no stss, all samples are keyframes */
8820       stream->all_keyframe = TRUE;
8821       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8822     }
8823   }
8824
8825 ctts:
8826   /* composition time to sample */
8827   if (stream->ctts_present == TRUE) {
8828     guint32 n_composition_times;
8829     guint32 ctts_count;
8830     gint32 ctts_soffset;
8831
8832     /* Fill in the pts_offsets */
8833     cur = first;
8834     n_composition_times = stream->n_composition_times;
8835
8836     for (i = stream->ctts_index; i < n_composition_times; i++) {
8837       if (stream->ctts_sample_index >= stream->ctts_count
8838           || !stream->ctts_sample_index) {
8839         stream->ctts_count =
8840             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8841         stream->ctts_soffset =
8842             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8843         stream->ctts_sample_index = 0;
8844       }
8845
8846       ctts_count = stream->ctts_count;
8847       ctts_soffset = stream->ctts_soffset;
8848
8849       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8850         cur->pts_offset = ctts_soffset;
8851         cur++;
8852
8853         if (G_UNLIKELY (cur > last)) {
8854           /* save state */
8855           stream->ctts_sample_index = j + 1;
8856           goto done;
8857         }
8858       }
8859       stream->ctts_sample_index = 0;
8860       stream->ctts_index++;
8861     }
8862   }
8863 done:
8864   stream->stbl_index = n;
8865   /* if index has been completely parsed, free data that is no-longer needed */
8866   if (n + 1 == stream->n_samples) {
8867     gst_qtdemux_stbl_free (stream);
8868     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8869     if (qtdemux->pullbased) {
8870       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8871       while (n + 1 == stream->n_samples)
8872         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8873           break;
8874     }
8875   }
8876   GST_OBJECT_UNLOCK (qtdemux);
8877
8878   return TRUE;
8879
8880   /* SUCCESS */
8881 already_parsed:
8882   {
8883     GST_LOG_OBJECT (qtdemux,
8884         "Tried to parse up to sample %u but this sample has already been parsed",
8885         n);
8886     /* if fragmented, there may be more */
8887     if (qtdemux->fragmented && n == stream->stbl_index)
8888       goto done;
8889     GST_OBJECT_UNLOCK (qtdemux);
8890     return TRUE;
8891   }
8892   /* ERRORS */
8893 out_of_samples:
8894   {
8895     GST_LOG_OBJECT (qtdemux,
8896         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8897         stream->n_samples);
8898     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8899         (_("This file is corrupt and cannot be played.")), (NULL));
8900     return FALSE;
8901   }
8902 corrupt_file:
8903   {
8904     GST_OBJECT_UNLOCK (qtdemux);
8905     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8906         (_("This file is corrupt and cannot be played.")), (NULL));
8907     return FALSE;
8908   }
8909 }
8910
8911 /* collect all segment info for @stream.
8912  */
8913 static gboolean
8914 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8915     GNode * trak)
8916 {
8917   GNode *edts;
8918   /* accept edts if they contain gaps at start and there is only
8919    * one media segment */
8920   gboolean allow_pushbased_edts = TRUE;
8921   gint media_segments_count = 0;
8922
8923   /* parse and prepare segment info from the edit list */
8924   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8925   stream->n_segments = 0;
8926   stream->segments = NULL;
8927   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8928     GNode *elst;
8929     gint n_segments;
8930     gint i, count, entry_size;
8931     guint64 time;
8932     GstClockTime stime;
8933     const guint8 *buffer;
8934     guint8 version;
8935     guint32 size;
8936
8937     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8938     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8939       goto done;
8940
8941     buffer = elst->data;
8942
8943     size = QT_UINT32 (buffer);
8944     /* version, flags, n_segments */
8945     if (size < 16) {
8946       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8947       goto done;
8948     }
8949     version = QT_UINT8 (buffer + 8);
8950     entry_size = (version == 1) ? 20 : 12;
8951
8952     n_segments = QT_UINT32 (buffer + 12);
8953
8954     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8955       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8956       goto done;
8957     }
8958
8959     /* we might allocate a bit too much, at least allocate 1 segment */
8960     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8961
8962     /* segments always start from 0 */
8963     time = 0;
8964     stime = 0;
8965     count = 0;
8966     buffer += 16;
8967     for (i = 0; i < n_segments; i++) {
8968       guint64 duration;
8969       guint64 media_time;
8970       gboolean time_valid = TRUE;
8971       QtDemuxSegment *segment;
8972       guint32 rate_int;
8973       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8974
8975       if (version == 1) {
8976         media_time = QT_UINT64 (buffer + 8);
8977         duration = QT_UINT64 (buffer);
8978         if (media_time == G_MAXUINT64)
8979           time_valid = FALSE;
8980       } else {
8981         media_time = QT_UINT32 (buffer + 4);
8982         duration = QT_UINT32 (buffer);
8983         if (media_time == G_MAXUINT32)
8984           time_valid = FALSE;
8985       }
8986
8987       if (time_valid)
8988         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8989
8990       segment = &stream->segments[count++];
8991
8992       /* time and duration expressed in global timescale */
8993       segment->time = stime;
8994       /* add non scaled values so we don't cause roundoff errors */
8995       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8996         time += duration;
8997         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8998         segment->duration = stime - segment->time;
8999       } else {
9000         /* zero duration does not imply media_start == media_stop
9001          * but, only specify media_start.*/
9002         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9003         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9004             && stime >= media_start) {
9005           segment->duration = stime - media_start;
9006         } else {
9007           segment->duration = GST_CLOCK_TIME_NONE;
9008         }
9009       }
9010       segment->stop_time = stime;
9011
9012       segment->trak_media_start = media_time;
9013       /* media_time expressed in stream timescale */
9014       if (time_valid) {
9015         segment->media_start = media_start;
9016         segment->media_stop = segment->media_start + segment->duration;
9017         media_segments_count++;
9018       } else {
9019         segment->media_start = GST_CLOCK_TIME_NONE;
9020         segment->media_stop = GST_CLOCK_TIME_NONE;
9021       }
9022       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9023
9024       if (rate_int <= 1) {
9025         /* 0 is not allowed, some programs write 1 instead of the floating point
9026          * value */
9027         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9028             rate_int);
9029         segment->rate = 1;
9030       } else {
9031         segment->rate = rate_int / 65536.0;
9032       }
9033
9034       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9035           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9036           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9037           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9038           i, GST_TIME_ARGS (segment->time),
9039           GST_TIME_ARGS (segment->duration),
9040           GST_TIME_ARGS (segment->media_start), media_time,
9041           GST_TIME_ARGS (segment->media_stop),
9042           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9043           stream->timescale);
9044       if (segment->stop_time > qtdemux->segment.stop) {
9045         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9046             " extends to %" GST_TIME_FORMAT
9047             " past the end of the file duration %" GST_TIME_FORMAT
9048             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9049             GST_TIME_ARGS (qtdemux->segment.stop));
9050         qtdemux->segment.stop = segment->stop_time;
9051       }
9052
9053       buffer += entry_size;
9054     }
9055     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9056     stream->n_segments = count;
9057     if (media_segments_count != 1)
9058       allow_pushbased_edts = FALSE;
9059   }
9060 done:
9061
9062   /* push based does not handle segments, so act accordingly here,
9063    * and warn if applicable */
9064   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9065     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9066     /* remove and use default one below, we stream like it anyway */
9067     g_free (stream->segments);
9068     stream->segments = NULL;
9069     stream->n_segments = 0;
9070   }
9071
9072   /* no segments, create one to play the complete trak */
9073   if (stream->n_segments == 0) {
9074     GstClockTime stream_duration =
9075         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9076
9077     if (stream->segments == NULL)
9078       stream->segments = g_new (QtDemuxSegment, 1);
9079
9080     /* represent unknown our way */
9081     if (stream_duration == 0)
9082       stream_duration = GST_CLOCK_TIME_NONE;
9083
9084     stream->segments[0].time = 0;
9085     stream->segments[0].stop_time = stream_duration;
9086     stream->segments[0].duration = stream_duration;
9087     stream->segments[0].media_start = 0;
9088     stream->segments[0].media_stop = stream_duration;
9089     stream->segments[0].rate = 1.0;
9090     stream->segments[0].trak_media_start = 0;
9091
9092     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9093         GST_TIME_ARGS (stream_duration));
9094     stream->n_segments = 1;
9095     stream->dummy_segment = TRUE;
9096   }
9097   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9098
9099   return TRUE;
9100 }
9101
9102 /*
9103  * Parses the stsd atom of a svq3 trak looking for
9104  * the SMI and gama atoms.
9105  */
9106 static void
9107 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9108     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9109 {
9110   const guint8 *_gamma = NULL;
9111   GstBuffer *_seqh = NULL;
9112   const guint8 *stsd_data = stsd_entry_data;
9113   guint32 length = QT_UINT32 (stsd_data);
9114   guint16 version;
9115
9116   if (length < 32) {
9117     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9118     goto end;
9119   }
9120
9121   stsd_data += 16;
9122   length -= 16;
9123   version = QT_UINT16 (stsd_data);
9124   if (version == 3) {
9125     if (length >= 70) {
9126       length -= 70;
9127       stsd_data += 70;
9128       while (length > 8) {
9129         guint32 fourcc, size;
9130         const guint8 *data;
9131         size = QT_UINT32 (stsd_data);
9132         fourcc = QT_FOURCC (stsd_data + 4);
9133         data = stsd_data + 8;
9134
9135         if (size == 0) {
9136           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9137               "svq3 atom parsing");
9138           goto end;
9139         }
9140
9141         switch (fourcc) {
9142           case FOURCC_gama:{
9143             if (size == 12) {
9144               _gamma = data;
9145             } else {
9146               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9147                   " for gama atom, expected 12", size);
9148             }
9149             break;
9150           }
9151           case FOURCC_SMI_:{
9152             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9153               guint32 seqh_size;
9154               if (_seqh != NULL) {
9155                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9156                     " found, ignoring");
9157               } else {
9158                 seqh_size = QT_UINT32 (data + 4);
9159                 if (seqh_size > 0) {
9160                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9161                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9162                 }
9163               }
9164             }
9165             break;
9166           }
9167           default:{
9168             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9169                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9170           }
9171         }
9172
9173         if (size <= length) {
9174           length -= size;
9175           stsd_data += size;
9176         }
9177       }
9178     } else {
9179       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9180     }
9181   } else {
9182     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9183         G_GUINT16_FORMAT, version);
9184     goto end;
9185   }
9186
9187 end:
9188   if (gamma) {
9189     *gamma = _gamma;
9190   }
9191   if (seqh) {
9192     *seqh = _seqh;
9193   } else if (_seqh) {
9194     gst_buffer_unref (_seqh);
9195   }
9196 }
9197
9198 static gchar *
9199 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9200 {
9201   GNode *dinf;
9202   GstByteReader dref;
9203   gchar *uri = NULL;
9204
9205   /*
9206    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9207    * atom that might contain a 'data' atom with the rtsp uri.
9208    * This case was reported in bug #597497, some info about
9209    * the hndl atom can be found in TN1195
9210    */
9211   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9212   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9213
9214   if (dinf) {
9215     guint32 dref_num_entries = 0;
9216     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9217         gst_byte_reader_skip (&dref, 4) &&
9218         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9219       gint i;
9220
9221       /* search dref entries for hndl atom */
9222       for (i = 0; i < dref_num_entries; i++) {
9223         guint32 size = 0, type;
9224         guint8 string_len = 0;
9225         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9226             qt_atom_parser_get_fourcc (&dref, &type)) {
9227           if (type == FOURCC_hndl) {
9228             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9229
9230             /* skip data reference handle bytes and the
9231              * following pascal string and some extra 4
9232              * bytes I have no idea what are */
9233             if (!gst_byte_reader_skip (&dref, 4) ||
9234                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9235                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9236               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9237               break;
9238             }
9239
9240             /* iterate over the atoms to find the data atom */
9241             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9242               guint32 atom_size;
9243               guint32 atom_type;
9244
9245               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9246                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9247                 if (atom_type == FOURCC_data) {
9248                   const guint8 *uri_aux = NULL;
9249
9250                   /* found the data atom that might contain the rtsp uri */
9251                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9252                       "hndl atom, interpreting it as an URI");
9253                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9254                           &uri_aux)) {
9255                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9256                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9257                     else
9258                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9259                           "didn't contain a rtsp address");
9260                   } else {
9261                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9262                         "atom contents");
9263                   }
9264                   break;
9265                 }
9266                 /* skipping to the next entry */
9267                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9268                   break;
9269               } else {
9270                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9271                     "atom header");
9272                 break;
9273               }
9274             }
9275             break;
9276           }
9277           /* skip to the next entry */
9278           if (!gst_byte_reader_skip (&dref, size - 8))
9279             break;
9280         } else {
9281           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9282         }
9283       }
9284       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9285     }
9286   }
9287   return uri;
9288 }
9289
9290 #define AMR_NB_ALL_MODES        0x81ff
9291 #define AMR_WB_ALL_MODES        0x83ff
9292 static guint
9293 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9294 {
9295   /* The 'damr' atom is of the form:
9296    *
9297    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9298    *    32 b       8 b          16 b           8 b                 8 b
9299    *
9300    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9301    * represents the highest mode used in the stream (and thus the maximum
9302    * bitrate), with a couple of special cases as seen below.
9303    */
9304
9305   /* Map of frame type ID -> bitrate */
9306   static const guint nb_bitrates[] = {
9307     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9308   };
9309   static const guint wb_bitrates[] = {
9310     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9311   };
9312   GstMapInfo map;
9313   gsize max_mode;
9314   guint16 mode_set;
9315
9316   gst_buffer_map (buf, &map, GST_MAP_READ);
9317
9318   if (map.size != 0x11) {
9319     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9320     goto bad_data;
9321   }
9322
9323   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9324     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9325         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9326     goto bad_data;
9327   }
9328
9329   mode_set = QT_UINT16 (map.data + 13);
9330
9331   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9332     max_mode = 7 + (wb ? 1 : 0);
9333   else
9334     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9335     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9336
9337   if (max_mode == -1) {
9338     GST_DEBUG ("No mode indication was found (mode set) = %x",
9339         (guint) mode_set);
9340     goto bad_data;
9341   }
9342
9343   gst_buffer_unmap (buf, &map);
9344   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9345
9346 bad_data:
9347   gst_buffer_unmap (buf, &map);
9348   return 0;
9349 }
9350
9351 static gboolean
9352 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9353     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9354 {
9355   /*
9356    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9357    * [0 1 2]
9358    * [3 4 5]
9359    * [6 7 8]
9360    */
9361
9362   if (gst_byte_reader_get_remaining (reader) < 36)
9363     return FALSE;
9364
9365   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9366   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9367   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9368   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9369   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9370   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9371   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9372   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9373   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9374
9375   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9376   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9377       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9378       matrix[2] & 0xFF);
9379   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9380       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9381       matrix[5] & 0xFF);
9382   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9383       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9384       matrix[8] & 0xFF);
9385
9386   return TRUE;
9387 }
9388
9389 static void
9390 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9391     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9392 {
9393
9394 /* [a b c]
9395  * [d e f]
9396  * [g h i]
9397  *
9398  * This macro will only compare value abdegh, it expects cfi to have already
9399  * been checked
9400  */
9401 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9402                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9403
9404   /* only handle the cases where the last column has standard values */
9405   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9406     const gchar *rotation_tag = NULL;
9407
9408     /* no rotation needed */
9409     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9410       /* NOP */
9411     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9412       rotation_tag = "rotate-90";
9413     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9414       rotation_tag = "rotate-180";
9415     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9416       rotation_tag = "rotate-270";
9417     } else {
9418       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9419     }
9420
9421     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9422         rotation_tag);
9423     if (rotation_tag != NULL) {
9424       if (*taglist == NULL)
9425         *taglist = gst_tag_list_new_empty ();
9426       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9427           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9428     }
9429   } else {
9430     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9431   }
9432 }
9433
9434 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9435  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9436  * Common Encryption (cenc), the function will also parse the tenc box (defined
9437  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9438  * (typically an enc[v|a|t|s] sample entry); the function will set
9439  * @original_fmt to the fourcc of the original unencrypted stream format.
9440  * Returns TRUE if successful; FALSE otherwise. */
9441 static gboolean
9442 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9443     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9444 {
9445   GNode *sinf;
9446   GNode *frma;
9447   GNode *schm;
9448   GNode *schi;
9449
9450   g_return_val_if_fail (qtdemux != NULL, FALSE);
9451   g_return_val_if_fail (stream != NULL, FALSE);
9452   g_return_val_if_fail (container != NULL, FALSE);
9453   g_return_val_if_fail (original_fmt != NULL, FALSE);
9454
9455   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9456   if (G_UNLIKELY (!sinf)) {
9457     if (stream->protection_scheme_type == FOURCC_cenc) {
9458       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9459           "mandatory for Common Encryption");
9460       return FALSE;
9461     }
9462     return TRUE;
9463   }
9464
9465   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9466   if (G_UNLIKELY (!frma)) {
9467     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9468     return FALSE;
9469   }
9470
9471   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9472   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9473       GST_FOURCC_ARGS (*original_fmt));
9474
9475   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9476   if (!schm) {
9477     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9478     return FALSE;
9479   }
9480   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9481   stream->protection_scheme_version =
9482       QT_UINT32 ((const guint8 *) schm->data + 16);
9483
9484   GST_DEBUG_OBJECT (qtdemux,
9485       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9486       "protection_scheme_version: %#010x",
9487       GST_FOURCC_ARGS (stream->protection_scheme_type),
9488       stream->protection_scheme_version);
9489
9490   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9491   if (!schi) {
9492     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9493     return FALSE;
9494   }
9495   if (stream->protection_scheme_type == FOURCC_cenc) {
9496     QtDemuxCencSampleSetInfo *info;
9497     GNode *tenc;
9498     const guint8 *tenc_data;
9499     guint32 isEncrypted;
9500     guint8 iv_size;
9501     const guint8 *default_kid;
9502     GstBuffer *kid_buf;
9503
9504     if (G_UNLIKELY (!stream->protection_scheme_info))
9505       stream->protection_scheme_info =
9506           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9507
9508     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9509
9510     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9511     if (!tenc) {
9512       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9513           "which is mandatory for Common Encryption");
9514       return FALSE;
9515     }
9516     tenc_data = (const guint8 *) tenc->data + 12;
9517     isEncrypted = QT_UINT24 (tenc_data);
9518     iv_size = QT_UINT8 (tenc_data + 3);
9519     default_kid = (tenc_data + 4);
9520     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9521     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9522     if (info->default_properties)
9523       gst_structure_free (info->default_properties);
9524     info->default_properties =
9525         gst_structure_new ("application/x-cenc",
9526         "iv_size", G_TYPE_UINT, iv_size,
9527         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9528         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9529     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9530         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9531     gst_buffer_unref (kid_buf);
9532   }
9533   return TRUE;
9534 }
9535
9536 /* parse the traks.
9537  * With each track we associate a new QtDemuxStream that contains all the info
9538  * about the trak.
9539  * traks that do not decode to something (like strm traks) will not have a pad.
9540  */
9541 static gboolean
9542 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9543 {
9544   GstByteReader tkhd;
9545   int offset;
9546   GNode *mdia;
9547   GNode *mdhd;
9548   GNode *hdlr;
9549   GNode *minf;
9550   GNode *stbl;
9551   GNode *stsd;
9552   GNode *mp4a;
9553   GNode *mp4v;
9554   GNode *wave;
9555   GNode *esds;
9556   GNode *pasp;
9557   GNode *colr;
9558   GNode *tref;
9559   GNode *udta;
9560   GNode *svmi;
9561   GNode *fiel;
9562
9563   QtDemuxStream *stream = NULL;
9564   gboolean new_stream = FALSE;
9565   gchar *codec = NULL;
9566   const guint8 *stsd_data;
9567   const guint8 *stsd_entry_data;
9568   guint remaining_stsd_len;
9569   guint stsd_entry_count;
9570   guint stsd_index;
9571   guint16 lang_code;            /* quicktime lang code or packed iso code */
9572   guint32 version;
9573   guint32 tkhd_flags = 0;
9574   guint8 tkhd_version = 0;
9575   guint32 w = 0, h = 0;
9576   guint32 fourcc;
9577   guint value_size, stsd_len, len;
9578   guint32 track_id;
9579   guint32 dummy;
9580
9581   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9582
9583   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9584       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9585       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9586     goto corrupt_file;
9587
9588   /* pick between 64 or 32 bits */
9589   value_size = tkhd_version == 1 ? 8 : 4;
9590   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9591       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9592     goto corrupt_file;
9593
9594   if (!qtdemux->got_moov) {
9595     if (qtdemux_find_stream (qtdemux, track_id))
9596       goto existing_stream;
9597     stream = _create_stream ();
9598     stream->track_id = track_id;
9599     new_stream = TRUE;
9600   } else {
9601     stream = qtdemux_find_stream (qtdemux, track_id);
9602     if (!stream) {
9603       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9604       goto skip_track;
9605     }
9606
9607     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9608
9609     /* flush samples data from this track from previous moov */
9610     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9611     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9612   }
9613   /* need defaults for fragments */
9614   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9615
9616   if ((tkhd_flags & 1) == 0)
9617     stream->disabled = TRUE;
9618
9619   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9620       tkhd_version, tkhd_flags, stream->track_id);
9621
9622   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9623     goto corrupt_file;
9624
9625   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9626     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9627     if (qtdemux->major_brand != FOURCC_mjp2 ||
9628         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9629       goto corrupt_file;
9630   }
9631
9632   len = QT_UINT32 ((guint8 *) mdhd->data);
9633   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9634   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9635   if (version == 0x01000000) {
9636     if (len < 38)
9637       goto corrupt_file;
9638     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9639     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9640     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9641   } else {
9642     if (len < 30)
9643       goto corrupt_file;
9644     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9645     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9646     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9647   }
9648
9649   if (lang_code < 0x400) {
9650     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9651   } else if (lang_code == 0x7fff) {
9652     stream->lang_id[0] = 0;     /* unspecified */
9653   } else {
9654     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9655     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9656     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9657     stream->lang_id[3] = 0;
9658   }
9659
9660   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9661       stream->timescale);
9662   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9663       stream->duration);
9664   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9665       lang_code, stream->lang_id);
9666
9667   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9668     goto corrupt_file;
9669
9670   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9671     /* chapters track reference */
9672     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9673     if (chap) {
9674       gsize length = GST_READ_UINT32_BE (chap->data);
9675       if (qtdemux->chapters_track_id)
9676         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9677
9678       if (length >= 12) {
9679         qtdemux->chapters_track_id =
9680             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9681       }
9682     }
9683   }
9684
9685   /* fragmented files may have bogus duration in moov */
9686   if (!qtdemux->fragmented &&
9687       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9688     guint64 tdur1, tdur2;
9689
9690     /* don't overflow */
9691     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9692     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9693
9694     /* HACK:
9695      * some of those trailers, nowadays, have prologue images that are
9696      * themselves video tracks as well. I haven't really found a way to
9697      * identify those yet, except for just looking at their duration. */
9698     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9699       GST_WARNING_OBJECT (qtdemux,
9700           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9701           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9702           "found, assuming preview image or something; skipping track",
9703           stream->duration, stream->timescale, qtdemux->duration,
9704           qtdemux->timescale);
9705       if (new_stream)
9706         gst_qtdemux_stream_free (qtdemux, stream);
9707       return TRUE;
9708     }
9709   }
9710
9711   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9712     goto corrupt_file;
9713
9714   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9715       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9716
9717   len = QT_UINT32 ((guint8 *) hdlr->data);
9718   if (len >= 20)
9719     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9720   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9721       GST_FOURCC_ARGS (stream->subtype));
9722
9723   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9724     goto corrupt_file;
9725
9726   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9727     goto corrupt_file;
9728
9729   /*parse svmi header if existing */
9730   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9731   if (svmi) {
9732     len = QT_UINT32 ((guint8 *) svmi->data);
9733     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9734     if (!version) {
9735       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9736       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9737       guint8 frame_type, frame_layout;
9738
9739       /* MPEG-A stereo video */
9740       if (qtdemux->major_brand == FOURCC_ss02)
9741         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9742
9743       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9744       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9745       switch (frame_type) {
9746         case 0:
9747           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9748           break;
9749         case 1:
9750           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9751           break;
9752         case 2:
9753           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9754           break;
9755         case 3:
9756           /* mode 3 is primary/secondary view sequence, ie
9757            * left/right views in separate tracks. See section 7.2
9758            * of ISO/IEC 23000-11:2009 */
9759           GST_FIXME_OBJECT (qtdemux,
9760               "Implement stereo video in separate streams");
9761       }
9762
9763       if ((frame_layout & 0x1) == 0)
9764         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9765
9766       GST_LOG_OBJECT (qtdemux,
9767           "StereoVideo: composition type: %u, is_left_first: %u",
9768           frame_type, frame_layout);
9769       stream->multiview_mode = mode;
9770       stream->multiview_flags = flags;
9771     }
9772   }
9773
9774   /* parse rest of tkhd */
9775   if (stream->subtype == FOURCC_vide) {
9776     guint32 matrix[9];
9777
9778     /* version 1 uses some 64-bit ints */
9779     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9780       goto corrupt_file;
9781
9782     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9783       goto corrupt_file;
9784
9785     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9786         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9787       goto corrupt_file;
9788
9789     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9790         &stream->stream_tags);
9791   }
9792
9793   /* parse stsd */
9794   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9795     goto corrupt_file;
9796   stsd_data = (const guint8 *) stsd->data;
9797
9798   /* stsd should at least have one entry */
9799   stsd_len = QT_UINT32 (stsd_data);
9800   if (stsd_len < 24) {
9801     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9802     if (stream->subtype == FOURCC_vivo) {
9803       if (new_stream)
9804         gst_qtdemux_stream_free (qtdemux, stream);
9805       return TRUE;
9806     } else {
9807       goto corrupt_file;
9808     }
9809   }
9810
9811   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9812   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9813   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9814   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9815
9816   stsd_entry_data = stsd_data + 16;
9817   remaining_stsd_len = stsd_len - 16;
9818   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9819     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9820
9821     /* and that entry should fit within stsd */
9822     len = QT_UINT32 (stsd_entry_data);
9823     if (len > remaining_stsd_len)
9824       goto corrupt_file;
9825
9826     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9827     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9828         GST_FOURCC_ARGS (entry->fourcc));
9829     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9830
9831     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9832       goto error_encrypted;
9833
9834     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9835       /* FIXME this looks wrong, there might be multiple children
9836        * with the same type */
9837       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9838       stream->protected = TRUE;
9839       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9840         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9841     }
9842
9843     if (stream->subtype == FOURCC_vide) {
9844       gboolean gray;
9845       gint depth, palette_size, palette_count;
9846       guint32 *palette_data = NULL;
9847
9848       entry->sampled = TRUE;
9849
9850       stream->display_width = w >> 16;
9851       stream->display_height = h >> 16;
9852
9853       offset = 16;
9854       if (len < 86)             /* TODO verify */
9855         goto corrupt_file;
9856
9857       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9858       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9859       entry->fps_n = 0;         /* this is filled in later */
9860       entry->fps_d = 0;         /* this is filled in later */
9861       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9862       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9863
9864       /* if color_table_id is 0, ctab atom must follow; however some files
9865        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9866        * if color table is not present we'll correct the value */
9867       if (entry->color_table_id == 0 &&
9868           (len < 90
9869               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9870         entry->color_table_id = -1;
9871       }
9872
9873       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9874           entry->width, entry->height, entry->bits_per_sample,
9875           entry->color_table_id);
9876
9877       depth = entry->bits_per_sample;
9878
9879       /* more than 32 bits means grayscale */
9880       gray = (depth > 32);
9881       /* low 32 bits specify the depth  */
9882       depth &= 0x1F;
9883
9884       /* different number of palette entries is determined by depth. */
9885       palette_count = 0;
9886       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9887         palette_count = (1 << depth);
9888       palette_size = palette_count * 4;
9889
9890       if (entry->color_table_id) {
9891         switch (palette_count) {
9892           case 0:
9893             break;
9894           case 2:
9895             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9896             break;
9897           case 4:
9898             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9899             break;
9900           case 16:
9901             if (gray)
9902               palette_data =
9903                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9904             else
9905               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9906             break;
9907           case 256:
9908             if (gray)
9909               palette_data =
9910                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9911             else
9912               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9913             break;
9914           default:
9915             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9916                 (_("The video in this file might not play correctly.")),
9917                 ("unsupported palette depth %d", depth));
9918             break;
9919         }
9920       } else {
9921         gint i, j, start, end;
9922
9923         if (len < 94)
9924           goto corrupt_file;
9925
9926         /* read table */
9927         start = QT_UINT32 (stsd_entry_data + offset + 70);
9928         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9929         end = QT_UINT16 (stsd_entry_data + offset + 76);
9930
9931         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9932             start, end, palette_count);
9933
9934         if (end > 255)
9935           end = 255;
9936         if (start > end)
9937           start = end;
9938
9939         if (len < 94 + (end - start) * 8)
9940           goto corrupt_file;
9941
9942         /* palette is always the same size */
9943         palette_data = g_malloc0 (256 * 4);
9944         palette_size = 256 * 4;
9945
9946         for (j = 0, i = start; i <= end; j++, i++) {
9947           guint32 a, r, g, b;
9948
9949           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9950           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9951           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9952           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9953
9954           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9955               (g & 0xff00) | (b >> 8);
9956         }
9957       }
9958
9959       if (entry->caps)
9960         gst_caps_unref (entry->caps);
9961
9962       entry->caps =
9963           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9964           &codec);
9965       if (G_UNLIKELY (!entry->caps)) {
9966         g_free (palette_data);
9967         goto unknown_stream;
9968       }
9969
9970       if (codec) {
9971         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
9972             GST_TAG_VIDEO_CODEC, codec, NULL);
9973         g_free (codec);
9974         codec = NULL;
9975       }
9976
9977       if (palette_data) {
9978         GstStructure *s;
9979
9980         if (entry->rgb8_palette)
9981           gst_memory_unref (entry->rgb8_palette);
9982         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9983             palette_data, palette_size, 0, palette_size, palette_data, g_free);
9984
9985         s = gst_caps_get_structure (entry->caps, 0);
9986
9987         /* non-raw video has a palette_data property. raw video has the palette as
9988          * an extra plane that we append to the output buffers before we push
9989          * them*/
9990         if (!gst_structure_has_name (s, "video/x-raw")) {
9991           GstBuffer *palette;
9992
9993           palette = gst_buffer_new ();
9994           gst_buffer_append_memory (palette, entry->rgb8_palette);
9995           entry->rgb8_palette = NULL;
9996
9997           gst_caps_set_simple (entry->caps, "palette_data",
9998               GST_TYPE_BUFFER, palette, NULL);
9999           gst_buffer_unref (palette);
10000         }
10001       } else if (palette_count != 0) {
10002         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10003             (NULL), ("Unsupported palette depth %d", depth));
10004       }
10005
10006       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10007           QT_UINT16 (stsd_entry_data + offset + 32));
10008
10009       esds = NULL;
10010       pasp = NULL;
10011       colr = NULL;
10012       fiel = NULL;
10013       /* pick 'the' stsd child */
10014       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10015       if (!stream->protected) {
10016         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10017           mp4v = NULL;
10018         }
10019       } else {
10020         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10021           mp4v = NULL;
10022         }
10023       }
10024
10025       if (mp4v) {
10026         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10027         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10028         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10029         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10030       }
10031
10032       if (pasp) {
10033         const guint8 *pasp_data = (const guint8 *) pasp->data;
10034         gint len = QT_UINT32 (pasp_data);
10035
10036         if (len == 16) {
10037           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10038           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10039         } else {
10040           CUR_STREAM (stream)->par_w = 0;
10041           CUR_STREAM (stream)->par_h = 0;
10042         }
10043       } else {
10044         CUR_STREAM (stream)->par_w = 0;
10045         CUR_STREAM (stream)->par_h = 0;
10046       }
10047
10048       if (fiel) {
10049         const guint8 *fiel_data = (const guint8 *) fiel->data;
10050         gint len = QT_UINT32 (fiel_data);
10051
10052         if (len == 10) {
10053           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10054           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10055         }
10056       }
10057
10058       if (colr) {
10059         const guint8 *colr_data = (const guint8 *) colr->data;
10060         gint len = QT_UINT32 (colr_data);
10061
10062         if (len == 19 || len == 18) {
10063           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10064
10065           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10066             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10067             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10068             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10069             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10070
10071             switch (primaries) {
10072               case 1:
10073                 CUR_STREAM (stream)->colorimetry.primaries =
10074                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10075                 break;
10076               case 5:
10077                 CUR_STREAM (stream)->colorimetry.primaries =
10078                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10079                 break;
10080               case 6:
10081                 CUR_STREAM (stream)->colorimetry.primaries =
10082                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10083                 break;
10084               case 9:
10085                 CUR_STREAM (stream)->colorimetry.primaries =
10086                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10087                 break;
10088               default:
10089                 break;
10090             }
10091
10092             switch (transfer_function) {
10093               case 1:
10094                 CUR_STREAM (stream)->colorimetry.transfer =
10095                     GST_VIDEO_TRANSFER_BT709;
10096                 break;
10097               case 7:
10098                 CUR_STREAM (stream)->colorimetry.transfer =
10099                     GST_VIDEO_TRANSFER_SMPTE240M;
10100                 break;
10101               default:
10102                 break;
10103             }
10104
10105             switch (matrix) {
10106               case 1:
10107                 CUR_STREAM (stream)->colorimetry.matrix =
10108                     GST_VIDEO_COLOR_MATRIX_BT709;
10109                 break;
10110               case 6:
10111                 CUR_STREAM (stream)->colorimetry.matrix =
10112                     GST_VIDEO_COLOR_MATRIX_BT601;
10113                 break;
10114               case 7:
10115                 CUR_STREAM (stream)->colorimetry.matrix =
10116                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10117                 break;
10118               case 9:
10119                 CUR_STREAM (stream)->colorimetry.matrix =
10120                     GST_VIDEO_COLOR_MATRIX_BT2020;
10121                 break;
10122               default:
10123                 break;
10124             }
10125
10126             CUR_STREAM (stream)->colorimetry.range =
10127                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10128                 GST_VIDEO_COLOR_RANGE_16_235;
10129           } else {
10130             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10131           }
10132         } else {
10133           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10134         }
10135       }
10136
10137       if (esds) {
10138         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10139             stream->stream_tags);
10140       } else {
10141         switch (fourcc) {
10142           case FOURCC_H264:
10143           case FOURCC_avc1:
10144           case FOURCC_avc3:
10145           {
10146             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10147             const guint8 *avc_data = stsd_entry_data + 0x56;
10148
10149             /* find avcC */
10150             while (len >= 0x8) {
10151               gint size;
10152
10153               if (QT_UINT32 (avc_data) <= len)
10154                 size = QT_UINT32 (avc_data) - 0x8;
10155               else
10156                 size = len - 0x8;
10157
10158               if (size < 1)
10159                 /* No real data, so break out */
10160                 break;
10161
10162               switch (QT_FOURCC (avc_data + 0x4)) {
10163                 case FOURCC_avcC:
10164                 {
10165                   /* parse, if found */
10166                   GstBuffer *buf;
10167
10168                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10169
10170                   /* First 4 bytes are the length of the atom, the next 4 bytes
10171                    * are the fourcc, the next 1 byte is the version, and the
10172                    * subsequent bytes are profile_tier_level structure like data. */
10173                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10174                       avc_data + 8 + 1, size - 1);
10175                   buf = gst_buffer_new_and_alloc (size);
10176                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10177                   gst_caps_set_simple (entry->caps,
10178                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10179                   gst_buffer_unref (buf);
10180
10181                   break;
10182                 }
10183                 case FOURCC_strf:
10184                 {
10185                   GstBuffer *buf;
10186
10187                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10188
10189                   /* First 4 bytes are the length of the atom, the next 4 bytes
10190                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10191                    * next 1 byte is the version, and the
10192                    * subsequent bytes are sequence parameter set like data. */
10193
10194                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10195                   if (size > 1) {
10196                     gst_codec_utils_h264_caps_set_level_and_profile
10197                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10198
10199                     buf = gst_buffer_new_and_alloc (size);
10200                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10201                     gst_caps_set_simple (entry->caps,
10202                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10203                     gst_buffer_unref (buf);
10204                   }
10205                   break;
10206                 }
10207                 case FOURCC_btrt:
10208                 {
10209                   guint avg_bitrate, max_bitrate;
10210
10211                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10212                   if (size < 12)
10213                     break;
10214
10215                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10216                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10217
10218                   if (!max_bitrate && !avg_bitrate)
10219                     break;
10220
10221                   /* Some muxers seem to swap the average and maximum bitrates
10222                    * (I'm looking at you, YouTube), so we swap for sanity. */
10223                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10224                     guint temp = avg_bitrate;
10225
10226                     avg_bitrate = max_bitrate;
10227                     max_bitrate = temp;
10228                   }
10229
10230                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10231                     gst_tag_list_add (stream->stream_tags,
10232                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10233                         max_bitrate, NULL);
10234                   }
10235                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10236                     gst_tag_list_add (stream->stream_tags,
10237                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10238                         NULL);
10239                   }
10240
10241                   break;
10242                 }
10243
10244                 default:
10245                   break;
10246               }
10247
10248               len -= size + 8;
10249               avc_data += size + 8;
10250             }
10251
10252             break;
10253           }
10254           case FOURCC_H265:
10255           case FOURCC_hvc1:
10256           case FOURCC_hev1:
10257           {
10258             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10259             const guint8 *hevc_data = stsd_entry_data + 0x56;
10260
10261             /* find hevc */
10262             while (len >= 0x8) {
10263               gint size;
10264
10265               if (QT_UINT32 (hevc_data) <= len)
10266                 size = QT_UINT32 (hevc_data) - 0x8;
10267               else
10268                 size = len - 0x8;
10269
10270               if (size < 1)
10271                 /* No real data, so break out */
10272                 break;
10273
10274               switch (QT_FOURCC (hevc_data + 0x4)) {
10275                 case FOURCC_hvcC:
10276                 {
10277                   /* parse, if found */
10278                   GstBuffer *buf;
10279
10280                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10281
10282                   /* First 4 bytes are the length of the atom, the next 4 bytes
10283                    * are the fourcc, the next 1 byte is the version, and the
10284                    * subsequent bytes are sequence parameter set like data. */
10285                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10286                       (entry->caps, hevc_data + 8 + 1, size - 1);
10287
10288                   buf = gst_buffer_new_and_alloc (size);
10289                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10290                   gst_caps_set_simple (entry->caps,
10291                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10292                   gst_buffer_unref (buf);
10293                   break;
10294                 }
10295                 default:
10296                   break;
10297               }
10298               len -= size + 8;
10299               hevc_data += size + 8;
10300             }
10301             break;
10302           }
10303           case FOURCC_mp4v:
10304           case FOURCC_MP4V:
10305           case FOURCC_fmp4:
10306           case FOURCC_FMP4:
10307           case FOURCC_xvid:
10308           case FOURCC_XVID:
10309           {
10310             GNode *glbl;
10311
10312             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10313                 GST_FOURCC_ARGS (fourcc));
10314
10315             /* codec data might be in glbl extension atom */
10316             glbl = mp4v ?
10317                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10318             if (glbl) {
10319               guint8 *data;
10320               GstBuffer *buf;
10321               gint len;
10322
10323               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10324               data = glbl->data;
10325               len = QT_UINT32 (data);
10326               if (len > 0x8) {
10327                 len -= 0x8;
10328                 buf = gst_buffer_new_and_alloc (len);
10329                 gst_buffer_fill (buf, 0, data + 8, len);
10330                 gst_caps_set_simple (entry->caps,
10331                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10332                 gst_buffer_unref (buf);
10333               }
10334             }
10335             break;
10336           }
10337           case FOURCC_mjp2:
10338           {
10339             /* see annex I of the jpeg2000 spec */
10340             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10341             const guint8 *data;
10342             const gchar *colorspace = NULL;
10343             gint ncomp = 0;
10344             guint32 ncomp_map = 0;
10345             gint32 *comp_map = NULL;
10346             guint32 nchan_def = 0;
10347             gint32 *chan_def = NULL;
10348
10349             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10350             /* some required atoms */
10351             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10352             if (!mjp2)
10353               break;
10354             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10355             if (!jp2h)
10356               break;
10357
10358             /* number of components; redundant with info in codestream, but useful
10359                to a muxer */
10360             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10361             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10362               break;
10363             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10364
10365             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10366             if (!colr)
10367               break;
10368             GST_DEBUG_OBJECT (qtdemux, "found colr");
10369             /* extract colour space info */
10370             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10371               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10372                 case 16:
10373                   colorspace = "sRGB";
10374                   break;
10375                 case 17:
10376                   colorspace = "GRAY";
10377                   break;
10378                 case 18:
10379                   colorspace = "sYUV";
10380                   break;
10381                 default:
10382                   colorspace = NULL;
10383                   break;
10384               }
10385             }
10386             if (!colorspace)
10387               /* colr is required, and only values 16, 17, and 18 are specified,
10388                  so error if we have no colorspace */
10389               break;
10390
10391             /* extract component mapping */
10392             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10393             if (cmap) {
10394               guint32 cmap_len = 0;
10395               int i;
10396               cmap_len = QT_UINT32 (cmap->data);
10397               if (cmap_len >= 8) {
10398                 /* normal box, subtract off header */
10399                 cmap_len -= 8;
10400                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10401                 if (cmap_len % 4 == 0) {
10402                   ncomp_map = (cmap_len / 4);
10403                   comp_map = g_new0 (gint32, ncomp_map);
10404                   for (i = 0; i < ncomp_map; i++) {
10405                     guint16 cmp;
10406                     guint8 mtyp, pcol;
10407                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10408                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10409                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10410                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10411                   }
10412                 }
10413               }
10414             }
10415             /* extract channel definitions */
10416             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10417             if (cdef) {
10418               guint32 cdef_len = 0;
10419               int i;
10420               cdef_len = QT_UINT32 (cdef->data);
10421               if (cdef_len >= 10) {
10422                 /* normal box, subtract off header and len */
10423                 cdef_len -= 10;
10424                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10425                 if (cdef_len % 6 == 0) {
10426                   nchan_def = (cdef_len / 6);
10427                   chan_def = g_new0 (gint32, nchan_def);
10428                   for (i = 0; i < nchan_def; i++)
10429                     chan_def[i] = -1;
10430                   for (i = 0; i < nchan_def; i++) {
10431                     guint16 cn, typ, asoc;
10432                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10433                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10434                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10435                     if (cn < nchan_def) {
10436                       switch (typ) {
10437                         case 0:
10438                           chan_def[cn] = asoc;
10439                           break;
10440                         case 1:
10441                           chan_def[cn] = 0;     /* alpha */
10442                           break;
10443                         default:
10444                           chan_def[cn] = -typ;
10445                       }
10446                     }
10447                   }
10448                 }
10449               }
10450             }
10451
10452             gst_caps_set_simple (entry->caps,
10453                 "num-components", G_TYPE_INT, ncomp, NULL);
10454             gst_caps_set_simple (entry->caps,
10455                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10456
10457             if (comp_map) {
10458               GValue arr = { 0, };
10459               GValue elt = { 0, };
10460               int i;
10461               g_value_init (&arr, GST_TYPE_ARRAY);
10462               g_value_init (&elt, G_TYPE_INT);
10463               for (i = 0; i < ncomp_map; i++) {
10464                 g_value_set_int (&elt, comp_map[i]);
10465                 gst_value_array_append_value (&arr, &elt);
10466               }
10467               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10468                   "component-map", &arr);
10469               g_value_unset (&elt);
10470               g_value_unset (&arr);
10471               g_free (comp_map);
10472             }
10473
10474             if (chan_def) {
10475               GValue arr = { 0, };
10476               GValue elt = { 0, };
10477               int i;
10478               g_value_init (&arr, GST_TYPE_ARRAY);
10479               g_value_init (&elt, G_TYPE_INT);
10480               for (i = 0; i < nchan_def; i++) {
10481                 g_value_set_int (&elt, chan_def[i]);
10482                 gst_value_array_append_value (&arr, &elt);
10483               }
10484               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10485                   "channel-definitions", &arr);
10486               g_value_unset (&elt);
10487               g_value_unset (&arr);
10488               g_free (chan_def);
10489             }
10490
10491             /* some optional atoms */
10492             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10493             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10494
10495             /* indicate possible fields in caps */
10496             if (field) {
10497               data = (guint8 *) field->data + 8;
10498               if (*data != 1)
10499                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10500                     (gint) * data, NULL);
10501             }
10502             /* add codec_data if provided */
10503             if (prefix) {
10504               GstBuffer *buf;
10505               gint len;
10506
10507               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10508               data = prefix->data;
10509               len = QT_UINT32 (data);
10510               if (len > 0x8) {
10511                 len -= 0x8;
10512                 buf = gst_buffer_new_and_alloc (len);
10513                 gst_buffer_fill (buf, 0, data + 8, len);
10514                 gst_caps_set_simple (entry->caps,
10515                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10516                 gst_buffer_unref (buf);
10517               }
10518             }
10519             break;
10520           }
10521           case FOURCC_SVQ3:
10522           case FOURCC_VP31:
10523           {
10524             GstBuffer *buf;
10525             GstBuffer *seqh = NULL;
10526             const guint8 *gamma_data = NULL;
10527             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10528
10529             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10530                 &seqh);
10531             if (gamma_data) {
10532               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10533                   QT_FP32 (gamma_data), NULL);
10534             }
10535             if (seqh) {
10536               /* sorry for the bad name, but we don't know what this is, other
10537                * than its own fourcc */
10538               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10539                   NULL);
10540               gst_buffer_unref (seqh);
10541             }
10542
10543             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10544             buf = gst_buffer_new_and_alloc (len);
10545             gst_buffer_fill (buf, 0, stsd_data, len);
10546             gst_caps_set_simple (entry->caps,
10547                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10548             gst_buffer_unref (buf);
10549             break;
10550           }
10551           case FOURCC_jpeg:
10552           {
10553             /* https://developer.apple.com/standards/qtff-2001.pdf,
10554              * page 92, "Video Sample Description", under table 3.1 */
10555             GstByteReader br;
10556
10557             const gint compressor_offset =
10558                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10559             const gint min_size = compressor_offset + 32 + 2 + 2;
10560             GNode *jpeg;
10561             guint32 len;
10562             guint16 color_table_id = 0;
10563             gboolean ok;
10564
10565             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10566
10567             /* recover information on interlaced/progressive */
10568             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10569             if (!jpeg)
10570               break;
10571
10572             len = QT_UINT32 (jpeg->data);
10573             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10574                 min_size);
10575             if (len >= min_size) {
10576               gst_byte_reader_init (&br, jpeg->data, len);
10577
10578               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10579               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10580               if (color_table_id != 0) {
10581                 /* the spec says there can be concatenated chunks in the data, and we want
10582                  * to find one called field. Walk through them. */
10583                 gint offset = min_size;
10584                 while (offset + 8 < len) {
10585                   guint32 size = 0, tag;
10586                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10587                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10588                   if (!ok || size < 8) {
10589                     GST_WARNING_OBJECT (qtdemux,
10590                         "Failed to walk optional chunk list");
10591                     break;
10592                   }
10593                   GST_DEBUG_OBJECT (qtdemux,
10594                       "Found optional %4.4s chunk, size %u",
10595                       (const char *) &tag, size);
10596                   if (tag == FOURCC_fiel) {
10597                     guint8 n_fields = 0, ordering = 0;
10598                     gst_byte_reader_get_uint8 (&br, &n_fields);
10599                     gst_byte_reader_get_uint8 (&br, &ordering);
10600                     if (n_fields == 1 || n_fields == 2) {
10601                       GST_DEBUG_OBJECT (qtdemux,
10602                           "Found fiel tag with %u fields, ordering %u",
10603                           n_fields, ordering);
10604                       if (n_fields == 2)
10605                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10606                             "interlace-mode", G_TYPE_STRING, "interleaved",
10607                             NULL);
10608                     } else {
10609                       GST_WARNING_OBJECT (qtdemux,
10610                           "Found fiel tag with invalid fields (%u)", n_fields);
10611                     }
10612                   }
10613                   offset += size;
10614                 }
10615               } else {
10616                 GST_DEBUG_OBJECT (qtdemux,
10617                     "Color table ID is 0, not trying to get interlacedness");
10618               }
10619             } else {
10620               GST_WARNING_OBJECT (qtdemux,
10621                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10622             }
10623
10624             break;
10625           }
10626           case FOURCC_rle_:
10627           case FOURCC_WRLE:
10628           {
10629             gst_caps_set_simple (entry->caps,
10630                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 82),
10631                 NULL);
10632             break;
10633           }
10634           case FOURCC_XiTh:
10635           {
10636             GNode *xith, *xdxt;
10637
10638             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10639             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10640             if (!xith)
10641               break;
10642
10643             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10644             if (!xdxt)
10645               break;
10646
10647             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10648             /* collect the headers and store them in a stream list so that we can
10649              * send them out first */
10650             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10651             break;
10652           }
10653           case FOURCC_ovc1:
10654           {
10655             GNode *ovc1;
10656             guint8 *ovc1_data;
10657             guint ovc1_len;
10658             GstBuffer *buf;
10659
10660             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10661             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10662             if (!ovc1)
10663               break;
10664             ovc1_data = ovc1->data;
10665             ovc1_len = QT_UINT32 (ovc1_data);
10666             if (ovc1_len <= 198) {
10667               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10668               break;
10669             }
10670             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10671             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10672             gst_caps_set_simple (entry->caps,
10673                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10674             gst_buffer_unref (buf);
10675             break;
10676           }
10677           case FOURCC_vc_1:
10678           {
10679             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10680             const guint8 *vc1_data = stsd_entry_data + 0x56;
10681
10682             /* find dvc1 */
10683             while (len >= 8) {
10684               gint size;
10685
10686               if (QT_UINT32 (vc1_data) <= len)
10687                 size = QT_UINT32 (vc1_data) - 8;
10688               else
10689                 size = len - 8;
10690
10691               if (size < 1)
10692                 /* No real data, so break out */
10693                 break;
10694
10695               switch (QT_FOURCC (vc1_data + 0x4)) {
10696                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10697                 {
10698                   GstBuffer *buf;
10699
10700                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10701                   buf = gst_buffer_new_and_alloc (size);
10702                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10703                   gst_caps_set_simple (entry->caps,
10704                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10705                   gst_buffer_unref (buf);
10706                   break;
10707                 }
10708                 default:
10709                   break;
10710               }
10711               len -= size + 8;
10712               vc1_data += size + 8;
10713             }
10714             break;
10715           }
10716           default:
10717             break;
10718         }
10719       }
10720
10721       GST_INFO_OBJECT (qtdemux,
10722           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10723           GST_FOURCC_ARGS (fourcc), entry->caps);
10724
10725     } else if (stream->subtype == FOURCC_soun) {
10726       int version, samplesize;
10727       guint16 compression_id;
10728       gboolean amrwb = FALSE;
10729
10730       offset = 16;
10731       /* sample description entry (16) + sound sample description v0 (20) */
10732       if (len < 36)
10733         goto corrupt_file;
10734
10735       version = QT_UINT32 (stsd_entry_data + offset);
10736       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10737       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10738       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10739       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10740
10741       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10742       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10743           QT_UINT32 (stsd_entry_data + offset + 4));
10744       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10745       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10746       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10747       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10748           QT_UINT16 (stsd_entry_data + offset + 14));
10749       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10750
10751       if (compression_id == 0xfffe)
10752         entry->sampled = TRUE;
10753
10754       /* first assume uncompressed audio */
10755       entry->bytes_per_sample = samplesize / 8;
10756       entry->samples_per_frame = entry->n_channels;
10757       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10758       entry->samples_per_packet = entry->samples_per_frame;
10759       entry->bytes_per_packet = entry->bytes_per_sample;
10760
10761       offset = 36;
10762       switch (fourcc) {
10763           /* Yes, these have to be hard-coded */
10764         case FOURCC_MAC6:
10765         {
10766           entry->samples_per_packet = 6;
10767           entry->bytes_per_packet = 1;
10768           entry->bytes_per_frame = 1 * entry->n_channels;
10769           entry->bytes_per_sample = 1;
10770           entry->samples_per_frame = 6 * entry->n_channels;
10771           break;
10772         }
10773         case FOURCC_MAC3:
10774         {
10775           entry->samples_per_packet = 3;
10776           entry->bytes_per_packet = 1;
10777           entry->bytes_per_frame = 1 * entry->n_channels;
10778           entry->bytes_per_sample = 1;
10779           entry->samples_per_frame = 3 * entry->n_channels;
10780           break;
10781         }
10782         case FOURCC_ima4:
10783         {
10784           entry->samples_per_packet = 64;
10785           entry->bytes_per_packet = 34;
10786           entry->bytes_per_frame = 34 * entry->n_channels;
10787           entry->bytes_per_sample = 2;
10788           entry->samples_per_frame = 64 * entry->n_channels;
10789           break;
10790         }
10791         case FOURCC_ulaw:
10792         case FOURCC_alaw:
10793         {
10794           entry->samples_per_packet = 1;
10795           entry->bytes_per_packet = 1;
10796           entry->bytes_per_frame = 1 * entry->n_channels;
10797           entry->bytes_per_sample = 1;
10798           entry->samples_per_frame = 1 * entry->n_channels;
10799           break;
10800         }
10801         case FOURCC_agsm:
10802         {
10803           entry->samples_per_packet = 160;
10804           entry->bytes_per_packet = 33;
10805           entry->bytes_per_frame = 33 * entry->n_channels;
10806           entry->bytes_per_sample = 2;
10807           entry->samples_per_frame = 160 * entry->n_channels;
10808           break;
10809         }
10810         default:
10811           break;
10812       }
10813
10814       if (version == 0x00010000) {
10815         /* sample description entry (16) + sound sample description v1 (20+16) */
10816         if (len < 52)
10817           goto corrupt_file;
10818
10819         switch (fourcc) {
10820           case FOURCC_twos:
10821           case FOURCC_sowt:
10822           case FOURCC_raw_:
10823             break;
10824           default:
10825           {
10826             /* only parse extra decoding config for non-pcm audio */
10827             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10828             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10829             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10830             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10831
10832             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10833                 entry->samples_per_packet);
10834             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10835                 entry->bytes_per_packet);
10836             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10837                 entry->bytes_per_frame);
10838             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10839                 entry->bytes_per_sample);
10840
10841             if (!entry->sampled && entry->bytes_per_packet) {
10842               entry->samples_per_frame = (entry->bytes_per_frame /
10843                   entry->bytes_per_packet) * entry->samples_per_packet;
10844               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10845                   entry->samples_per_frame);
10846             }
10847             break;
10848           }
10849         }
10850       } else if (version == 0x00020000) {
10851         union
10852         {
10853           gdouble fp;
10854           guint64 val;
10855         } qtfp;
10856
10857         /* sample description entry (16) + sound sample description v2 (56) */
10858         if (len < 72)
10859           goto corrupt_file;
10860
10861         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10862         entry->rate = qtfp.fp;
10863         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10864
10865         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10866         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10867         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10868         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10869             QT_UINT32 (stsd_entry_data + offset + 20));
10870         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10871             QT_UINT32 (stsd_entry_data + offset + 24));
10872         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10873             QT_UINT32 (stsd_entry_data + offset + 28));
10874         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10875             QT_UINT32 (stsd_entry_data + offset + 32));
10876       } else if (version != 0x00000) {
10877         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10878             version);
10879       }
10880
10881       if (entry->caps)
10882         gst_caps_unref (entry->caps);
10883
10884       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10885           stsd_entry_data + 32, len - 16, &codec);
10886
10887       switch (fourcc) {
10888         case FOURCC_in24:
10889         {
10890           GNode *enda;
10891           GNode *in24;
10892
10893           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10894
10895           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10896           if (!enda) {
10897             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10898             if (wave)
10899               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10900           }
10901           if (enda) {
10902             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10903             gst_caps_set_simple (entry->caps,
10904                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10905                 NULL);
10906           }
10907           break;
10908         }
10909         case FOURCC_owma:
10910         {
10911           const guint8 *owma_data;
10912           const gchar *codec_name = NULL;
10913           guint owma_len;
10914           GstBuffer *buf;
10915           gint version = 1;
10916           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10917           /* FIXME this should also be gst_riff_strf_auds,
10918            * but the latter one is actually missing bits-per-sample :( */
10919           typedef struct
10920           {
10921             gint16 wFormatTag;
10922             gint16 nChannels;
10923             gint32 nSamplesPerSec;
10924             gint32 nAvgBytesPerSec;
10925             gint16 nBlockAlign;
10926             gint16 wBitsPerSample;
10927             gint16 cbSize;
10928           } WAVEFORMATEX;
10929           WAVEFORMATEX *wfex;
10930
10931           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10932           owma_data = stsd_entry_data;
10933           owma_len = QT_UINT32 (owma_data);
10934           if (owma_len <= 54) {
10935             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10936             break;
10937           }
10938           wfex = (WAVEFORMATEX *) (owma_data + 36);
10939           buf = gst_buffer_new_and_alloc (owma_len - 54);
10940           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10941           if (wfex->wFormatTag == 0x0161) {
10942             codec_name = "Windows Media Audio";
10943             version = 2;
10944           } else if (wfex->wFormatTag == 0x0162) {
10945             codec_name = "Windows Media Audio 9 Pro";
10946             version = 3;
10947           } else if (wfex->wFormatTag == 0x0163) {
10948             codec_name = "Windows Media Audio 9 Lossless";
10949             /* is that correct? gstffmpegcodecmap.c is missing it, but
10950              * fluendo codec seems to support it */
10951             version = 4;
10952           }
10953
10954           gst_caps_set_simple (entry->caps,
10955               "codec_data", GST_TYPE_BUFFER, buf,
10956               "wmaversion", G_TYPE_INT, version,
10957               "block_align", G_TYPE_INT,
10958               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10959               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10960               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10961               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10962           gst_buffer_unref (buf);
10963
10964           if (codec_name) {
10965             g_free (codec);
10966             codec = g_strdup (codec_name);
10967           }
10968           break;
10969         }
10970         case FOURCC_wma_:
10971         {
10972           gint len = QT_UINT32 (stsd_entry_data) - offset;
10973           const guint8 *wfex_data = stsd_entry_data + offset;
10974           const gchar *codec_name = NULL;
10975           gint version = 1;
10976           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10977           /* FIXME this should also be gst_riff_strf_auds,
10978            * but the latter one is actually missing bits-per-sample :( */
10979           typedef struct
10980           {
10981             gint16 wFormatTag;
10982             gint16 nChannels;
10983             gint32 nSamplesPerSec;
10984             gint32 nAvgBytesPerSec;
10985             gint16 nBlockAlign;
10986             gint16 wBitsPerSample;
10987             gint16 cbSize;
10988           } WAVEFORMATEX;
10989           WAVEFORMATEX wfex;
10990
10991           /* FIXME: unify with similar wavformatex parsing code above */
10992           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10993
10994           /* find wfex */
10995           while (len >= 8) {
10996             gint size;
10997
10998             if (QT_UINT32 (wfex_data) <= len)
10999               size = QT_UINT32 (wfex_data) - 8;
11000             else
11001               size = len - 8;
11002
11003             if (size < 1)
11004               /* No real data, so break out */
11005               break;
11006
11007             switch (QT_FOURCC (wfex_data + 4)) {
11008               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11009               {
11010                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11011
11012                 if (size < 8 + 18)
11013                   break;
11014
11015                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11016                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11017                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11018                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11019                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11020                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11021                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11022
11023                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11024                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11025                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11026                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11027                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11028                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11029
11030                 if (wfex.wFormatTag == 0x0161) {
11031                   codec_name = "Windows Media Audio";
11032                   version = 2;
11033                 } else if (wfex.wFormatTag == 0x0162) {
11034                   codec_name = "Windows Media Audio 9 Pro";
11035                   version = 3;
11036                 } else if (wfex.wFormatTag == 0x0163) {
11037                   codec_name = "Windows Media Audio 9 Lossless";
11038                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11039                    * fluendo codec seems to support it */
11040                   version = 4;
11041                 }
11042
11043                 gst_caps_set_simple (entry->caps,
11044                     "wmaversion", G_TYPE_INT, version,
11045                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11046                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11047                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11048                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11049
11050                 if (size > wfex.cbSize) {
11051                   GstBuffer *buf;
11052
11053                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11054                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11055                       size - wfex.cbSize);
11056                   gst_caps_set_simple (entry->caps,
11057                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11058                   gst_buffer_unref (buf);
11059                 } else {
11060                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11061                 }
11062
11063                 if (codec_name) {
11064                   g_free (codec);
11065                   codec = g_strdup (codec_name);
11066                 }
11067                 break;
11068               }
11069               default:
11070                 break;
11071             }
11072             len -= size + 8;
11073             wfex_data += size + 8;
11074           }
11075           break;
11076         }
11077         case FOURCC_opus:
11078         {
11079           const guint8 *opus_data;
11080           guint8 *channel_mapping = NULL;
11081           guint32 rate;
11082           guint8 channels;
11083           guint8 channel_mapping_family;
11084           guint8 stream_count;
11085           guint8 coupled_count;
11086           guint8 i;
11087
11088           opus_data = stsd_entry_data;
11089
11090           channels = GST_READ_UINT8 (opus_data + 45);
11091           rate = GST_READ_UINT32_LE (opus_data + 48);
11092           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11093           stream_count = GST_READ_UINT8 (opus_data + 55);
11094           coupled_count = GST_READ_UINT8 (opus_data + 56);
11095
11096           if (channels > 0) {
11097             channel_mapping = g_malloc (channels * sizeof (guint8));
11098             for (i = 0; i < channels; i++)
11099               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11100           }
11101
11102           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11103               channel_mapping_family, stream_count, coupled_count,
11104               channel_mapping);
11105           break;
11106         }
11107         default:
11108           break;
11109       }
11110
11111       if (codec) {
11112         GstStructure *s;
11113         gint bitrate = 0;
11114
11115         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11116             GST_TAG_AUDIO_CODEC, codec, NULL);
11117         g_free (codec);
11118         codec = NULL;
11119
11120         /* some bitrate info may have ended up in caps */
11121         s = gst_caps_get_structure (entry->caps, 0);
11122         gst_structure_get_int (s, "bitrate", &bitrate);
11123         if (bitrate > 0)
11124           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11125               GST_TAG_BITRATE, bitrate, NULL);
11126       }
11127
11128       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11129       if (!stream->protected) {
11130       } else {
11131         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11132           mp4v = NULL;
11133         }
11134       }
11135       if (stream->protected && fourcc == FOURCC_mp4a) {
11136         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11137           mp4a = NULL;
11138         }
11139       } else {
11140         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11141           mp4a = NULL;
11142         }
11143       }
11144
11145       wave = NULL;
11146       esds = NULL;
11147       if (mp4a) {
11148         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11149         if (wave)
11150           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11151         if (!esds)
11152           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11153       }
11154
11155
11156       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11157          16 bits is a byte-swapped wave-style codec identifier,
11158          and we can find a WAVE header internally to a 'wave' atom here.
11159          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11160          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11161          is big-endian).
11162        */
11163       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11164         if (len < offset + 20) {
11165           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11166         } else {
11167           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11168           const guint8 *data = stsd_entry_data + offset + 16;
11169           GNode *wavenode;
11170           GNode *waveheadernode;
11171
11172           wavenode = g_node_new ((guint8 *) data);
11173           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11174             const guint8 *waveheader;
11175             guint32 headerlen;
11176
11177             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11178             if (waveheadernode) {
11179               waveheader = (const guint8 *) waveheadernode->data;
11180               headerlen = QT_UINT32 (waveheader);
11181
11182               if (headerlen > 8) {
11183                 gst_riff_strf_auds *header = NULL;
11184                 GstBuffer *headerbuf;
11185                 GstBuffer *extra;
11186
11187                 waveheader += 8;
11188                 headerlen -= 8;
11189
11190                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11191                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11192
11193                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11194                         headerbuf, &header, &extra)) {
11195                   gst_caps_unref (entry->caps);
11196                   /* FIXME: Need to do something with the channel reorder map */
11197                   entry->caps =
11198                       gst_riff_create_audio_caps (header->format, NULL, header,
11199                       extra, NULL, NULL, NULL);
11200
11201                   if (extra)
11202                     gst_buffer_unref (extra);
11203                   g_free (header);
11204                 }
11205               }
11206             } else
11207               GST_DEBUG ("Didn't find waveheadernode for this codec");
11208           }
11209           g_node_destroy (wavenode);
11210         }
11211       } else if (esds) {
11212         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11213             stream->stream_tags);
11214       } else {
11215         switch (fourcc) {
11216 #if 0
11217             /* FIXME: what is in the chunk? */
11218           case FOURCC_QDMC:
11219           {
11220             gint len = QT_UINT32 (stsd_data);
11221
11222             /* seems to be always = 116 = 0x74 */
11223             break;
11224           }
11225 #endif
11226           case FOURCC_QDM2:
11227           {
11228             gint len = QT_UINT32 (stsd_entry_data);
11229
11230             if (len > 0x3C) {
11231               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11232
11233               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11234               gst_caps_set_simple (entry->caps,
11235                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11236               gst_buffer_unref (buf);
11237             }
11238             gst_caps_set_simple (entry->caps,
11239                 "samplesize", G_TYPE_INT, samplesize, NULL);
11240             break;
11241           }
11242           case FOURCC_alac:
11243           {
11244             GNode *alac, *wave = NULL;
11245
11246             /* apparently, m4a has this atom appended directly in the stsd entry,
11247              * while mov has it in a wave atom */
11248             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11249             if (alac) {
11250               /* alac now refers to stsd entry atom */
11251               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11252               if (wave)
11253                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11254               else
11255                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11256             }
11257             if (alac) {
11258               const guint8 *alac_data = alac->data;
11259               gint len = QT_UINT32 (alac->data);
11260               GstBuffer *buf;
11261
11262               if (len < 36) {
11263                 GST_DEBUG_OBJECT (qtdemux,
11264                     "discarding alac atom with unexpected len %d", len);
11265               } else {
11266                 /* codec-data contains alac atom size and prefix,
11267                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11268                 buf = gst_buffer_new_and_alloc (len);
11269                 gst_buffer_fill (buf, 0, alac->data, len);
11270                 gst_caps_set_simple (entry->caps,
11271                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11272                 gst_buffer_unref (buf);
11273
11274                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11275                 entry->n_channels = QT_UINT8 (alac_data + 21);
11276                 entry->rate = QT_UINT32 (alac_data + 32);
11277               }
11278             }
11279             gst_caps_set_simple (entry->caps,
11280                 "samplesize", G_TYPE_INT, samplesize, NULL);
11281             break;
11282           }
11283           case FOURCC_fLaC:
11284           {
11285             /* The codingname of the sample entry is 'fLaC' */
11286             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11287
11288             if (flac) {
11289               /* The 'dfLa' box is added to the sample entry to convey
11290                  initializing information for the decoder. */
11291               const GNode *dfla =
11292                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11293
11294               if (dfla) {
11295                 const guint32 len = QT_UINT32 (dfla->data);
11296
11297                 /* Must contain at least dfLa box header (12),
11298                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11299                 if (len < 50) {
11300                   GST_DEBUG_OBJECT (qtdemux,
11301                       "discarding dfla atom with unexpected len %d", len);
11302                 } else {
11303                   /* skip dfLa header to get the METADATA_BLOCKs */
11304                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11305                   const guint32 metadata_blocks_len = len - 12;
11306
11307                   gchar *stream_marker = g_strdup ("fLaC");
11308                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11309                       strlen (stream_marker));
11310
11311                   guint32 index = 0;
11312                   guint32 remainder = 0;
11313                   guint32 block_size = 0;
11314                   gboolean is_last = FALSE;
11315
11316                   GValue array = G_VALUE_INIT;
11317                   GValue value = G_VALUE_INIT;
11318
11319                   g_value_init (&array, GST_TYPE_ARRAY);
11320                   g_value_init (&value, GST_TYPE_BUFFER);
11321
11322                   gst_value_set_buffer (&value, block);
11323                   gst_value_array_append_value (&array, &value);
11324                   g_value_reset (&value);
11325
11326                   gst_buffer_unref (block);
11327
11328                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11329                    * of data, and we haven't already finished parsing */
11330                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11331                     remainder = metadata_blocks_len - index;
11332
11333                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11334                     block_size = 4 +
11335                         (metadata_blocks[index + 1] << 16) +
11336                         (metadata_blocks[index + 2] << 8) +
11337                         metadata_blocks[index + 3];
11338
11339                     /* be careful not to read off end of box */
11340                     if (block_size > remainder) {
11341                       break;
11342                     }
11343
11344                     is_last = metadata_blocks[index] >> 7;
11345
11346                     block = gst_buffer_new_and_alloc (block_size);
11347
11348                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11349                         block_size);
11350
11351                     gst_value_set_buffer (&value, block);
11352                     gst_value_array_append_value (&array, &value);
11353                     g_value_reset (&value);
11354
11355                     gst_buffer_unref (block);
11356
11357                     index += block_size;
11358                   }
11359
11360                   /* only append the metadata if we successfully read all of it */
11361                   if (is_last) {
11362                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11363                             (stream)->caps, 0), "streamheader", &array);
11364                   } else {
11365                     GST_WARNING_OBJECT (qtdemux,
11366                         "discarding all METADATA_BLOCKs due to invalid "
11367                         "block_size %d at idx %d, rem %d", block_size, index,
11368                         remainder);
11369                   }
11370
11371                   g_value_unset (&value);
11372                   g_value_unset (&array);
11373
11374                   /* The sample rate obtained from the stsd may not be accurate
11375                    * since it cannot represent rates greater than 65535Hz, so
11376                    * override that value with the sample rate from the
11377                    * METADATA_BLOCK_STREAMINFO block */
11378                   CUR_STREAM (stream)->rate =
11379                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11380                 }
11381               }
11382             }
11383             break;
11384           }
11385           case FOURCC_sawb:
11386             /* Fallthrough! */
11387             amrwb = TRUE;
11388           case FOURCC_samr:
11389           {
11390             gint len = QT_UINT32 (stsd_entry_data);
11391
11392             if (len > 0x24) {
11393               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11394               guint bitrate;
11395
11396               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11397
11398               /* If we have enough data, let's try to get the 'damr' atom. See
11399                * the 3GPP container spec (26.244) for more details. */
11400               if ((len - 0x34) > 8 &&
11401                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11402                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11403                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11404               }
11405
11406               gst_caps_set_simple (entry->caps,
11407                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11408               gst_buffer_unref (buf);
11409             }
11410             break;
11411           }
11412           case FOURCC_mp4a:
11413           {
11414             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11415             gint len = QT_UINT32 (stsd_entry_data);
11416
11417             if (len >= 34) {
11418               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11419
11420               if (sound_version == 1) {
11421                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11422                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11423                 guint8 codec_data[2];
11424                 GstBuffer *buf;
11425                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11426
11427                 gint sample_rate_index =
11428                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11429
11430                 /* build AAC codec data */
11431                 codec_data[0] = profile << 3;
11432                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11433                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11434                 codec_data[1] |= (channels & 0xF) << 3;
11435
11436                 buf = gst_buffer_new_and_alloc (2);
11437                 gst_buffer_fill (buf, 0, codec_data, 2);
11438                 gst_caps_set_simple (entry->caps,
11439                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11440                 gst_buffer_unref (buf);
11441               }
11442             }
11443             break;
11444           }
11445           default:
11446             GST_INFO_OBJECT (qtdemux,
11447                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11448             break;
11449         }
11450       }
11451       GST_INFO_OBJECT (qtdemux,
11452           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11453           GST_FOURCC_ARGS (fourcc), entry->caps);
11454
11455     } else if (stream->subtype == FOURCC_strm) {
11456       if (fourcc == FOURCC_rtsp) {
11457         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11458       } else {
11459         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11460             GST_FOURCC_ARGS (fourcc));
11461         goto unknown_stream;
11462       }
11463       entry->sampled = TRUE;
11464     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11465         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11466
11467       entry->sampled = TRUE;
11468       entry->sparse = TRUE;
11469
11470       entry->caps =
11471           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11472           &codec);
11473       if (codec) {
11474         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11475             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11476         g_free (codec);
11477         codec = NULL;
11478       }
11479
11480       /* hunt for sort-of codec data */
11481       switch (fourcc) {
11482         case FOURCC_mp4s:
11483         {
11484           GNode *mp4s = NULL;
11485           GNode *esds = NULL;
11486
11487           /* look for palette in a stsd->mp4s->esds sub-atom */
11488           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11489           if (mp4s)
11490             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11491           if (esds == NULL) {
11492             /* Invalid STSD */
11493             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11494             break;
11495           }
11496
11497           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11498               stream->stream_tags);
11499           break;
11500         }
11501         default:
11502           GST_INFO_OBJECT (qtdemux,
11503               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11504           break;
11505       }
11506       GST_INFO_OBJECT (qtdemux,
11507           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11508           GST_FOURCC_ARGS (fourcc), entry->caps);
11509     } else {
11510       /* everything in 1 sample */
11511       entry->sampled = TRUE;
11512
11513       entry->caps =
11514           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11515           &codec);
11516
11517       if (entry->caps == NULL)
11518         goto unknown_stream;
11519
11520       if (codec) {
11521         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11522             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11523         g_free (codec);
11524         codec = NULL;
11525       }
11526     }
11527
11528     /* promote to sampled format */
11529     if (entry->fourcc == FOURCC_samr) {
11530       /* force mono 8000 Hz for AMR */
11531       entry->sampled = TRUE;
11532       entry->n_channels = 1;
11533       entry->rate = 8000;
11534     } else if (entry->fourcc == FOURCC_sawb) {
11535       /* force mono 16000 Hz for AMR-WB */
11536       entry->sampled = TRUE;
11537       entry->n_channels = 1;
11538       entry->rate = 16000;
11539     } else if (entry->fourcc == FOURCC_mp4a) {
11540       entry->sampled = TRUE;
11541     }
11542
11543
11544     stsd_entry_data += len;
11545     remaining_stsd_len -= len;
11546
11547   }
11548
11549   /* collect sample information */
11550   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11551     goto samples_failed;
11552
11553   if (qtdemux->fragmented) {
11554     guint64 offset;
11555
11556     /* need all moov samples as basis; probably not many if any at all */
11557     /* prevent moof parsing taking of at this time */
11558     offset = qtdemux->moof_offset;
11559     qtdemux->moof_offset = 0;
11560     if (stream->n_samples &&
11561         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11562       qtdemux->moof_offset = offset;
11563       goto samples_failed;
11564     }
11565     qtdemux->moof_offset = 0;
11566     /* movie duration more reliable in this case (e.g. mehd) */
11567     if (qtdemux->segment.duration &&
11568         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11569       stream->duration =
11570           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11571   }
11572
11573   /* configure segments */
11574   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11575     goto segments_failed;
11576
11577   /* add some language tag, if useful */
11578   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11579       strcmp (stream->lang_id, "und")) {
11580     const gchar *lang_code;
11581
11582     /* convert ISO 639-2 code to ISO 639-1 */
11583     lang_code = gst_tag_get_language_code (stream->lang_id);
11584     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11585         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11586   }
11587
11588   /* Check for UDTA tags */
11589   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11590     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11591   }
11592
11593   /* now we are ready to add the stream */
11594   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11595     goto too_many_streams;
11596
11597   if (!qtdemux->got_moov) {
11598     qtdemux->streams[qtdemux->n_streams] = stream;
11599     qtdemux->n_streams++;
11600     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11601   }
11602
11603   return TRUE;
11604
11605 /* ERRORS */
11606 skip_track:
11607   {
11608     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11609     if (new_stream)
11610       gst_qtdemux_stream_free (qtdemux, stream);
11611     return TRUE;
11612   }
11613 corrupt_file:
11614   {
11615     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11616         (_("This file is corrupt and cannot be played.")), (NULL));
11617     if (new_stream)
11618       gst_qtdemux_stream_free (qtdemux, stream);
11619     return FALSE;
11620   }
11621 error_encrypted:
11622   {
11623     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11624     if (new_stream)
11625       gst_qtdemux_stream_free (qtdemux, stream);
11626     return FALSE;
11627   }
11628 samples_failed:
11629 segments_failed:
11630   {
11631     /* we posted an error already */
11632     /* free stbl sub-atoms */
11633     gst_qtdemux_stbl_free (stream);
11634     if (new_stream)
11635       gst_qtdemux_stream_free (qtdemux, stream);
11636     return FALSE;
11637   }
11638 existing_stream:
11639   {
11640     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11641         track_id);
11642     if (new_stream)
11643       gst_qtdemux_stream_free (qtdemux, stream);
11644     return TRUE;
11645   }
11646 unknown_stream:
11647   {
11648     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11649         GST_FOURCC_ARGS (stream->subtype));
11650     if (new_stream)
11651       gst_qtdemux_stream_free (qtdemux, stream);
11652     return TRUE;
11653   }
11654 too_many_streams:
11655   {
11656     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11657         (_("This file contains too many streams. Only playing first %d"),
11658             GST_QTDEMUX_MAX_STREAMS), (NULL));
11659     return TRUE;
11660   }
11661 }
11662
11663 /* If we can estimate the overall bitrate, and don't have information about the
11664  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11665  * the overall bitrate minus the sum of the bitrates of all other streams. This
11666  * should be useful for the common case where we have one audio and one video
11667  * stream and can estimate the bitrate of one, but not the other. */
11668 static void
11669 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11670 {
11671   QtDemuxStream *stream = NULL;
11672   gint64 size, sys_bitrate, sum_bitrate = 0;
11673   GstClockTime duration;
11674   gint i;
11675   guint bitrate;
11676
11677   if (qtdemux->fragmented)
11678     return;
11679
11680   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11681
11682   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11683       || size <= 0) {
11684     GST_DEBUG_OBJECT (qtdemux,
11685         "Size in bytes of the stream not known - bailing");
11686     return;
11687   }
11688
11689   /* Subtract the header size */
11690   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11691       size, qtdemux->header_size);
11692
11693   if (size < qtdemux->header_size)
11694     return;
11695
11696   size = size - qtdemux->header_size;
11697
11698   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11699     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11700     return;
11701   }
11702
11703   for (i = 0; i < qtdemux->n_streams; i++) {
11704     switch (qtdemux->streams[i]->subtype) {
11705       case FOURCC_soun:
11706       case FOURCC_vide:
11707         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11708             CUR_STREAM (qtdemux->streams[i])->caps);
11709         /* retrieve bitrate, prefer avg then max */
11710         bitrate = 0;
11711         if (qtdemux->streams[i]->stream_tags) {
11712           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11713               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11714           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11715           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11716               GST_TAG_NOMINAL_BITRATE, &bitrate);
11717           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11718           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11719               GST_TAG_BITRATE, &bitrate);
11720           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11721         }
11722         if (bitrate)
11723           sum_bitrate += bitrate;
11724         else {
11725           if (stream) {
11726             GST_DEBUG_OBJECT (qtdemux,
11727                 ">1 stream with unknown bitrate - bailing");
11728             return;
11729           } else
11730             stream = qtdemux->streams[i];
11731         }
11732
11733       default:
11734         /* For other subtypes, we assume no significant impact on bitrate */
11735         break;
11736     }
11737   }
11738
11739   if (!stream) {
11740     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11741     return;
11742   }
11743
11744   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11745
11746   if (sys_bitrate < sum_bitrate) {
11747     /* This can happen, since sum_bitrate might be derived from maximum
11748      * bitrates and not average bitrates */
11749     GST_DEBUG_OBJECT (qtdemux,
11750         "System bitrate less than sum bitrate - bailing");
11751     return;
11752   }
11753
11754   bitrate = sys_bitrate - sum_bitrate;
11755   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11756       ", Stream bitrate = %u", sys_bitrate, bitrate);
11757
11758   if (!stream->stream_tags)
11759     stream->stream_tags = gst_tag_list_new_empty ();
11760   else
11761     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11762
11763   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11764       GST_TAG_BITRATE, bitrate, NULL);
11765 }
11766
11767 static GstFlowReturn
11768 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11769 {
11770   gint i;
11771   GstFlowReturn ret = GST_FLOW_OK;
11772
11773   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11774
11775   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11776     QtDemuxStream *stream = qtdemux->streams[i];
11777     guint32 sample_num = 0;
11778
11779     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11780         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11781
11782     if (qtdemux->fragmented) {
11783       /* need all moov samples first */
11784       GST_OBJECT_LOCK (qtdemux);
11785       while (stream->n_samples == 0)
11786         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11787           break;
11788       GST_OBJECT_UNLOCK (qtdemux);
11789     } else {
11790       /* discard any stray moof */
11791       qtdemux->moof_offset = 0;
11792     }
11793
11794     /* prepare braking */
11795     if (ret != GST_FLOW_ERROR)
11796       ret = GST_FLOW_OK;
11797
11798     /* in pull mode, we should have parsed some sample info by now;
11799      * and quite some code will not handle no samples.
11800      * in push mode, we'll just have to deal with it */
11801     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11802       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11803       gst_qtdemux_remove_stream (qtdemux, i);
11804       i--;
11805       continue;
11806     }
11807
11808     /* parse the initial sample for use in setting the frame rate cap */
11809     while (sample_num == 0 && sample_num < stream->n_samples) {
11810       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11811         break;
11812       ++sample_num;
11813     }
11814     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11815       stream->first_duration = stream->samples[0].duration;
11816       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11817           stream->track_id, stream->first_duration);
11818     }
11819   }
11820
11821   return ret;
11822 }
11823
11824 static GstFlowReturn
11825 qtdemux_expose_streams (GstQTDemux * qtdemux)
11826 {
11827   gint i;
11828   GSList *oldpads = NULL;
11829   GSList *iter;
11830
11831   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11832
11833   for (i = 0; i < qtdemux->n_streams; i++) {
11834     QtDemuxStream *stream = qtdemux->streams[i];
11835     GstPad *oldpad = stream->pad;
11836     GstTagList *list;
11837
11838     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11839         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11840
11841     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11842         stream->track_id == qtdemux->chapters_track_id) {
11843       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11844          so that it doesn't look like a subtitle track */
11845       gst_qtdemux_remove_stream (qtdemux, i);
11846       i--;
11847       continue;
11848     }
11849
11850     /* now we have all info and can expose */
11851     list = stream->stream_tags;
11852     stream->stream_tags = NULL;
11853     if (oldpad)
11854       oldpads = g_slist_prepend (oldpads, oldpad);
11855     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11856       return GST_FLOW_ERROR;
11857   }
11858
11859   gst_qtdemux_guess_bitrate (qtdemux);
11860
11861   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11862
11863   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11864     GstPad *oldpad = iter->data;
11865     GstEvent *event;
11866
11867     event = gst_event_new_eos ();
11868     if (qtdemux->segment_seqnum)
11869       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11870
11871     gst_pad_push_event (oldpad, event);
11872     gst_pad_set_active (oldpad, FALSE);
11873     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11874     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11875     gst_object_unref (oldpad);
11876   }
11877
11878   /* check if we should post a redirect in case there is a single trak
11879    * and it is a redirecting trak */
11880   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11881     GstMessage *m;
11882
11883     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11884         "an external content");
11885     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11886         gst_structure_new ("redirect",
11887             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11888             NULL));
11889     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11890     qtdemux->posted_redirect = TRUE;
11891   }
11892
11893   for (i = 0; i < qtdemux->n_streams; i++) {
11894     QtDemuxStream *stream = qtdemux->streams[i];
11895
11896     qtdemux_do_allocation (qtdemux, stream);
11897   }
11898
11899   qtdemux->exposed = TRUE;
11900   return GST_FLOW_OK;
11901 }
11902
11903 /* check if major or compatible brand is 3GP */
11904 static inline gboolean
11905 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11906 {
11907   if (major) {
11908     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11909         FOURCC_3g__);
11910   } else if (qtdemux->comp_brands != NULL) {
11911     GstMapInfo map;
11912     guint8 *data;
11913     gsize size;
11914     gboolean res = FALSE;
11915
11916     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11917     data = map.data;
11918     size = map.size;
11919     while (size >= 4) {
11920       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11921           FOURCC_3g__);
11922       data += 4;
11923       size -= 4;
11924     }
11925     gst_buffer_unmap (qtdemux->comp_brands, &map);
11926     return res;
11927   } else {
11928     return FALSE;
11929   }
11930 }
11931
11932 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11933 static inline gboolean
11934 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11935 {
11936   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11937       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11938       || fourcc == FOURCC_albm;
11939 }
11940
11941 static void
11942 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11943     const char *tag, const char *dummy, GNode * node)
11944 {
11945   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11946   int offset;
11947   char *name;
11948   gchar *data;
11949   gdouble longitude, latitude, altitude;
11950   gint len;
11951
11952   len = QT_UINT32 (node->data);
11953   if (len <= 14)
11954     goto short_read;
11955
11956   data = node->data;
11957   offset = 14;
11958
11959   /* TODO: language code skipped */
11960
11961   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11962
11963   if (!name) {
11964     /* do not alarm in trivial case, but bail out otherwise */
11965     if (*(data + offset) != 0) {
11966       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11967           "giving up", tag);
11968     }
11969   } else {
11970     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11971         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11972     offset += strlen (name);
11973     g_free (name);
11974   }
11975
11976   if (len < offset + 2 + 4 + 4 + 4)
11977     goto short_read;
11978
11979   /* +1 +1 = skip null-terminator and location role byte */
11980   offset += 1 + 1;
11981   /* table in spec says unsigned, semantics say negative has meaning ... */
11982   longitude = QT_SFP32 (data + offset);
11983
11984   offset += 4;
11985   latitude = QT_SFP32 (data + offset);
11986
11987   offset += 4;
11988   altitude = QT_SFP32 (data + offset);
11989
11990   /* one invalid means all are invalid */
11991   if (longitude >= -180.0 && longitude <= 180.0 &&
11992       latitude >= -90.0 && latitude <= 90.0) {
11993     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11994         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11995         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11996         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11997   }
11998
11999   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12000
12001   return;
12002
12003   /* ERRORS */
12004 short_read:
12005   {
12006     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12007     return;
12008   }
12009 }
12010
12011
12012 static void
12013 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12014     const char *tag, const char *dummy, GNode * node)
12015 {
12016   guint16 y;
12017   GDate *date;
12018   gint len;
12019
12020   len = QT_UINT32 (node->data);
12021   if (len < 14)
12022     return;
12023
12024   y = QT_UINT16 ((guint8 *) node->data + 12);
12025   if (y == 0) {
12026     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12027     return;
12028   }
12029   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12030
12031   date = g_date_new_dmy (1, 1, y);
12032   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12033   g_date_free (date);
12034 }
12035
12036 static void
12037 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12038     const char *tag, const char *dummy, GNode * node)
12039 {
12040   int offset;
12041   char *tag_str = NULL;
12042   guint8 *entity;
12043   guint16 table;
12044   gint len;
12045
12046   len = QT_UINT32 (node->data);
12047   if (len <= 20)
12048     goto short_read;
12049
12050   offset = 12;
12051   entity = (guint8 *) node->data + offset;
12052   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12053     GST_DEBUG_OBJECT (qtdemux,
12054         "classification info: %c%c%c%c invalid classification entity",
12055         entity[0], entity[1], entity[2], entity[3]);
12056     return;
12057   }
12058
12059   offset += 4;
12060   table = QT_UINT16 ((guint8 *) node->data + offset);
12061
12062   /* Language code skipped */
12063
12064   offset += 4;
12065
12066   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12067    * XXXX: classification entity, fixed length 4 chars.
12068    * Y[YYYY]: classification table, max 5 chars.
12069    */
12070   tag_str = g_strdup_printf ("----://%u/%s",
12071       table, (char *) node->data + offset);
12072
12073   /* memcpy To be sure we're preserving byte order */
12074   memcpy (tag_str, entity, 4);
12075   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12076
12077   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12078
12079   g_free (tag_str);
12080
12081   return;
12082
12083   /* ERRORS */
12084 short_read:
12085   {
12086     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12087     return;
12088   }
12089 }
12090
12091 static gboolean
12092 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12093     const char *tag, const char *dummy, GNode * node)
12094 {
12095   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12096   GNode *data;
12097   char *s;
12098   int len;
12099   guint32 type;
12100   int offset;
12101   gboolean ret = TRUE;
12102   const gchar *charset = NULL;
12103
12104   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12105   if (data) {
12106     len = QT_UINT32 (data->data);
12107     type = QT_UINT32 ((guint8 *) data->data + 8);
12108     if (type == 0x00000001 && len > 16) {
12109       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12110           env_vars);
12111       if (s) {
12112         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12113         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12114         g_free (s);
12115       } else {
12116         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12117       }
12118     }
12119   } else {
12120     len = QT_UINT32 (node->data);
12121     type = QT_UINT32 ((guint8 *) node->data + 4);
12122     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12123       gint str_len;
12124       gint lang_code;
12125
12126       /* Type starts with the (C) symbol, so the next data is a list
12127        * of (string size(16), language code(16), string) */
12128
12129       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12130       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12131
12132       /* the string + fourcc + size + 2 16bit fields,
12133        * means that there are more tags in this atom */
12134       if (len > str_len + 8 + 4) {
12135         /* TODO how to represent the same tag in different languages? */
12136         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12137             "text alternatives, reading only first one");
12138       }
12139
12140       offset = 12;
12141       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12142       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12143
12144       if (lang_code < 0x800) {  /* MAC encoded string */
12145         charset = "mac";
12146       }
12147     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12148             QT_FOURCC ((guint8 *) node->data + 4))) {
12149       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12150
12151       /* we go for 3GP style encoding if major brands claims so,
12152        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12153       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12154           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12155               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12156         offset = 14;
12157         /* 16-bit Language code is ignored here as well */
12158         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12159       } else {
12160         goto normal;
12161       }
12162     } else {
12163     normal:
12164       offset = 8;
12165       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12166       ret = FALSE;              /* may have to fallback */
12167     }
12168     if (charset) {
12169       GError *err = NULL;
12170
12171       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12172           charset, NULL, NULL, &err);
12173       if (err) {
12174         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12175             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12176             err->message);
12177         g_error_free (err);
12178       }
12179     } else {
12180       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12181           len - offset, env_vars);
12182     }
12183     if (s) {
12184       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12185       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12186       g_free (s);
12187       ret = TRUE;
12188     } else {
12189       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12190     }
12191   }
12192   return ret;
12193 }
12194
12195 static void
12196 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12197     const char *tag, const char *dummy, GNode * node)
12198 {
12199   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12200 }
12201
12202 static void
12203 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12204     const char *tag, const char *dummy, GNode * node)
12205 {
12206   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12207   guint8 *data;
12208   char *s, *t, *k = NULL;
12209   int len;
12210   int offset;
12211   int count;
12212
12213   /* first try normal string tag if major brand not 3GP */
12214   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12215     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12216       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12217        * let's try it 3gpp way after minor safety check */
12218       data = node->data;
12219       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12220         return;
12221     } else
12222       return;
12223   }
12224
12225   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12226
12227   data = node->data;
12228
12229   len = QT_UINT32 (data);
12230   if (len < 15)
12231     goto short_read;
12232
12233   count = QT_UINT8 (data + 14);
12234   offset = 15;
12235   for (; count; count--) {
12236     gint slen;
12237
12238     if (offset + 1 > len)
12239       goto short_read;
12240     slen = QT_UINT8 (data + offset);
12241     offset += 1;
12242     if (offset + slen > len)
12243       goto short_read;
12244     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12245         slen, env_vars);
12246     if (s) {
12247       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12248       if (k) {
12249         t = g_strjoin (",", k, s, NULL);
12250         g_free (s);
12251         g_free (k);
12252         k = t;
12253       } else {
12254         k = s;
12255       }
12256     } else {
12257       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12258     }
12259     offset += slen;
12260   }
12261
12262 done:
12263   if (k) {
12264     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12265     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12266   }
12267   g_free (k);
12268
12269   return;
12270
12271   /* ERRORS */
12272 short_read:
12273   {
12274     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12275     goto done;
12276   }
12277 }
12278
12279 static void
12280 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12281     const char *tag1, const char *tag2, GNode * node)
12282 {
12283   GNode *data;
12284   int len;
12285   int type;
12286   int n1, n2;
12287
12288   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12289   if (data) {
12290     len = QT_UINT32 (data->data);
12291     type = QT_UINT32 ((guint8 *) data->data + 8);
12292     if (type == 0x00000000 && len >= 22) {
12293       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12294       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12295       if (n1 > 0) {
12296         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12297         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12298       }
12299       if (n2 > 0) {
12300         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12301         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12302       }
12303     }
12304   }
12305 }
12306
12307 static void
12308 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12309     const char *tag1, const char *dummy, GNode * node)
12310 {
12311   GNode *data;
12312   int len;
12313   int type;
12314   int n1;
12315
12316   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12317   if (data) {
12318     len = QT_UINT32 (data->data);
12319     type = QT_UINT32 ((guint8 *) data->data + 8);
12320     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12321     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12322     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12323       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12324       if (n1) {
12325         /* do not add bpm=0 */
12326         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12327         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12328             NULL);
12329       }
12330     }
12331   }
12332 }
12333
12334 static void
12335 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12336     const char *tag1, const char *dummy, GNode * node)
12337 {
12338   GNode *data;
12339   int len;
12340   int type;
12341   guint32 num;
12342
12343   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12344   if (data) {
12345     len = QT_UINT32 (data->data);
12346     type = QT_UINT32 ((guint8 *) data->data + 8);
12347     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12348     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12349     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12350       num = QT_UINT32 ((guint8 *) data->data + 16);
12351       if (num) {
12352         /* do not add num=0 */
12353         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12354         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12355       }
12356     }
12357   }
12358 }
12359
12360 static void
12361 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12362     const char *tag1, const char *dummy, GNode * node)
12363 {
12364   GNode *data;
12365   int len;
12366   int type;
12367   GstSample *sample;
12368
12369   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12370   if (data) {
12371     len = QT_UINT32 (data->data);
12372     type = QT_UINT32 ((guint8 *) data->data + 8);
12373     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12374     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12375       GstTagImageType image_type;
12376
12377       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12378         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12379       else
12380         image_type = GST_TAG_IMAGE_TYPE_NONE;
12381
12382       if ((sample =
12383               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12384                   len - 16, image_type))) {
12385         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12386         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12387         gst_sample_unref (sample);
12388       }
12389     }
12390   }
12391 }
12392
12393 static void
12394 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12395     const char *tag, const char *dummy, GNode * node)
12396 {
12397   GNode *data;
12398   char *s;
12399   int len;
12400   int type;
12401
12402   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12403   if (data) {
12404     len = QT_UINT32 (data->data);
12405     type = QT_UINT32 ((guint8 *) data->data + 8);
12406     if (type == 0x00000001 && len > 16) {
12407       guint y, m = 1, d = 1;
12408       gint ret;
12409
12410       s = g_strndup ((char *) data->data + 16, len - 16);
12411       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12412       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12413       if (ret >= 1 && y > 1500 && y < 3000) {
12414         GDate *date;
12415
12416         date = g_date_new_dmy (d, m, y);
12417         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12418         g_date_free (date);
12419       } else {
12420         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12421       }
12422       g_free (s);
12423     }
12424   }
12425 }
12426
12427 static void
12428 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12429     const char *tag, const char *dummy, GNode * node)
12430 {
12431   GNode *data;
12432
12433   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12434
12435   /* re-route to normal string tag if major brand says so
12436    * or no data atom and compatible brand suggests so */
12437   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12438       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12439     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12440     return;
12441   }
12442
12443   if (data) {
12444     guint len, type, n;
12445
12446     len = QT_UINT32 (data->data);
12447     type = QT_UINT32 ((guint8 *) data->data + 8);
12448     if (type == 0x00000000 && len >= 18) {
12449       n = QT_UINT16 ((guint8 *) data->data + 16);
12450       if (n > 0) {
12451         const gchar *genre;
12452
12453         genre = gst_tag_id3_genre_get (n - 1);
12454         if (genre != NULL) {
12455           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12456           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12457         }
12458       }
12459     }
12460   }
12461 }
12462
12463 static void
12464 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12465     const gchar * tag, guint8 * data, guint32 datasize)
12466 {
12467   gdouble value;
12468   gchar *datacopy;
12469
12470   /* make a copy to have \0 at the end */
12471   datacopy = g_strndup ((gchar *) data, datasize);
12472
12473   /* convert the str to double */
12474   if (sscanf (datacopy, "%lf", &value) == 1) {
12475     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12476     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12477   } else {
12478     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12479         datacopy);
12480   }
12481   g_free (datacopy);
12482 }
12483
12484
12485 static void
12486 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12487     const char *tag, const char *tag_bis, GNode * node)
12488 {
12489   GNode *mean;
12490   GNode *name;
12491   GNode *data;
12492   guint32 meansize;
12493   guint32 namesize;
12494   guint32 datatype;
12495   guint32 datasize;
12496   const gchar *meanstr;
12497   const gchar *namestr;
12498
12499   /* checking the whole ---- atom size for consistency */
12500   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12501     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12502     return;
12503   }
12504
12505   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12506   if (!mean) {
12507     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12508     return;
12509   }
12510
12511   meansize = QT_UINT32 (mean->data);
12512   if (meansize <= 12) {
12513     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12514     return;
12515   }
12516   meanstr = ((gchar *) mean->data) + 12;
12517   meansize -= 12;
12518
12519   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12520   if (!name) {
12521     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12522     return;
12523   }
12524
12525   namesize = QT_UINT32 (name->data);
12526   if (namesize <= 12) {
12527     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12528     return;
12529   }
12530   namestr = ((gchar *) name->data) + 12;
12531   namesize -= 12;
12532
12533   /*
12534    * Data atom is:
12535    * uint32 - size
12536    * uint32 - name
12537    * uint8  - version
12538    * uint24 - data type
12539    * uint32 - all 0
12540    * rest   - the data
12541    */
12542   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12543   if (!data) {
12544     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12545     return;
12546   }
12547   datasize = QT_UINT32 (data->data);
12548   if (datasize <= 16) {
12549     GST_WARNING_OBJECT (demux, "Data atom too small");
12550     return;
12551   }
12552   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12553
12554   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12555       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12556     static const struct
12557     {
12558       const gchar name[28];
12559       const gchar tag[28];
12560     } tags[] = {
12561       {
12562       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12563       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12564       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12565       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12566       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12567       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12568       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12569       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12570     };
12571     int i;
12572
12573     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12574       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12575         switch (gst_tag_get_type (tags[i].tag)) {
12576           case G_TYPE_DOUBLE:
12577             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12578                 ((guint8 *) data->data) + 16, datasize - 16);
12579             break;
12580           case G_TYPE_STRING:
12581             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12582             break;
12583           default:
12584             /* not reached */
12585             break;
12586         }
12587         break;
12588       }
12589     }
12590     if (i == G_N_ELEMENTS (tags))
12591       goto unknown_tag;
12592   } else {
12593     goto unknown_tag;
12594   }
12595
12596   return;
12597
12598 /* errors */
12599 unknown_tag:
12600 #ifndef GST_DISABLE_GST_DEBUG
12601   {
12602     gchar *namestr_dbg;
12603     gchar *meanstr_dbg;
12604
12605     meanstr_dbg = g_strndup (meanstr, meansize);
12606     namestr_dbg = g_strndup (namestr, namesize);
12607
12608     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12609         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12610
12611     g_free (namestr_dbg);
12612     g_free (meanstr_dbg);
12613   }
12614 #endif
12615   return;
12616 }
12617
12618 static void
12619 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12620     const char *tag_bis, GNode * node)
12621 {
12622   guint8 *data;
12623   GstBuffer *buf;
12624   guint len;
12625   GstTagList *id32_taglist = NULL;
12626
12627   GST_LOG_OBJECT (demux, "parsing ID32");
12628
12629   data = node->data;
12630   len = GST_READ_UINT32_BE (data);
12631
12632   /* need at least full box and language tag */
12633   if (len < 12 + 2)
12634     return;
12635
12636   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12637   gst_buffer_fill (buf, 0, data + 14, len - 14);
12638
12639   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12640   if (id32_taglist) {
12641     GST_LOG_OBJECT (demux, "parsing ok");
12642     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12643     gst_tag_list_unref (id32_taglist);
12644   } else {
12645     GST_LOG_OBJECT (demux, "parsing failed");
12646   }
12647
12648   gst_buffer_unref (buf);
12649 }
12650
12651 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12652     const char *tag, const char *tag_bis, GNode * node);
12653
12654 /* unmapped tags
12655 FOURCC_pcst -> if media is a podcast -> bool
12656 FOURCC_cpil -> if media is part of a compilation -> bool
12657 FOURCC_pgap -> if media is part of a gapless context -> bool
12658 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12659 */
12660
12661 static const struct
12662 {
12663   guint32 fourcc;
12664   const gchar *gst_tag;
12665   const gchar *gst_tag_bis;
12666   const GstQTDemuxAddTagFunc func;
12667 } add_funcs[] = {
12668   {
12669   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12670   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12671   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12672   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12673   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12674   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12675   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12676   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12677   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12678   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12679   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12680   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12681   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12682   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12683   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12684   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12685   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12686   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12687   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12688   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12689   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12690   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12691   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12692         qtdemux_tag_add_num}, {
12693   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12694         qtdemux_tag_add_num}, {
12695   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12696   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12697   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12698   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12699   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12700   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12701   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12702   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12703   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12704   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12705   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12706   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12707   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12708   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12709   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12710   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12711   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12712   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12713         qtdemux_tag_add_classification}, {
12714   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12715   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12716   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12717
12718     /* This is a special case, some tags are stored in this
12719      * 'reverse dns naming', according to:
12720      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12721      * bug #614471
12722      */
12723   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12724     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12725   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12726 };
12727
12728 struct _GstQtDemuxTagList
12729 {
12730   GstQTDemux *demux;
12731   GstTagList *taglist;
12732 };
12733 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12734
12735 static void
12736 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12737 {
12738   gint len;
12739   guint8 *data;
12740   GstBuffer *buf;
12741   gchar *media_type;
12742   const gchar *style;
12743   GstSample *sample;
12744   GstStructure *s;
12745   guint i;
12746   guint8 ndata[4];
12747   GstQTDemux *demux = qtdemuxtaglist->demux;
12748   GstTagList *taglist = qtdemuxtaglist->taglist;
12749
12750   data = node->data;
12751   len = QT_UINT32 (data);
12752   buf = gst_buffer_new_and_alloc (len);
12753   gst_buffer_fill (buf, 0, data, len);
12754
12755   /* heuristic to determine style of tag */
12756   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12757       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12758     style = "itunes";
12759   else if (demux->major_brand == FOURCC_qt__)
12760     style = "quicktime";
12761   /* fall back to assuming iso/3gp tag style */
12762   else
12763     style = "iso";
12764
12765   /* santize the name for the caps. */
12766   for (i = 0; i < 4; i++) {
12767     guint8 d = data[4 + i];
12768     if (g_ascii_isalnum (d))
12769       ndata[i] = g_ascii_tolower (d);
12770     else
12771       ndata[i] = '_';
12772   }
12773
12774   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12775       ndata[0], ndata[1], ndata[2], ndata[3]);
12776   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12777
12778   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12779   sample = gst_sample_new (buf, NULL, NULL, s);
12780   gst_buffer_unref (buf);
12781   g_free (media_type);
12782
12783   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12784       len, s);
12785
12786   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12787       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12788
12789   gst_sample_unref (sample);
12790 }
12791
12792 static void
12793 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12794 {
12795   GNode *meta;
12796   GNode *ilst;
12797   GNode *xmp_;
12798   GNode *node;
12799   gint i;
12800   GstQtDemuxTagList demuxtaglist;
12801
12802   demuxtaglist.demux = qtdemux;
12803   demuxtaglist.taglist = taglist;
12804
12805   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12806   if (meta != NULL) {
12807     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12808     if (ilst == NULL) {
12809       GST_LOG_OBJECT (qtdemux, "no ilst");
12810       return;
12811     }
12812   } else {
12813     ilst = udta;
12814     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12815   }
12816
12817   i = 0;
12818   while (i < G_N_ELEMENTS (add_funcs)) {
12819     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12820     if (node) {
12821       gint len;
12822
12823       len = QT_UINT32 (node->data);
12824       if (len < 12) {
12825         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12826             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12827       } else {
12828         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12829             add_funcs[i].gst_tag_bis, node);
12830       }
12831       g_node_destroy (node);
12832     } else {
12833       i++;
12834     }
12835   }
12836
12837   /* parsed nodes have been removed, pass along remainder as blob */
12838   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12839       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12840
12841   /* parse up XMP_ node if existing */
12842   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12843   if (xmp_ != NULL) {
12844     GstBuffer *buf;
12845     GstTagList *xmptaglist;
12846
12847     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12848         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12849     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12850     gst_buffer_unref (buf);
12851
12852     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12853   } else {
12854     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12855   }
12856 }
12857
12858 typedef struct
12859 {
12860   GstStructure *structure;      /* helper for sort function */
12861   gchar *location;
12862   guint min_req_bitrate;
12863   guint min_req_qt_version;
12864 } GstQtReference;
12865
12866 static gint
12867 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12868 {
12869   GstQtReference *ref_a = (GstQtReference *) a;
12870   GstQtReference *ref_b = (GstQtReference *) b;
12871
12872   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12873     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12874
12875   /* known bitrates go before unknown; higher bitrates go first */
12876   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12877 }
12878
12879 /* sort the redirects and post a message for the application.
12880  */
12881 static void
12882 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12883 {
12884   GstQtReference *best;
12885   GstStructure *s;
12886   GstMessage *msg;
12887   GValue list_val = { 0, };
12888   GList *l;
12889
12890   g_assert (references != NULL);
12891
12892   references = g_list_sort (references, qtdemux_redirects_sort_func);
12893
12894   best = (GstQtReference *) references->data;
12895
12896   g_value_init (&list_val, GST_TYPE_LIST);
12897
12898   for (l = references; l != NULL; l = l->next) {
12899     GstQtReference *ref = (GstQtReference *) l->data;
12900     GValue struct_val = { 0, };
12901
12902     ref->structure = gst_structure_new ("redirect",
12903         "new-location", G_TYPE_STRING, ref->location, NULL);
12904
12905     if (ref->min_req_bitrate > 0) {
12906       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12907           ref->min_req_bitrate, NULL);
12908     }
12909
12910     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12911     g_value_set_boxed (&struct_val, ref->structure);
12912     gst_value_list_append_value (&list_val, &struct_val);
12913     g_value_unset (&struct_val);
12914     /* don't free anything here yet, since we need best->structure below */
12915   }
12916
12917   g_assert (best != NULL);
12918   s = gst_structure_copy (best->structure);
12919
12920   if (g_list_length (references) > 1) {
12921     gst_structure_set_value (s, "locations", &list_val);
12922   }
12923
12924   g_value_unset (&list_val);
12925
12926   for (l = references; l != NULL; l = l->next) {
12927     GstQtReference *ref = (GstQtReference *) l->data;
12928
12929     gst_structure_free (ref->structure);
12930     g_free (ref->location);
12931     g_free (ref);
12932   }
12933   g_list_free (references);
12934
12935   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12936   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12937   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12938   qtdemux->posted_redirect = TRUE;
12939 }
12940
12941 /* look for redirect nodes, collect all redirect information and
12942  * process it.
12943  */
12944 static gboolean
12945 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12946 {
12947   GNode *rmra, *rmda, *rdrf;
12948
12949   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12950   if (rmra) {
12951     GList *redirects = NULL;
12952
12953     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12954     while (rmda) {
12955       GstQtReference ref = { NULL, NULL, 0, 0 };
12956       GNode *rmdr, *rmvc;
12957
12958       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12959         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12960         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12961             ref.min_req_bitrate);
12962       }
12963
12964       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12965         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12966         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12967
12968 #ifndef GST_DISABLE_GST_DEBUG
12969         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12970 #endif
12971         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12972
12973         GST_LOG_OBJECT (qtdemux,
12974             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12975             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12976             bitmask, check_type);
12977         if (package == FOURCC_qtim && check_type == 0) {
12978           ref.min_req_qt_version = version;
12979         }
12980       }
12981
12982       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12983       if (rdrf) {
12984         guint32 ref_type;
12985         guint8 *ref_data;
12986         guint ref_len;
12987
12988         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12989         if (ref_len > 20) {
12990           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12991           ref_data = (guint8 *) rdrf->data + 20;
12992           if (ref_type == FOURCC_alis) {
12993             guint record_len, record_version, fn_len;
12994
12995             if (ref_len > 70) {
12996               /* MacOSX alias record, google for alias-layout.txt */
12997               record_len = QT_UINT16 (ref_data + 4);
12998               record_version = QT_UINT16 (ref_data + 4 + 2);
12999               fn_len = QT_UINT8 (ref_data + 50);
13000               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13001                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13002               }
13003             } else {
13004               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13005                   ref_len);
13006             }
13007           } else if (ref_type == FOURCC_url_) {
13008             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13009           } else {
13010             GST_DEBUG_OBJECT (qtdemux,
13011                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13012                 GST_FOURCC_ARGS (ref_type));
13013           }
13014           if (ref.location != NULL) {
13015             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13016             redirects =
13017                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13018           } else {
13019             GST_WARNING_OBJECT (qtdemux,
13020                 "Failed to extract redirect location from rdrf atom");
13021           }
13022         } else {
13023           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13024         }
13025       }
13026
13027       /* look for others */
13028       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13029     }
13030
13031     if (redirects != NULL) {
13032       qtdemux_process_redirects (qtdemux, redirects);
13033     }
13034   }
13035   return TRUE;
13036 }
13037
13038 static GstTagList *
13039 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13040 {
13041   const gchar *fmt;
13042
13043   if (tags == NULL) {
13044     tags = gst_tag_list_new_empty ();
13045     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13046   }
13047
13048   if (qtdemux->major_brand == FOURCC_mjp2)
13049     fmt = "Motion JPEG 2000";
13050   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13051     fmt = "3GP";
13052   else if (qtdemux->major_brand == FOURCC_qt__)
13053     fmt = "Quicktime";
13054   else if (qtdemux->fragmented)
13055     fmt = "ISO fMP4";
13056   else
13057     fmt = "ISO MP4/M4A";
13058
13059   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13060       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13061
13062   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13063       fmt, NULL);
13064
13065   return tags;
13066 }
13067
13068 /* we have read the complete moov node now.
13069  * This function parses all of the relevant info, creates the traks and
13070  * prepares all data structures for playback
13071  */
13072 static gboolean
13073 qtdemux_parse_tree (GstQTDemux * qtdemux)
13074 {
13075   GNode *mvhd;
13076   GNode *trak;
13077   GNode *udta;
13078   GNode *mvex;
13079   GstClockTime duration;
13080   GNode *pssh;
13081   guint64 creation_time;
13082   GstDateTime *datetime = NULL;
13083   gint version;
13084
13085   /* make sure we have a usable taglist */
13086   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13087
13088   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13089   if (mvhd == NULL) {
13090     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13091     return qtdemux_parse_redirects (qtdemux);
13092   }
13093
13094   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13095   if (version == 1) {
13096     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13097     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13098     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13099   } else if (version == 0) {
13100     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13101     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13102     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13103   } else {
13104     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13105     return FALSE;
13106   }
13107
13108   /* Moving qt creation time (secs since 1904) to unix time */
13109   if (creation_time != 0) {
13110     /* Try to use epoch first as it should be faster and more commonly found */
13111     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13112       GTimeVal now;
13113
13114       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13115       /* some data cleansing sanity */
13116       g_get_current_time (&now);
13117       if (now.tv_sec + 24 * 3600 < creation_time) {
13118         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13119       } else {
13120         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13121       }
13122     } else {
13123       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13124       GDateTime *dt, *dt_local;
13125
13126       dt = g_date_time_add_seconds (base_dt, creation_time);
13127       dt_local = g_date_time_to_local (dt);
13128       datetime = gst_date_time_new_from_g_date_time (dt_local);
13129
13130       g_date_time_unref (base_dt);
13131       g_date_time_unref (dt);
13132     }
13133   }
13134   if (datetime) {
13135     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13136     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13137         datetime, NULL);
13138     gst_date_time_unref (datetime);
13139   }
13140
13141   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13142   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13143
13144   /* check for fragmented file and get some (default) data */
13145   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13146   if (mvex) {
13147     GNode *mehd;
13148     GstByteReader mehd_data;
13149
13150     /* let track parsing or anyone know weird stuff might happen ... */
13151     qtdemux->fragmented = TRUE;
13152
13153     /* compensate for total duration */
13154     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13155     if (mehd)
13156       qtdemux_parse_mehd (qtdemux, &mehd_data);
13157   }
13158
13159   /* set duration in the segment info */
13160   gst_qtdemux_get_duration (qtdemux, &duration);
13161   if (duration) {
13162     qtdemux->segment.duration = duration;
13163     /* also do not exceed duration; stop is set that way post seek anyway,
13164      * and segment activation falls back to duration,
13165      * whereas loop only checks stop, so let's align this here as well */
13166     qtdemux->segment.stop = duration;
13167   }
13168
13169   /* parse all traks */
13170   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13171   while (trak) {
13172     qtdemux_parse_trak (qtdemux, trak);
13173     /* iterate all siblings */
13174     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13175   }
13176
13177   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13178
13179   /* find tags */
13180   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13181   if (udta) {
13182     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13183   } else {
13184     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13185   }
13186
13187   /* maybe also some tags in meta box */
13188   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13189   if (udta) {
13190     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13191     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13192   } else {
13193     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13194   }
13195
13196   /* parse any protection system info */
13197   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13198   while (pssh) {
13199     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13200     qtdemux_parse_pssh (qtdemux, pssh);
13201     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13202   }
13203
13204   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13205
13206   return TRUE;
13207 }
13208
13209 /* taken from ffmpeg */
13210 static int
13211 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13212 {
13213   int count = 4;
13214   int len = 0;
13215
13216   while (count--) {
13217     int c;
13218
13219     if (ptr >= end)
13220       return -1;
13221
13222     c = *ptr++;
13223     len = (len << 7) | (c & 0x7f);
13224     if (!(c & 0x80))
13225       break;
13226   }
13227   *end_out = ptr;
13228   return len;
13229 }
13230
13231 /* this can change the codec originally present in @list */
13232 static void
13233 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13234     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13235 {
13236   int len = QT_UINT32 (esds->data);
13237   guint8 *ptr = esds->data;
13238   guint8 *end = ptr + len;
13239   int tag;
13240   guint8 *data_ptr = NULL;
13241   int data_len = 0;
13242   guint8 object_type_id = 0;
13243   const char *codec_name = NULL;
13244   GstCaps *caps = NULL;
13245
13246   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13247   ptr += 8;
13248   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13249   ptr += 4;
13250   while (ptr + 1 < end) {
13251     tag = QT_UINT8 (ptr);
13252     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13253     ptr++;
13254     len = read_descr_size (ptr, end, &ptr);
13255     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13256
13257     /* Check the stated amount of data is available for reading */
13258     if (len < 0 || ptr + len > end)
13259       break;
13260
13261     switch (tag) {
13262       case ES_DESCRIPTOR_TAG:
13263         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13264         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13265         ptr += 3;
13266         break;
13267       case DECODER_CONFIG_DESC_TAG:{
13268         guint max_bitrate, avg_bitrate;
13269
13270         object_type_id = QT_UINT8 (ptr);
13271         max_bitrate = QT_UINT32 (ptr + 5);
13272         avg_bitrate = QT_UINT32 (ptr + 9);
13273         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13274         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13275         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13276         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13277         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13278         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13279           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13280               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13281         }
13282         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13283           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13284               avg_bitrate, NULL);
13285         }
13286         ptr += 13;
13287         break;
13288       }
13289       case DECODER_SPECIFIC_INFO_TAG:
13290         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13291         if (object_type_id == 0xe0 && len == 0x40) {
13292           guint8 *data;
13293           GstStructure *s;
13294           guint32 clut[16];
13295           gint i;
13296
13297           GST_DEBUG_OBJECT (qtdemux,
13298               "Have VOBSUB palette. Creating palette event");
13299           /* move to decConfigDescr data and read palette */
13300           data = ptr;
13301           for (i = 0; i < 16; i++) {
13302             clut[i] = QT_UINT32 (data);
13303             data += 4;
13304           }
13305
13306           s = gst_structure_new ("application/x-gst-dvd", "event",
13307               G_TYPE_STRING, "dvd-spu-clut-change",
13308               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13309               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13310               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13311               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13312               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13313               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13314               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13315               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13316               NULL);
13317
13318           /* store event and trigger custom processing */
13319           stream->pending_event =
13320               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13321         } else {
13322           /* Generic codec_data handler puts it on the caps */
13323           data_ptr = ptr;
13324           data_len = len;
13325         }
13326
13327         ptr += len;
13328         break;
13329       case SL_CONFIG_DESC_TAG:
13330         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13331         ptr += 1;
13332         break;
13333       default:
13334         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13335             tag);
13336         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13337         ptr += len;
13338         break;
13339     }
13340   }
13341
13342   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13343    * in use, and should also be used to override some other parameters for some
13344    * codecs. */
13345   switch (object_type_id) {
13346     case 0x20:                 /* MPEG-4 */
13347       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13348        * profile_and_level_indication */
13349       if (data_ptr != NULL && data_len >= 5 &&
13350           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13351         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13352             data_ptr + 4, data_len - 4);
13353       }
13354       break;                    /* Nothing special needed here */
13355     case 0x21:                 /* H.264 */
13356       codec_name = "H.264 / AVC";
13357       caps = gst_caps_new_simple ("video/x-h264",
13358           "stream-format", G_TYPE_STRING, "avc",
13359           "alignment", G_TYPE_STRING, "au", NULL);
13360       break;
13361     case 0x40:                 /* AAC (any) */
13362     case 0x66:                 /* AAC Main */
13363     case 0x67:                 /* AAC LC */
13364     case 0x68:                 /* AAC SSR */
13365       /* Override channels and rate based on the codec_data, as it's often
13366        * wrong. */
13367       /* Only do so for basic setup without HE-AAC extension */
13368       if (data_ptr && data_len == 2) {
13369         guint channels, rate;
13370
13371         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13372         if (channels > 0)
13373           entry->n_channels = channels;
13374
13375         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13376         if (rate > 0)
13377           entry->rate = rate;
13378       }
13379
13380       /* Set level and profile if possible */
13381       if (data_ptr != NULL && data_len >= 2) {
13382         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13383             data_ptr, data_len);
13384       } else {
13385         const gchar *profile_str = NULL;
13386         GstBuffer *buffer;
13387         GstMapInfo map;
13388         guint8 *codec_data;
13389         gint rate_idx, profile;
13390
13391         /* No codec_data, let's invent something.
13392          * FIXME: This is wrong for SBR! */
13393
13394         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13395
13396         buffer = gst_buffer_new_and_alloc (2);
13397         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13398         codec_data = map.data;
13399
13400         rate_idx =
13401             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13402             (stream)->rate);
13403
13404         switch (object_type_id) {
13405           case 0x66:
13406             profile_str = "main";
13407             profile = 0;
13408             break;
13409           case 0x67:
13410             profile_str = "lc";
13411             profile = 1;
13412             break;
13413           case 0x68:
13414             profile_str = "ssr";
13415             profile = 2;
13416             break;
13417           default:
13418             profile = 3;
13419             break;
13420         }
13421
13422         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13423         codec_data[1] =
13424             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13425
13426         gst_buffer_unmap (buffer, &map);
13427         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13428             GST_TYPE_BUFFER, buffer, NULL);
13429         gst_buffer_unref (buffer);
13430
13431         if (profile_str) {
13432           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13433               G_TYPE_STRING, profile_str, NULL);
13434         }
13435       }
13436       break;
13437     case 0x60:                 /* MPEG-2, various profiles */
13438     case 0x61:
13439     case 0x62:
13440     case 0x63:
13441     case 0x64:
13442     case 0x65:
13443       codec_name = "MPEG-2 video";
13444       caps = gst_caps_new_simple ("video/mpeg",
13445           "mpegversion", G_TYPE_INT, 2,
13446           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13447       break;
13448     case 0x69:                 /* MPEG-2 BC audio */
13449     case 0x6B:                 /* MPEG-1 audio */
13450       caps = gst_caps_new_simple ("audio/mpeg",
13451           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13452       codec_name = "MPEG-1 audio";
13453       break;
13454     case 0x6A:                 /* MPEG-1 */
13455       codec_name = "MPEG-1 video";
13456       caps = gst_caps_new_simple ("video/mpeg",
13457           "mpegversion", G_TYPE_INT, 1,
13458           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13459       break;
13460     case 0x6C:                 /* MJPEG */
13461       caps =
13462           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13463           NULL);
13464       codec_name = "Motion-JPEG";
13465       break;
13466     case 0x6D:                 /* PNG */
13467       caps =
13468           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13469           NULL);
13470       codec_name = "PNG still images";
13471       break;
13472     case 0x6E:                 /* JPEG2000 */
13473       codec_name = "JPEG-2000";
13474       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13475       break;
13476     case 0xA4:                 /* Dirac */
13477       codec_name = "Dirac";
13478       caps = gst_caps_new_empty_simple ("video/x-dirac");
13479       break;
13480     case 0xA5:                 /* AC3 */
13481       codec_name = "AC-3 audio";
13482       caps = gst_caps_new_simple ("audio/x-ac3",
13483           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13484       break;
13485     case 0xA9:                 /* AC3 */
13486       codec_name = "DTS audio";
13487       caps = gst_caps_new_simple ("audio/x-dts",
13488           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13489       break;
13490     case 0xE1:                 /* QCELP */
13491       /* QCELP, the codec_data is a riff tag (little endian) with
13492        * 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). */
13493       caps = gst_caps_new_empty_simple ("audio/qcelp");
13494       codec_name = "QCELP";
13495       break;
13496     default:
13497       break;
13498   }
13499
13500   /* If we have a replacement caps, then change our caps for this stream */
13501   if (caps) {
13502     gst_caps_unref (entry->caps);
13503     entry->caps = caps;
13504   }
13505
13506   if (codec_name && list)
13507     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13508         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13509
13510   /* Add the codec_data attribute to caps, if we have it */
13511   if (data_ptr) {
13512     GstBuffer *buffer;
13513
13514     buffer = gst_buffer_new_and_alloc (data_len);
13515     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13516
13517     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13518     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13519
13520     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13521         buffer, NULL);
13522     gst_buffer_unref (buffer);
13523   }
13524
13525 }
13526
13527 static inline GstCaps *
13528 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13529 {
13530   GstCaps *caps;
13531   guint i;
13532   char *s, fourstr[5];
13533
13534   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13535   for (i = 0; i < 4; i++) {
13536     if (!g_ascii_isalnum (fourstr[i]))
13537       fourstr[i] = '_';
13538   }
13539   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13540   caps = gst_caps_new_empty_simple (s);
13541   g_free (s);
13542   return caps;
13543 }
13544
13545 #define _codec(name) \
13546   do { \
13547     if (codec_name) { \
13548       *codec_name = g_strdup (name); \
13549     } \
13550   } while (0)
13551
13552 static GstCaps *
13553 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13554     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13555     const guint8 * stsd_entry_data, gchar ** codec_name)
13556 {
13557   GstCaps *caps = NULL;
13558   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13559
13560   switch (fourcc) {
13561     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13562       _codec ("PNG still images");
13563       caps = gst_caps_new_empty_simple ("image/png");
13564       break;
13565     case FOURCC_jpeg:
13566       _codec ("JPEG still images");
13567       caps =
13568           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13569           NULL);
13570       break;
13571     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13572     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13573     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13574     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13575       _codec ("Motion-JPEG");
13576       caps =
13577           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13578           NULL);
13579       break;
13580     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13581       _codec ("Motion-JPEG format B");
13582       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13583       break;
13584     case FOURCC_mjp2:
13585       _codec ("JPEG-2000");
13586       /* override to what it should be according to spec, avoid palette_data */
13587       entry->bits_per_sample = 24;
13588       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13589       break;
13590     case FOURCC_SVQ3:
13591       _codec ("Sorensen video v.3");
13592       caps = gst_caps_new_simple ("video/x-svq",
13593           "svqversion", G_TYPE_INT, 3, NULL);
13594       break;
13595     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13596     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13597       _codec ("Sorensen video v.1");
13598       caps = gst_caps_new_simple ("video/x-svq",
13599           "svqversion", G_TYPE_INT, 1, NULL);
13600       break;
13601     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13602       caps = gst_caps_new_empty_simple ("video/x-raw");
13603       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13604       _codec ("Windows Raw RGB");
13605       stream->alignment = 32;
13606       break;
13607     case FOURCC_raw_:
13608     {
13609       guint16 bps;
13610
13611       bps = QT_UINT16 (stsd_entry_data + 82);
13612       switch (bps) {
13613         case 15:
13614           format = GST_VIDEO_FORMAT_RGB15;
13615           break;
13616         case 16:
13617           format = GST_VIDEO_FORMAT_RGB16;
13618           break;
13619         case 24:
13620           format = GST_VIDEO_FORMAT_RGB;
13621           break;
13622         case 32:
13623           format = GST_VIDEO_FORMAT_ARGB;
13624           break;
13625         default:
13626           /* unknown */
13627           break;
13628       }
13629       break;
13630     }
13631     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13632       format = GST_VIDEO_FORMAT_I420;
13633       break;
13634     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13635     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13636       format = GST_VIDEO_FORMAT_I420;
13637       break;
13638     case FOURCC_2vuy:
13639     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13640       format = GST_VIDEO_FORMAT_UYVY;
13641       break;
13642     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13643       format = GST_VIDEO_FORMAT_v308;
13644       break;
13645     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13646       format = GST_VIDEO_FORMAT_v216;
13647       break;
13648     case FOURCC_v210:
13649       format = GST_VIDEO_FORMAT_v210;
13650       break;
13651     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13652       format = GST_VIDEO_FORMAT_r210;
13653       break;
13654       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13655          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13656          format = GST_VIDEO_FORMAT_v410;
13657          break;
13658        */
13659       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13660        * but different order than AYUV
13661        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13662        format = GST_VIDEO_FORMAT_v408;
13663        break;
13664        */
13665     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13666     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13667       _codec ("MPEG-1 video");
13668       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13669           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13670       break;
13671     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13672     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13673     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13674     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13675     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13676     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13677     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13678     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13679     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13680     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13681     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13682     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13683     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13684     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13685     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13686     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13687     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13688     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13689     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13690     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13691     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13692     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13693     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13694     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13695     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13696     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13697     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13698     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13699     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13700     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13701     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13702     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13703     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13704     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13705     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13706     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13707     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13708     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13709     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13710     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13711     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13712     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13713     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13714     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13715     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13716     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13717     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13718       _codec ("MPEG-2 video");
13719       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13720           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13721       break;
13722     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13723       _codec ("GIF still images");
13724       caps = gst_caps_new_empty_simple ("image/gif");
13725       break;
13726     case FOURCC_h263:
13727     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13728     case FOURCC_s263:
13729     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13730       _codec ("H.263");
13731       /* ffmpeg uses the height/width props, don't know why */
13732       caps = gst_caps_new_simple ("video/x-h263",
13733           "variant", G_TYPE_STRING, "itu", NULL);
13734       break;
13735     case FOURCC_mp4v:
13736     case FOURCC_MP4V:
13737       _codec ("MPEG-4 video");
13738       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13739           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13740       break;
13741     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13742     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13743       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13744       caps = gst_caps_new_simple ("video/x-msmpeg",
13745           "msmpegversion", G_TYPE_INT, 43, NULL);
13746       break;
13747     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13748       _codec ("DivX 3");
13749       caps = gst_caps_new_simple ("video/x-divx",
13750           "divxversion", G_TYPE_INT, 3, NULL);
13751       break;
13752     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13753     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13754       _codec ("DivX 4");
13755       caps = gst_caps_new_simple ("video/x-divx",
13756           "divxversion", G_TYPE_INT, 4, NULL);
13757       break;
13758     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13759       _codec ("DivX 5");
13760       caps = gst_caps_new_simple ("video/x-divx",
13761           "divxversion", G_TYPE_INT, 5, NULL);
13762       break;
13763
13764     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13765       _codec ("FFV1");
13766       caps = gst_caps_new_simple ("video/x-ffv",
13767           "ffvversion", G_TYPE_INT, 1, NULL);
13768       break;
13769
13770     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13771     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13772     case FOURCC_XVID:
13773     case FOURCC_xvid:
13774     case FOURCC_FMP4:
13775     case FOURCC_fmp4:
13776     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13777       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13778           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13779       _codec ("MPEG-4");
13780       break;
13781
13782     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13783       _codec ("Cinepak");
13784       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13785       break;
13786     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13787       _codec ("Apple QuickDraw");
13788       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13789       break;
13790     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13791       _codec ("Apple video");
13792       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13793       break;
13794     case FOURCC_H264:
13795     case FOURCC_avc1:
13796       _codec ("H.264 / AVC");
13797       caps = gst_caps_new_simple ("video/x-h264",
13798           "stream-format", G_TYPE_STRING, "avc",
13799           "alignment", G_TYPE_STRING, "au", NULL);
13800       break;
13801     case FOURCC_avc3:
13802       _codec ("H.264 / AVC");
13803       caps = gst_caps_new_simple ("video/x-h264",
13804           "stream-format", G_TYPE_STRING, "avc3",
13805           "alignment", G_TYPE_STRING, "au", NULL);
13806       break;
13807     case FOURCC_H265:
13808     case FOURCC_hvc1:
13809       _codec ("H.265 / HEVC");
13810       caps = gst_caps_new_simple ("video/x-h265",
13811           "stream-format", G_TYPE_STRING, "hvc1",
13812           "alignment", G_TYPE_STRING, "au", NULL);
13813       break;
13814     case FOURCC_hev1:
13815       _codec ("H.265 / HEVC");
13816       caps = gst_caps_new_simple ("video/x-h265",
13817           "stream-format", G_TYPE_STRING, "hev1",
13818           "alignment", G_TYPE_STRING, "au", NULL);
13819       break;
13820     case FOURCC_rle_:
13821       _codec ("Run-length encoding");
13822       caps = gst_caps_new_simple ("video/x-rle",
13823           "layout", G_TYPE_STRING, "quicktime", NULL);
13824       break;
13825     case FOURCC_WRLE:
13826       _codec ("Run-length encoding");
13827       caps = gst_caps_new_simple ("video/x-rle",
13828           "layout", G_TYPE_STRING, "microsoft", NULL);
13829       break;
13830     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13831     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13832       _codec ("Indeo Video 3");
13833       caps = gst_caps_new_simple ("video/x-indeo",
13834           "indeoversion", G_TYPE_INT, 3, NULL);
13835       break;
13836     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13837     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13838       _codec ("Intel Video 4");
13839       caps = gst_caps_new_simple ("video/x-indeo",
13840           "indeoversion", G_TYPE_INT, 4, NULL);
13841       break;
13842     case FOURCC_dvcp:
13843     case FOURCC_dvc_:
13844     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13845     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13846     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13847     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13848     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13849     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13850       _codec ("DV Video");
13851       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13852           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13853       break;
13854     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13855     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13856       _codec ("DVCPro50 Video");
13857       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13858           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13859       break;
13860     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13861     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13862       _codec ("DVCProHD Video");
13863       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13864           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13865       break;
13866     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13867       _codec ("Apple Graphics (SMC)");
13868       caps = gst_caps_new_empty_simple ("video/x-smc");
13869       break;
13870     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13871       _codec ("VP3");
13872       caps = gst_caps_new_empty_simple ("video/x-vp3");
13873       break;
13874     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13875       _codec ("VP6 Flash");
13876       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13877       break;
13878     case FOURCC_XiTh:
13879       _codec ("Theora");
13880       caps = gst_caps_new_empty_simple ("video/x-theora");
13881       /* theora uses one byte of padding in the data stream because it does not
13882        * allow 0 sized packets while theora does */
13883       entry->padding = 1;
13884       break;
13885     case FOURCC_drac:
13886       _codec ("Dirac");
13887       caps = gst_caps_new_empty_simple ("video/x-dirac");
13888       break;
13889     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13890       _codec ("TIFF still images");
13891       caps = gst_caps_new_empty_simple ("image/tiff");
13892       break;
13893     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13894       _codec ("Apple Intermediate Codec");
13895       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13896       break;
13897     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13898       _codec ("AVID DNxHD");
13899       caps = gst_caps_from_string ("video/x-dnxhd");
13900       break;
13901     case FOURCC_VP80:
13902       _codec ("On2 VP8");
13903       caps = gst_caps_from_string ("video/x-vp8");
13904       break;
13905     case FOURCC_apcs:
13906       _codec ("Apple ProRes LT");
13907       caps =
13908           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13909           NULL);
13910       break;
13911     case FOURCC_apch:
13912       _codec ("Apple ProRes HQ");
13913       caps =
13914           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13915           NULL);
13916       break;
13917     case FOURCC_apcn:
13918       _codec ("Apple ProRes");
13919       caps =
13920           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13921           "standard", NULL);
13922       break;
13923     case FOURCC_apco:
13924       _codec ("Apple ProRes Proxy");
13925       caps =
13926           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13927           "proxy", NULL);
13928       break;
13929     case FOURCC_ap4h:
13930       _codec ("Apple ProRes 4444");
13931       caps =
13932           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13933           "4444", NULL);
13934       break;
13935     case FOURCC_ap4x:
13936       _codec ("Apple ProRes 4444 XQ");
13937       caps =
13938           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13939           "4444xq", NULL);
13940       break;
13941     case FOURCC_cfhd:
13942       _codec ("GoPro CineForm");
13943       caps = gst_caps_from_string ("video/x-cineform");
13944       break;
13945     case FOURCC_vc_1:
13946     case FOURCC_ovc1:
13947       _codec ("VC-1");
13948       caps = gst_caps_new_simple ("video/x-wmv",
13949           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13950       break;
13951     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13952     default:
13953     {
13954       caps = _get_unknown_codec_name ("video", fourcc);
13955       break;
13956     }
13957   }
13958
13959   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13960     GstVideoInfo info;
13961
13962     gst_video_info_init (&info);
13963     gst_video_info_set_format (&info, format, entry->width, entry->height);
13964
13965     caps = gst_video_info_to_caps (&info);
13966     *codec_name = gst_pb_utils_get_codec_description (caps);
13967
13968     /* enable clipping for raw video streams */
13969     stream->need_clip = TRUE;
13970     stream->alignment = 32;
13971   }
13972
13973   return caps;
13974 }
13975
13976 static guint
13977 round_up_pow2 (guint n)
13978 {
13979   n = n - 1;
13980   n = n | (n >> 1);
13981   n = n | (n >> 2);
13982   n = n | (n >> 4);
13983   n = n | (n >> 8);
13984   n = n | (n >> 16);
13985   return n + 1;
13986 }
13987
13988 static GstCaps *
13989 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13990     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
13991     int len, gchar ** codec_name)
13992 {
13993   GstCaps *caps;
13994   const GstStructure *s;
13995   const gchar *name;
13996   gint endian = 0;
13997   GstAudioFormat format = 0;
13998   gint depth;
13999
14000   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14001
14002   depth = entry->bytes_per_packet * 8;
14003
14004   switch (fourcc) {
14005     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14006     case FOURCC_raw_:
14007       /* 8-bit audio is unsigned */
14008       if (depth == 8)
14009         format = GST_AUDIO_FORMAT_U8;
14010       /* otherwise it's signed and big-endian just like 'twos' */
14011     case FOURCC_twos:
14012       endian = G_BIG_ENDIAN;
14013       /* fall-through */
14014     case FOURCC_sowt:
14015     {
14016       gchar *str;
14017
14018       if (!endian)
14019         endian = G_LITTLE_ENDIAN;
14020
14021       if (!format)
14022         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14023
14024       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14025       _codec (str);
14026       g_free (str);
14027
14028       caps = gst_caps_new_simple ("audio/x-raw",
14029           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14030           "layout", G_TYPE_STRING, "interleaved", NULL);
14031       stream->alignment = GST_ROUND_UP_8 (depth);
14032       stream->alignment = round_up_pow2 (stream->alignment);
14033       break;
14034     }
14035     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14036       _codec ("Raw 64-bit floating-point audio");
14037       caps = gst_caps_new_simple ("audio/x-raw",
14038           "format", G_TYPE_STRING, "F64BE",
14039           "layout", G_TYPE_STRING, "interleaved", NULL);
14040       stream->alignment = 8;
14041       break;
14042     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14043       _codec ("Raw 32-bit floating-point audio");
14044       caps = gst_caps_new_simple ("audio/x-raw",
14045           "format", G_TYPE_STRING, "F32BE",
14046           "layout", G_TYPE_STRING, "interleaved", NULL);
14047       stream->alignment = 4;
14048       break;
14049     case FOURCC_in24:
14050       _codec ("Raw 24-bit PCM audio");
14051       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14052        * endian later */
14053       caps = gst_caps_new_simple ("audio/x-raw",
14054           "format", G_TYPE_STRING, "S24BE",
14055           "layout", G_TYPE_STRING, "interleaved", NULL);
14056       stream->alignment = 4;
14057       break;
14058     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14059       _codec ("Raw 32-bit PCM audio");
14060       caps = gst_caps_new_simple ("audio/x-raw",
14061           "format", G_TYPE_STRING, "S32BE",
14062           "layout", G_TYPE_STRING, "interleaved", NULL);
14063       stream->alignment = 4;
14064       break;
14065     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14066       _codec ("Raw 16-bit PCM audio");
14067       caps = gst_caps_new_simple ("audio/x-raw",
14068           "format", G_TYPE_STRING, "S16LE",
14069           "layout", G_TYPE_STRING, "interleaved", NULL);
14070       stream->alignment = 2;
14071       break;
14072     case FOURCC_ulaw:
14073       _codec ("Mu-law audio");
14074       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14075       break;
14076     case FOURCC_alaw:
14077       _codec ("A-law audio");
14078       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14079       break;
14080     case 0x0200736d:
14081     case 0x6d730002:
14082       _codec ("Microsoft ADPCM");
14083       /* Microsoft ADPCM-ACM code 2 */
14084       caps = gst_caps_new_simple ("audio/x-adpcm",
14085           "layout", G_TYPE_STRING, "microsoft", NULL);
14086       break;
14087     case 0x1100736d:
14088     case 0x6d730011:
14089       _codec ("DVI/IMA ADPCM");
14090       caps = gst_caps_new_simple ("audio/x-adpcm",
14091           "layout", G_TYPE_STRING, "dvi", NULL);
14092       break;
14093     case 0x1700736d:
14094     case 0x6d730017:
14095       _codec ("DVI/Intel IMA ADPCM");
14096       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14097       caps = gst_caps_new_simple ("audio/x-adpcm",
14098           "layout", G_TYPE_STRING, "quicktime", NULL);
14099       break;
14100     case 0x5500736d:
14101     case 0x6d730055:
14102       /* MPEG layer 3, CBR only (pre QT4.1) */
14103     case FOURCC__mp3:
14104       _codec ("MPEG-1 layer 3");
14105       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14106       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14107           "mpegversion", G_TYPE_INT, 1, NULL);
14108       break;
14109     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14110       _codec ("MPEG-1 layer 2");
14111       /* MPEG layer 2 */
14112       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14113           "mpegversion", G_TYPE_INT, 1, NULL);
14114       break;
14115     case 0x20736d:
14116     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14117       _codec ("EAC-3 audio");
14118       caps = gst_caps_new_simple ("audio/x-eac3",
14119           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14120       entry->sampled = TRUE;
14121       break;
14122     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14123     case FOURCC_ac_3:
14124       _codec ("AC-3 audio");
14125       caps = gst_caps_new_simple ("audio/x-ac3",
14126           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14127       entry->sampled = TRUE;
14128       break;
14129     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14130     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14131       _codec ("DTS audio");
14132       caps = gst_caps_new_simple ("audio/x-dts",
14133           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14134       entry->sampled = TRUE;
14135       break;
14136     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14137     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14138       _codec ("DTS-HD audio");
14139       caps = gst_caps_new_simple ("audio/x-dts",
14140           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14141       entry->sampled = TRUE;
14142       break;
14143     case FOURCC_MAC3:
14144       _codec ("MACE-3");
14145       caps = gst_caps_new_simple ("audio/x-mace",
14146           "maceversion", G_TYPE_INT, 3, NULL);
14147       break;
14148     case FOURCC_MAC6:
14149       _codec ("MACE-6");
14150       caps = gst_caps_new_simple ("audio/x-mace",
14151           "maceversion", G_TYPE_INT, 6, NULL);
14152       break;
14153     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14154       /* ogg/vorbis */
14155       caps = gst_caps_new_empty_simple ("application/ogg");
14156       break;
14157     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14158       _codec ("DV audio");
14159       caps = gst_caps_new_empty_simple ("audio/x-dv");
14160       break;
14161     case FOURCC_mp4a:
14162       _codec ("MPEG-4 AAC audio");
14163       caps = gst_caps_new_simple ("audio/mpeg",
14164           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14165           "stream-format", G_TYPE_STRING, "raw", NULL);
14166       break;
14167     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14168       _codec ("QDesign Music");
14169       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14170       break;
14171     case FOURCC_QDM2:
14172       _codec ("QDesign Music v.2");
14173       /* FIXME: QDesign music version 2 (no constant) */
14174       if (FALSE && data) {
14175         caps = gst_caps_new_simple ("audio/x-qdm2",
14176             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14177             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14178             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14179       } else {
14180         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14181       }
14182       break;
14183     case FOURCC_agsm:
14184       _codec ("GSM audio");
14185       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14186       break;
14187     case FOURCC_samr:
14188       _codec ("AMR audio");
14189       caps = gst_caps_new_empty_simple ("audio/AMR");
14190       break;
14191     case FOURCC_sawb:
14192       _codec ("AMR-WB audio");
14193       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14194       break;
14195     case FOURCC_ima4:
14196       _codec ("Quicktime IMA ADPCM");
14197       caps = gst_caps_new_simple ("audio/x-adpcm",
14198           "layout", G_TYPE_STRING, "quicktime", NULL);
14199       break;
14200     case FOURCC_alac:
14201       _codec ("Apple lossless audio");
14202       caps = gst_caps_new_empty_simple ("audio/x-alac");
14203       break;
14204     case FOURCC_fLaC:
14205       _codec ("Free Lossless Audio Codec");
14206       caps = gst_caps_new_simple ("audio/x-flac",
14207           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14208       break;
14209     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14210       _codec ("QualComm PureVoice");
14211       caps = gst_caps_from_string ("audio/qcelp");
14212       break;
14213     case FOURCC_wma_:
14214     case FOURCC_owma:
14215       _codec ("WMA");
14216       caps = gst_caps_new_empty_simple ("audio/x-wma");
14217       break;
14218     case FOURCC_opus:
14219       _codec ("Opus");
14220       caps = gst_caps_new_empty_simple ("audio/x-opus");
14221       break;
14222     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14223     {
14224       guint32 flags = 0;
14225       guint32 depth = 0;
14226       guint32 width = 0;
14227       GstAudioFormat format;
14228       enum
14229       {
14230         FLAG_IS_FLOAT = 0x1,
14231         FLAG_IS_BIG_ENDIAN = 0x2,
14232         FLAG_IS_SIGNED = 0x4,
14233         FLAG_IS_PACKED = 0x8,
14234         FLAG_IS_ALIGNED_HIGH = 0x10,
14235         FLAG_IS_NON_INTERLEAVED = 0x20
14236       };
14237       _codec ("Raw LPCM audio");
14238
14239       if (data && len >= 56) {
14240         depth = QT_UINT32 (data + 40);
14241         flags = QT_UINT32 (data + 44);
14242         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14243       }
14244       if ((flags & FLAG_IS_FLOAT) == 0) {
14245         if (depth == 0)
14246           depth = 16;
14247         if (width == 0)
14248           width = 16;
14249         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14250             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14251             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14252         caps = gst_caps_new_simple ("audio/x-raw",
14253             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14254             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14255             "non-interleaved" : "interleaved", NULL);
14256         stream->alignment = GST_ROUND_UP_8 (depth);
14257         stream->alignment = round_up_pow2 (stream->alignment);
14258       } else {
14259         if (width == 0)
14260           width = 32;
14261         if (width == 64) {
14262           if (flags & FLAG_IS_BIG_ENDIAN)
14263             format = GST_AUDIO_FORMAT_F64BE;
14264           else
14265             format = GST_AUDIO_FORMAT_F64LE;
14266         } else {
14267           if (flags & FLAG_IS_BIG_ENDIAN)
14268             format = GST_AUDIO_FORMAT_F32BE;
14269           else
14270             format = GST_AUDIO_FORMAT_F32LE;
14271         }
14272         caps = gst_caps_new_simple ("audio/x-raw",
14273             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14274             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14275             "non-interleaved" : "interleaved", NULL);
14276         stream->alignment = width / 8;
14277       }
14278       break;
14279     }
14280     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14281       /* ? */
14282     default:
14283     {
14284       caps = _get_unknown_codec_name ("audio", fourcc);
14285       break;
14286     }
14287   }
14288
14289   if (caps) {
14290     GstCaps *templ_caps =
14291         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14292     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14293     gst_caps_unref (caps);
14294     gst_caps_unref (templ_caps);
14295     caps = intersection;
14296   }
14297
14298   /* enable clipping for raw audio streams */
14299   s = gst_caps_get_structure (caps, 0);
14300   name = gst_structure_get_name (s);
14301   if (g_str_has_prefix (name, "audio/x-raw")) {
14302     stream->need_clip = TRUE;
14303     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14304     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14305   }
14306   return caps;
14307 }
14308
14309 static GstCaps *
14310 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14311     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14312     const guint8 * stsd_entry_data, gchar ** codec_name)
14313 {
14314   GstCaps *caps;
14315
14316   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14317
14318   switch (fourcc) {
14319     case FOURCC_mp4s:
14320       _codec ("DVD subtitle");
14321       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14322       stream->need_process = TRUE;
14323       break;
14324     case FOURCC_text:
14325       _codec ("Quicktime timed text");
14326       goto text;
14327     case FOURCC_tx3g:
14328       _codec ("3GPP timed text");
14329     text:
14330       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14331           "utf8", NULL);
14332       /* actual text piece needs to be extracted */
14333       stream->need_process = TRUE;
14334       break;
14335     case FOURCC_stpp:
14336       _codec ("XML subtitles");
14337       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14338       break;
14339     default:
14340     {
14341       caps = _get_unknown_codec_name ("text", fourcc);
14342       break;
14343     }
14344   }
14345   return caps;
14346 }
14347
14348 static GstCaps *
14349 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14350     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14351     const guint8 * stsd_entry_data, gchar ** codec_name)
14352 {
14353   GstCaps *caps;
14354
14355   switch (fourcc) {
14356     case FOURCC_m1v:
14357       _codec ("MPEG 1 video");
14358       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14359           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14360       break;
14361     default:
14362       caps = NULL;
14363       break;
14364   }
14365   return caps;
14366 }
14367
14368 static void
14369 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14370     const gchar * system_id)
14371 {
14372   gint i;
14373
14374   if (!qtdemux->protection_system_ids)
14375     qtdemux->protection_system_ids =
14376         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14377   /* Check whether we already have an entry for this system ID. */
14378   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14379     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14380     if (g_ascii_strcasecmp (system_id, id) == 0) {
14381       return;
14382     }
14383   }
14384   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14385   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14386           -1));
14387 }